SharePoint Development from a Documentation Perspective

Andrew May

April, 2004

  • Andrew May's WebLog

    Importing Content into OneNote 2003 SP1 Preview

    • 35 Comments

    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.

  • Andrew May's WebLog

    The OneNote 1.1 SimpleImport XML Schema

    • 6 Comments

    The Office 2003: XML Reference Schemas download is now available. The download includes a copy of the OneNote import schema, as well as the complete element, type, and attribute documentation we posted online awhile back. It also include an introduction detailing how to use the schema to import content into OneNote.

    To view the OneNote schema reference help online, see the Microsoft Office OneNote 2003 Software Development Kit (SDK) on the Office Developer Center. The SDK contains reference documentation for the OneNote SimpleImport XML Schema, including descriptions of elements and types.

  • Andrew May's WebLog

    Working with multimedia files in PowerPoint

    • 1 Comments

    My first two developer articles for PowerPoint are now available on the Office Developer Center:

    How PowerPoint 2003 Plays Multimedia Files in a Presentation

    The title pretty much say it all. The first article should actually be of interest to more than just PowerPoint developers. It explains how PowerPoint 2002 and 2003 decide which Microsoft media technology to use to play a given multimedia file, and includes some advice on how to help ensure PowerPoint plays your sound and movie files as you want, whether on your machine or somewhere else. I’ve seen questions about this issue come up a lot in the newsgroups, so hopefully this article provides some answers. And while it’s published on MSDN, it should be understandable and useful to anyone who uses multimedia files with PowerPoint; there’s not a single line of code in it, I promise.

    Adding Multimedia to a PowerPoint 2003 Presentation

    The second article is more firmly aimed at a developer audience. It covers how to programmatically insert audio and video into PowerPoint presentations, and the advantages of inserting the files as media object, as opposed to OLE objects.

    I’m really happy with how these turned out. Give ‘em a read, and let me know what you think.

  • Andrew May's WebLog

    Assigning Build Levels to Text

    • 0 Comments

    So, as I may have mentioned, I’m currently writing a few articles dealing with PowerPoint animations. One of the interesting concepts here is that of the build, in which the sub-objects of a shape enter the slide, either individually or in subsets, to build the final shape. One of the most prevalent uses of this is the dreaded ‘text build’, where the various bullet points of a text box enter a slide.

    Because you assign build effects to a shape’s text based on the indent levels of the text paragraphs, such as first-level, second-level, etc., it’s worth discussing how to specify the indent level for text.

    Each Shape has a TextFrame object, which in turn has a TextRange object that contains all the text in a shape. You can then use various methods of the TextRange object to return other TextRange objects that represent various subset of the text in the shape, such as paragraphs, sentences, lines, runs, words, or characters. The IndentLevel property of a given TextRange returns or sets the indent level assigned to that text.

    You can specify one build level per paragraph. If you assign an indent level to a text range that is a sub-set of a paragraph, such as a single sentence or character run, that indent level is applied to the entire paragraph. If you assign an indent level to a text range that encompasses text in multiple paragraphs, then each of those paragraphs is assigned the specified indent level. For example, if you change the indent level of a sentence, word, or run in a second-level paragraph to 3, then the indent level for the entire paragraph is set to 3.

    Because the objects returned by the various TextRange methods are TextRange objects themselves, they have all the methods and properties of that type. For example, TextRange.TextRange.Paragraphs.Count returns the number of paragraphs contained in a shape’s text frame. Use the Paragraphs method to set the indent level of your paragraphs.

    The code below adds four paragraphs, or bullet points, to a shape on a slide. It then uses the Paragraphs method to individually return and set the indent level of each of those paragraphs.

        With objShape.TextFrame.TextRange

            .Text = "This is the first level heading" & vbCrLf

            .InsertAfter "This is the second level heading" & vbCrLf

            .InsertAfter "This is the third level heading" & vbCrLf

            .InsertAfter "This is another first level heading"

            .Paragraphs(1, 1).IndentLevel = 1

            .Paragraphs(2, 1).IndentLevel = 2

            .Paragraphs(3, 1).IndentLevel = 3

            .Paragraphs(4, 1).IndentLevel = 1

        End With

    And here’s how the text would display on the slide:

    ·         This is the first level heading

    ·         This is the second level heading

    ·         This is the third level heading

    ·         This is another first level heading

  • Andrew May's WebLog

    Final 'Automating Prepress Tasks' article now live

    • 0 Comments

    The final article in my three-part series on how to automate prepress processes in Publisher 2003 is now live on the Office Developer Center.

    This one deals with several topics, including generating composite CMYK, PostScript, and PDF output from Publisher files. We also discuss some issues to take into account if you plan to automate imposition using Publisher, and even touch on a few things you can’t do using the Publisher object model.

    All that and more, available for free at:

    http://msdn.microsoft.com/office/default.aspx?pull=/library/en-us/odc_pb2003_ta/html/odc_PB_Prepress_3.asp

    And remember, if you read it, please take a minute to rate it. Thanks.

     

  • Andrew May's WebLog

    OneNote Import Example: Generating GUIDs and XML

    • 0 Comments

    One thing I didn’t have time to include in my OneNote SP1 Preview article entry was a simple example that generates GUIDs for elements as necessary, and then creates its own XML string for the Import method. That’s something I definitely want to include in the final MSDN article, and I thought it might be helpful to preview it here first as well. So without further ado:

    The following example demonstrates how you can programmatically generate xml strings and object GUIDs for use with the OneNote import functionality. In this sample, the user specifies a location, and optionally, a title, for a new page that the application then creates using the CSimpleImporterClass.Import method.

    Once the sample has stored the user input in two variables, it calls the NewGuid method to generate a new GUID for the page to be created. Note that because the NewGuid method is a shared method, you do not have to instantiate a Guid object in order to call it. In order for OneNote to correctly process it, the generated GUID must be wrapped in angle brackets ({}).

    The sample then constructs the simple xml document required for the Import method. The code employs an XMLTextWriter object and its various methods to generate an xml stream. The code creates <Import> and <EnsurePage> elements and their required attributes. If the user has specified a page title, the code creates the optional title attribute of the <EnsurePage> element as well. Once it has created the xml stream, it flushes the XmlTextWriter and moves the position back to the beginning of the stream.

    At this point, the code uses a StreamReader object to write the contents of the xml stream to the console, to demonstrate what the xml generated looks like. Because the Import method takes a string, not a stream, the code uses the StreamReader.ReadToEnd method to get a string representing the contents of the xml stream. The code then passes this string as the required argument to the Import method, thereby creating the desired page. Finally, the code calls the NavigateToPage method, and passes it the page path and page GUID variables set earlier, in order to navigate to the new page in OneNote.

    Imports System.Xml

    Imports System.IO

    Private Sub btnCreate_Click(ByVal sender As System.Object, _

        ByVal e As System.EventArgs) Handles btnCreate.Click

        Dim pagePath As String

        Dim pageTitle As String

        Dim pageGuid As String

        Dim XmlImportStream As MemoryStream = New MemoryStream

        Dim XmlImportWriter As XmlTextWriter = _

            New XmlTextWriter(XmlImportStream, Nothing)

        Dim strEnsurePage As String

        Dim OneNoteImporter As OneNote.CSimpleImporterClass

     

        'store user input for path and optional page title

        pagePath = Me.txtPagePath.Text.ToString

        pageTitle = Me.txtPageTitle.Text.ToString

        'generate a new GUID for the page to be created

        pageGuid = "{" & Guid.NewGuid.ToString & "}"

     

        'Generate the xml as a stream

        With XmlImportWriter

            .WriteStartDocument()

            'Generate root Import element

            'and specify OneNote schema namespace

            .WriteStartElement("Import")

            .WriteAttributeString("xmlns", _

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

            .WriteStartElement("EnsurePage")

            'Generate required path attribute

            .WriteAttributeString("path", pagePath)

            'Generate required GUID attribute

            .WriteAttributeString("guid", pageGuid)

            'Generate opotional title attribute, if title was specified

            If Not pageTitle = "" Then

                .WriteAttributeString("title", pageTitle)

            End If

            .WriteEndElement()

            .WriteEndElement()

            .WriteEndDocument()

        End With

        'Flush the xmltextwriter

        XmlImportWriter.Flush()

        'Move to the start of the xml stream

        XmlImportStream.Position = 0

        'Create a streamreader for the xml stream

        Dim XmlImportReader As StreamReader = New StreamReader(XmlImportStream)

        'Write the xml stream to the console

        Console.WriteLine(XmlImportReader.ReadToEnd)

        Console.ReadLine()

        'Move back to the start of the xml stream

        XmlImportStream.Position = 0

        'Store entire xml stream in variable as a string

        strEnsurePage = XmlImportReader.ReadToEnd

        'Create instance of OneNote simple importer

        OneNoteImporter = New OneNote.CSimpleImporterClass

        'Pass xml string to import method to create page

        OneNoteImporter.Import(strEnsurePage)

        'Navigate to new page, based on path and GUID variables

        OneNoteImporter.NavigateToPage(pagePath, pageGuid)

     

    End Sub

    For more information on creating and using GUIDs, see GUID Structure in the .NET Framework Class Library.

    For more information on creating XML using the .NET framework, see Well-Formed XML Creation with the XMLTextWriter.

Page 1 of 1 (6 items)