SharePoint Development from a Documentation Perspective

Andrew May

  • Andrew May's WebLog

    InfoPath Forms in Office SharePoint Server 2007


    I’m sure it comes as no surprise that Office InfoPath 2007 is the forms designer of choice for Office SharePoint Server 2007. But the average SharePoint developer, used to reaching for ASP.NET when he needs to create a form for SharePoint, might be surprised at all the places you can employ InfoPath to quickly create forms for enterprise management functions.

    The main reason for this is the fact that in InfoPath 2007 you can create what the InfoPath guys are calling symmetrical forms. Symmetrical forms are InfoPath forms that can be hosted either in the Office client applications like Word, PowerPoint, and Excel, as well as in the SharePoint Server browser interface. So you can create a single form, and know it’ll look and work the same whether the user sees it in an Office application or in the browser interface.

    (How is this possible? Short version: SharePoint Server 2007 uses Office Forms Services, a server-based run-time environment for InfoPath 2007 forms, to host the forms in the browser. Office Forms Services consumes the forms you create in the InfoPath client and renders them in an ASP.NET framework, which acts as a run-time environment for the form. This environment presents a form editing experience that matches the InfoPath 2007 client application. The Office client applications, on the other hand, include the ability to host the native InfoPath forms. )

    So naturally, symmetrical forms are very handy for enterprise content management areas, where the user might be working with documents in their native client application, or online through the SharePoint Server browser interface.

    Here’re a couple of the places where you can employ InfoPath forms for enterprise content management in SharePoint Server 2007:

    ·         Document Information Panels

    A document information panel is a form that is displayed within the client application, and which contains fields for the document metadata. Document information panels enable users to enter important metadata about a file anytime they want, without having to leave the Microsoft Office system client application. For files stored in document libraries, the document information is actually the columns of the content type assigned to that file. The document information panel displays a field for each content type property, or column, the user can edit.

    You can create document information panels either from within SharePoint Server, or directly from InfoPath 2007.

    How to: Create or Edit a Custom Document Information Panel from within Office SharePoint Server 2007

    How to: Create a Custom Document Information Panel from InfoPath 

    ·         Workflow Forms

    You can create InfoPath forms for use with workflows in SharePoint Server 2007. That way, the user can interact with the workflow form from within the Office client application, and not just through the browser.

    SharePoint Server 2007 uses Office Forms Services to display workflow forms, be they association, initiation, modification, or edit task forms. The only difference is that there’s a different .aspx page hosting the Office Forms Services control for each type of workflow form. Initiation forms are hosted by a different .aspx page than modification forms, for example. Each different hosting page knows how to submit the information from its type of form to SharePoint Server (and hence, to the workflow engine).

    The .aspx pages that contain the Office Forms Services web part are included as part of SharePoint Server, of course.

    How to: Design an InfoPath Form for a Workflow in Office SharePoint Server 2007

    So if your putting together an enterprise content management solution in Office SharePoint Server, and you’d like your user to be able to interact with your custom forms in the client application and the browser, it might be worth your while to take a look at InfoPath 2007 and Office Forms Services.


    Written while listening to Johnny Cash : Personal File

  • Andrew May's WebLog

    Records Repository Technical Poster for Download


    Today I'm making another SharePoint technical poster available for download. This one details the records repository functionality offered in Windows SharePoint Services V3 and Office SharePoint Server 2007.

    (As always, it's the fine folk at Office who are doing the real heavy lifting by hosting the poster I have for download. Many thanks, guys. To check out the other SharePoint technical poster and namespace diagrams available for download, refer to this topic, and this one too.)

    Just click the link below to download a full-color PDF of the poster:

    Using Record Repository Features in Windows SharePoint Services (version 3) and SharePoint Server 2007

    And what are records repositories, you ask? Read on for a quick overview:

    Now, everyone knows that SharePoint offers a great environment for collaborating on documents. But sooner or later, most documents are 'finished'; that is, they reach a state where you're not going to be making further changes to them. And you may want to store some of these documents, in their finalized state, for a long time. To facilitate long-term storage for such documents, SharePoint offers several features of interest to developers:


    The Official File Web Service

    The Official File Web Service, part of Windows SharePoint Services V3, is a Web Service that enables you to automate the process of moving documents into a records repository. Now, what exactly that records repository is is up to you: it could be a SharePoint site (which we'll talk about in a minute), or it could be an entirely different storage system. It's your choice. There's nothing inherently SharePoint-specific about the Web Service. Basically, the Web service enables you to pass a document, along with any metadata you want to package with it, to some document storage facility. You can also specify a record routing type, which is simply the name of a location within the repository where you want to store the document. How the document storage facility processes the document and its metadata internally is, of course, up to it.

    When you send a file to the record repository, either manually or through the object model, you are sending a copy of that file. The original file is not altered in any way and contains no link to its copy in the record repository. However, the copy is submitted to the repository with a pointer to the location of the original file.

    To read more about the Official File Web Service in the Windows SharePoint Services V3 SDK, start here.


    The Records Repository Site Template

    Office SharePoint Server 2007 builds on the Official File Web Service by including a site template that has been optimized for use as a records repository. The Records Repository site template has been customized for use as a records repository. Site features that are not useful for a records repository, such as Discussions, have been hidden by default. Conversely, useful site components, such as Reporting, are prominently featured.

    In addition to implementing the Official File Web Service, the site template includes several features that enable record managers to customize that implementation:

    ·         A record routing type table, which lets record managers specify where different types of content are stored within the records repository.

    ·         A record routing type entry in that table, called Unclassified Records, which is the default record routing type.

    ·         A default document library, Unclassified Records, for storage of files assigned the Unclassified Records record routing type.

    To read more about the records repository site template in the Office SharePoint Server 2007 SDK, start here.


    IRouter Interface for Custom Records Repository Routers

    Lastly, Office SharePoint Server also includes the IRouter interface, which enables you to implement custom records repository routers. You can use a custom router to perform your own custom processing on submitted documents; either before SharePoint does its own standard processing, or to replace that processing altogether.

    You can specify one custom router for a specific record routing type. When a user submits a file of that record series type to the record repository, the record repository calls the custom router to perform its custom processing before the records repository performs any of its standard processing. When complete, the router returns whether it succeeded, and if successful, whether the record repository should perform its standard processing and storage of the submitted file.

    The custom router has the ability to edit the submitted document and its associated metadata, as well as update the location to which the submitted document is to be stored.

    After you specify a custom router for a given record routing type, the records repository invokes the router whenever a file of that record routing type is submitted through any mechanism, including the user interface, object model, and STMP.

    To read more about implementing custom routers, start with this topic.


    Written while listening to Richard Thompson : More Guitar

  • Andrew May's WebLog

    SharePoint Beta 2: Enterprise Content Management Samples Now Online


    If you're interested in extending the enterprise content management features in Office SharePoint Server 2007, take note: we've just released the Enterprise Content Management Starter Kit on MSDN.

    This download is a great grab-bag full of information and examples of the extensible ECM features included in Office Server 2007. Among the sample code projects are examples of custom:

    ·         Document Inspector modules

    ·         Record repository routers

    ·         Record repository Web Service application

    ·         Search and process tools

    ·         Multiple flavors of custom workflows, including: sequential and state workflows, custom workflow activities, multi-stage and replicating workflows, and workflow modifications.

    So if you want sample projects for the ECM features, chock full of tips, tricks and best practices straight from the product team, this one's for you.

    Just as important, if you plan on rolling your own workflows for the SharePoint environment, are the two Visual Studio workflow project templates included in the download. These project templates are designed to get you up and coding SharePoint workflows with a minimum of fuss: they include references to the necessary SharePoint namespaces, as well as having the SharePoint-specific workflow activities included on the designer Toolbox. One is for creating workflows for Windows SharePoint Services V3; the other, for workflows you plan to use in SharePoint Server 2007.


    Written while listening to Artic Monkeys : Whatever People Say I Am, That's What I'm Not

  • Andrew May's WebLog

    SharePoint Object Model Maps for Download


    The guys at have generously agreed to host a few more of the large-size diagrams I’ve created for internal usage. So I’m offering up several object model maps for download. These are poster-size (11” by 17”) diagrams that illustrate key objects and namespaces in the SharePoint environment, suitable for sticking up in your office or hanging in your home as fine art.

    Each object model map was created in Visio, but the downloads are PDFs for ease of viewing and printing.

    Just click on any or all of the links below to download the maps you want. And leave me a message in the comments section telling me what you thought of the format, design, layout, etc. of the diagrams. Thanks.

    ·         The Windows.SharePoint.Workflow Namespace

    Workflow is another area you’re going to be hearing a lot about this release. The diagram illustrates the classes and members of the Workflow namespace, which you’d use to associate, initiate, and otherwise manage the workflow templates and instances in a Windows SharePoint Services deployment.

    ·         The Windows.SharePoint.SPContentType Object

    This object model map highlights the members and child objects of the SPContentType object. Content types are a core concept for this next release of Windows SharePoint Services, as I explain here. This object model maps compliments the conceptual diagrams of content types I offered for download here.

    ·         The Microsoft.Office.RightsManagement.InformationPolicy Namespace

    I haven’t talked about information policy on this blog yet, but there’s plenty of material in the Office SharePoint Server 2007 (Beta 2) SDK to fill you in. (Start here.) This diagram illustrates the classes and members of the InformationPolicy namespace, which you’d use to manage the policies, policy features, and policy resources on a SharePoint Server 2007 installation.

    I’ve still got a few more diagrams to make available; check back early next week for more full-color, absolutely free goodness.

    Written while listening to Greg Dulli : Amber Headlights

  • Andrew May's WebLog

    Content Type Technical Posters for Download


    The title pretty much says it all. For some of our earlier, internal technical events, I created a number of large-format (11” by 17”) technical illustrations to explain the more complicated aspects of enterprise content management in a SharePoint environment. The two posters I’m offering for download today deal with content types, a core concept in Windows SharePoint Services V3 that I’ve blogged about here. If you’re planning on using content types, I think it’ll be worth your while to take a look at these.

    As you can probably tell, I created the posters with Visio. I then converted them to PDF format using Visio 2007 (Beta)’s spiffy new Publish to PDF feature. I have to say I’m fairly impressed with the results. These are pretty complex diagrams, and as far as I can tell, Visio converted them flawlessly to PDF. Well done.

    Using Columns and Content Types to Organize Your Content in Windows SharePoint Services (version 3)

    This diagram explains the relationship between site and list content types, as well as content type ‘inheritance’ and customizing/deriving content types. It also illustrates how you can use site columns in your content types to ensure data uniformity, and how content type reference site columns and list columns.

    Using Content Types in Windows SharePoint Services (version 3) and SharePoint Server 2007

    Explains what content types are, and the advantages of using them to categorize and manage your enterprise content. Illustrates the conceptual structure of the various feature information you can encapsulate in a content type, such as columns, document templates, workflows, and custom solutions information such as forms and information policy.

    Note that these diagrams were created to be used with Adobe Reader 7.0, and will undoubtedly appear best using that version. I haven’t tested to determine if the diagrams display or print accurately in earlier versions.

    If you download either (or both) of the posters, take a second and let me know what you think of them in the comments section. Were they useful in explaining the various concepts they illustrated? Would you like to see something like this rolled into the SDKs at some point? I’m very visually-oriented; most of the technical illustrations I create start with me jotting something down on a napkin, to explain a concept to myself. But I have no idea if that’s true of developers in general. Are illustrations helpful in technical documentation like SDKs? Let me know what you think.

    And special thanks to Steve and Ryan and all the good folks at Office Zealot, who graciously agreed to host these diagrams for downloaded. I greatly appreciate it. Take a few minutes and visit their site; they’ve got tons of interesting content for the Office developer. It’s time well spent.

    And check back here next week. I hope to get some object model maps done for a few of the SharePoint namespaces, and I’ll make those available for download once I do.

    Written while listening to Isobel Campbell and Mark Lanegan : Ballad of the Broken Seas

  • Andrew May's WebLog

    What Are Content Types, Anyway?


    One of the major new concepts in Windows SharePoint Services V3 is content types. They're a core concept that enables a lot of the functionality in both Windows SharePoint Services and Office SharePoint Server 2007, so they seemed like a logical choice to talk about.

    A content type is a reusable collection of settings you want to apply to a certain category of content. Content types enable you to manage the metadata and behaviors of a document or item type in a centralized, reusable way. Basically, content types include the columns (or fields, if you prefer) you want to apply to a certain type of content, plus other optional settings such as a document template, and custom new, edit, and display forms to use.

    You can think of a content type as a refinement and extension of a Windows SharePoint Services 2.0 list. The list schema defined a single group of data requirements for each item on that list. So in Windows SharePoint Services 2.0, the schema of an item was inextricably bound to its location.

    With content types, you can define a schema for types of content, but that schema is no longer bound to a specific location. And to look at it in reverse, each SharePoint list is no longer limited to a single data schema to which the documents stored there must adhere. You can assign the same content type to multiple document libraries, and you can assign multiple content types to a given document library. Content types, in essence, let you:

    ·         Store the exact same type of content in multiple locations

    ·         Store multiple types of content in the same location

    Site and List Content Types: Parents and Children

    There are two different levels of content types I should mention: site content types, and list content types. Think of site content types as templates, and list content types as instances of those templates. You define site content types at the um, site level, hence the name. Since site content types aren't bound to a specific list, you can assign them to any list within the site you want. The site at which you define the site content type determines the scope of that content type.

    List content types are more like instances, or single-serving content types. When you assign a site content type to a list, a copy of that content type is copied locally onto the list. That's a list content type. You can even tweak a list content type so that it's different from its site content type 'parent'. Also, you can create a content type directly on a list, but it's a one-off. You can't then assign that list content type to other sites or lists.

    One other thing about site content types: you can base content types on other site content types. For example, Windows SharePoint Server comes with a built-in hierarchy of content types for basic SharePoint objects, such as Document, Task, Folder, etc. You can create your own site or list content types based on one of these site content types. Ultimately, all content types derive from the grandfather of them all, System.

    Also, if you make changes to a site content type, Windows SharePoint Services includes a mechanism whereby you can 'push down', or propagate those changes out to the child content types (be they site or list content types). Doesn't work the other way, though; no pushing changes to child content types up the family tree.

    E is for Extensible

    You can see how content types were designed to encapsulate and modularize schema settings in Windows SharePoint Services V3. One very powerful aspects of this is that you can use content types to encapsulate whatever custom data you want to include in them. The content type schema includes a <XMLDocuments> node, which you can use to store nodes of any valid XML. As far as Windows SharePoint Services is concerned, the contents of the <XMLDocuments> node is a black box. Windows SharePoint Services makes no attempt to parse any of the XML documents you store there; it simply makes sure that they are included in any children content types, such as when you assign the content type to a list.

    The <XMLDocuments> node was designed to be utilized by third-party solutions. Use it to store information pertinent to any special settings or behavior you want to specify for a certain type of content. Office SharePoint Server uses this mechanism to store information various features need, such as information policies and document information panels, among others. You can programmatically access a SharePoint item’s content type, and from there access the XML documents include in the content type.

    Find Out More

    To learn out more about content types, browse the topics included in the Content Types section in the Windows SharePoint Services V3 (Beta) SDK.

    And here’s a few places content types are utilized to facilitate Office SharePoint Server functionality:

    Using content types to specify document information panel.

    Using content types to specify document to page converters.

    Using content types to specify information policy.


    Written while listening to Bob Mould : Body of Song

  • Andrew May's WebLog

    SharePoint Beta 2 SDKs Online and Available for Download


    Well, as you've probably already heard, yesterday was a big day for us here, what with the Beta releases of Office 2007, Windows Vista, and Windows Server "Longhorn". What you may not realize is that the Office developer documentation team has been working overtime to make sure there's lots of in-depth developer documentation ready to highlight all the great developer features built into Office this time around.

    And with that, I take great pleasure in announcing the two projects that have been consuming most of my professional life for the past year: the Windows SharePoint Services V3 (Beta) and Office SharePoint Server 2007 (Beta) SDKs. Each SDK comes in two flavors: as a downloadable help file, or as online topics on MSDN.

    To download the SDKs, go here:

    To browse the SDKs online at MSDN:

    But that's not all. We've totally redesigned the Office Developer Center and its sub-sites, and posted tons of new developer content for the 2007 Office System. (And I mean 'we' in the most general, corporate sense of the word, as I really had nothing to do with it.) Go take a look and see what's new for 2007 for your favorite Office app. For example, how about that new Office SharePoint Server 2007 Developer Center?

    We've even launched a brand-spanking new developer portal to give Windows SharePoint Services developers a place of their very own: the Windows SharePoint Services Developer Center. And it too has lots of articles, demos, and screen casts to bring you up to speed on V3.

    It's actually a little intimidating to look at how much developer extensibility there is in Windows SharePoint Services and Office SharePoint Server this time around. So where do you start? Over the next few weeks I plan to excerpt some of the conceptual material from the SDKs to highlight the areas I've been documenting: the enterprise document management features. After that, if all goes well, I'll be able to give you previews of information that didn't make it into the Beta releases of the SDKs, but will be included in the final release.

    But for now, dig in. There's plenty to keep you busy.

    One article you might notice on both SharePoint portals is one that goes by the catchy title of Developer Introduction to Workflows for Windows SharePoint Services V3 and SharePoint Server 2007. This article pulls together information from both SDKs, as well as Windows Workflow Foundation, Office SharePoint Designer 2007, and InfoPath 2007 developer documentation, to provide a high-level overview of how workflows are implemented in the SharePoint Server and Office client environment. I wrote the article to give developers a unified picture of workflows in Office, and the tools and technologies you can use to create them. If you're interested at all in the new workflow foundation functionality, give it a read. And, as always, if you read it, please let us know what you thought by rating the article.

    Written while listening to The New Pornographers: Electric Version

  • Andrew May's WebLog

    ...Annnnnd we're back.


    Okay, so it’s been months since I last blogged. But that’s not because I haven’t been busy, or haven’t wanted to. I’ve just been working on stuff that I couldn’t talk about. But all that’s about to change.


    Watch this space.


    Written while listening to: The Twilight Singers : Powder Burns

  • Andrew May's WebLog

    Publisher Object Model Overview Article Now Live on MSDN


    Yesterday saw the publication of my penultimate article on Publisher 2003, 7 Things Developers Should Know About the Publisher 2003 Object Model, Part 1. If you're an Office developer new to the Publisher object model (or new to Publisher in general), this article and its sequel aim to give you a quick overview of the unique aspects of the Publisher developer story.

    These articles grew out of the fact that I was handing off the responsibility for Publisher developer documentation to another programmer-writer for the Office "12" release. As part of the transition, I had thought of a handful of areas where Publisher functionality or the object model was unique enough to require some explanation, even to the experienced programmer-writer taking my place. I wrote up a few of these areas on this blog (here, here, and here), then decided to turn the whole thing into an MSDN article. Which naturally became two.

    Part 1 covers the following areas:

    ·         General object model structure

    ·         The ThisDocument object

    ·         Commercial Printing Support in the object model

    ·         Catalog and mail merge

    While Part 2, most likely to be published next week, tackles these topics:

    ·         Wizards and templates

    ·         Web pages

    ·         Stories and linked text boxes

    I actually wrote these articles a few months back, but for various publishing reasons they're only now seeing the light of day. (My editor told me they were holding off publishing them in order to not overshadow the release of Harry Potter VI. I can see that.)

  • Andrew May's WebLog

    Publisher 2003: Creating and Managing Linked Text Boxes


    (Note:   This is the third in a series of entries that aim to introduce experienced programmers to the Publisher object model.

    The first entry covered creating Web pages programmatically. You can read it here.

    The second entry covered working with wizards and templates. You can read it here.)

    While the way you work with text in the Publisher object model is very similar to how you work with text in other word processing applications, such as Word, in does differ in one very important aspect: because Publisher is a desktop design and publishing application, it provides you to ability to include multiple text flows in a single publication, and programmatically control how those flows are laid out and formatted.

    For example, suppose you needed to create a newsletter. You would probably want to include several different articles, each with their own distinct content and formatting. In addition, a given article might continue from one page to another; those pages might not be contiguous. The final result might look something like the three-page newsletter in Figure 1.


    Figure 1. Lay out of a sample newsletter.

    In Publisher, each distinct flow of text is referred to as a story. A given story may span one or more textboxes, on one or more pages. Those pages need not be contiguous. Consider the sample newsletter in Figure 1. The first story is contained in a single text box on the first page. The second story starts in a text box on page one, then concludes in another textbox on page three. Story three is contained in three text boxes: two on page two, and a single text box on page three.

    Publisher lets you link multiple text boxes together to contain a story, and automatically manages how text flows from one text box to the next. If there isn't room to display all the story text in the first text box, the text flows into the second, and so on. If there's too much text to display in the final text box, Publisher stores the remaining text in an overflow buffer. Publisher automatically adjusts the amount of text contained in each text box as you resize the textboxes, format the text, etc.

    Using the Story Object to Manage Text

    When working with story text through the Publisher object model, it is important to distinguish between the story itself, and the individual text boxes that contain it. Each story in a given publication is represented by a Story object contained in the Document.Stories collection. Operations performed on a Story object affect the entire story, regardless of the textboxes in which it is contained. For example, the following code sets the font size for a story to 12 points, for all the text boxes that contain that story.


    The following example, on the other hand, set the font size for only the story text contained in the specific textbox:

    Activedocument.Pages(1).Shapes("Story2TextBox1") _


    You can not create or delete stories through the Stories collection. Rather, when you add a textbox to the publication, you are also adding a new story to the publication. For example, the following code adds a textbox, and therefore a story, to the active publication, even though no text has been specified for the text box.

    ActiveDocument.Pages(1).Shapes.AddTextbox _

      Orientation:=pbTextOrientationHorizontal, _

      Left:=72, Top:=72, Width:=200, Height:=200

    If you then deleted the text box, or linked it to an existing text box, the number of stories in the publication would decrease by one. Use the Stories.Count property to return the number of stories in a publication at a given time.

    To delete a story, you must delete each text box that contains the story text.

    Use the TextFrame property to access the text frame of the first text box of a story. Use the TextRange property to return the full text of the story.

    A story may also be placed within a table, in which case the story would be contained in one or more Cell objects rather than TextFrame objects. In such a case, use the Cell.TextRange property to access the text in a specific table cell. Use the HasTextFrame property to determine if a story is contained in one or more TextFrame objects.

    The only objects to which you can link a text box are:

    ·         An empty text box that is not already part of a chain of connected text boxes.

    ·         A drawing shape that has a text frame. To determine if a shape has a text frame, use the Shape.HasTextFrame property.

    Using the TextFrame Object to Manage Story Content

    Each text box contains a TextFrame object, which contains the text in shape, as well as the properties that control the margins and orientation of the text frame. The TextFrame object includes several members that enable you to determine if a text box is part of a linked story, and to set or sever the connections between text boxes.

    To determine if a text box is connected to a preceding or following text box, use the HasPreviousLink and HasNextLink properties, respectively. To access the text frames of those connected shapes, use the PreviousLinkedTextFrame and NextLinkedTextFrame properties. To connect one text box to the text box you want to follow it, use the NextLinkedTextFrame property as well.

    To break the forward link for a specified text frame, use the BreakForwardLink method. Applying this method to a shape in the middle of a chain of shapes with linked text frames will break the chain, leaving two sets of linked shapes. All of the text, however, will remain in the first series of linked shapes.

    The following example illustrates the relationship between a story and the connected text boxes that contain it. The example adds three text boxes to the active publication, and adds text to the first text box. At this point, with the text boxes not connected, three stories have been added to the publication's Stories collection. Next, the example links the three text boxes together by setting the NextLinkedTextFrame property of the first two text boxes. By doing this, two stories have been removed from the Stories collection. Note that the code calls the ValidLinkTarget method to determine if each text frame is a legitimate target to which to link.

    Finally, the third text box is disconnected by calling the BreakForwardLink method for the second text box. The story text is now stored only in the first two text boxes, and the overflow buffer if necessary. In addition, text box three now represents a new, empty story.

    Sub BreakTextLink()

      Dim tb1 As Shape

      Dim tb2 As Shape

      Dim tb3 As Shape


      Set tb1 = ActiveDocument.Pages(1).Shapes.AddTextbox _

          (Orientation:=msoTextOrientationHorizontal, _

          Left:=72, Top:=36, Width:=72, Height:=36)

      tb1.TextFrame.TextRange = "This is some text. " _

          & "This is some more text. This is even more text. " _

          & "And this is some more text and even more text."


      Set tb2 = ActiveDocument.Pages(1).Shapes.AddTextbox _

          (Orientation:=msoTextOrientationHorizontal, _

          Left:=72, Top:=108, Width:=72, Height:=36)


      Set tb3 = ActiveDocument.Pages(1).Shapes.AddTextbox _

          (Orientation:=msoTextOrientationHorizontal, _

          Left:=72, Top:=180, Width:=72, Height:=36)




      If tb1.TextFrame.ValidLinkTarget(tb2) Then

        tb1.TextFrame.NextLinkedTextFrame = tb2.TextFrame

      End If


      If tb2.TextFrame.ValidLinkTarget(tb3) Then

        tb2.TextFrame.NextLinkedTextFrame = tb3.TextFrame

      End If







    End Sub


    Function ShowStoryCount()

      MsgBox "There are currently " & _

        ActiveDocument.Stories.Count & _

        " stories in this publication.", , "Story Count"

    End Function

    There is no object in the Publisher object model that represents the overflow buffer for a specific story. Each TextFrame has an Overflowing property, however, that indicates whether text is overflowing from that text box into the overflow buffer. For linked text frames, only the final text frame can be overflowing.

    For a given story, the text in the overflow buffer is the difference between the End property of the final linked TextFrame in the story, and the End property of the Story object itself.

    For example, the following procedures retrieves the text in the overflow buffer. First, the code determines if the selected text box has overflow text. If it does, the procedure retrieves the text contained in the overflow buffer by using the Characters method. This method returns a TextRange object that contains the characters from the end of the text box TextRange object to the end of the Story object. The code then uses the Text property of the resulting TextRange object to return a string representing the overflow text, which it then displays in a message box.

    Sub GetOverflowText()

      Dim ot As String

      With Selection.ShapeRange(1).TextFrame

        If .Overflowing Then

          With .TextRange

            ot = .Characters(.End, .Story.TextRange.End).Text

            MsgBox prompt:=ot, Title:="Overflow Text"

          End With

        End If

      End With

    End Sub

    Also, each TextFrame object also has an AutoFitText property, which lets you set how you want Publisher to deal with overflowing text:

    ·         Allow the text to overflow

    ·         Reduce the text size so that the it fits in the text frame

    ·         Reduce or enlarge the text size so it fills the text frame

    The following text boxes cannot be part of a chain of connected text boxes: headers or footers, navigation bars, inline objects, personal information text boxes, text boxes already containing text, or text boxes set to automatically reduce text size.

    Finally, each TextFrame and TextRange object has a Story property, which enables you to access the Story object associated with a specific text frame or text range.

    The Publisher Story Object Model

    Figure 2 illustrates the structure of the Publisher object model surrounding the Story object. It also includes the TextFrame properties concerned with manipulating the text frames of a specific story.


    Figure 2. The Story Object Model Structure

  • Andrew May's WebLog

    Working with Publisher Wizards and Templates


    Note:   This is the second in a series of entries that aim to introduce experienced programmers to the Publisher object model. The first entry covered creating Web pages programmatically. You can read it here.

    Publisher has a different concept of templates and wizards than other Office programs, such as Word. In Publisher, both terms refer to publication types on which you can base your publications, with important differences:

    ·         Publication wizards are pre-defined publications that come bundled with Publisher. These publication wizards contain text boxes and other design elements that you can customize, and to which you can add your content, in the publications you create using them. Publication wizards also contain design automation options that enable you to quickly change the lay out and design of your publication.

    ·         Templates are user-created publications that you can save to use as the basis for creating other publications. If you save the template to a specific location, Publisher then makes it available as a template on the New Publication task pane in the application interface.

    Let’s examine each of these in detail.

    Using Wizards in Publisher 2003

    Publication wizards are one of the most powerful and versatile features in Microsoft® Office Publisher 2003. As mentioned above, wizards are pre-defined publication templates included as part of Publisher. Wizards enable you to quickly generate professional-looking publications in a wide range of formats, from invitations to flyers to catalogs to websites.

    When you create a publication using a wizard, Publisher populates the new publication with design elements based on the wizard type and design you choose. You can add your content to these elements, as well as customize the elements as you desire. You can change the appearance of the publication later by simply specifying a different design available for that wizard. The wizard then morphs the publication to adhere to that design scheme.

    In Publisher, morphing refers to an object’s ability (be it a shape, page, or entire publication) to change its appearance based on the user’s choice of design. Choose a different design, and Publisher automatically updates the object according to the design chosen.

    Some wizards generate multi-page publications, with different content and design options depending on the page. For example, a newsletter may include different design elements present on the front cover than on the interior pages.

    Unlike templates in applications such as Word, you cannot access or alter publication wizards themselves. However, you can create a user-defined template based on a publication wizard. In such a case, you can alter the template in any way you like, such as adding VBA code to the publication, and the template retains the morphing and other functionality of the wizard on which it is based. For more information, see “Working with Templates.”

    The Publisher object model lets you extend the design flexibility in publication wizards even farther by automating the generation and customization of publications based on wizards. Any publication created based on a publication wizard template has a Wizard object as the child of its Document object. If you create a publication based on a multi-page wizard template, the individual pages in the publication may have wizard properties that apply to only that page. In such a case, each Page object in the publication contains its own Wizard object as well. For more information on programmatically working with publication wizards, see Creating and Customizing Wizard Publications in Publisher 2003.

    But not only do publications and pages have wizard properties, but shapes do as well. Any shape that Publisher adds to the default appearance of a publication based on a wizard design has properties that uniquely identify it. Publisher uses these properties to keep track of shapes that ‘belong’ to the wizard design, as opposed to any custom shapes the user might add to the publication later. For more information, see Identifying wizard shapes in a publication.

    Note   Publisher also includes group wizard shapes, which are related to, but independent from, the publication and page-level wizards. Group wizard shapes are pre-defined group shapes, such as calendars, coupons or Web navigation bars, that contain design automation options. Unlike wizard publications, you can add group wizard shapes to any publication, whether or not it’s based on a publication wizard. Also, You set the design of each group wizard shape individually. For more information, see Working with group wizard shapes.

    Creating and Using Templates in Publisher 2003

    You can also create templates in Publisher. Templates are especially useful if you create certain publications, such as newsletters, flyers, or postcards, over and over again. Templates enable you to design master publications that reflect your company’s brand and identity; you can then use that template to create new publications, adding only the information that is unique to each publication.

    Publisher templates are simply publications saved to a specific user directory. Each time you launch a new instance of Publisher, the application makes the publications in that directory available as template on the New Publication task pane.

    To create a template, save your publication to the following user directory:

    Drive:\Documents and Settings\userName\Application Data\Microsoft\Templates

    Where Drive represents the computer drive letter, and userName represents the name of the user to whom you want to make this publication available as a template. If you want to make the template available to multiple users on the same computer, you must save the template to the above location in each user’s directory.

    Publisher displays available templates under Templates in the New Publications task pane. Because Publisher loads the available templates on launch, you need to open a new instance of Publisher to for the new template to be available. Even then, the new template is not displayed in any instances of Publisher launched before the template was saved.

    If you do not have any templates saved, the Templates folder does not appear on the New Publication task pane.

    To save a publication as a template programmatically, use the Document.SaveAs method, specifying the file location above in the Filename parameter. This is directly equivalent to selecting Save as type: Publisher Template in the Save As dialog box.

    The following function saves the specified document as a template:

    Function SaveAsTemplate(pub As Document, fileName As String)

      With pub

       .SaveAs fileName:= _

       "C:\Documents and Settings\user\Application Data\Microsoft\Templates\" _

          & fileName, _

          Format:=pbFilePublication, _


      End With

    End Function

    You can specify custom categories to group your templates. The custom categories are listed under Templates in the New Publications task pane. To do this, specify a category for the publication before you save it as a template. From the File menu, select Properties. On the Summary tab, enter a value for Category. If you do not specify a category for your template, Publisher displays it in a category named My Templates by default.

    Note   There is no way to programmatically set a publication's properties, such as Category, using the Publisher object model.

    Any Visual Basic for Applications (VBA) code contained in the template gets copied into any publications you later create based on the template.

    If you create a template based on a publication wizard, any publications you create based on the template retain the design automation functionality of the wizard.

    Publications based on a template retain no link to that template. Any changes you later make in the template are not propagated to any publications previously created from that template.

    Programmatically, work with templates as you would with any other Publisher files. There are no object model objects or properties specific to templates. For example, you cannot create a publication based on a template using the NewDocument method. In such a case, use the Document.Open method to open the template file directly, and then use the Document.SaveAs method to create a new publication based on the template.

    Making Macros Available in Publisher Templates

    As mentioned above, you cannot edit any of the publication wizards included in Publisher. You can, however, create a template based on a publication wizard. This template could include any code you wanted to make available for publications based on that publication wizard.

    However, because users employ a number of publication wizards to create a wide range of publication types, in many cases it’s not practical to make your macro code available through creating templates. If you had particular macro functionality you wanted to make available for all publication types, you would have to create a separate template with that code for each publication wizard. In such cases, it’s best to just create an add-in for Publisher and deploy your code that way.

  • Andrew May's WebLog

    Publisher 2003: Using the NewDocument and DocumentOpen Events


    I got an email the other day from a user who asked if the NewDocument event in Publisher actually worked. It does, but it is a little more complicated than you'd think. Read on.

    To enable event handling within a typical application, you create a new class module, and declare an Application object with events:

    Public WithEvents App As Publisher.Application

    Then, write your event handlers:

    Private Sub App_NewDocument(ByVal Doc As Document)

      MsgBox "You've created a new publication", , "New Pub Created"

    End Sub

    Finally, initialize the your object with the Application object:

    Dim pub As New Class1

    Sub Register_Event_Handler()

      Set pub.App = Publisher.Application

    End Sub

    Which is exactly what the user was doing. But whenever he created a new document, either through the user interface or programmatically, his NewDocument event handler was never invoked. The NewDocument event didn't seem to be firing.

    Actually, it was; he just hadn't hooked up his event handler to the right Publisher.Application object.

    Publisher is a single document interface (SDI) application; each document you have open resides in a separate instance of Publisher. Which means if you have an instance of Publisher that already contains an open document, and you open another document, you're actually launching another instance of Publisher first. That second instance of Publisher then opens the document, even though it looks like you're launching the document directly from the first instance.

    That's why his NewDocument event handler never fired. His code was watching the first instance of Publisher; but with a document already open in the first instance, any commands to create a new document actually launched another instance of Publisher, which is where the NewDocument event was raised.

    The same is true of the DocumentOpen event; if the instance of Publisher already contains an open document, then an additional instance launches, and the DocumentOpen event is raised in that second instance.

    The only time either event would occur in an existing instance of Publisher is if Publisher was open, but didn't have a document open. Which means you can't write VBA code in a document to have it watch it's own application instance for those events. By simple fact that the document containing the VBA code was open, additional instances of Publisher would be launched for any open or new document commands.

    You can, of course, use the DocumentOpen and NewDocument events from:

    ·         Another instance of Publisher

    ·         A Publisher add-in

    ·         Another application

    So let's create an example for the first bullet point, another instance of Publisher. The example below creates a new instance of Publisher, and initializes code to respond to events raised within that instance.

    First, create a new class module, and declare an Application object with events, as you would normally:

    Public WithEvents App As Publisher.Application

    Then, write handler procedures for all the application events to which you want to respond:

    Private Sub App_DocumentBeforeClose(ByVal Doc As Document, Cancel As Boolean)

      MsgBox "You are about to close: " & Doc.Name

    End Sub


    Private Sub App_DocumentOpen(ByVal Doc As Document)

      MsgBox "You have opened: " & Doc.Name, , "Document Open"

    End Sub


    Private Sub App_NewDocument(ByVal Doc As Document)

      MsgBox "You've created a new publication", , "New Pub Created"

    End Sub


    Private Sub App_WindowPageChange(ByVal Vw As View)

      MsgBox "Hey", , "Window Page Change Event"

    End Sub

    However, in the procedure that initializes your application object, set your variable to the application instance launched when Publisher opens a new document, not the application instance that contains the document with the VBA project.

    For example, the following code creates a new document, and initializes the pub.App variable with the resulting new instance of Publisher. The event handlers now fire when events are raised in that application instance. Calling the NewDocument method, as the next line of code does, actually results in two events: the DocumentBeforeClose event for the new document open in the previous line, and then the NewDocument event for the new document that replaces it.

    Dim pub As New Class1

    Sub InitializeNewPubInstance()

      Set pub.App = NewDocument.Application


    End Sub

    You could also create a new instance of Publisher using the New VB keyword. However, instances of Publisher launched this way are not visible by default; this enables you to launch Publisher and automate it without displaying it to the user. So you have to explicitly specify the application be visible, like so:

    Sub NewDocTest()

      Set pub.App = New Publisher.Application

      pub.App.ActiveWindow.Visible = True


    End Sub

    Now you event handler can respond to events the user raises in that Publisher instance, including DocumentOpen and NewDocument events. The event handlers I wrote simply pop up message boxes, but you get the idea. Just remember, those message boxes will appear in the Publisher instance running the code, not the Publisher instance actually raising the events.

    One last piece of house-keeping. We want to release the pub.App variable if and when the user closes that instance of Publisher. So let's create a procedure that does that, and place it in the ThisDocument project:

    Public Sub FreeApp()

      Set pub.App = Nothing

    End Sub

    And then call that procedure from the Quit event handler:

    Private Sub App_Quit()


    End Sub

    On a related note, did you know it's impossible to programmatically arrive at a Publisher instance that doesn't have a document open? The New keyword launches a new instance of Publisher, with a new blank publication open. The Document.Close method closes the current publication, but then opens a new blank publication in it's place. There is no way to launch Publisher without also opening a publication. Likewise, there is no way to programmatically close the current publication without either also closing Publisher, or getting a new publication in its place. To get an instance of Publisher without an open publication, you have to go through the user interface.

  • Andrew May's WebLog

    Creating Web Pages with the Publisher Object Model


    You know, sometimes it's the obvious things you miss. I was meeting a few days ago with the programmer-writer who is taking over writing Publisher developer help for the next release. I was giving him a guided tour of the Publisher object model, and I thought "you know, this should really be written down somewhere."


    I had written an entire series for beginning developers on how to get started with the Publisher object model. But somehow I had never gotten around to writing an article that contained the things an experienced programmer would want to know if they were coming to the Publisher object model—and perhaps Publisher as a whole—for the first time.

    So I've decided to see if I can't write a series of entries here that address the issues an experienced programmer would encounter as they ramp up on the Publisher object model. With any luck, I'll be able to roll them into an actual article somewhere down the road.

    Here's the first of those topics. It's a snappy little number I like to call:

    Creating Web Pages with the Publisher Object Model

    You can create web pages with Publisher 2003. In Publisher 2003, there are two types of publications: print publications, and web publications. A web publication represents a group of web pages. Each publication page corresponds to a single web page. You create and design the pages within Publisher as you would a print publication. When you have finished designing your web publication, you publish the file to the web.

    You can also publish a print publication to the web; however, the appearance of the Web pages may differ from the printed publication.

    When Publisher publishes a publication to the web, it creates an HTML representation of each page in the publication, and then saves those HTML files, along with any necessary supporting files, to the specified URL location.

    The HTML files that Publisher publishes have no link to the original Publisher file used to generate them. If you later need to make changes to the web pages, do not edit them directly. Rather, make your changes to the original Publisher web publication, and then re-publish the file to the same URL location. Changes made to the HTML directly are not propagated back to the original web publication; indeed, if you do edit the HTML, and later re-publish the Publisher file, your changes are overwritten.

    By default, Publisher treats the first page in the publication as the initial page in your web site. By default, Publisher saves the HTML file representing the first publication page as 'index.htm'. Publisher saves the HTML pages for any other publication pages, as well as any support files (such as image files), in a folder called 'index_file', located in the same directory as the index file. If you do not specify the file name for an HTML file, Publisher generates a name for it automatically.

    To determine if a publication is a print or web publication, use the Document.PublicationType property. To convert a print publication to a web publication, or vice versa, use the Document.ConvertPublicationType method. Note that this overwrites the previous version of the file.

    To publish a file to the web, use the Document.SaveAs method. For the Format parameter, specify pbFileHTMLFiltered. For the FileName parameter, specify the URL location to which you want to publish the file. This corresponds to choosing the Publish to the Web command from the File menu. Note that the .htm file extension is automatically added to the value of the Filename parameter if the value of the Format parameter is pbFileHTMLFiltered.

    This example saves the active Web publication as a set of filtered HTML pages and supporting files. In this example, Publisher names the HTML file representing the first publication page after the original web publication name. (Note that URLPath must be replaced with a valid file path for this example to work.)

    With ActiveDocument

        .SaveAs Filename:="URLPath" & .Name, Format:=pbFileHTMLFiltered

    End With

    Note   The pbFilePublicationHTML value of the Format parameter represent an HTML file format available in Publisher 2002 that enabled re-importation of the HTML Publisher generated. Because of the resulting large file size, however, this file format has been deprecated and should not be used.

    If you specify pbFileWebArchive for the Format parameter, Publisher generates an .mht file. An .mht file is an HTML file that has all of its support files, such as images and other files, embedded in it.

    If you later make changes to the web publication and need to re-publish it, simply use the SaveAs method with the same file path specified. This overwrites the existing HTML files; no warning is given.

    To generate a preview of a web publication, use the Document.WebPreview method. This method generates a local HTML copy of the publication, and displays it in the users default browser. The Web preview opens with the active page displayed. Preview Web pages are generated for each page in the publication. However, if the publication is a print publication or otherwise lacks a navigation bar, there may be no way to navigate to those pages.

    The following example sets the active page of the publication and generates a Web preview of the publication.

    With ActiveDocument

        .ActiveView.ActivePage = .Pages(2)


    End With

    Publisher 2003 includes pre-defined web navigation bars that you can include in your Web publication. For more information on how to use web navigation bars programmatically, see Adding Navigation Bars to Web Publications in Microsoft Office Publisher 2003.

    To specify settings for the web publications you create, use the WebOptions object. This object contains properties that represent settings that newly created Web publication inherit, such as encoding and font options. When you modify any of these settings, any Web publications you create inherit the modified properties.

    For example, if you need to re-publish a large Web publication, you might want to set the EnableIncrementalUpload to True. This specifies that only changes made to a publication will be uploaded to the Web server when published, rather than the entire publication. The EnableIncrementalUpload property applies only to Web publications that have already been published to a Web server. If a Web publication has not already been published to a Web server, the entire publication will be published to the server during the initial publishing process, regardless of whether the EnableIncrementalUpload property is set to True.

    The WebOptions object settings are application-level settings specific to each user.

    To specify web properties for a specific page, use the WebPageOptions object. This object contains properties that represent web characteristics of the specified publication page, such as background sound, page description, and whether to include the page on new web navigation bars. To specify a file name for the HTML file generated from a publication page, use the WebPageOptions.PublishFileName property. As mentioned earlier, specifying a file name for a Web page is optional. When a publication is saved as filtered HTML, Publisher automatically generates file names for any Web page that does not have a file name specified. User defined file names are only used when a publication is saved as filtered HTML. File names must be specified without a file extension.

  • Andrew May's WebLog

    Windows Server 2003: Screen Resolution Weirdness


    Here's the second of two tips my manager shared with me concerning installing Windows Server 2003.

    The first tip dealt with being unable to connect to the Internet.

    This tip deals with screen resolution, and has a very strange workaround.

    After installing WS2003, he had a problem with his screen resolution: he could only set it as far as 256 colors, and 1024 by 768 pixels. He spent a fair amount of time talking to the Help Desk, and messing with the video adapters and drivers, to no avail.

    (To see what resolutions your adapter supports: On the Start menu, point to Settings and click Control Panel, and then click. the Display icon. On the Settings tab, click the Advanced button. On the Adapter tab, click List All Modes. Windows displays a list of the resolutions which the adapter you're using supports.)

    Finally, here's the workaround he stumbled on:

    1.      On the Start menu, point to Settings and click Control Panel.

    2.      Double-click Regional and Language Options.

    3.      On the Languages tab, select the Install files for East Asian languages, and then click OK.

    4.      Follow the steps to install the East Asian language support and reboot your system.

    And that did the trick.

    Someone else suggested that perhaps his adapter was too new to be included in the WS2003 distribution, so it used a generic driver which was replaced by the language upgrade. If anyone's got any other theories, I'd love to hear them.

    In any case, now his screen resolution is a comfortable 32-bit color quality and 1600 by 1200 pixels.

    And he can write things like 度主ありが十ございます

  • Andrew May's WebLog

    Windows Server 2003: Unable to Connect to the Internet


    A few months back, when I first moved over to working on Windows SharePoint Services, I decided to turn one of my work computers into a WSS box. I later decided to install a Virtual PC profile on the machine instead. But my new manager forwarded me a few tips concerning issues he'd run into when he initially installed Windows Server 2003. These were things that the Help Desk was, well, less than helpful in fixing.

    So I thought I'd put them out here, in case someone with the same problems runs across them.

    Here's the first:

    Once he had Windows Server 2003 installed, he couldn't connect to the Internet at all. What's more, anytime he browsed to an intranet site, he was prompted for his username and password for each site the master page was linking to.

    Turns out he needed to adjust his internet security configuration. Here's how:

    1.      On the Start menu, point to Settings and click Control Panel.

    2.      Double-click Add or Remove Programs.

    3.      Click Add/Remove Windows Components.

    4.      In the Windows Components Wizard, de-select Internet Explorer Enhanced Security Configuration and then click Next.

  • Andrew May's WebLog

    John Durant Moves On


    If you've read his blog lately, or visited the Office Developer Center front page, then you know that John Durant has relinquished the reins at the ODC, in order to become a program manager for Visual Studio Tools for Office.

    I've worked with John for the better part of two years now, and count myself lucky to have done so. John has been a huge influence on my development as an Office programmer. He was always available for a quick tutoring session on the programming topic of the day, and his enthusiasm for diving into new APIs and finding out what made them tick was great encouragement for someone like me, for whom any API was a new API. His faith that I could become a successful Office programmer-writer is a large part of the reason I am a successful Office programmer-writer.

    So I wanted to take a moment and add my personal thanks to the chorus of praise he's been getting this week, and to wish him the best in his new role.

    Below is a sketch I did of John in his bike gear, for the ODC portal page. We were waiting to run it this spring, so we never got to use it. (Yes, I know that John bikes year 'round in any weather. But we figured we'd wait to use it at a time of the year most sane people equate with biking-ride weather.)

    Ride on, brother.

  • Andrew May's WebLog

    Rock Thought for the Day: Garbage


    At the risk of further poaching on John Durant's turf, it turns out I have another Rock Thought of the Day® to share:

    Garbage's new CD, Bleed Like Me, is out today. At first listen, you'd never know the band's been gone for the past five years. It sounds much like business as usual. And that may be part of the problem: four CD's in, I had hoped to hear the band move beyond the territory they staked out with their first three efforts. This time around, they've gone for a rougher sound: the guitars are louder, the song hooks buried, and Shirley Manson's vocals filtered in many places until they sound like she's singing through a drive-thru window speaker. But for all the surface changes, the music doesn't really incorporate any new influences, present any new ideas, or ever take any unexpected turns. (As much as I like the title track, it takes you about a verse and a half to realize they're doing an intentional riff on Lou Reed's Walk on the Wild Side.) Granted, I've listened to the CD a grand total of two times, so I reserve the right to change my opinion. But at first blush, there's not much here to reach beyond the die-hard Garbage fan.

    Money For Nothing

    I was actually supposed to see Garbage last Friday here in Seattle, at the opening show of their American tour. I was jazzed, to say the least: I've seen them twice before, and thoroughly enjoyed both shows. Add to that the fact that we'd be hearing their new material before the CD was even released, and I was looking forward to a special night.

    Unfortunately, the band, fresh from a European promotional tour, got sick and had to cancel at the last minute.

    Which is understandable; it happens. And at forty dollars a ticket, you don't really want to see a sick band limp through a show, do you?

    What's not so understandable, is the fact that no one knew anything about whether the show was cancelled, postponed, or happening the next night. We were originally told by the Paramount staff that the show might be moved to Saturday night, and to call TicketMaster or listen to The End, which promoted the show. Except TicketMaster refused to confirm or deny anything. And the DJ on The End couldn't find out any information either, even though he'd been inundated with calls from people like us all day Saturday. (The Paramount ticket office is open bankers' hours during the week, so no help there.)

    Finally, late Sunday, TicketMaster sent out an email saying the show was cancelled and that you could return your tickets for a refund—minus 3.35 USD per ticket, which TicketMaster decided it was keeping.

    Now, it's bad enough that TicketMaster's "service fees" amounted to a 28% tax on the tickets to begin with (30.50 USD per ticket, plus 8.50 USD per ticket service fees). But to keep 3.35 USD per head for a show that didn't even happen? When did that become acceptable? The Paramount has 2807 seats; so, for the sold-out Garbage show, TicketMaster pocketed 9403.45 USD—nearly ten grand from Garbage fans who got exactly nothing in return.

    For my little party of 4, we ended up donating 13 USD to TicketMaster—just about the cost of a new Garbage CD.

  • Andrew May's WebLog

    OneNote: Importing Pages that Vanish


    Here's an interesting little "gotcha" that was found by Saul Candib, the programmer-writer who is taking over documenting OneNote programming features, now that I've moved over to SharePoint.

    Using my article Importing Content into OneNote 2003 SP1 as a guide, Saul wrote some code that imported content into OneNote. The code seemed to work fine: OneNote would create the page the user specified, and import the specified content no problem.

    Except, once you closed OneNote, when you opened it again the page and all its contents were gone.

    Turns out Saul wasn't specifying the '.one' file extension for the page. So the import routine worked perfectly; OneNote created the page and imported the content. You could even go in and add or edit the content on the new page, whatever you wanted. OneNote actually was saving the page in the My Notebooks folder, but without an extension. So the next time you launched OneNote, it saw the imported page as an unknown file and so didn't load it.

    All of this was news to me. In my XML examples in the article, I used the .one file extension. For example:

    <PlaceObjects pagePath="MSN Instant Messenger\" pageGuid="{8FDD3C41-5BB5-4595-B019-7E7E9BC9D38E}">

    But I never specifically called out that this was a requirement; to be honest, I don’t remember if I ever realized it was a requirement. I certainly never experimented with what happened if I didn't specify the file extension.

    What's worse, in my example in the article, I wrote a really basic application that let the user enter the name of the page they wanted to create. But I didn't write any code that checked the specified page name to make sure it contained the file extension, or add the extension if the page name didn't. Shame on me.

  • Andrew May's WebLog

    Rock Thought for the Day


    So here it is, the next to last day of March, and I haven't blogged all month. Truth is, I've been working long and hard on some internal documentation for the next version of Office. Which of course, as cool as it is, I can't talk about. Hence the lack of blog entries lately.

    I noticed the other day that my friend and office neighbor, John Durant, mentioned I was listening to Everlast in one of his blog entries. (Luckily, he wasn't around earlier when I was blasting The Magnetic Fields for all to hear. John's a meat-and-potatoes rock and roll kind of guy; I'm not sure he would have understood.) Now, John and I regularly talk music, and I notice he ends all of his blog entries with a 'Rock Thought for the Day', and that got me thinking.

    So here, in honor of John Durant and my lack of blog ideas, is my very own Rock Thought of the Day®.

    (Rock Thought of the Day ™ and ® 2005 John R. Durant)

    Not to sound like I'm channeling Andy Rooney, but here's something that's always annoyed me: greatest hits collections that include new songs. Leave aside that by the very fact of it being previously unreleased, the new song cannot be a greatest hit, and therefore does not belong on the collection to start with. What really gets mine in a bunch is the thought process behind including the songs in the first place: let's put the screws to the artist's most loyal fans and squeeze as much money out of them as we can. Doesn't really sound like the aesthetic rock and roll is founded on, now does it?

    Greatest hits collection are by definition aimed at the casual fan, someone who's mainly interested in an artist's (commercial, if not artistic,) high points. If you're a dedicated fan of an artist, you've already got everything likely to appear on that artist's greatest hits collection. So how to get those fans to shell out cash for a collection of material they've already got? Simple, just put on a new song or two, even if those songs are just lame covers, or if putting those songs on leaves less room for the legitimate hits the collection purports to collect.

    And let's be honest, these songs almost always suck. In fact, in the entire history of greatest hits collections, I can only think of two new songs that deserve to take their place alongside the artist's greatest hits:

    ·         Under Pressure, which originally appeared on Queen's Greatest Hits.

    ·         Mary Jane's Last Dance, from Tom Petty's Greatest Hits collection.

    That's it. All the others range from decent songs in their own right (such as Wrong Number from the Cure, or This Hard Land from Bruce Springsteen), to workmanlike but perfunctory (Walk Tall by John "Don't Call Me Cougar" Mellencamp) to downright awful. With most belonging to the last category.

    So, as a fan, you get to contemplate spending fifteen bucks for 14 songs you already have, just to get one probably-mediocre song you don't have. Leaves you with a warm feeling toward that artist, doesn't it?

    (One of the worst offenders at this sort of thing is an artist whose work I thoroughly enjoy, and whose ethics and generosity in most other areas I greatly admire: Bruce Springsteen. Springsteen released a greatest hits collection with three new songs on it, but lacking any songs from his first two albums: no Blinded By the Light, no Growin' Up, no E Street Shuffle, no Rosalita, for God's sake. He recently released The Essential Bruce Springsteen, a three-disc greatest hits collection that includes a disc of mix-and-match unreleased songs and live versions. So, if you're a die-hard Springsteen fan, you've bought songs like Born to Run three times, simply to get the unreleased material. And it gets worse: Springsteen released a five-CD (!) set of unreleased tracks, called, well, Tracks. Which was wonderful, except that he then released a best-of collection from the set, called 18 Tracks. Which had three unreleased songs not included on Tracks.)

    Today's assignment: Track down Gordon, by Barenaked Ladies, and listen to Boxed Set. Twice.

  • Andrew May's WebLog

    OneNote XML Schema Map Notation, Take Two


    So, I was so annoyed when I realized I had broken one of the basic rules of information design with my diagram of the OneNote 2003 SP1 SimpleImport schema, I had to take a few minutes and see if I could fix it. As I mentioned in my last entry, my diagram uses indenting and boxes to show the element hierarchy in the OneNote schema. But, because I was illustrating the same information (the element hierarchy) two different ways (indenting and boxing), the diagram contained redundant information, and was more complicated than it needed to be.

    And I hated those damn boxes anyway. Chopping a diagram up into a grid like that only ends up distracting from the information. I knew it at the time, but I was on a deadline and couldn't come up with a better solution, so…

    Below is my latest attempt. The grid lines are gone; element hierarchy is denoted now solely by the indenting of the element names. By formatting the information inside each element (such as data type and attributes) gray, I think I've been able to keep the element names prominent enough I don’t need boxes to denote where one element ends and another starts.

    One thing that I still see as problematic is the indenting of the element information, like the data type and attributes. In this small example, I was able to keep all that information at the same left-alignment for all the elements, which again keeps that information from distracting from the element names. But, had the schema hierarchy included a few more levels, I would've had to move the element information even further over, perhaps to the point where it was so far removed from the element names in the top-level elements that it would seem disconnected.

    All in all, I think this diagram is quite a bit more successful than the one that currently appears in the article. Looks like it's time to file a bug and get that image swapped out…

  • Andrew May's WebLog

    Know Any Good Object Model and XML Schema Map Notations?


    Now that I've told you how I create the technical illustrations I use in my blog entries and MSDN articles, I have a question for you:

    Anybody got a decent notation for diagramming object models or XML schemas?

    I've been looking around, and I don't really see any. As for what I'm using in my articles, well…I've pretty much been making it up as I go along.

    Detailing discreet sections of a COM object model is fairly straight-forward. All you really have to keep track of are objects, members, events, and enumerations. But when I was trying to diagram how Donovan's OneNote SimpleImporter classes were structured, I wanted to include inheritance, as well as both public and private members (with appropriate scope noted). So I ended up with a legend that looked like this:

    Take a look at the finished diagrams in this entry.

    For the most part, this seems to have worked. But I have to think that someone else out there has tackled this problem. Someone with a lot more experience and talent in technical illustration.

    I'm especially interested in how (or if) people are diagramming XML schemas. Here's the notation I used to diagram the OneNote SimpleImport XML schema:

    But, as you can see, it gets pretty complicated pretty quick, even with a relatively short and straight-forward schema like SimpleImport:

    Also, it doesn't show other schema information, such as the maximum/minimum times an element can/must appear. This information wasn't really important in this particular example, but I can see cases where it would be.

    I hate that everything is in a grid, which makes it hard to read. I tried an alternate version of this, with shaded block rather than grid lines, but the results weren't any better. In fact, now that I look at it again, because I both indented the elements and separated them in boxes, I broke a basic rule of information design: I used two design schemes to denote the same information (the element hierarchy), thereby making the diagram more graphically complex than it needed to be.

    That's the problem with producing content on a deadline. But I'm sure this won't be last time I need to diagram an XML schema for an article.

    So, anybody got any better suggestions?

  • Andrew May's WebLog

    Creating Object Model and XML Schema Maps


    Several people have asked what program(s) I use to create the object model maps and other technical illustrations I use here on the blog and in the articles I write.

    Unsurprisingly, I use Visio. Granted, I may be biased, having worked on the product for several years, but I haven't found any other drawing tool that lets me create, connect, and re-use custom shapes and design elements as easily as Visio does.

    Now here's the bad news: while Visio can dynamically generate class structure diagrams from source code, all the object model maps you see in my blog entries and MSDN articles were created the old-fashion way, one shape at a time.

    I do it by hand because I want to control the focus of the illustration and what information it includes. Most of the time I only want to illustrate part of an object model or class library, and need to be very selective about the information I want to highlight. I tend to do a large amount of tweaking and massaging to the diagram, for both informational and aesthetic reasons. All in all, it's quicker for me to just start with a blank page and fill it manually, rather than have Visio generate an automated diagram and have to then delete most of it and fold, spindle, and mutilate what's left.

    To create the final gif image, I turn off the grid, rulers, and connection points in Visio, and then simply take a screen shot of the image (granted, this doesn't work if your diagram is larger than your monitor display, but MSDN has image size restrictions anyway, so that's not an issue for me.) Just hit ALT + PrintScreen; this puts a bitmap image of the active application onto the clipboard. Once I've got the screen shot, I paste it into Photoshop, crop as necessary, and save it as a gif file. I use Photoshop for two reasons:
    a) I already have it loaded on my computer, so I'm familiar with it
    b) It's got the best 'save as gif' conversion I've found. I've used a few other image editors, and when I save the bitmap image as a gif in them, the image tends to degrade: color gradients become grainy, and text loses crispness. Not with Photoshop; I just accept the default conversion settings, and I have yet to be disappointed.

    Now, using Photoshop for saving screen shots as gifs is like using an elephant gun to hunt squirrel. Since I already have Photoshop, I haven't really looked around for another application that does this well. But if you poke around the web a little, you can probably find something that works just as well for this purpose, either as shareware or at least without Photoshop's hefty price tag. Just look for something that's been optimized to create web-ready graphics.

  • Andrew May's WebLog

    OneNote: An In-Depth Look at the OneNoteImporter Managed Assembly (Part 5 of 5)


    In this series of entries, we're taking an in-depth at the OneNoteImporter manage class, which provides an object model interface for the programmability functionality added in OneNote 2003 SP 1.

    Read part one here.

    Read part two here.

    Read part three here.

    Read part four here.

    Object Model Maps

    The following figures diagram the OneNoteImporter assembly object model, including abstract classes and inheritance. The diagrams mainly document how the objects in the assembly relate to each other. In most cases, when a member takes an object as a parameter, or returns an object, that object is included on the diagram. Value types, such as string or integers, are for the most part not displayed.

    For the sake of clarity, the following object information, pertaining to methods that most of the classes have, has been left off the diagrams:

    ·         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 object suitable for use in hashing algorithms and data structures like a hash table.

    ·         Inheritance from System.Object is not shown.

    Figure 2. The Application Object (and Legend)



    Figure 3. The ImportNode Abstract Class, and Page Class

    Figure 4. The PageObject Abstract Class, and Derived Classes

    Figure 5. The OutlineContent Abstract Class, and Derived Classes

    Figure 6. The Data Abstract Class, and Derived Classes


    The OneNoteImporter managed assembly provides a convenient and multi-functional ‘wrapper’ for working with the SimpleImporter and command line functionality in OneNote 2003 SP1. Moreover, using the provided source files for the assembly, a developer can customize and extend the classes as required for his particular application.

  • Andrew May's WebLog

    OneNote: An In-Depth Look at the OneNoteImporter Managed Assembly (Part 4 of 5)


    In this series of entries, we're taking an in-depth at the OneNoteImporter manage class, which provides an object model interface for the programmability functionality added in OneNote 2003 SP 1.

    Read part one here.

    Read part two here.

    Read part three here.

    Figure 1 diagrams the internal method calls of the Commit method. It shows the OneNoteImporter classes and methods called, and the Import XML elements generated at each step. The various calls to System.Xml methods are not diagrammed.


    Figure 1. The Page.Commit Method, and XML Elements Generated

    In our final entry, we'll look at some object model maps that detail how the OneNoteImporter class is structured.

    Read part five here.

  • Andrew May's WebLog

    OneNote: An In-Depth Look at the OneNoteImporter Managed Assembly (Part 3 of 5)


    In this series of entries, we're taking an in-depth at the OneNoteImporter manage class, which provides an object model interface for the programmability functionality added in OneNote 2003 SP 1.

    Read part one here.

    Read part two here.

    Importing Objects into OneNote

    The actual creation of the XML import document, and importing the page contents, takes place when you call the Page.Commit method. This method, in turn, invokes a number of methods in other OneNoteImporter objects. Because of this method’s importance and complexity, it’s worth examining how the method functions.

    First, the code checks to see if the page has changed in any way from the last time it was imported. It does this by determining if the Page object’s CommitPending property is set to True. If it is, it calls the SimpleImporter.Import method.

    The code calls the Page.ToString method to generate the XML string it passes to the Import method. The ToString method in turn calls the Page.SerializeToXml method.

    This begins a series of recursive calls to the SerializeToXml methods of the various objects. Each object’s SerializeToXml method includes instructions to call the SerializeToXml method of any child objects, and append the resulting XML to the parent element. This in turn invokes the SerializeToXml method of any child objects the original child object might have, and so on, until the entire page structure has been serialized to xml in a single xml document.

    The Page.SerializeToXml begins by creating a new XmlDocument object, and generating <Import> and <EnsurePage> elements and adding them to the document. Page object property values are used to set the various attributes of the <EnsurePage> element.

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

    The code then generates a <PlaceObjects> element. For each of the Page object’s children whose CommitPending property is set to True, the code calls the PageObject.SerializeToXml method.

    If the page object’s DeletePending property is set to True, the PageObject.SerializeToXml method generates a <Delete> element. If not, the method does three things:

    ·         Generates a <Position> element, whose attributes are set according to Position object property values.

    ·         Calls the SerializeObjectToXml method for the specific PageObject-derived class involved, i.e., ImageObject, InkObject, or OutlineObject.

    ·         Calls the SerializeToXml method for the specific OutlineContent-derived class involved, i.e., HtmlContent, InkContent, or ImageContent.

    Executing the SerializeToXml method for each of these content types includes a call to the SerializeToXml method for the Data-derived object they contain: BinaryData, FileData, or StringData. In this way, the entire page structure is serialized to xml in a single xml document.

    Note that the HtmlContent.SerializeToXml method includes a call to another internal method of that same object, called CleanHtml. The CleanHtml method reads through the html string or file data and makes sure the HTML is formatted in a way that OneNote accepts. It identifies and replaces problematic formatting with characters which OneNote can process. For example, the CleanHtml method wraps the HTML string with the appropriate <html> and <body> tags if the HTML lacks them.

    The serialization of the page nodes is now complete. If the Page object had no children, the <PlaceObjects> element remains empty. In such a case, the Page.SerializeToXml method does not append it to the <Import> element.

    Finally, the Page.SerializeToXml method determines the appropriate namespace designation and adds it to the <Import> element.

    The ToString method then takes the XmlDocument object, saves it as a text stream, converts it to a string, and passes it back to the SimpleImporter.Import method. This Import method uses the XML string to import the specified content into OneNote.

    Now that the content has been imported into OneNote, the Commit method performs some vital housekeeping. Using the RemoveChild method, it removes any of the Page object’s children who have their DeletePending property set to True. It then sets the private committed field to True, thereby making the Date, PreviousPage, RTL, and Title properties read-only. You cannot change these attributes once you import a page into OneNote.

    Lastly, it sets the CommitPending property of the Page to False. This it turn sets the CommitPending properties of all the Page object’s remaining children to False as well.

    In part four, we'll examine the internal method calls of the Commit method.

    Read part four here.

Page 2 of 5 (108 items) 12345