Importing Content into OneNote 2003 SP1 Preview

The OneNote Service Pack 1 Preview is currently available for download. This Service Pack includes some cool new features that'll be of great interest to developers. We've already been seeing some questions about this new functionality in the newsgroups, so we posting a draft of the article that will appear on MSDN once SP1 is released. Keep in mind that, while we've tried to make sure the information is as accurate and complete as possible, it is a draft document, and provided as such. Void where prohibited.

 

Anyway, here's the article:


Importing Content into OneNote 2003 SP1 Preview

Applies To:

    Microsoft Office OneNote 2003 SP1

Summary: Learn about the new extensibility features available for developers in Microsoft Office OneNote 2003 SP1. The new OneNote 1.1 Type Library includes functionality which enables you to programmatically import images, ink, and HTML into OneNote.

Introduction

For the Service Pack 1 (SP1) Preview, OneNote 2003 has added extensibility functionality that enables applications to interoperate with it in an important, fundamental way—they can add content to OneNote notebooks. You can now push content to OneNote that includes html, images, and even ink (such as from a Tablet PC). You can even create the folder, section, or page onto which you want to place your content.

Note These extensibility features are only available in the OneNote 2003 Service Pack 1 Preview. You can upgrade to the OneNote SP1 Preview here.

Using the CSimpleImporterClass

OneNote SP1 exposes the OneNote 1.1 Type Library, which consists of a single class, CSimpleImporterClass, which enables you to programmatically add content to a OneNote notebook. You can add text in html form, images, and even ink from a Tablet PC. The CSimpleImporterClass enables you to specify where in the notebook you want to place the content; you can even create new folders, sections, and pages for content, and then programmatically display the desired page. OneNote’s import functionality also lets you later delete the content you import.

The CSimpleImporterClass consists of two methods:

· Import, which enables you to add, update, or delete images, ink, and html content to a specific page in a OneNote folder and section.

· NavigateToPage, which enables you to display a specified page.

To use the CSimpleImportClass, you must add a reference to the OneNote 1.1 Type Library to your project. To add a reference, in Visual Studio .NET, on the Solution Explorer window, right-click References and then click Add Reference. On the COM tab, select OneNote 1.1 Type Library in the list, click Select, and then click OK.

While this article focuses on implementing OneNote’s import functionality using .NET languages, you can also use the OneNote 1.1 Type Library with unmanaged code, such as Visual Basic 6.0 or Visual C++.

The Data Import Schema

The Import method has the following signature:

Import (bstrXml as String)

The method takes an xml string describing the content object(s) you want to import, as well as the location in the notebook where you want them placed. You can also use the import command to delete objects you have previously placed in the notebook.

When called, OneNote executes the Import method with minimal intrusion on the user. OneNote does open if it is not already opened, which means the OneNote splash screen displays, but OneNote does not assume focus. Nor does it change the user’s location in the notebook if OneNote is already running. To change the focus of the OneNote application to the new content, use the NavigateToPage method, discussed later.

If the Import method fails, OneNote does not display an error to the user. However, the COM interface does return an “Unknown Error” to the application making the call.

The figure below outlines the xml schema to which the import file must adhere.

 

Figure 1. XML Schema Structure of the Import Root Element

 

 

Figure 2. Schema Structure of the PlaceObjects Element

The OneNote data import schema can be found at The OneNote 1.1 SimpleImport XML Schema.

Note The namespace for the Import method will be different in the final version of OneNote SP1 from what it is in the SP1 Preview.

The current namespace for the OneNote SP1 Preview is:

http://schemas.microsoft.com/office/onenote/01/2004/import

While the final namespace for OneNote SP1 will be:

http://schemas.microsoft.com/office/onenote/2004/import

Be advised that if you’re programming against the Preview namespace, you must update your code for the new namespace in order for it to be compatible with the final OneNote SP1.

There are two elements directly below the root <Import> element. Use the first element, <EnsurePage>, to make sure the folder, section, and page on which you want to place content exists. Use the second element, <PlaceObjects>, to actually place or delete objects from the page. The schema requires that the root element contain either at least one <EnsurePage> or <PlaceObjects> element. Any <EnsurePage> elements must appear before any <PlaceObjects> element.

Creating Folders and Pages for Content

Before you import content, the target pages for that content must exist in the OneNote notebook. Use the <EnsurePage> element to verify or create the target pages for your content. For each page you specify in an <EnsurePage> element, OneNote checks to determine if the page exists, and if not, creates it. You can even create new notebook folders and sections by specifying folders or sections that don’t exist.

You are required to pass OneNote a string representing the path to the desired page, as well as a GUID for that page. If the path is not fully-qualified, OneNote assumes the string starts from the notebook root location for the user. Additionally, you can specify the title, date, reading direction, and page placement relative to other pages in the notebook.

By default, OneNote inserts each new page at the end of the specified section. If you specify a page GUID for the insertAfter attribute, OneNote inserts the new page as a sub-page of the page whose GUID you specified. In such cases, OneNote labels the sub-page with the title and date of the page after which it’s inserted, rather than what you specify in the title and date attributes for the sub-page. If the page you specify does not exist (for example, if it was never added, or the user deleted it), then OneNote ignores the insertAfter attribute and inserts the new page at the end of the specified section, with any specified title and date values.

Consider the following example. This <EnsurePage> element specifies a page in the OneNote section title Negotiations, in the folder Johnson Contract, in the user’s root notebook folder. The page is titled “Budget Concerns”.

      <EnsurePage path="Johnson Contract\Negotiations.one"

      guid="{8FDD3C41-5BB5-4595-B019-7E7E9BC9D38E}"

      title="Budget Concerns"/>

OneNote uses the optional attributes of the <EnsurePage> element if it creates the page you specify. If you specify attributes for an existing page, OneNote leaves the page unchanged. For example, if you use a GUID for an existing page, and specify a title that differs from that page’s current title, OneNote does not change the page title.

Additionally, OneNote only searches the path you specify for the desired page GUID. If the page GUID does not exist in the specified section, OneNote creates it; it does not look for the GUID in other sections of the notebook.

You can use multiple <EnsurePage> elements to create multiple pages within the OneNote notebook. You must verify or create the page before you can place content on it. You are not required to include an <EnsurePage> element for each page on which you want to place content. However, if you use the <PlaceObjects> element to try and place objects on a page that does not exist, the Import method fails. In some cases, this may be the desired outcome; for example, if you only wanted to update content on a page if the page still exists, and not add the content if the page has been deleted by the user.

Placing Content on Pages

Once you’ve ensured that the pages onto which you want to import data exist in the OneNote notebook, you can start placing objects on them using the <PlaceObjects> element. Multiple objects can be imported to multiple pages if desired. You create a <PlaceObjects> element for each page on which you want to place content. Same as the <EnsurePage> element, <PlaceObjects> has two required attributes: the path to the page, and the guid assigned to the page. You must include at least one <Object> element in each <PlaceObjects> element.

To create the xml string that describes the content you want to import into OneNote, follow these general steps:

· If you want to make sure the page exists to place content onto, create an <EnsurePage> to verify or create the folder, section, and page as necessary.

· Create a <PlaceObjects> element for the page to which you want to add or delete content.

· Create an <Object> element for the first object you want to alter (add, update, or delete) on the page.

· To delete the object, add the <Delete/> element to that object.

· To import the object, add a <Position> element and use its x and y attributes to specify where on the page to place the object.

· Specify the type of object you’re importing to the page by using the appropriate element, <Image>, <Ink>, or <Outline>, and setting the appropriate optional attributes, if desired.

· If you’re importing an outline object, specify the sub-objects the outline contains in the order in which you want them to appear in the outline. You can specify any number and order of <Image>, <Ink>, and <Html> elements. However, you are required to specify at least one <Image>, <Ink>, or <Html> element for the outline.

· Repeat this procedure for all objects you want to alter on the page. Then repeat this procedure for all pages on which you want to alter content.

Some other technical requirement to keep in mind as you create the xml string:

· OneNote positions objects based on absolute x and y coordinates, where x and y represent measurements in points. Seventy-two points equal one inch.

· Ink objects must be described in Ink Serialized Format (ISF) format, base-64 encoded, or specified by a path to the source file. If you specify a file path, the source file should be a plain file with the byte stream containing the ISF. If you include the ink as data in the XML, then it should be base64 encoded. For more information on programmatically capturing and manipulating ink, see this Ink Serialization Sample.

· Image objects can be specified by a path to a source file, or base-64 encoded.

· Text must be described in html, within a CDATA block, or specified by a path to a source file. In a CDATA block, all characters are treated as a literal part of the element’s character data, rather than as XML markup. XML and HTML use some of the same characters to designate special processing instructions. Using the CDATA block prevents OneNote from misinterpreting HTML content as XML instructions.

· Although the schema does not currently support importing audio or video files, you can include links to these files within the HTML content you import.

Updating Content

To update objects that are already in a notebook, simply re-import the objects to the same page, using the same GUIDs. Be aware, however, that re-importing an object overwrites that object without notifying the user. Any changes made to the content since it was last imported are lost.

Deleting Content

To delete an object, place the <Delete/> element within the object element. To delete an object, you must be able to identify it by its GUID and path. In practical terms, this generally means an application can only delete objects it places in OneNote to begin with. However, if the application stores the GUID across sessions, it can delete objects it imported into OneNote in previous sessions. You cannot delete folders, sections, or pages, even those you created.

Sample XML String

Below is an example of what a typical xml string for the Import method might resemble. This xml file describes the placement of three new objects onto an existing page, and the deletion of an object already contained on that page.

<?xml version="1.0"?>

<Import xmlns="http://schemas.microsoft.com/office/onenote/01/2004/import">

 

      <EnsurePage path="MSN Instant Messenger\Conversations.one"

      guid="{8FDD3C41-5BB5-4595-B019-7E7E9BC9D38E}"

      title="Personal"

      date="2003-10-16T17:30:00-08:00"

      insertAfter="{05239BEA-894E-406d-80AD-8678D1BC1EDD}"/>

 

      <PlaceObjects pagePath="MSN Instant Messenger\Conversations.one"

      pageGuid="{8FDD3C41-5BB5-4595-B019-7E7E9BC9D38E}">

 

            <Object guid="{5FCFD7F9-02C2-42fc-B6AF-7A8450D43C2D}">

                  <Position x="72" y="72"/>

                  <Image backgroundImage="true">

                        <File path="c:\image.png"/>

                  </Image>

            </Object>

 

            <Object guid="{F6FC4149-1092-48ea-806D-0067C8661A18}">

                  <Position x="72" y="72"/>

                  <Ink>

                        <File path="c:\ink.isf"/>

                  </Ink>

            </Object>

 

            <Object guid="{7EA551C4-F778-40ce-9181-21A3DB6D33CA}">

                  <Position x="72" y="432"/>

                  <Outline width="360">

                        <Html>

                              <Data>

                                    <![CDATA[

                                          <html><body><p>Sample text here.</p></body></html>

                                          ]]>

                              </Data>

                        </Html>

                  </Outline>

            </Object>

 

            <Object guid="{1A6648BA-D792-48f1-AC6A-43DF6E258851}">

                  <Delete/>

            </Object>

 

      </PlaceObjects>

 

</Import>

The following example demonstrates a basic implementation of the OneNote import functionality. The code displays a dialog that enables the user to select an xml file, and then passes the contents of that xml file as an argument for the Import method. This example assumes the xml file conforms to the OneNote data import schema. This example also assumes the project contains a reference to the OneNote 1.0 Type Library.

  Dim strFileName As String

  Dim XmlFileStream As StreamReader

  Dim strImportXml As String

  Dim objOneNote As OneNote.CSimpleImporterClass

 

  OpenFileDialog1.Filter = "XML files (*.XML)|*.XML|Text files (*.TXT)|*.TXT"

  OpenFileDialog1.ShowDialog()

  strFileName = OpenFileDialog1.FileName()

 

  objOneNote = New OneNote.CSimpleImporterClass

  XmlFileStream = New StreamReader(strFileName)

  strImportXml = XmlFileStream.ReadToEnd

  objOneNote.Import(strImportXml)

 

  XmlFileStream.Close()

For the sake of simplicity, so as to highlight how the Import method is implemented, this example assumes that an XML file has already been created to use as the string for the Import method. In most cases, however, the application that calls the Import method will first create the XML string itself. For more information on creating XML using the .NET framework, see Well-Formed XML Creation with the XMLTextWriter.

In addition, most applications will need to create and assign GUIDs to the pages and objects they create. Use the NewGuid method to create a new GUID, and the ToString method to get the string representation of the value of GUID, which the XML string requires. For more information, see GUID Structure in the .NET Framework Class Library.

Displaying a Specified Page

By design, the Import method executes with minimal focus, so that when you import data, the user is not distracted by OneNote displaying data they might not want to see, or worse, navigate away from a OneNote page the user is currently using. Also, in the cases where you import multiple objects to multiple pages, OneNote does not have to make assumptions about which page the user wants to see, if any.

To display a specific page, use the NavigateToPage method. If OneNote is not open, this method opens OneNote to the specified page. If OneNote is already open, the method navigates to the specified page in the current instance of OneNote.

To select the page to display, you must specify the path to the page, as well as the GUID for that page. If you specify a page that does not exist, OneNote returns an error.

The NavigateToPage method has the following signature:

NavigateToPage(bstrPath as String, bstrGuid as string)

Conclusion

OneNote’s new import functionality opens up exciting possibilities for interacting with other applications. Any application that can save data (either its own or another application’s) as html text, images, or ISF can now push that content into OneNote and place it wherever is desired. And as long as the application retains the GUIDs used, it can update or delete the content it pushed whenever necessary.