Smart Documents Made Easier for .NET Developers

 

Susan Warren
Keith Craig
Vertigo Software, Inc.

May 2004

Applies to:
     Microsoft® Office 2003 Editions
     Microsoft Visual Studio® .NET 2003

Summary: Smart documents are a powerful application paradigm, but don't natively take advantage of the object-oriented, event-driven nature of .NET-based languages. This article describes the Vertigo Managed Smart Documents Wrapper, a managed wrapper and set of Microsoft Visual Studio .NET 2003 project templates that make developing smart documents using .NET-based languages easier and more cost effective. The Managed Smart Documents Wrapper is a free download from Vertigo Software, Inc. (20 printed pages)

The Vertigo Managed Smart Documents Wrapper is available at the Vertigo Software company Web site.

Contents

Introduction
Smart Document Basics
Creating a Managed Smart Document Using Visual Studio .NET
A Quick Test Drive of a Managed Smart Document
A Peek Under the Hood
Customizing the Smart Document
Debugging a Smart Document
Getting Fancy: Control Arrays
Conclusion

Introduction

I am in love with the user experience for smart documents. They do an amazing job of making document-centric tasks smoother and more productive by integrating data, processes and help right where the knowledge worker lives in Microsoft® Office Word 2003 or Microsoft Office Excel 2003. When I first saw smart documents, it was one of those "Ah-ha!" moments: instead of building, deploying, supporting and training users for yet another new application, put the application smarts right into the documents themselves. Ah-ha, beautiful idea!

But I am also a true believer in object-oriented, event-driven programming for business productivity applications. The reason is simple: it's significantly cheaper to develop, debug and maintain an application written in event-driven, managed code. Soon after my epiphany, we received a request from a client to develop a smart document solution and I dived head first into smart document development excited to get a chance to use this powerful new application paradigm. It did not take long for me to realize that implementing a smart document meant writing procedural, not object-oriented, code. Not fun.

Together with co-developer Will Allan and co-author Keith Craig, I set out to create a set of classes and tools that make smart document development easier and more productive while preserving that low cost of ownership we've become addicted to with .NET-based development. This article introduces our solution, the Vertigo Managed Smart Documents Wrapper, and gives a quick tutorial for getting started with smart document development using Microsoft Visual Studio® .NET 2003.

The Managed Smart Documents Wrapper supplies some of the missing links for smart document development in the .NET-based environment. The most significant component and the place where my ASP.NET roots really show a managed wrapper for the procedural ISmartDocument interface. The wrapper supplies the "plumbing" to satisfy the inner workings of the interface as a base class to the document's code-behind class, called ConfiguredSmartDocument. It reads the layout and event wire-up for elements in the document's task pane from a XML configuration file. ISmartDocument's programmability hooks are exposed as events you can handle in the document's code-behind class.

Another significant part of the Managed Smart Documents Wrapper is a set of new Visual Studio .NET 2003 project types for creating both Word and Excel smart documents in Microsoft Visual Basic® .NET and Microsoft Visual C#® development language. As you'll see, a smart document solution is composed of several interdependent files. The Visual Studio .NET projects create a working starter solution that makes managing these files and the dependencies between them easier.

Note   The next version of the Visual Studio Tools for the Microsoft Office System (beta: July 2004; targeted availability: first-half 2005) will provide even more powerful task pane customization for creating smart documents.

Here are the pieces installed with the Vertigo Managed Smart Documents Wrapper.

  • .NET-based wrapper library for the ISmartDocument interface
  • New Visual Studio .NET 2003 projects for creating managed smart documents in Visual Basic .NET and C#
  • Visual Studio .NET statement completion schemas for smart document Manifest files and XML configuration files
  • Full source for the wrapper library in a Visual Studio .NET C# project
  • A sample that demonstrates using the wrapper library
  • Documentation

We'll walk through creating a managed smart document later in this article but first, let's review the basics of smart documents briefly.

Smart Document Basics

Smart documents are documents in Word 2003 or workbooks in Excel 2003 that are associated with an XML schema so data in a document, rather than just being a paragraph or range of cells, have contextual identities. For example, rather than identifying a cell as Sheet1!C34, it would be much more valuable to know that the cell contains the entertainment expenses for an expense report. Context-specific logic and user interaction is the other part of a smart document solution. When the user selects the entertainment expenses cell, the smart document can display information and actions in the task pane that specifically pertain to policies regarding entertainment expenses.

The Anatomy a Smart Document

The document and XML schema are just two of several files in the smart document solution; additional files support securing, deploying and updating the code behind the smart document. A smart document solution is composed of the following files:

  • Smart document. Word document or Excel spreadsheet.
  • Schema file. XML schema file that defines the meaningful regions of the document.
  • Action handler code. The .NET-based assembly (DLL) that implements the ISmartDocument interface and handles the user's interactions with the task pane.
  • XML expansion pack manifest file. An XML file that that specifies the identity and location of component files that are necessary to fully enable a specific smart document solution.

In addition, the Managed Smart Documents Wrapper adds the following files:

  • SmartDocumentWrapper.dll. The .NET-based assembly containing the wrapper classes.
  • Configuration.xml. An****XML file that defines the layout and functionality of the task pane using a declarative XML syntax.

These files are shown in Figure 1.

Figure 1. Expansion pack files

For more detailed information about smart documents, I recommend looking at the SDK documentation: Office 2003 Smart Document Software Development Kit (SDK).

Creating a Managed Smart Document Using Visual Studio .NET

In his article The Definitive "Hello World" Managed Smart Document Tutorial, John Durant does an awesome job of describing how to create a managed smart document from scratch interacting directly with the ISmartDocument interface, with a lot of nitty-gritty detail. It's very useful information for any developer creating smart documents in a .NET-based environment, and I recommend you give it a read.

But here let's walk through doing with the library and project templates installed with the Managed Smart Documents Wrapper.

A Quick Test Drive of a Managed Smart Document

When you install the Managed Smart Documents Wrapper, new Visual Studio .NET 2003 project templates are added for creating managed smart document projects using the wrapper assembly. Templates are provided for both Visual C# and Visual Basic .NET, for both Word and Excel documents.

To take a quick test drive of managed smart documents, follow these five steps:

  1. Open Visual Studio .NET 2003. On the File menu, point to New, and click Project. The new project dialog opens:

    Figure 2. New projects dialog box with smart document projects

  2. Select the project type, fill in the project name (which is a bit tricky to change later) and the location, and then click OK. The project opens with the following files in the Solution Explorer:

    Figure 3. Files in a newly created smart documents project

  3. Press F5 to start the project compiles, and Word opens with the SmartDoc.doc document:

    Figure 4. Word template document before attaching expansion pack

  4. At this point, the expansion pack is not attached to the document the document is not "smart" yet! Follow the instructions in the green help text in the file to attach the expansion pack, and the Document Actions task pane appears (at this point, the smart document is now running):

    Figure 5. Word template document after attaching expansion pack

  5. Click Click Me! in the Document Actions task pane to display a simple message box:

    Figure 6. Word template document after clicking the button

That's it!

The new project templates did most of the work behind the scenes they automatically created:

  • XML manifest file. Manifest.xml lists the files that are part of the expansion pack.
  • XML schema file. The DocumentSchema.xsd file is used to describe the logical structure of the document. Sample sections are included, with comments on how to extend it.
  • XML configuration file. Configuration.xml defines the Document Actions task pane controls and their attributes using a simple markup language. It includes sample Document Action sections, with sample controls.
  • Code-behind code class. The OfficeCodeBehind class derives from the class that wraps the ISmartDocument interface: ConfiguredSmartDocument. The class includes event handlers to load and initialize the smart document, and sample control event handlers that demonstrate how to handle smart document control events.
  • Smart document. This is a Word 2003 document or Excel 2003 workbook, depending on the project template selected. The document includes help text about how to attach the expansion pack to the document.

In addition, the project template configures debugging and code access security for the project.

  • Debugging. Pressing F5 launches the smart document in Word or Excel, and configures the working folder to be the one containing the Manifest.xml file.
  • Code access security. A command file is created and customized at project creation time, and automatically executed. It configures URL-based code access security for the project. It is also added to the project and commented for later use and possible modification.

A Peek Under the Hood

Now let's take a peek under the hood and see how the smart document you just created works. Looking at the code, the following section of the Configuration.xml file defines the button:

<DocumentAction ActionXmlType="actionPertainsToEntireSchema" 
                PaneCaption="Entire Schema Section">
    <Control Name="Button1"
             Type="C_TYPE_BUTTON"
             Caption="This caption gets replaced and is never used!" 
             OnSetCaption="Button1_SetCaption"
             OnPreRender="Button1_PreRender"
             OnAction="Button1_Action" />
    <!-- TODO: Add additional controls here if desired. -->
</DocumentAction>

The <Control> tag is wrapped in a <DocumentAction> tag. The <DocumentAction> tag defines the control set for a given ActionXmlType —basically a logical section of the document. In this case, the "actionPertainsToEntireSchema" value means that controls in this <DocumentAction> section appear at the top of the Document Actions task pane regardless of the current selection position in the document.

The <Control> tag defines the button's name, type (a button), a caption, and several event handlers. The OnSetCaption attribute defines the name of the event handler to set the caption. This code lives in the OfficeCodeBehind class:

Private Sub Button1_SetCaption(ByVal controlName As String, 
                               ByVal e As SetCaptionEventArgs)
    e.Caption = "Click Me!"
End Sub

When a control is about to be rendered, the SetCaption and PreRender events are fired in that order. SetCaption allows the caption to be dynamically set. PreRender allows other control values and attributes to be set:

Private Sub Button1_PreRender(ByVal controlName As String, 
                              ByVal e As PreRenderEventArgs)
    ' Set the button caption to bold
    e.DisplayProps.FontWeight = "bold"
End Sub

For more complex controls, you can use the PreRender event to greater effect for example, for the radio group, list box, and combo controls, you can dynamically set the items displayed in the control in the PreRender event.

Finally, the OnAction attribute in the Configuration.xml file sets the name of the Action event handler in the case of the button, this fires when the user clicks the button:

Private Sub Button1_Action(ByVal controlName As String, 
                           ByVal e As ActionEventArgs)
    ' Show a message box when the button is clicked
    MessageBox.Show(string.Format("You clicked button '{0}'!",
                        controlName))        
End Sub

As you can see, conceptually this is very similar to ASP.NET:

  • Controls are declaratively defined (in the .aspx file or the Configuration.xml file).
  • Event handlers configure the controls and respond to user interaction their code is in a separate file (the code-behind file in ASP.NET, or the OfficeCodeBehind class in smart documents).

Customizing the Smart Document

We can customize our test smart document by first editing the contents of the DocumentStructure.xsd file to logically define the structure the document. Then we can have different controls appear in the task pane depending on the location of the current selection in the document. For this example, we use the existing contents of the DocumentStructure.xsd file.

  1. First, let's delete the existing green help text from the document.

  2. Next, click Document Actions at the top of the task pane. A drop-down list appears; click XML Structure. The task pane now looks like this:

    Figure 7. XML Structure task pane for assigning XML structure to document

  3. Click the documentSections element in the list box at the bottom of the task pane. A dialog box appears, asking if you want to apply this element to the entire document or just the current selection.

  4. Choose Apply to Entire Document. If Show XML tags in the document in the task pane is not checked, click it. You now see the XML formatting as pink tags in the document.

  5. Now add text "Section 1" and "Section 2" to the body of the document, inside the <documentSections> tags.

  6. Select the "Section 1" text, and then click Section 1 from the list box at the bottom of the task pane.

  7. Next, select the "Section 2" text, and then click Section 2 from the list box. The document should now look like this:

    Figure 8. Assigning XML structure to document sections

    We have now associated the text "Section 1" with the Section1 element of the DocumentStructure.xsd file, and "Section 2" with the Section2 element.

  8. Click XML Structure at the top of the task pane, and then click Document Actions to display the Document Actions task pane again.

Now, the controls appearing in the task pane will change, depending on if the current selection is in the "Section 1" text or the "Section 2" text. Here are the controls when the selection is on "Section 1":

Figure 9. Smart document running with "Section 1" selected

Here are the controls when the selection is on "Section 2":

Figure 10. Smart document running with "Section 2" selected

Looking at the task pane, the "Sample" section containing the Section 1 Button control only appears if part of the document text "Section 1" is selected. This is because the Section 1 Button control is defined in the Configuration.xml file to reside in the Section1 DocumentAction section:

<DocumentAction ActionXmlType="Section1" PaneCaption="Sample">       
    <Control Name="Section1Button" 
             Type="C_TYPE_BUTTON"
             Caption="Section 1 Button" />
</DocumentAction>

Currently, there is no DocumentAction section for Section2 defined in the Configuration.xml file. This is why there are no controls displayed below the "Entire Schema Section" when the selection is in "Section 2" (see Figure 10).

Debugging a Smart Document

Debugging could not be much simpler. Just set a breakpoint in the code, press F5, and start using the smart document when execution hits the breakpoint, it pauses in Visual Studio. Part of what makes this so easy is that the Manifest.xml file uses the <runFromServer/> attribute for the assemblies. This attribute means that the assembly is not downloaded to the smart documents solution folder, but instead is run from its existing location. This means that it is unnecessary to remove, delete, and then attach the expansion pack to the document to get an updated copy of the code.

As a simple example, set a breakpoint in the Button1_SetCaption method and press F5:

Figure 11. Debugging the SetCaption event of a smart document

Here you can see the original caption from the Configuration.xml file (e.Caption = "This caption gets replaced and is never used!") in the debugger pop-up information box. The code is about to replace the existing value with the new caption, "Click Me!"

Getting Fancy: Control Arrays

The model described above works great if you know at design time how many controls you will need, and what their types are. This is the most common case in smart documents development. However, in some cases, it would be cool to be able to dynamically populate the task pane with controls based on information available only at runtime —for example, the information in a database. Control arrays are designed for this situation.

The idea of a control array is simple: put a placeholder in the Configuration.xml where you want to dynamically add controls, and then use the ControlArrayInitialize event to populate the controls. You can have any number of control arrays (although the current implementation of smart documents limits a single DocumentAction section from having more than 256 controls).

Let's look at a simple example with control arrays. Add the following code to the Configuration.xml file in the "actionPertainsToEntireSchema" <DocumentAction> section, just below the Button1 control:

<Control Name="MyControlArray"
         Type="ControlArray"
         OnControlArrayInitialize="MyControlArray_Initialize"/>

Next, add the following ControlArrayInitialize event handler to the OfficeCodeBehind class:

Private Sub MyControlArray_Initialize(ByVal controlName As String, 
                         ByVal e As ControlArrayInitializeEventArgs)

    ' Create a label:
    Dim label As SmartDocumentConfiguration.ControlRow

    label = e.ControlTable.NewControlRow()

    label.Name = "DynamicLabel"
    label.Caption = "Dynamic Label Control"
    label.Type = "C_TYPE_LABEL"

    e.ControlTable.AddControlRow(label)

    ' Create a button:
    Dim button As SmartDocumentConfiguration.ControlRow

    button = e.ControlTable.NewControlRow()

    button.Name = "DynamicButton"
    button.Caption = "Dynamic Button"
    button.Type = "C_TYPE_BUTTON"

    e.ControlTable.AddControlRow(button)

    ' Add the FontWeight = 'bold' property to the button
    Dim buttonProperty As SmartDocumentConfiguration.PropertyRow

    buttonProperty = e.PropertyTable.NewPropertyRow()

    buttonProperty.Name = "FontWeight"
    buttonProperty.Property_Text = "bold"

    e.PropertyTable.AddPropertyRow(buttonProperty)

    ' Associate this property with the button control
    buttonProperty.SetParentRow(button)

End Sub

Now, press F5 to run the project. The first thing you notice is that the control array doesn't appear it didn't work! This is because we have not yet updated the files in the expansion pack. In short, when you attach the expansion pack to the document, it copies the files to a new location. The reason for this is that it simplifies smart document deployment when you attach the expansion pack to the document; it downloads the files (presumably from a server) onto the local computer. However, it's a bit of a pain during development: the files exist in two locations, one set in the Visual Studio project folder, and another set in the smart documents solution folder. (The smart documents solution folder is located at C:\Documents and Settings\user\Local Settings\Application Data\Microsoft\Schemas\solutionNamespace\solutionID.) The documentation installed with the Managed Smart Documents Wrapper describes a procedure to reconfigure the project so that it is unnecessary to manually delete and reattach the expansion pack to update the Configuration.xml file.

To download a new copy of the expansion pack files

  1. On the Word Tools menu, click Templates and Add-Ins. . ., and then click the XML Expansion Pack tab.
  2. Click Remove to detach the expansion pack from the document, and then click the name of the expansion pack in the list and click Delete, and then click Yes to confirm the delete.
  3. Then click Add. . ., browse to the Manifest.xml file, and then click Open.
  4. Click No to avoid re-activating expansion pack manifest security, and finally click OK to attach the expansion pack.

When the expansion has loaded and the smart document starts running, the Document Actions task pane looks like this:

Figure 12. Document Actions task pane with control array

Note that the font on the button is bold (due to the property set on the control), and that the controls in the control array were added where the control array placeholder was in the Configuration.xml file.

Conclusion

The Managed Smart Documents Wrapper combines the user experience of smart documents with the productivity advantages of object-oriented, declarative, event-driven programming. In addition, the new project templates automate most of the tedious work of creating a smart document project. The Managed Smart Documents Wrapper also installs extensive documentation, and a sample smart document created with Visual Basic .NET and Word to demonstrate nearly all aspects of the usage of the wrapper assembly. Regardless of whether you are a .NET-oriented developer who has never seen a smart document, or a .NET-oriented developer experienced in creating smart documents, the Managed Smart Documents Wrapper offers a wealth of benefits.

About the Authors

Susan Warren is a senior software engineer at Vertigo Software, Inc., a Microsoft Gold Certified Partner for e-Business Solutions. She recently served as design and development lead for the IssueVision smart client application featured at DevDays 2004. Prior to joining Vertigo, Susan was a program manager at Microsoft responsible for the pages and controls framework in ASP.NET, Web Matrix and the Web Forms Designer in Visual Studio .NET.

Keith Craig is a senior software engineer at Vertigo Software Inc. Before joining Vertigo, he developed ASP.NET and ASP web applications, SQL Server databases, Visual Basic 6 client-server data warehouse applications, and many other software projects. Keith has a Ph.D. in Physics from the University of California at Santa Barbara, and is a Microsoft Certified Solution Developer (MCSD) for .NET.

© Microsoft Corporation. All rights reserved.