SharePoint Development from a Documentation Perspective

Andrew May

  • Andrew May's WebLog

    OneNote import Managed Assembly: Customizing How OneNote Launches


    Here’s still more functionality packed into the OneNoteImporter assembly:

    You can also modify how OneNote starts by using the following methods of the Application object. These methods ‘wrap’ command line switches that customize how the OneNote application starts.

    The table below lists the Application object methods, and the command line switch each invokes. If a method is overloaded, the number of overloads is noted next to the method name. In most cases, the method is overloaded to account for the fact that the command line switch takes a series of optional string arguments.

    All the method parameters take strings, except the openReadonly parameter of the Open method, which takes a Boolean value.

    Application method


    Command line switch

    JoinSharedSession (2)


    (sessionAddress, password, sectionPath)


    Open (2)


    (sectionPath, openReadonly)











    StartSharedSession (3)



    (sectionPath, password)





    StartVideoNote (4)



    (videoDevice, audioDevice)

    (videoDevice, audioDevice, recordingProfilepath)






    Be aware that these Application methods have been implemented as asynchronous command line calls. Because of this, your code continues to run after it calls Application method is called, independent of whether or not the OneNote application has yet launched.

    In addition, you can use the Activate method to bring the OneNote application to the foreground.

    For more information on the command line switches, see Customizing OneNote 2003 SP 1 Using New Command Line Switches.

    Is there anything these guys didn’t think of?

  • Andrew May's WebLog

    OneNote Import Managed Assembly: The Quick Rundown (2 of 2)


    In part one, we discussed how to use the OneNote managed class assembly to import content into OneNote. Now let’s actually look at the XML the Page class generates for the SimpleImporter.Import method.

    Looking at the XML

    If you want to preview what the XML that’s passed to the SimpleImport.Import method will look like before you run the Commit method, call the Page.ToString method. This is the method that actually serializes the page and its contents to XML prior to importing. Just remember that once you’ve committed a page, none of the object on that page will be included in the generated import XML, unless they’ve subsequently been modified in some way.

    Also remember that the Commit method generates import XML with both <EnsurePage> and <PlaceObjects> elements for that page. Specifying an <EnsurePage> element for a page guarantees that the page exists before OneNote attempts to import objects onto it. So if your application includes a scenario where you only want to import objects onto a page if the page already exists, you’ll need to modify this method, or use another means.

    So let’s a quick look at the code sample Donovan gives over on his blog (I think he’ll forgive me if I rewrite it in VB). This sample creates a new page, title “General”, with one object on that page: an outline containing the text “Hello world!”

    Sub TrivialImportVB()

       Dim p As New Page("General")

       Dim outline As New OutlineObject

       outline.AddContent(New HtmlContent("Hello <i>world</i>!"))




    End Sub

    And here’s the resulting XML that gets passed to the SimpleImport.Import method. Notice that the necessary GUIDs are there, and the HTML has even been cleaned up so that OneNote accepts it with no problem. How’s that for service?

    <?xml version="1.0" encoding="utf-16"?>

    <Import xmlns="">

          <EnsurePage path="General" guid="{e5bf863a-7070-4058-a0f5-

    343e4a45dc05}" date="2004-07-23T09:52:17.0963010-07:00" />

          <PlaceObjects pagePath="General" pageGuid="{e5bf863a-7070-4058-a0f5-


                <Object guid="{a5af80e4-8105-4109-b3ac-538851e9e3fa}">

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








    Object Model Diagrams

    And what’s an object model without an object model map? Anyone who’s read this blog has probably realized how fond I am of presenting technical information graphically (which I’m sure has nothing to do with my being the programmer-writer for PowerPoint and Publisher.) So here are some diagrams of how the classes fit together. But first, some caveats:

    The following diagrams show only the public members of each class. None of the abstract classes are diagramed, and I’ve left any inheritance information off the diagrams, although I’ve listed any members that a class inherits in the individual classes themselves. For example, ImageObject, InkObject, and OutlineObject all inherit the Height, Position, and Width properties from the abstract class PageObject, which is not diagrammed.

    I mainly want to show how the various object relate to one another. For the most part, if a member gets or sets a data type, I haven’t bothered showing that in the diagram. In addition, for the sake of clarity, I’ve left off the following information for basic methods that most classes here have:

    ·         The Clone method returns the type of object from which you call it.

    ·         The Equals method takes a System.Object as a parameter.

    ·         The GetHashCode method returns a System.Int32 suitable for use in hashing algorithms and data structures like a hash table.

    Trust me, I’ve got much more detailed diagrams of the internal workings of each class tacked up around my office, and those will most likely make it into the finished article, which discusses the class source code. But these should give you a good at-a-glance idea of how things flow.


    Figure 1. Page object (and legend)


    Figure 2. ImageObject, InkObject, and OutlineObject


    Figure 3. HtmlContent, ImageContent, and InkContent

  • Andrew May's WebLog

    OneNote Import Managed Assembly: The Quick Rundown (1 of 2)


    If you haven’t already seen this, get over to Donovan Lange’s blog. Donovan, Omar, and David have put together an abstracted managed assembly that provides an object model for the SimpleImport functionality OneNote added for SP1. That’s right; you don’t even have to create the XML for the import yourself. The OneNote guys have you covered.

    I’m currently putting together an article that highlights this class library and all the functionality it provides. I’ve been pouring over the code for the last week or so, and I think I’ve finally got it. (The assembly itself is written in C#. Did I mention I’m about as fluent in C# as in ancient Armenian?) I have to say, this is some very well-thought-out work.

    The OneNote guys have included detailed technical documentation in the download itself, but I thought it might be worth taking a few minutes and putting together a high-level overview of how the classes work. So if you just want to get up and running, and aren’t too concerned about how the assembly does what it does so well, then read on.

    I’m going to assume you have a passing familiarity with the OneNote SimpleImport class and the xml schema it uses. (If you don’t, follow the links and then come back. I’ll wait.)

    They’ve really made the class library easy to use. Here’s all you need to do:

    Create a new Page object

    Not much to say here. Once you’ve created the page, you can set its attributes using various properties such as Date, PreviousPage, RTL, SectionPath, and Title. The PreviousPage property sets the value of the ‘InsertAfter’ XML attribute; the others are pretty self-explanatory.

    Create the content you want to add to your new page

    There are three types of objects you can add to a page: ImageObject, InkObject, or OutlineObject objects. All page objects share common properties, such as Height, Width, and Position.

    Note While the OutlineObject inherits the Height property from its base class for consistency, outlines cannot have an explicitly specified height. Therefore, accessing or modifying the Height property of an OutlineObject will result in an error.

    Each ImageObject and InkObject contains data representing the actual image or ink content you want to add to the page. You get and set this data by using the ImageData and InkData properties, respectively.

    You use these properties to get or set a BinaryData or FileData object. The BinaryData class represents raw binary data in memory. When you add an ImageObject or InkObject object containing BinaryData to a page, the OneNote Import Managed Assembly ensures this data is properly base-64 encoded. The FileData class represents data that is stored in an external file, and is marshaled to OneNote as a file path.

    For the most part, you’ll really only need to create BinaryData and FileData objects directly when you want to update existing image or ink objects. The ImageObject and InkObject each provide convenience constructors that create the appropriate data object, when passed a System.IO.FileInfo object or binary array of bytes as a method parameter.

    OutlineObject objects are slightly more complex because outlines can be comprised of ImageContent, InkContent and HtmlContent objects. Add content to an OutlineObject using the AddContent method. Outline content objects are displayed within the outline in the same order in which they are added to the OutlineObject object.

    The ImageContent and InkContent classes are very similar to the ImageObject and InkObject classes. Again, the actual image or ink content is represented by either a BinaryData or FileData object. This object is also created based on the specified argument passed to the ImageContent or InkContent constructor, and you can subsequently access it using the ImageData or InkData property, respectively. Note that neither the ImageContent or InkContent classes contain properties for setting their position and size on the page, as these properties are set for the outline as a whole.

    The HtmlContent object also contains data within the HtmlData property, except it’s data is represented as either a FileData or StringData object. The StringData object represent string data as a System.String. Constructors on the HtmlContent object enable you to create a new HtmlContent object based off of pre-existing HTML in a string object or a FileInfo object containing the path to an HTML file.

    Add objects to the page

    Add the objects you’ve created to the Page object using the AddObject method. You can add as many as you want, in any order. How the objects are arranged on the page depends on the coordinates specified in the Position child object for each ImageObject, InkObject, or OutlineObject.

    Import the page

    Now that you’ve got your page set up with all your content, it’s time to import it into OneNote. You do this using the Page.Commit method. This method does several vital things, including:

    ·         Creates the XML document to be used for the OneNote SimpleImport class.

    ·         Specifies the correct OneNote namespace, based on whether the OneNote SP1 Preview or SP1 release version is installed on the current machine. (Now, how thoughtful is that?)

    ·         Adds an <EnsurePage> element for the page, using the Page object properties you’ve set.

    ·         If your page contains objects, then the method also creates a <PlaceObjects> element to insert, edit, or delete those objects as specified.

    ·         Serializes the page and all its contents to XML, and adds them to the XML import document. In the course of this, it also does some minor checking of any HTML content to format it property for OneNote.

    ·         Validates the XML it created, to make sure OneNote accepts it.

    ·         Calls the SimpleImporter class and imports the content into OneNote.

    Pretty slick, no?

    Here’s some things to keep in mind:

    Generating GUIDs

    The OneNote classes internally generate the necessary GUIDs that OneNote needs to identify each object and page. You cannot access a page or object’s GUID from outside the OneNote class assembly. The GUIDs do appear in the XML passed to the SimpleImporter.Import method, of course.

    On a sidenote, Donovan tells me he intends to change this. Originally, the intent was to hide the GUIDs for the benefit of new users. But it turns out that many scenerios require control over the Page and PageObject GUIDs. If you do need access to these GUIDs, here’s two strategies to consider:

    ·         Override the class, and make the GUID properties publicly accessible.

    ·         Serialize and persist the Page object between sessions, and then deserialize it as necessary.

    Re-Importing Objects

    Page objects keep track of whether they have been committed (or in other words, imported) and, additionally, keep track of modifications that require an update (that is, another import). So, after you commit a Page for the first time, if you then immediately call the Commit method again, none of the original objects would be re-imported. However, suppose that, after you commit a page, you then added new objects to that page, or changed the content or properties of an existing object on the page. In that case those new or modified objects will be re-imported the next time you execute the Commit method.

    The OneNote SimpleImport API does not permit you to change a page’s date, title, insertAfter, or RTL attributes once you’ve imported the page. Because of this, once you’ve called the Commit method for a Page object, the following Page properties become read-only and throw an exception if you try and set them: Date, PreviousPage, RTL, and Title.

    Deleting Objects

    You can delete an object from a page using the Page.DeleteObject method. Much like the Page.AddObject method, the deletion does not in fact occur until you execute  the Commit method; only then is it deleted within OneNote and removed as a child of the Page object.

    Next time, I'll include an example and we'll take a look at the XML actually produced.

  • Andrew May's WebLog

    Visio Update and PIA Issues


    I received a question from a user the other day in regards to the samples contained in the Visio Managed Code Tutorial that shipped as part of the Visio 2003 SDK. Seems the user couldn’t compile the samples because Visual Studio couldn’t find the Microsoft.Office.Interop.Visio assembly. I suggested the user check and see if the Visio PIAs were actually installed, because they don’t always install by default (more on that later).

    Turns out there may be more to it than that. The Visio test team did some research, and it seems that one of the Visio Update patches actually disables the Visio Interop PIA. Here’s what the test team found:

    Installing the Microsoft Office Visio 2003 Update: KB831925 causes all the Tutorial samples to fail compiling. When you open the Tutorial samples in Visual Studio, Visual Studio fails to find the Visio Interop PIA. To fix this problem, open Visio 2003, and from the Help menu, choose Detect and Repair.

    Note: Just starting the Visio application does not launch a repair operation in this case.

    So even if you know you installed the PIAs previously, it might be a good idea to repair them via the method above if you’ve downloaded the update.

    (My thanks to Curt on the Visio test team for running this problem down. Great work, Curt.)

    This issue will be written up in the Knowledge Base, but since the user asked the question here, I figured I’d go ahead and answer it here.

    Here’s how Visio PIA installation usually works:

    If you install Visio on a computer that does not have Visual Studio 2003 (version 7.1) or the .Net Framework 1.1 installed, then Visio doesn’t install the PIAs. If Visual Studio or the .NET Framework is already present on your computer when you install Visio, then the Visio PIAs are installed by default.

    Do the following to have Visio explicitly install the PIAs:

    ·         From the Start menu, click Settings, click Control Panel, then Add or Remove Programs.

    ·         In the program list, select Microsoft Office Visio 2003, and click the Change button. Click Add or Remove Features, and then click Next.

    ·         Expand the Microsoft Office Visio icon and select .NET Programmability Support, and then click Update. You may want to try uninstalling this and then reinstalling to force it to install.

    One way to check to see if the PIAs are installed is to navigate to your windows directory in explorer, e.g.



    and see if you see the Visio PIAs for Visio version 11 in the list of assemblies. There are three PIAs for Visio. The primary one is Microsoft.Office.Interop.Visio.

    Note If you install an add-in when the Visio PIAs are not installed, you must re-install the add-in after you install the Interop PIA (in other words, just installing the PIAs is not enough to fix the add-in.)

  • Andrew May's WebLog

    Animating Shapes in PowerPoint 2000 and 97 (Part 4 of 4)


    (Previous entries in this series: part one, part two, and part three.)

    Creating Animation Effects for Media and OLE Objects

    For audio and video files inserted as media objects, not only can you set the shape’s animation effect, as with other shapes, but you can customize how the file plays as part of its animation effect as well. The PlaySettings object contains properties that enable you to customize how sound and movies play when they are animated. Table 1 lists these properties, and what you use each for.

    Table 1. Selected PlaySettings object properties.

    PlaySettings property



    Set whether to display the media object when it is not playing.


    Set the file to play continuously until it’s stopped by the user clicking it, or the next slide transition.


    Set whether the animation sequence for the slide is paused until the file completes playing.


    Set whether the file plays when the file’s entry effect occurs as part of the slide’s animation sequence.


    For video files, set whether the first frame of the movie is automatically redisplayed as soon as the movie has finished playing.


    Set the file to stop playing after a specified number of slides have been displayed or when the media clip comes to an end, whichever happens first.


    You can also specify that an OLE object perform one of its verbs as part of its animation effect. Use the ActionVerb property to specify which of its verbs the OLE object performs.

    Each Shape that represents an OLE object contains a OLEFormat object. The actions an OLE object can perform are contained in the ObjectVerbs collection, which is a child of the OLEFormat object. For example, the following code returns the verbs available for the specified OLE object:

    Dim intCount As Integer

    With ActivePresentation.Slides(5).Shapes("AVI File") _


        For intCount = 1 To .Count

            Debug.Print intCount & "  " & .Item(intCount)


    End With

    Note that if you insert an audio or video file as an OLE object, rather than as a media object, you cannot set PlaySettings properties for that shape that apply to media objects.

    To determine if a given shape is a media or OLE object, use the Type property of the Shape object. This property returns an MsoShapeType constant, such as MsoEmbeddedOLEObject, or MsoLinkedOLEObject or MsoMedia.

    For more information on adding media and OLE objects to your presentations programmatically, see Adding Multimedia to a PowerPoint 2003 Presentation.

    Object Model Maps

    The following diagrams detail the structure of the AnimationSettings object model section.


    Figure 1. The AnimationSettings Object


    Figure 2. The PlaySettings and SoundEffect Objects

    So there you go. As you might have guessed, about half way through writing these entries, I realized I had a full-blown article on my hands. So I’ll probably roll these entries together, clean ‘em up, and submit them as a single article for the Office Developer Center. But it may be awhile until the finished, polished article appears on MSDN, so in the meantime, here’s the information in draft form.

  • Andrew May's WebLog

    Animating Shapes in PowerPoint 2000 and 97 (Part 3 of 4)


    Today, we talking about build effects. If you’re just joining us, you can find the first two parts of this series here and here.

    Creating Build Animation Effects for Text and Charts

    As mentioned earlier, you can create a special type of animation effect for text and chart objects. For these types of shapes, you can specify a build animation, in which sub-objects of the shape are animated sequentially so that they combine, or build, to display the complete shape. For example, suppose you have a single text box that contains five bullet points. You can specify that each bullet point enter the slide individually.

    Use the ChartUnitEffect property for chart shapes, or the TextLevelEffect property for text boxes, to specify a Shape object’s build level; this refers to the lowest level of sub-objects at which you want to assign the effect. For example, for a text box effect with a build level of ppAnimateBySecondLevel, each first and second level bullet point, or paragraph, would be animated separately. Third, fourth, and fifth level paragraphs would be animated at the same time as the second level paragraph above them.

    By default, the ChartUnitEffect property is set to ppAnimateByChartAllAtOnce, and the TextLevelEffect property is set to ppAnimateByLevelNone.

    In addition, for text you can use the TextUnitEffect property to specify the level at which you want PowerPoint to animate the text within each paragraph: by character, word, or paragraph. By default, the TextUnitEffect property is set to ppAnimateByParagraph.

    Finally, you can use the AnimateTextInReverse property to have PowerPoint animate your text build in reverse order, last point first, first point last. For example, if you constructed a slide listing the top ten reasons for something, or the top ten finalists in a contest, you might want to display the list in reverse order.

    The following example creates a new slide in the active presentation, and adds a title and three paragraphs, or bullet points. The code sets the title to be animated character-by-character, and uses a color scheme to set the dim color for the title once its animation concludes. For the body text, the code sets the build level to the first level, meaning that the second level paragraph appears on the slide at the same time as the first level paragraph above it. The code also sets the dim color for the body text paragraphs.

    With ActivePresentation.Slides.Add(2, ppLayoutText).Shapes

        With .Item(1)

            .TextFrame.TextRange.Text = "Title"

            With .AnimationSettings

                .Animate = msoTrue

                .TextLevelEffect = ppAnimateByAllLevels

                .TextUnitEffect = ppAnimateByCharacter

                .AfterEffect = ppAfterEffectDim

                .DimColor.SchemeColor = ppShadow

            End With

        End With

        With .Item(2)

            With .TextFrame.TextRange

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

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

                .InsertAfter "This is another first level heading"

                .Paragraphs(1, 1).IndentLevel = 1

                .Paragraphs(2, 1).IndentLevel = 2

                .Paragraphs(3, 1).IndentLevel = 1

            End With

            With .AnimationSettings

                .Animate = msoTrue

                .TextLevelEffect = ppAnimateByFirstLevel

                .AfterEffect = ppAfterEffectDim

                .DimColor.RGB = RGB(100, 150, 130)

            End With

        End With

    End With

    To determine if a given shape is a chart, placeholder or text box, use the Type property of the Shape object. This property returns an MsoShapeType constant, such as MsoChart, or MsoPlaceholder or MsoTextBox. Placeholder shapes contain a PlaceholderFormat child object, which in turn includes a Type property that identifies what kind of placeholder the shape is.

    Assigning Indent Levels to Text

    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 that 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 indent 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, TextFrame.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 following code example 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

    Tomorrow we’ll talk about setting media objects and OLE objects to perform as part of their animation effects. And if you’re good, maybe I’ll throw in some object model diagrams as well.

  • Andrew May's WebLog

    Animating Shapes in PowerPoint 2000 and 97 (Part 2 of 4)


    So yesterday we started talking about how to animate shapes if you’re programming for PowerPoint 97 or 2000. Today we continue by discussing how to trigger your animation effects, and control the order in which they occur. We’ll also touch on how to further customize a shape’s animation, by adding sound and/or changing the shape’s post-animation appearance.

    Setting the Order in Which PowerPoint Animates Shapes

    The AnimationOrder property of each shape determines the order in which PowerPoint animates the shape, from the lowest number to the highest. By default, if you don’t explicitly specify an animation order, PowerPoint sets the animation order in the order in which you set the Shape objects to be animated; that is, the order in which you set the Animate property to msoTrue for each Shape object. The first shape for which you set Animate to msoTrue is first in the animation sequence, the next second, and so on. If you later set a Shape objects AnimationOrder property to a specific value, PowerPoint re-orders the index of each shape’s animation accordingly.

    The following code demonstrates this. The code creates a new blank slide, then adds four shapes and specifies that each be animated. No animation index is specified, so PowerPoint sets each shape as the next in the animation sequence as the code specifies each to be animated. The code prints the name and animation order of each shape. Then the code adds a fifth shape, and explicitly sets the animation index of this shape to ‘2’. PowerPoint automatically resets the animation order index of each shape that comes after the new shape in the animation order. Lastly, the code prints the name of each shape, and its revised animation order.

    Sub DemoAnimationIndexing()

    Dim iCount As Integer

    Dim objShape As Shape


    ActivePresentation.Slides.Add Index:=1, Layout:=ppLayoutBlank


    With ActivePresentation.Slides(1).Shapes

        For iCount = 1 To 4

            Set objShape = .AddShape(msoShapeCube, 100, 100, 100, 100)

            objShape.Name = "Cube " & iCount

            With objShape.AnimationSettings

                .Animate = msoTrue

                '.AnimationOrder = iCount

            End With

            Debug.Print objShape.Name & _

                " Animation Order: " & _


        Next iCount


        Set objShape = .AddShape(msoShapeCube, 100, 100, 100, 100)

        objShape.Name = "Cube 5"

        With objShape.AnimationSettings

            .Animate = msoTrue

            .AnimationOrder = 2

        End With


        For iCount = 1 To .Count

            Debug.Print .Item(iCount).Name & _

                " Animation Order: " & _


        Next iCount


    End With

    End Sub

    Setting How PowerPoint Advances to the Next Animation Effect

    You can specify when you want PowerPoint to advance to the next shape animation in the animation sequence: either when the user clicks the slide, or after a specified time interval. Use the AdvanceMode property to specify whether you want PowerPoint to perform a shape’s animation when the user clicks on the slide, or after a certain period of time. For timed advancement, use the AdvanceTime property to specify the time, in seconds, PowerPoint should wait after the last animation effect before performing the specified animation.

    By default, the AdvanceMode property is set to ppAdvanceModeOnClick.

    The following example sets a shape to be the first shape animated when the slide loads, and for PowerPoint to automatically animate the shape five seconds after the slide loads.

    Dim objShape As Shape

    With ActivePresentation.Slides(1).Shapes


        Set objShape = .Item("Title")

            With objShape.AnimationSettings

                .EntryEffect = ppEffectBlindsHorizontal

                .AnimationOrder = 1

                .AdvanceMode = ppAdvanceOnTime

                .AdvanceTime = 5

            End With

    End With

    Further Customizing Your Animation Effects

    Once you’ve set which shapes get animated, with which animation effects and in which order, you can customize the animation effect for each shape even further. You can add a sound effect to a shape’s animation, and alter the appearance of a shape once PowerPoint has performed the shape’s animation effect.

    In addition, certain types of Shape objects have additional animation functionality. You can animate text and charts to build piece-by-piece, to reveal the complete shape. If you animate media or OLE objects, you can customize how they perform as part of their animation effect.

    Adding Sound to Your Animation Effects

    You can also add a sound effect to a shape’s animation effect. This is different from adding sound files to the slide itself. An animation sound effect is not an independent shape that appears on the slide; rather, it is a sound file that plays when PowerPoint animates the shape to which it is assigned. The SoundEffect object, a child of the AnimationsSettings object, contains members that enable you to set and control a Shape object’s animation sound effect.

    Use the ImportFromFile method to specify a sound file you want imported and used as an animation sound effect. You can also use a sound effect that is native to PowerPoint by setting the Name property.

    You can also use the SoundEffect object to stop a sound effect from a previous shape’s animation effect. By default, PowerPoint plays each sound effect through once, unless the next shape’s animation starts first, and it has a sound effect. But you might want to stop the previous sound effect when the next shape’s animation begins, but that shape’s animation effect does not have a sound effect. In this case, set the SoundEffect.Type property of the second shape to ppSoundEffectStopPrevious. This stops the previous sound effect; you do not need to specify a sound file for the sound effect.

    For shapes with build animations, such as text or charts, the sound effect restarts each time PowerPoint animates the next sub-object. For example, if you set the TextLevelEffect property to ppAnimateByFirstLevel, the sound effect restarts each time PowerPoint animates the next first level paragraph. In addition, if you set the TextUnitEffect property to ppAnimateByCharacter or ppAnimateByWord, then the sound effect restarts each time PowerPoint animates the next character or word, respectively.

    The following example specifies the animation settings for the selected shape on a slide. The code specifies that PowerPoint display the text in the shape character by character, playing the typewriter sound effect each time PowerPoint displays a new character. Note that “Typewriter” is a native PowerPoint sound effect.

    With .Shapes("Body Text").AnimationSettings

      .TextLevelEffect = ppAnimateByFirstLevel

      .TextUnitEffect = ppAnimateByCharacter

      .SoundEffect.Name = "Typewriter"

    End With

    Changing the Appearance of the Shape Once PowerPoint Completes the Animation Effect

    You can also specify how you want the Shape to appear once the animation is finished by using the AfterEffect property. You can use after effects to de-emphasize a slide element once you want to move the user’s focus elsewhere, and to conserve slide ‘real estate’. For example, you can set shapes or text to turn a neutral color, so they fade into the slide background and do not distract from the slide shape being animated next. You can also set PowerPoint to render a shape invisible, either immediately after PowerPoint finishes animating it, or on the next slide click. With the exception of ppAfterEffectHideOnClick, PowerPoint performs the specified after effect as soon as it finishes animating the shape.

    By default, the AfterEffect property is set to ppAfterEffectNothing.

    If you specify ppAfterEffectDim, you can use the DimColor property to specify a ColorFormat object representing the dim color you want. The dim color is the color PowerPoint turns the shape or text once PowerPoint is done animating it.

    Next time, we’ll cover build effect animations: what they are, and how to assign and customize them.

  • Andrew May's WebLog

    Animating Shapes in PowerPoint 2000 and 97 (Part 1)


    So, while I was out of town, my first article dealing with PowerPoint animation made its debut:

    Comparing Ways to Control Animation in PowerPoint 2002 and 2003

    As I’ve mentioned in previous blog entries, there are actually two ways to programmatically animate shapes on a slide: one that works best for PowerPoint 2002 and 2003, and one that’s been retained for compatibility with PowerPoint 2000 and 97. This article examines the differences between the two, and discusses when using each is appropriate.

    Slated for publication next week is the first of a two-part article that covers how to use the revised and greatly expanded animation functionality included in PowerPoint 2002 and 2003.

    Now, while my articles naturally focus on the advantages of using the 2002 and 2003 functionality, in order to write these articles I had to learn how to use the 2000 and 97 functionality as well. And since there’s a large number of developers out there still working with those versions, it seems worthwhile to take a few minutes and present that information here. So for the next few days, I’ll be covering how to animate shapes using the AnimationSettings object.

    Applies to:

        Microsoft PowerPoint 2000

        Microsoft PowerPoint 97


    In PowerPoint, the term animations refers to special visual or sound effects you add to text or an object. Animation effects give motion to text, pictures, and other content on your slides. Besides adding action, they help you guide audience focus, emphasize important points, transition between slides, and maximize slide space by moving things on and off.

    These effects can include how the shape (or its component parts) enter the slide, what the shape does once it appears on the slide, and how it appears once the animation sequence moves to the next shape. You can set the animation sequence to advance to the next animation effect by the user clicking on the slide, or pre-set timing settings.

    Important If you are programming for PowerPoint versions 2002 or 2003, you should be using the TimeLine object model for dealing with animation effects; the AnimationSettings object model should only be used for PowerPoint versions 2000 and 97. The two object models are not compatible. Using the AnimationSettings object model for programming PowerPoint 2002 or 2003 is not recommended, as it can have unexpected and undesirable results for your animation sequences. For more information see Comparing Ways to Control Animation in PowerPoint 2002 and 2003.

    Animations in PowerPoint 2000 and 97

    In PowerPoint 2000 and 97, each Shape object on a slide can have a single animation effect, represented by that Shape object’s AnimationSettings object. You create and customize animations using the AnimationSettings object’s members and child objects. While each Shape object can have only one animation effect, in the case of charts or text, the animation effect may be a build effect, in which sub-objects of the shape are animated sequentially so that they combine, or build, to display the complete shape. We discuss build effect animations is greater detail later.

    Shapes that are not animated appear on the slide when it first loads.

    The individual animation effects for each shape collectively make up a slide’s animation sequence. There is one animation sequence per slide, and it starts when the slide loads.

    Setting the Type, Timing, and Order of a Slide’s Animation Sequence

    When you decide to add animation effects to a slide, the general questions you need to answer concern the sequence and timing of the shapes you want to animate:

    ·         Which shapes do you want to animate?

    ·         What kind of animation do you want PowerPoint to perform on each shape?

    ·         In what order do you want PowerPoint to animate the shapes?

    ·         How do you want to initiate each shape’s animation effect?

    Setting Which Shapes Get Animated

    For PowerPoint to animate a shape, you set the Animate property of its AnimationSettings object to msoTrue. PowerPoint automatically sets the Animate property to msoTrue in either of the following instances:

    ·         You set the TextLevelEffect property to a value other than ppAnimateLevelNone.

    ·         You set the EntryEffect property to a value other than ppEntryEffectNone.

    The converse is also true. PowerPoint automatically sets the Animate property to msoFalse if you set the TextLevelEffect property to ppAnimateLevelNone, or set the EntryEffect property to ppEntryEffectNone.

    Even if you have set other properties of the AnimationSettings object, PowerPoint disregards them and does not animate the shape unless the Animate property is set to msoTrue.

    Shapes with an EntryEffect property of ppEffectNone are visible when the slide loads.

    There are instances when you would want to set the EntryEffect property to ppEffectNone. For example, you could have a media object you want visible on the slide when it loads, even if you do not want to play the file until the fourth animation in the sequence. The following code does just that. Note that the code explicitly sets the Animate property is to True after it specifies the EntryEffect property as ppEffectNone.

    With ActivePresentation.Slides(1).Shapes


        Set objShape = .Item("Title")

            With objShape.AnimationSettings

                .EntryEffect = ppEffectBlindsHorizontal

                .AnimationOrder = 1

            End With

        Set objShape = .Item("Shape1")

            With objShape.AnimationSettings

                .EntryEffect = ppEffectFlyFromLeft

                .AnimationOrder = 2

            End With

        Set objShape = .Item("MovieClip")

            With objShape.AnimationSettings

                .EntryEffect = ppEffectNone

                .Animate = msoTrue

                .AnimationOrder = 3

            End With

    End With

    Specifying the Animation Effect PowerPoint Performs on a Shape

    Use the EntryEffect property to specify which animation effect you want PowerPoint to perform on the selected shape. All animation effects created using the AnimationSettings object are entrance effects. Entrance effects are animations that control how the shape becomes visible on the slide. For example, this could involve having the shape appear to move onto the slide from outside the slide boundaries, such as flying in from the right edge of the slide; or having the shape become visible in place in a particular manner, such as dissolving into visibility.

    By default, if you do not set an animation effect for a shape, PowerPoint uses the ‘Appear’ effect, ppEntryEffectAppear. The code example in the following section demonstrates this.

    Tomorrow, we’ll tackle setting the animation order of the shapes on a slide, and how to trigger a shape’s animation effect.

  • Andrew May's WebLog

    OneNote 2003 SP1 Preview Documentation Live On MSDN


    The title pretty much says it all. The final versions of the OneNote SP1 Preview documentation I posted here in draft version about a month ago went live on MSDN last night:

    Importing Content into OneNote 2003 SP1 Preview

    Customizing OneNote 2003 SP 1 Using New Command Line Switches

    So we’ve pulled together the information from my assorted blog entries, cleaned it up, and made it ready for prime time. It’s worth taking a look at, even if you’ve already read the original blog entries. And do me a favor: rate the articles. It’s the only way we know if we’re addressing your needs. Thanks.

  • Andrew May's WebLog

    Playing Invisible Sound Clips Revisited


    So, it turns out there’s still more to report on how to programmatically control your media objects in PowerPoint. And it’s good news, so read on.

    I originally wrote about how to have a sound clip play automatically when a slide is loaded, without having the sound file icon visible. I used the AnimationSettings.PlaySettings object, which works fine for PowerPoint 2000 and below. But it’s the exact wrong thing to do with PowerPoint 2002 and 2003, as it may lead to some of your other animation effects being deleted from the slide. Then I showed how you could do the same thing using the TimeLine object. Unfortunately, because of a flaw in the object model, when you access the PlaySettings object through the TimeLine object, you still might end up deleting effects unless you’re very careful.

    Now, thanks to PowerPoint’s wonderful development team, I’ve learned that you can actually set a media object to play, pause, and stop, all without accessing the PlaySettings object. This presents a nice work-around that prevents you from accidentally deleting animations from your slide. Here’s how it works:

    Turns out there are three effect types that control the playing of a sound or movie file: MsoAnimEffectMediaPause, MsoAnimEffectMediaPlay, and MsoAnimEffectMediaStop. By assigning Effect objects of these effect types to a media object, you can control when the audio or video file plays during your animation sequence, without accessing the PlaySettings object.

    So, going back to our example from those previous entries, here’s how you would insert a sound file, move it off the viewable slide area, and create an Effect object that would play the file as soon as the slide loads:


    Sub AddAudioOffSlide()

    Dim shpSound As Shape


    With ActivePresentation.Slides(1)

        'Add sound file

        With .Shapes

            Set shpSound = .AddMediaObject _

                (FileName:="C:\soundfiles\bobmould\black sheets of rain.mp3")

            'Position sound file off viewable slide area

            With shpSound

                .Left = 0 - .Width

                .Top = 0 - .Height

            End With

        End With


        With .TimeLine.MainSequence

            'Add effect to play sound file

            'As first effect in main sequence

            'set effect to perform when slide is loaded

            .AddEffect Shape:=shpSound, _

                effectId:=msoAnimEffectMediaPlay, _

                trigger:=msoAnimTriggerWithPrevious, _



        End With


    End With

    Now obviously, with the ability to play, pause, and stop media files, you create much more complex animation sequences than the above example.

    One interesting thing worth mentioning: the MsoAnimEffectMediaPause effect type actually functions to toggle whether the media object is playing or not. That is, if the media file is playing, assigning an MsoAnimEffectMediaPause effect to the file pauses it; but if the file is already paused, assigning another MsoAnimEffectMediaPause effect to the file causes the file to resume playing from the point at which it was pause. Conversely, an MsoAnimEffectMediaPlay effect always starts the file playing from the beginning of the file, whether or not the file is currently paused at a certain point in the file.

    The following example adds effects for a video file to a slide’s main animation sequence. When the user clicks the page, the video file plays for 10 seconds, then pauses for 10 seconds, then starts playing for another 10 seconds before it stops. To accomplish this, the code adds four effects to the sequence. The first starts the file playing; the second pauses the file; the third starts the file playing again; and the final effect stops the file playing. The first effect is triggered when the user clicks the page; the other three are set to be triggered with the previous effect. The code sets the trigger delay time for each effect is set to different durations; otherwise, PowerPoint would perform all the effects simultaneously.

    Note that the third effect, the one that resumes the file playing from the point where it was paused, is of type MsoAnimEffectMediaPause rather than type MsoAnimEffectMediaPlay.


    Dim shpVideo As Shape

    Dim effPause As Effect

    Dim effPlayAgain As Effect

    Dim effStop As Effect


    With ActivePresentation.Slides(1)

        Set shpVideo = .Shapes("demovideo")


        With .TimeLine.MainSequence

            .AddEffect Shape:=shpVideo, _

                effectId:=msoAnimEffectMediaPlay, _


            Set effPause = .AddEffect(Shape:=shpVideo, _

                effectId:=msoAnimEffectMediaPause, _


            effPause.Timing.TriggerDelayTime = 10

            Set effPlayAgain = .AddEffect(Shape:=shpVideo, _

                effectId:=msoAnimEffectMediaPause, _


            effPlayAgain.Timing.TriggerDelayTime = 20

            Set effStop = .AddEffect(Shape:=shpVideo, _

                effectId:=msoAnimEffectMediaStop, _


            effStop.Timing.TriggerDelayTime = 30

        End With

    End With

    For more information about inserting media objects to a presentation, you can always refer to my article Adding Multimedia to a PowerPoint 2003 Presentation.

    I’m working on several articles dealing with how to create and customize animation sequences in PowerPoint 2002 and above. With any luck they’ll be published in a few weeks. Of course, I’ll post the links here once those articles go live.

    Many thanks again to the PowerPoint development team for their willingness to bring me up to speed and (gently) correct my mistakes.

  • Andrew May's WebLog

    Creating Personalized Thank You Cards with Publisher 2003 (Part 4 of 4)


    (Previously: Part 1, Part 2, and Part 3)

    Perform the Merge

    Now you’re ready to actually preview how the cards will look when merged. To set up the data source, do the following:

    ·         Sort the records based on Gift? = True, so you select only the records for people who sent you gifts.

    ·         If you’re planning on performing more than one merge, sort on Record merged? = False, so you only select the records that haven’t already been merged.

    Preview the cards to make sure they look like you want them, and then perform the merge to a new publication.

    So what does the final card interior look like? Well, here’s one of ours:

    Again, I’ve formatted the text that’s coming from merge records in blue, so you can more easily see the personalization of each card.


    (What, you didn’t think I was going to post a clear picture of my ugly mug on the web, did you? What’s the point of the witness protection program if I do something like that?)

    Once you’ve performed the merge and saved the merged file, remember to go back and set the Record merged? field to True for those records you’ve just merged. That way they won’t be included in the next merge you perform, so you won’t get duplicate cards.

    Print the Cards

    When you print the merge results, you’ll actually be printing them on the other side of the card exterior, which you printed earlier. It’s a good idea to print a test page or two to make sure you’ve got the paper fed correctly into the printer. For example, in our case, I had to make sure that the gift picture on the inside printed on the other side from the card front.

    Once you’ve printed the cards, all that remains is to cut them, fold them, and mail them to your loved ones. Seriously, the response we got from the cards was wonderful. People gushed; they really loved receiving such a unique personalized card. Except for the people who thought we should have taken all the money we obviously spent on this expensive service and used it to provide more cake.

    And I’m sure you’ve realized that you can use this method for a lot more than just wedding gifts. The next time someone is having a birthday party, have someone there taking digital pictures as they unwrap their loot. A few days later, everyone who gave a present receives a nice personalized card with a picture of the birthday girl/boy’s look of joy as they open the present that person brought.

    But even after this success, my fiancée still put the brakes on my idea of performing our vows as a PowerPoint presentation.


    Yeah, that was probably a good call on her part.

  • Andrew May's WebLog

    Creating Personalized Thank You Cards with Publisher 2003 (Part 3 of 4)


    Now that we’ve got the card exterior designed, we’re ready to work on the catalog merge.

    Create the Data Source

    Next, create the data source for the cards. We used the same one we used for addressing the invitation. We just added several fields to the spreadsheet:

    ·         Salutation: The informal name you use for the person, like “Uncle Jim and Aunt Jane”, as opposed to the formal name you’d use on the wedding invitation.

    ·         Gift?: This is just a simple yes/no field. You’ll use it to filter the records you’ll use to perform the catalog merge.

    ·         Gift: Informal description of whatever the gift actually was.

    ·         General comment: Whatever heart-felt sentiment you want to say. Because Publisher only prints the first 256 characters in a field, I added two comment field next to each other. Each field is roughly enough for two or three short sentences.

    ·         General comment 2: See above.

    ·         Picture: The path to the picture of you with this gift.

    ·         Record merged?: If you’re not going to merge and print the cards all at once, you might want to include a data field to designate whether or not the card has been included in a merge. Just remember to change the value from False to True once you create the merge and print it. That way you can sort out the printed cards, so they won’t be included in any subsequent merge.

    Fill in the data source records, and you’re ready to create the card interior itself.

    Design the Card Interior

    Below is the design I came up with for the inside of our Thank You cards. Notice that the inside of the card is one large catalog merge area, sized so that it repeats twice per page. I placed the picture of us with the gift on the inner side of the card front, with the personal thank you comments underneath. But that’s hardly the only way to do it. Play around, see what works for you.

    I’ve marked the merge fields blue in the screen shot below to emphasize them, so you can see what they look like before the merge happens. The merge fields don’t appear in blue normally.


    For the purpose of this blog, I’m assuming you know how to create and perform a catalog merge. If you don’t, take a look at these Office Online resources:

    Create a catalog merge

    Demo: Catalog merge turns data into designs

    Create catalogs or directories

    Or, for you programming types, I just happen to have written a few articles on the topic:

    Create Catalogs with Publisher 2003

    Sort and Filter Your Data for Mail or Catalog Merges in Publisher 2003

    Tomorrow, we bring it all together.

  • Andrew May's WebLog

    Creating Personalized Thank You Cards with Publisher 2003 (Part 2 of 4)


    Now that we’ve covered the basics of the project, let’s jump into the details:


    Here’s the household items you’ll need for this project:

    ·         Elmer’s glue (or paste)

    ·         Safety scissors

    ·         A 6-inch length of string

    ·         Glitter

    Oh wait, that’s a different arts and craft project. The tools for this one are a little more upscale:

    ·         Microsoft Office Publisher 2003

    ·         A digital camera capable of downloading images to a computer

    ·         A color printer capable of producing photo-quality prints (or access to one at work)

    ·         A computer (preferably a laptop or TabletPC)

    ·         A paper cutter (you can substitute safety scissors if you must)

    Now, if you don’t already have these basic household items, don’t be afraid to include them in your wedding budget, especially if her father’s picking up the tab. This works best if you don’t call them out in the budget as individual line items. Group them with similar expenses. For example, go ahead and roll the cost of the digital camera into the “Wedding party corsages” line item, or expense the photo-quality color printer under “Table decorations (misc.).”

    Bribe a Friend

    Actually, I forgot an additional item you’ll need for this project: a friend willing (or willing to be bribed) to take the pictures of the happy couple with each gift. If they can work a digital camera, even better. Alcohol, chocolate, and/or food make excellent inducements, depending on the friend. One piece of advice, though: don’t be too free with the alcohol until all the pictures are taken. Also, things go most smoothly when you unwrap and sort the presents before the camera person gets there. A laptop’s great for entering the gift information in the spreadsheet as you open each gift.

    One thing we hadn’t anticipated was how many people would be giving us the universal gift: cash. Or gift cards/certificates to the stores included on our registry. Since we didn’t feel a picture of us fondling a gift check, or rolling in a pile of low-denomination bills was appropriate, for these generous souls we included a picture of us on our wedding day.

    Now granted, you could take the pictures with a conventional camera, and scan them into the computer later. But the great thing about digital is there’s no wasted film, you can be sure you’ve got the photo you want as soon as you take it, and you don’t have to get the photos developed. And in the end, isn’t your wedding worth it?

    (If she buys that argument, my work here is done.)

    Once you’ve got the pictures taken, download them to the computer.

    Design the Card Exterior

    You’ll use Publisher for the rest of the steps. First, design the outside (front and back) of the card. In our case, we made the cards 5.5 by 8.5 (5.5 by 4.25 when folded) so that two would fit on a regular 8.5 by 11 inch sheet. So the basic layout looked like this:

    Remember that anything on the back of the card needs to be upside-down in your layout, so that’s correct once the card has been cut and folded. To flip shapes, including text boxes, select the shape and then, from the Arrange menu, click Rotate or Flip, and then click Flip Vertical.

    Then print as many as you’ll need.

    The ruler guides mark quarter-inch borders around the actual faces of each card . Once the cards were done, we cut them on the center vertical ruler, and folded them along the center horizontal guide. Just don’t cut yours yet, because we still need to print the personalized inside of the card.

    Which we’ll cover tomorrow.

  • Andrew May's WebLog

    Creating Personalized Thank You Cards with Publisher 2003 (Part 1 of 4)


    Well, it’s spring time again, and of course that means one thing: Tech Ed. But rather than focus on the definitive Microsoft conference for building, deploying, securing, and managing connected solutions, I’d like to take a few entries and address another industry that gears up every spring.

    That’s right, it’s wedding season.

    So over the next few entries I’d like to discuss something very cool my wife and I came up with for our wedding: using Publisher to create personalized Thank You cards for wedding gifts. We created an individual Thank You card for everyone who sent us a gift. Printed inside each card was a picture of us holding that person's particular gift, along with printed comments specific to that person.

    We personalized the Thank You because we wanted people to know how important they were to us and how much their gifts meant. Also, since our registry was online, and we had family and friends all over the country, a lot of the gifts got ordered online and shipped directly from the store. In many cases, the people buying the gifts had never really seen what they were sending us.

    Pretty cool, huh? Trust me, people loved these cards.

    And the best thing was, using Publisher’s catalog merge functionality, it was easy. We did all this through the user interface; I didn’t have to write a single line of code to customize or extend Publisher’s functionality. (So consider this a warning: the following entries don’t contain a single line of code.)

    Unnecessary Backstory

    Anyway, about six months ago, I got married. (That in itself is a success story, but not one in which Microsoft products played a large part. I assume. Maybe she created a mathematically-weighted list of my pros and cons in Excel and the balance sheet came out in my favor. I don't know. But if that's the case, she should probably check her math.) No, the cool thing we did with Publisher was to create personalized Thank You cards.

    Once we decided to be married, we actually realized that we’d have to go through the process of getting married. For some unknown reason, we decided not to elope, and instead opted for a simple wedding. ‘Simple wedding’, of course, being equivalent to ‘military intelligence’ on the oxymoron rating scale.

    Simple as our wedding was, most of the planning fell to my fiancée. Once I realized the incredible stress and pressure she was under from dealing with the marital-industrial complex, I resolved to help and support her in any way humanly possible that didn't involve actually dealing with any aspects of the planning process that didn't interest me. In short, I began looking for those activities that would let me continue to dink on the computer while giving the appearance of being an active participant in planning my own wedding. I spent long hard hours on such tasks as generating facility expense comparisons, keeping our invitation address database current, maintaining our website, and much more. I did this incidentally to move our plans for the blessed day forward, but primarily just to avoid being dragged into interminable discussions of floral arrangement plans and linen design options.

    (And trust me, the wedding was much better for my lack of involvement. One of the few times I actually rendered an opinion, it nearly doomed the whole damn thing. Just remember: at weddings, people want and expect cake. Any cake. People do not want wonderful and expensive lemon torte with fresh-picked organic berries--unless it is served on cake. If you tell people ahead of time there will be no cake, they will revolt, and threaten to bring their own cake and serve it tail-gate style out in the reception parking lot. Seriously. Cake.)

    Publisher 2003 was great for stuff like this. I created our website in Publisher; I designed our Save the Date cards and the wedding program in Publisher. I even used Publisher's mail merge feature to address the invitations. Those all turned out looking professional and pleased my fiancée immensely. But the one thing I'm particularly proud of was our Thank You cards.

    We used Publisher's catalog merge functionality. It was easy. Here's the basic steps, each of which I discuss in more detail later:

    ·         Take digital photos of the happy couple with each gift

    ·         Design the outside of your Thank You card

    ·         Create the data source for the catalog merge

    ·         Design the inside of the card as a catalog merge area

    ·         Perform the catalog merge

    ·         Print the cards

    In my entry tomorrow I’ll cover the first two of these steps.

  • Andrew May's WebLog

    OneNote Namespace Change for SP1


    Here’s a heads-up for developers that are using the SimpleImport interface available in the OneNote 2003 Service Pack 1 (SP1) Preview. Be advised that the namespace for the Import method will be different in the final released SP1 from what it is in the Preview version.

    The current namespace for the OneNote SP1 Preview is:

    While the final namespace for OneNote SP1 will be:

    From what I understand, it’s become standard procedure here in Office to use a ‘beta’ namespace for early versions of a product, and then switch to another namespace once the schema has been finalized. Just be advised that if you’re programming against the Preview namespace, you’ll need to update your code for the new namespace in order for it to be compatible with the final OneNote SP1, once it’s released.

    I’ve already edited my blog entry detailing how to use the SimpleImport functionality, but I wanted to call this out in a separate entry for anyone who’s already using the documentation.

  • Andrew May's WebLog

    Customizing OneNote 2003 SP1 Using New Command Line Switches


    The last aspect of the OneNote SP1 developer story that we should talk about is the half-dozen or so command line switches that OneNote SP1 has added. Once again, here's a draft version of an article that we'll publish on MSDN once OneNote 2003 SP1 is available. The information has been reviewed by the OneNote team, but this is still draft documentation, and should be considered as such.

    Here you go:


    Applies To:

        Microsoft Office OneNote 2003 SP1 Preview

    Summary:    OneNote 2003 SP1 Preview features several new command line switches, including switches you can use to record video notes, import content, and collaborate with others.


    For SP1 Preview, OneNote 2003 has added six new command line switches that enable you to customize OneNote’s performance. The first three new switches let you automatically start, pause, and stop recording a video note. Two others deal with collaborating with others in a shared work space. The final switch duplicates the content importing functionality of OneNote’s new CSimpleImporter interface.

    You can employ these command line switches in scripts, application programming, or even include them in desktop shortcuts.

    Note These extensibility features are only available when you upgrade to the OneNote 2003 Service Pack 1 (SP1) Preview.

    Running OneNote with Command Line Switches

    You can modify how OneNote 2003 starts by adding switches when you launch OneNote from the command line. Several of these switches where available in the initial release of OneNote 2003. For example, you could open OneNote to a specific page, print a specific page, start audio recording, or open a side note. OneNote 2003 SP1 extends this functionality with the new switches.

    To use a command line switch to customize how OneNote starts, pass the command line a string composed of:

    ·         The fully qualified path to the OneNote application, and

    ·         The switch you want to use, plus strings for any parameters it requires.

    These switches work whether or not OneNote is already open. If you execute a command line switch and OneNote is already running, the switch action executes on the currently running instance of OneNote.

    The path of the OneNote exe can be found in the registry key: HKEY_CLASSES_ROOT\CLSID\{22148139-F1FC-4EB0-B237-DFCD8A38EFFC\LocalServer32

    Using Switches to Create Audio and Video Notes

    You can use four of the new switches to automatically create OneNote video notes:

    ·         /videonote, which starts OneNote recording on the active page, and lets you choose the audio and video devices to use, as well as specify a custom profile.

    ·         /pauserecording, which pauses video or audio recording in the current instance of OneNote. You can resume recording by passing this command line switch again.

    ·         /stoprecording, which stops recording the video or audio note in the current instance of OneNote.

    ·         /recordingprofile, which lets you use an external recording profile, instead of built-in profiles from OneNote.

    Note that the pauserecording and stoprecording switches also work with audio notes. You can use audionote, a command line switch present in OneNote 2003, to automatically start recording audio on the active page.

    Specifying Audio and Video Devices

    The videonote switch consists of the switch name and three optional string parameters:

    /videonote videodevice audiodevice recordingprofilepath

    To find the device you’ve specified, OneNote takes each string argument and compares it to the strings it gets from the system enumerating the devices installed. You do not need to pass the entire string for a device; instead, the string should be any unique subsection of that string, so OneNote can correctly determine the intended device. OneNote uses the first device it encounters whose string matches. If the string is not unique to a single device, OneNote may select the wrong device. Note that the class ID by itself is not sufficient to distinguish between devices.

    For example, suppose you had the following two video capture devices installed on your system:



    The class ID in each case is identical. However, each string does contain information that is unique. So you could pass the following switches to designate the first and second video devices, respectively:

    OneNote.exe /videonote vid_046d&pid_08b2

    OneNote.exe /videonote vid_046d&pid_08f0

    Similarly, suppose you had the following three audio capture devices installed:

    @device:cm:{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Intel(r) Integrated Audio
    @device:cm:{33D9A762-90C8-11D0-BD43-00A0C911CE86}\USB Audio Device

    Again, the class ID is the same in each case, but each string contains unique information to distinguish which device you want to specify.

    So, to start OneNote recording a video note, using the first video and audio device in each list, you would pass the following command line switch:

    OneNote.exe /videonote vid_046d&pid_08b2 “Intel(r) Integrated Audio”

    Also be aware that, because a space serves as the delimiter between parameters, you cannot pass an argument string that contains a space, unless you enclose the string in quotes. If you pass an argument string that contains a space without enclosing it, OneNote assumes the space signifies the end of that string, and the switch fails.

    If you do not specify a video or audio device, OneNote uses the default device, if one is available.

    Specifying a recording profile

    Two of the command line switches enable you to specify a custom recording profile. You can either:

    ·         Use the recordingprofile switch.

    ·         Use the optional recordingprofilepath parameter of the videonote switch.

    The recordingprofile switch has the following signature:

    /recordingprofile filepath

    Filepath is a required parameter that takes a string representing the fully-qualified path to a recording profile file.

    Alternately, you can specify a custom recording profile when you use the videonote switch. That switch’s optional recordingprofilepath parameter also takes a string representing the fully-qualified path to a recording profile file.

    A recording profile is a text file contains configuration information concerning video and audio recording, such as bit rate, sampling, and decoding. You can generate recording profiles using WMGenProfile, which is included as a sample application in the Media Windows Media Format 9 Software Developer’s Kit (SDK). For more information on recording profiles, see the SDK.

    Using Switches to Collaborate

    The next two command line switches we’ll discuss involve the important collaboration functionality added to OneNote 2003 SP1. Now, you can share a notebook page with one or more users, with each user able to dynamically add, edit, and delete content in real time to the page, and each user retaining a copy of the notebook page at the end of the session.

    One user starts the session by setting up a shared session. The user selects the notebook page they want to share, then specifies a password for the session if desired. He can then invite other users to join the session. Users who want to join the session must specify the address (either IP or network domain) of the computer on which the session was started, and the password if one has been set. The user who started the session also determines whether other users have the ability to edit the shared notebook page.

    The command line switches, startsharing and joinsharing, enable you to programmatically initiate or join a shared session, respectively.

    The startsharing switch has the following signature:

    /startsharing password filename

    As its name implies, this switch initiates a shared session from the computer on which it’s executed. The filename string parameter refers to the notebook section to share. The filename string must be a fully-qualified path to the section, including section name and file extension (that is, .one). The page shared is the page most recently selected in that section.

    The password parameter is optional. If you specify a password, all other users are required to specify that password in order to join the session. The password can contain any characters; however, strings that contain spaces must be enclosed in quotes. You will need to communicate the computer address and session password to participants in order for them to join the session.

    Once the shared session has been started, other users can join and collaborate. The joinsharing switch has the following signature:

    /joinsharing sessionaddress password filename

    Executing this command line switch adds the computer to the shared session. In order to join a session, you must know the address of the computer that started the session, and the password, if one has been specified. The sessionaddress parameter takes a string that represents the address of the computer that started the session; this address may be the computer’s IP address, or full network domain name. The password and filename parameters represent the password for the session, if one has been set, and the section of the notebook that is being shared, respectively. You will need to receive this information from the session initiator in order to join the session. The filename parameter is optional; if you omit it, OneNote opens to the last section opened. You can only share one notebook section at a time.

    To start or join a session using the user interface, from the Tools menu select Shared Session, and then click Start Shared Session or Join Shared Session.

    The following function programmatically initiates a shared session in OneNote. The calling application passes string representing the location of the OneNote application and the notebook section to share. The example function generates a random numeric string to use as a password, then starts a new process that initiates a shared session in OneNote. The function then returns the password to the calling application. Note that the auto-generated password offers no extra security, and is only done for convenience.

    Public Function ShareOneNote(ByVal appLocation As String, _

        ByVal section As String) As String

        Dim NoteSwitch As String

        Dim OneNoteProcess As Process

        Dim Ran As New Random

        Dim Password As String


        'Generate a random numeric password

        'NOT for security, just for convenience

        Password = Ran.Next(100000001).ToString

        'Compose command line switch

        NoteSwitch = " /startsharing " & Password & " " & section

        'Pass command line to OneNote application

        OneNoteProcess = Process.Start(fileName:=appLocation, _


        'Return generated session password to calling application

        Return Password


    End Function

    Using the Import Switch to Place Content in OneNote

    You can also use a command line switch to automatically import images, ink, and HTML into OneNote. You can even create the folders, sections, or pages onto which you want to place your content.

    The import switch consists of the switch name and a single required parameter:

    /import filename

    The filename parameter takes an XML file that specifies:

    ·         The folders, sections, and pages on which you want to place content. If a folder, section, or page does not exist, OneNote creates them.

    ·         Details of the images, ink, and outlines (in HTML form) that you want to place on each specified page.

    The file must adhere to the requirements of The OneNote 1.1 SimpleImport XML Schema.

    This switch duplicates some of the functionality of OneNote’s CSimpleImporter interface. For more information about this interface, including a discussion of the OneNote SimpleImport schema, see Importing Content into OneNote 2003 SP1 Preview.

    Using Other Command Line Switches

    Below is a list of the command line switches previously available in OneNote 2003. All parameters take strings as arguments.

    / filename

    Opens a file, where filename is a fully qualified file name, including the disk, folder path, and .one file extension.

    /new filename

    Creates a new section, called New Section 1, in the default folder (such as My Notebook), although filename is a required parameter that includes the disk and folder path and any unique file name with the .one file extension.

    Note  If a section called New Section 1 already exists in the folder, the number in the section name is increased incrementally, such as New Section 2.

    /newfromexisting folder filename

    Copies the file that is specified by filename to the folder that is specified by folder and opens the file.

    /openro filename

    Opens a file as read-only, where filename is a fully qualified file name, including the disk and folder path and .one file extension.

    /print filename

    Prints a file, where filename is a fully qualified file name, including the disk and folder path and .one file extension.

    /forcerepair filename

    Runs the file repair feature for a file, where filename is a fully qualified file name, including the disk and folder path. This is the same file repair feature that OneNote automatically runs if it detects file corruption while opening a file.


    Starts OneNote in a miniature window, open to the Side Notes section by default.


    Starts recording on the active page.


    Opens the New task pane.


    Pastes the contents of the Clipboard.


    Command line switches offer an easy-to-implement way of customizing OneNote not just from the command line, but through scripts, code, or even desktop shortcuts.

  • Andrew May's WebLog

    OneNote Import Example: Generating GUIDs and XML


    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


            'Generate root Import element

            'and specify OneNote schema namespace


            .WriteAttributeString("xmlns", _



            '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




        End With

        'Flush the xmltextwriter


        '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



        '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


        '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.

  • Andrew May's WebLog

    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.


    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:

    While the final namespace for OneNote SP1 will be:

    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\"


                      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="">


          <EnsurePage path="MSN Instant Messenger\"






          <PlaceObjects pagePath="MSN Instant Messenger\"



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

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

                      <Image backgroundImage="true">

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




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

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


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




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

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

                      <Outline width="360">




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







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







    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"


      strFileName = OpenFileDialog1.FileName()


      objOneNote = New OneNote.CSimpleImporterClass

      XmlFileStream = New StreamReader(strFileName)

      strImportXml = XmlFileStream.ReadToEnd




    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)


    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


    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


    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

    Final 'Automating Prepress Tasks' article now live


    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:

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


  • Andrew May's WebLog

    Assigning Build Levels to Text


    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

    How Not to Animate Your Slide


    Hey, remember that nifty tip in my last blog entry about how to set up a sound file so that’s it’s ‘invisible’ and plays automatically when the slide loads? Nice trick, huh? Turns out that entry, in addition to being my first official PowerPoint blog entry, afforded me the rare opportunity to be horribly wrong with my advice in two completely different ways. Not only should you not set up the file to play automatically using the code I wrote, but even if you wrote the correct code, it might well screw up other animation effects for your entire slide.

    Here’s the deal:

    Unbeknownst to me at the time, it turns out that in PowerPoint 2002 and above there are actually two separate, incompatible sections of the object model that enable you to set up animation effects for your slide. The new, expanded object model section, contained in the TimeLine object, provides more flexibility and options for richer interactive animations then ever before. This is the object model section you should use for animation whenever possible. The other section, contained in the AnimationSettings object, was retained strictly for backward compatibility reasons. Unless you’re programming for PowerPoint 2000 and below, never use the Animation Settings object. (This, of course, make me wonder why this section of the object model wasn’t hidden for PowerPoint 2002 and above, but that’s a minor digression.)

    Still with me? Because of basic differences in the way they are organized, the two object models are not compatible. The AnimationSettings object model only supports entry effects for shapes (which is one reason the TimeLine object model was created, to offer users multiple effects for a single shape.) Here’s where the fun begins. If your code uses the AnimationSettings object to set any effect properties, PowerPoint assumes you are programming for PowerPoint 2000 or below, and therefore deletes any animation effects that are not entry effects, for the entire slide. This includes effects that were added using the user interface.


    So naturally, the code I wrote for my tip inserted the sound file ‘offscreen’, and then used the AnimationSettings object to set the file to play when the slide loaded. Let me apologize right now if I blew up anyone’s slide and you’ve been trying to figure out why ever since.

    Now, normally at this point, having finished my mea culpa, I would show you the proper way to set the file to play automatically, using the TimeLine object model.

    Except it doesn’t work that way either.

    Turns out there’s currently a bug in the PowerPoint object model. You set a file to play automatically by setting PlaySettings.PlayOnEntry to True. You can access the PlaySettings object through either object model. Unfortunately, because of the bug, when you access certain properties of the PlaySettings object, even if you do so through the TimeLine object model, PowerPoint assumes you are programming for PowerPoint 2000 or below, and—you guessed it—deletes any animation effects that are not entry effects, for the entire slide.

    This is true for the following PlaySettings properties: ActionVerb, HideWhileNotPlaying, PauseAnimation, PlayOnEntry, and StopAfterSlides. It seems like you can access the following two properties and not suffer any ill effects, but no guarantees: LoopUntilStopped and RewindMovie.

    Did I mention that I was still learning my way around the PowerPoint object model?

    Actually, I’m in the process right now of writing several articles on how to create, customize and control animation effects in PowerPoint. And unlike these helpful blog entries, the articles will be tech reviewed by developers on the PowerPoint team. Stay tuned.

  • Andrew May's WebLog

    Playing Sound Clips Without Seeing the Icon


    So here it is, my first official blog entry dealing with programming PowerPoint presentations. It’s a modest tip, but then, I’m still learning my way around the PowerPoint object model.

    When you insert a sound clip into a PowerPoint presentation, a small icon representing the sound file appears on the specified slide. Which is fine if you intend to start the sound file playing by user interaction, that is, by clicking on the icon or moving your mouse over top of it. But what if you just want the clip to play automatically when the slide loads? Then the icon is just visual clutter.

    In the user interface, if you drag the icon off into the ‘work space’ area around the slide, then the icon won’t appear during the presentation. Just remember to set the sound clip to play automatically when the slide appears, however, because without the icon you don’t have any way to start the slide during the presentation itself.

    The following code does the same thing programmatically. First, it inserts the sound file. Then it moves the sound file (now represented by a Shape object, the icon) over to above the upper left hand corner of the slide. Then it sets several properties of the AnimationSettings object, which controls the playback behavior of the sound file. Specifically, the sound file is set to be the first shape on the slide animated, but to have no entry effect (so it just appears—or rather, doesn’t, as it’s positioned off the slide), and to play as soon as it appears, which is when the slide appears.


    Sub AddAudioOffSlide()

    Dim shpSound As Shape


    With ActivePresentation.Slides(2).Shapes

       Set shpSound = .AddMediaObject _


        With shpSound

            .Left = 0 - .Width

            .Top = 0 - .Height

            With .AnimationSettings

                .Animate = msoTrue

                .AnimationOrder = 1

                .EntryEffect = ppEffectNone

                .PlaySettings.PlayOnEntry = msoTrue

                .AdvanceMode = ppAdvanceOnTime

                .AdvanceTime = 0

            End With

        End With

    End With

    End Sub

    I believe you could also set the sound file to play in conjunction with another shape’s animation by setting the AnimationSettings.AnimationOrder of both Shape objects to the same value, but I haven’t tested that. And anyway, if you just wanted to play the sound file once as part of another shape’s animation, you can just use the AnimationSettings.SoundEffect property to do that, without having to add the sound file to the slide at all.


  • Andrew May's WebLog

    Print Preview: what you see and what you get


    Ever print something and have it be slightly different than what you saw in Print Preview? Conversely, ever go into Print Preview and see something that’s just a tad off from what your file actually looks like? For the most part, the differences are probably minor, but why does it happen at all?

    This situation usually occurs when the application file contains information that is not under its direct control; for example, OLE (object linking and embedding) objects, or EPS (encapsulated PostScript) files. Here’s what happens in Publisher in these cases, and I’m pretty sure this is standard throughout Office applications:

    Basically, when you select Print Preview, Publisher creates a .wmf (Windows metafile) file based on the contents of the publication. This metafile is what you see in the Print Preview window.

    OLE objects

    The application (that is, Publisher) creates a metafile to display the OLE object on the screen. When you choose Print Preview, it in turn creates a metafile of the Publisher file, including the metafile of the OLE object. So at this point, what’s display in Print Preview is a rendering of a rendering of the actual OLE content.

    When you print the file, Publisher calls the OLE server to find out what to print in place of the OLE object, and sends that raw information to the printer for printing.

    EPS files

    The application (Publisher) uses its built-in EPS filter to create a metafile of the EPS image. Note that Publisher does not use the bitmap preview image that’s usually included in the EPS file. Instead, it relies on its EPS filter, which interprets the PostScript, for more accurate (but still not perfect) rendering.

    What gets printed depends on whether you’re using a PostScript-enabled printer or not. For non-PostScript printers, the Publisher passes the metafile it created of the EPS, and that’s what gets printed. For printers that can handle the PostScript language, Publisher passes the raw EPS to the printer, and that’s what ends up on the page.

    Keep in mind that the Print Preview also takes into account information about the printer you have selected. For example, if you’ve selected a black-and-white printer, then your preview image is black and white, regardless of whether your publication contains color. Also, the clipping area (margin around the paper edge on which the printer cannot print) varies from printer to printer. This is reflected in the Print Preview image as well. So in general it’s best to select the printer you want before you print preview your publication.

Page 4 of 5 (108 items) 12345