Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)
Smart documents are a new technology in Office 2003. Smart documents build on the concepts of smart tags and enhance the user experience of working with document metaphors. For example, say you are designing an expense report in Excel. You might want relevant information to appear in the task pane in Office, depending on what the user is doing. You might also want to provide a Submit button in your application that is aware of context and is integrated into the task pane area. With smart documents, you can provide richer extensibility to Office-based solutions through standard XML or code that you write. In Office 2003, only Word and Excel support smart documents.
If you think about it, smart documents are the logical step beyond smart tags. While smart tags allow you to tag content in a document and associate actions, smart documents go one step further and allow you to customize the user interface and track interactions with the document. Because the two technologies are intertwined, you'll see many similarities between smart tags and smart documents. The smart document object model is actually part of the smart tag library.
To show you the benefits of a smart document solution, let's walk through building and deploying a review form in Word. Using the review form, a user enters her performance evaluation, and throughout the process, the smart document provides feedback. When the user finishes filling in the form, the smart document solution allows her to submit her review form through e-mail in Outlook. Our example is simple, so refer to the smart tag SDK for more information about building complex smart document solutions. Figure 9-13 shows the sample smart document solution.
The Parts of a Smart Document Solution
In the review form sample, the smart document solution includes a number of parts that we need to build. First we need the document, specifically a Word document for this example. Most documents that become smart documents have an XML schema (XSD) associated with them and are also marked up with XML tags. The markup allows you to apply your smart document logic to the document quite easily.
Next you need whatever support files your smart document requires. These support files might be ActiveX controls that you want to display in the document actions pane for your smart document, images, XML documents, or XSL stylesheets. You can also integrate smart documents with smart tags and COM add-ins to build more complex smart document solutions.
The final piece of a smart document solution is the manifest, or XML expansion pack file. A manifest file makes it easier to deploy smart document solutions. This file has an XML schema and is a description of your solution, with a list of the files needed for your solution and any actions to perform on those files. For example, if you create a DLL that needs to be deployed with your solution, you add the DLL to your manifest, and Office will copy the DLL from the location you specify and even register your DLL (using regsvr32). Furthermore, using a manifest file, you can deploy other files that are part of your smart document solution. Finally, the manifest can update your files if any changes are made. You'll learn more about manifest files later in this chapter.
Building a Smart Document Solution
Let's assume you already have a Word document that has an XML schema and has been marked up like the review form sample. To show you what XML markup looks like in Word, Figure 9-14 shows the review form with its XML structure displayed.
The next step is to create a DLL that implements the ISmartDocument interface. This interface is part of the Smart Tags 2.0 Library. To implement the interface, you must implement a number of properties and functions that the interface requires. Table 9-14 lists the properties and functions you need to implement. As you can see, the implementation is similar to the implementation of a smart tag.
Element | Description |
---|---|
Private Property Get ISmartDocument_ControlCaptionFromID(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal bstrText As String, ByVal bstrXML As String, ByVal Target As Object) As String | A property that specifies dynamic captions for the controls you create in your smart document solution. |
Private Property Get ISmartDocument_ControlCount(ByVal SmartDocName As String) As Long | A property that specifies the number of controls supported by a specific smart document type. |
Private Property Get ISmartDocument_ControlID(ByVal SmartDocName As String, ByVal ControlIndex As Long) As Long | A property that dynamically sets a unique control identifier for your smart document controls. The unique identifier ensures that controls do not have collisions when events fire for the controls. |
Private Property Get ISmartDocument_ControlNameFromID(ByVal ControlID As Long) As String | A property that specifies a unique name for your control based on its unique ID. |
Private Property Get ISmartDocument_ControlTypeFromID(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long) As C_TYPE | A property that specifies the type of your control, based on your control ID. Examples include combo box, text box, radio group , image, label, and link. |
Private Sub ISmartDocument_ImageClick(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal Target As Object, ByVal Text As String, ByVal Xml As String, ByVal LocaleID As Long, ByVal XCoordinate As Long, ByVal YCoordinate As Long) | The first of the many Click events you'll see in the ISmartDocument interface. The Click event allows you to listen for your unique controls, based on their ID, and perform some action. |
Private Sub ISmartDocument_InvokeControl (ByVal ControlID As Long, ByVal ApplicationName As String, ByVal Target As Object, ByVal Text As String, ByVal Xml As String, ByVal LocaleID As Long) | A method that works with the new document-fragments capabilities of smart documents. Document fragments are content that is either locally stored or remotely stored as XML document fragments . The difference between a label and a document fragment is that when a user clicks on a document fragment, it can be inserted into the document. This method is called when the user clicks on the document fragment. |
Private Property Get ISmartDocument_IsControlDynamic(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long) As Boolean | A property that specifies whether your control caption is dynamic. |
Private Sub ISmartDocument_OnCheckboxChange(ByVal ControlID As Long, ByVal Target As Object, ByVal Checked As Boolean) | A method that is called when a check box value changes for one of your check box controls. |
Private Sub ISmartDocument_OnListOrComboSelectChange (ByVal ControlID As Long, ByVal Target As Object, ByVal Selected As Long, ByVal Value As String) | A method that is called when a list or combo box value is changed. |
Private Sub ISmartDocument_OnPaneUpdateComplete(ByVal Document As Object) | A method that is called when the document actions pane is redrawn. |
Private Sub ISmartDocument_OnRadioGroupSelectChange(ByVal ControlID As Long, ByVal Target As Object, ByVal Selected As Long, ByVal Value As String) | A method that is called when the value of a radio group changes. |
Private Sub ISmartDocument_OnTextboxContentChange(By Val ControlID As Long, ByVal Target As Object, ByVal Value As String) | A method that is called when the value in a text box changes. |
Private Sub ISmartDocument_PopulateActiveXProps(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, ByVal ActiveXPropBag As SmartTagLib.ISmartDocProperties) | The first of many populate methods for your controls, which are used to fill in the content of your controls. This method also allows you to customize your ActiveX controls. For example, you can specify the size of your control by writing Props.Write "W", 150 for the width and Props.Write "H", 200 for the height. |
Private Sub ISmartDocument_PopulateCheckbox(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, Checked As Boolean) | A method for customizing or populating your check box controls. |
Private Sub ISmartDocument_PopulateDocumentFragment(By Val ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, DocumentFragment As String) | A method that populates your document fragment controls. |
Private Sub ISmartDocument_PopulateHelpContent(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, Content As String) | A method that populates your help controls. |
Private Sub ISmartDocument_PopulateImage(ByVal Control- ID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, ImageSrc As String) | A method that populates any image controls you have. |
Private Sub ISmartDocument_PopulateListOrComboContent(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, List() As String, Count As Long, InitialSelected As Long) | A method that populates list or combo box controls. |
Private Sub ISmartDocument_PopulateOther (ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties) | A method that applies to all controls that do not have a specific populate method. One example is a separator control. |
Private Sub ISmartDocument_PopulateRadioGroup(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, List() As String, Count As Long, InitialSelected As Long) | A method that populates radio group controls. |
Private Sub ISmartDocument_PopulateTextboxContent(ByVal ControlID As Long, ByVal ApplicationName As String, ByVal LocaleID As Long, ByVal Text As String, ByVal Xml As String, ByVal Target As Object, ByVal Props As SmartTagLib.ISmartDocProperties, Value As String) | A method that populates any text box content for your text box controls. |
Private Sub ISmartDocument_SmartDocInitialize(ByVal ApplicationName As String, ByVal Document As Object, ByVal SolutionPath As String, ByVal SolutionRegKeyRoot As String) | An important method that is called to initialize your smart document. You can then modify the document, store the Document object for your application, and determine where your solution files are installed. |
Private Property Get ISmartDocument_SmartDocXmlTypeCaption (ByVal SmartDocID As Long, ByVal LocaleID As Long) As String | A property that specifies the captions for your XML tags in your document. These captions are shown in the document actions pane. |
Private Property Get ISmartDocument_SmartDocXmlTypeCount() As Long | A property that specifies the number of XML types your document supports. |
Private Property Get ISmartDocument_SmartDocXmlTypeName(ByVal SmartDocID As Long) As String | A property that specifies the names of the types of your XML tags, such as http://schema/type |
Now that you've seen the interfaces that need to be implemented, let's look at the code that implements the review form sample. We'll look at the initialization routine for the sample:
Private Sub ISmartDocument_SmartDocInitialize( _ ByVal ApplicationName As String, _ ByVal Document As Object, _ ByVal SolutionPath As String, _ ByVal SolutionRegKeyRoot As String) Dim oUnlockedNodes As Word.XMLNodes Dim oWordDocument As Word.Document Dim oWordRangeObject As Word.Range Dim initializeCounter As Integer Dim oXMLNode, oUserList As MSXML2.DOMDocument50 Dim importName As Integer Dim boolHeader As Boolean Dim boolGoals As Boolean On Error GoTo ErV2 'Turn on XML tags. ActiveDocument.Application.ActiveWindow.View.ShowXMLMarkup = 65535 'Set up. Set oWordDocument = Document Set oUserList = New MSXML2.DOMDocument50 Set oXMLNode = New MSXML2.DOMDocument50 'We need to set the path where our files are 'installed on the client machine. FilesPath = SolutionPath & "\" 'Turn off the submittal button initially as well. readyToSubmit = False 'To check if our employee has filled out the document, 'we'll use the state of the name field. If oWordDocument.XMLNodes(1).SelectSingleNode(".//u:Name", _ "xmlns:u='" & reviewFormURI & "'").Text = "" Then sWorkflowState = EmployeeState Else sWorkflowState = ReviewerState End If Select Case sWorkflowState Case EmployeeState 'First, we'll unlock the appropriate sections of the document. Set oUnlockedNodes = _ oWordDocument.XMLNodes(1).SelectNodes( _ ".//u:EmployeeResponse", _ "xmlns:u='" & reviewFormURI & "'") initializeCounter = 0 Do While initializeCounter < oUnlockedNodes.Count Set oWordRangeObject = _ oUnlockedNodes(initializeCounter + 1).Range oWordRangeObject.MoveStart 1, -1 oWordRangeObject.Editors.Add wdEditorEveryone oUnlockedNodes(initializeCounter + 1).PlaceholderText = _ "[Fill in this information.]" initializeCounter = initializeCounter + 1 Loop 'Unlock the Employee Section of Company Values On Error Resume Next Set oUnlockedNodes = _ oWordDocument.XMLNodes(1).SelectNodes(".//u:Employee", _ "xmlns:u='" & reviewFormURI & "'") Dim oUnlockedNode As Word.XMLNode For Each oUnlockedNode In oUnlockedNodes Set oWordRangeObject = oUnlockedNode.Range oWordRangeObject.Editors.Add wdEditorEveryone Next On Error GoTo ErV2 'Also, unlock the employee comments. Set oUnlockedNodes = _ oWordDocument.XMLNodes(1).SelectNodes( _ ".//u:EmployeeComments", "xmlns:u='" & _ reviewFormURI & "'") initializeCounter = 0 Do While initializeCounter < oUnlockedNodes.Count Set oWordRangeObject = _ oUnlockedNodes(initializeCounter + 1).Range oWordRangeObject.MoveStart 1, -1 oWordRangeObject.Editors.Add wdEditorEveryone oUnlockedNodes(initializeCounter + 1).PlaceholderText = _ "[Fill in this information.]" initializeCounter = initializeCounter + 1 Loop 'This will populate the header fields: boolHeader = MsgBox("Do you want to import the " & _ "personal information for the " & _ header automatically?", vbYesNo) If (boolHeader = vbYes) Then 'If you want to load from a file, use this code 'oUserList.setProperty "SelectionNamespaces", _ ' "xmlns:u='userNames'" 'oUserList.async = False 'oUserList.Load FilesPath & "userNames.xml" 'oXMLNode.setProperty "SelectionNamespaces", _ ' "xmlns:u='userNames'" 'oXMLNode.async = False 'oXMLNode.loadXML _ 'oUserList.SelectSingleNode(".//u:user").Xml 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Date", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = Date 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Name", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:name").Text 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Alias", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:alias").Text 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:EmployeeID", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:id").Text 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Title", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:title").Text 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Reviewer", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:managerAlias").Text 'oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Department", "xmlns:u='" & _ ' reviewFormURI & "'").Range.Text = _ ' oXMLNode.SelectSingleNode(".//u:department").Text 'Save the names to customize some of the SmartDoc pane. 'sReviewName = _ ' oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Name").Text 'sReviewerName = _ ' oWordDocument.XMLNodes(1).SelectSingleNode( _ ' ".//u:Reviewer").Text 'Try to lookup info from the GAL Dim oSession As New MAPI.Session oSession.Logon "", "", True, True, 0, True 'Get the current user's name Dim oWSHNetwork As Object Set oWSHNetwork = CreateObject("WScript.Network") Dim strUserName As String strUserName = oWSHNetwork.UserName Set oWSHNetwork = Nothing Dim oMailItem As MAPI.Message Dim oRecipients As MAPI.Recipients Dim oRecipient As MAPI.Recipient Set oMailItem = oSession.Outbox.Messages.Add Set oRecipients = oMailItem.Recipients Set oRecipient = oRecipients.Add(strUserName) oRecipients.Resolve True Dim oAE As MAPI.AddressEntry Set oAE = oRecipient.AddressEntry oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Date", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = Date oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Name", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = strUserName oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Alias", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = oAE.Fields(&H3A00001E).Value oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:EmployeeID", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = "999999" oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Title", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = oAE.Fields(&H3A17001E).Value oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Reviewer", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = oAE.Manager.Name oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Department", "xmlns:u='" & reviewFormURI & _ "'").Range.Text = oAE.Fields(&H3A18001F).Value 'Save the names to customize some of the SmartDoc pane. sReviewName = strUserName sReviewerName = oAE.Manager.Name 'Discard CDO Stuff and logoff Set oAE = Nothing Set oMailItem = Nothing oSession.Logoff Set oSession = Nothing End If 'This part will import the previous review's goals. boolGoals = MsgBox("Do you want to import your previous " & _ "review goals automatically?", vbYesNo) If (boolGoals = vbYes) Then Set oXMLNode = New MSXML2.DOMDocument50 oXMLNode.Load FilesPath & "goals.xml" oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:CurrentObjectives//u:EmployeeResponse", _ "xmlns:u='" & _ reviewFormURI & "'").Range.InsertXML (oXMLNode.Xml) End If 'Clean up. Set oXMLNode = Nothing Set oWordRangeObject = Nothing Case ReviewerState 'First, we'll unlock appropriate sections of the document. Set oUnlockedNodes = oWordDocument.XMLNodes(1).SelectNodes( _ ".//u:ManagerResponse", "xmlns:u='" & reviewFormURI & "'") initializeCounter = 0 While initializeCounter < oUnlockedNodes.Count Set oWordRangeObject = _ oUnlockedNodes(initializeCounter + 1).Range oWordRangeObject.MoveStart 1, -1 oWordRangeObject.Editors.Add wdEditorEveryone oUnlockedNodes(initializeCounter + 1).PlaceholderText = _ "[Type Here]" initializeCounter = initializeCounter + 1 Wend 'Save the names to customize some of the SmartDoc pane. sReviewName = oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Name", "xmlns:u='" & reviewFormURI & "'").Text sReviewerName = oWordDocument.XMLNodes(1).SelectSingleNode( _ ".//u:Reviewer", "xmlns:u='" & reviewFormURI & "'").Text 'Clean up. Set oWordRangeObject = Nothing End Select 'Turn on XML tags. ActiveDocument.Application.ActiveWindow.View.ShowXMLMarkup = 0 oWordDocument.Protect Password:="", NoReset:=False, _ Type:=wdAllowOnlyReading Exit Sub ErV2: MsgBox "ISmartDocument_SmartDocInitialize:" & Err.Description Resume Next End Sub
The code does some work to unlock nodes in the document that employees should fill out to complete their review. The code also leverages Outlook to look up the user's header information ”his alias, department, and manager's name, for example. The code can also import previous performance goals from the user's last review. The code then saves off some global variables to be used later in the application. Finally, the code locks down sections of the document that the user should not be able to modify.
Next, using the XML type information that we specify from our XML types in our document, Office can figure out which XML types should display the controls for our smart document. For example, we tell our smart document that we support different XML types as smart document types by using the SmartDocXMLTypeName and SmartDocXMLTypeCount properties. When Office hits an XML tag that's been designated as a smart document, it determines which controls should be loaded into the document actions pane and calls the populate methods for the controls that are loaded into the pane.
To figure out the controls, Office calls the ControlCount property and passes each of the XML tags from your document. If there is a nonzero number for this property in your code, Office knows that your XML tag has some smart document controls associated with it. Using the ControlID property, you assign unique control ID ranges to the controls in your smart document solution. Then, when the user clicks through your smart document, Office passes the ControlID to the ControlCaptionFromID (if your caption is dynamic) and to the correct populate method for your control.
Two special schema names you should be aware of are yourschemaname#ActionPertainstoEntireSchema and http://schemas.microsoft.com/office/smartdocuments/2003#Default . You should use these special schema tags for the smart document controls you want to display, regardless of the XML type the user has selected. You can think of these controls as global controls for your solution.
Note | Keep in mind that XML is case-sensitive. You might find that your solution does not work as you expect because of case issues in your XML schema or XML tags. |
Deploying Your Smart Document Solution
To deploy your smart document solution, you can use the XML Expansion Pack technology included with Office. This is a text document with an XML schema that allows you to specify particular tags that will download, install, and update your smart document solutions. For the full breadth of XML tags that the XML Expansion Pack technology supports, see the smart tag SDK. Here is the XML Expansion Pack file for the review form sample:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <manifest xmlns= "http://schemas.microsoft.com/office/xmlexpansionpacks/2003"> <version>1.11</version> <location>http://thomrizrc2:801/manifest.xml</location> <updateFrequency>20160</updateFrequency> <uri>http://thomrizrc2:801/</uri> <solution> <solutionID>ProgOutExchReviewFormSolution01</solutionID> <type>smartDocument</type> <alias lcid="1033">Review Form Solution</alias> <file> <type>solutionActionHandler</type> <version>1.0</version> <filePath>file:///C:/ReviewForm/SmartDoc/reviewform.dll</filePath> <CLSID>{29568A81-7FF3-4A28-8C4A-C30C98253079}</CLSID> <regsvr32/> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/xml/usernames.xml</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/docfragments/goals.xml</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath> http://thomrizrc2:801/docfragments/justification.xml </filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/intro.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/Part1BHelp.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/Part1CHelp.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/Part2AHelp.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/Part2Help.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/PartAHelp.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating25.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating30.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating35.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating40.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating45.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/helpfiles/rating50.htm</filePath> </file> <file> <type>other</type> <version>1.0</version> <filePath>http://thomrizrc2:801/images/hr.gif</filePath> </file> </solution> <solution> <solutionID>schema</solutionID> <type>schema</type> <alias lcid="1033">Review Form Schema</alias> <file> <type>schema</type> <version>1.0</version> <filePath>http://thomrizrc2:801/xml/review.xsd</filePath> </file> </solution> </manifest>
As you can see in the XML, the file lists the version, location, and update frequency for the solution. It also lists the component of the solution, whether it is a DLL, such as the smart document action DLL included with the solution, or other files, such as the XML schema and images that need to be downloaded with the solution. When you use this type of file for your deployment, you can easily deploy smart documents across multiple desktops using Web technologies.
One interesting tag is the <regsvr32/> tag. You can have Office download and register the DLLs for you on the client machine. Also, XML Expansion Packs support tags that allow you to write to the registry and run solutions from the server.
To see how to deploy a solution that calls the XML Expansion Pack file, choose Templates And Add-Ins from the Tools menu in Word and click on the Solutions tab. Figure 9-15 shows the user interface for adding a solution manually.
Another way to attach your solution to your documents is to add two custom properties to your documents as Office document properties. These two properties are Solution URL and Solution ID . Solution URL specifies the URL of the XML Expansion Pack file for your solution so Office can download and install the necessary components . Solution ID is a GUID, or unique identifier, that uniquely identifies a solution. Figure 9-16 shows these properties set in Word. Figure 9-17 shows the user interface that is displayed when a user opens an Office document with these custom properties set.
By using these properties, you can easily deploy a smart document solution to your users.
MOSTL Support for Smart Documents
To support building smart documents without using DLLs, Office supports the smart document technology in MOSTL through some new tags. If you create your solution using MOSTL, however, you should still create an XML Expansion Pack file that deploys the MOSTL solution to your clients . The following is an example of a smart document solution that uses the new MOSTL tags:
<FL:smarttaglist xmlns:FL="urn:schemas-microsoft-com:smarttags:list"> <FL:name>Sample MOSTL Smart Doc Solution</FL:name> <FL:lcid>1033</FL:lcid> <FL:description>MOSTL description</FL:description> <FL:moreinfourl></FL:moreinfourl> <FL:lastcheckpoint></FL:lastcheckpoint> <FL:lastupdate></FL:lastupdate> <FL:updateurl></FL:updateurl> <FL:downloadurl></FL:downloadurl> <FL:updateable></FL:updateable> <FL:updatefrequency></FL:updatefrequency> <FL:autoupdate></FL:autoupdate> <FL:smartdoc type= "http://schemas.microsoft.com/office/smartdocuments/2003#Default"> <FL:caption>Default SmartDoc Action</FL:caption> <FL:actions> <FL:action id="defLink"> <FL:actionType>Link</FL:actionType> <FL:caption>Microsoft Home Page</FL:caption> <FL:url>http://www.microsoft.com</FL:url> </FL:action> <FL:action id="defHelp"> <FL:actionType>Help</FL:actionType> <FL:caption>Help Text</FL:caption> <FL:help> <html><body>Default Help</body></html> </FL:help> </FL:action> <FL:action id="defHelpURL"> <FL:actionType>HelpURL</FL:actionType> <FL:caption>HelpURL text</FL:caption> <FL:help> http://localhost/ </FL:help> </FL:action> <FL:action id="defSeparator"> <FL:actionType>Separator</FL:actionType> </FL:action> <FL:action id="defButton"> <FL:actionType>Button</FL:actionType> <FL:caption>Go to MSPress Homepage</FL:caption> <FL:url>http://mspress.microsoft.com</FL:url> </FL:action> <FL:action id="defLabel"> <FL:actionType>Sample Label</FL:actionType> <FL:caption>This is sample label text</FL:caption> </FL:action> <FL:action id="defImage"> <FL:actionType>Image</FL:actionType> <FL:caption>Sample Image</FL:caption> <FL:imageurl> http://localhost/pagerror.gif </FL:imageurl> </FL:action> </FL:actions> </FL:smartdoc> </FL:smarttaglist>
This MOSTL file applies actions to the entire document and shows how to use the different control types for smart documents in MOSTL. Figure 9-18 shows the MOSTL solution in Word.