|
Provide Feedback on this Broadcast
Microsoft Support WebCast
Introduction to Microsoft Office 2003 smart document development
February 25, 2004
Note This document is based on the original spoken WebCast transcript. It has been edited for clarity.
Lori Turner: Thanks to everyone for joining us today. This is Lori Turner, and I'm here to introduce you to Microsoft® Office 2003 smart document development. I'm here with my co-worker, Ken Laws, and we are ready to talk to you about smart documents.
The objectives (slide 2) for this WebCast are to provide you with an overview of the new smart document feature in Microsoft Office Word 2003 and Office Excel 2003. In this WebCast you will learn about smart document architecture and how you can create your own custom smart document solutions using Microsoft Visual Studio® .NET.
The agenda for today (slide 3) will be we will first cover an introduction to what a smart document is. We'll discuss the architecture of smart documents: how you develop one, how you use one, and some things you should consider when you create your own smart document solutions. And then we'll briefly touch on troubleshooting.
Today Ken and I will be teaming for this WebCast. Ken will cover the first portions of the WebCast, which will include the introduction and architecture, and at that point I'll take over for some development topics. So at this point I'll hand you over to Ken.
Ken Laws: To start off, let's see exactly what a smart document is (slide 4). Basically, a smart document is a document that is programmed to determine what your users must do for a particular task, and then help them, guide them along the way to accomplish that task.
Smart documents are ideal for creating documents that are task based and that follow a specific process. They're primarily designed to be used with Excel 2003 and Word 2003, and as such, they give you some additional functionality, because you can incorporate the features that are built into the host applications within your smart document. You can also include add ins that can be used with a document or template, as well as macros that are inside the smart document itself. Additionally, smart documents can also interact with a variety of databases, such as Microsoft SQL Server™ and Microsoft Office Access 2003. And, if you to need to, you can interact with Microsoft BizTalk® Server to get some additional tracking workflow. Some common examples for using smart documents are listed here: expense reports, content creation, and order entry and invoicing.
Let's look on the next slide (slide 5) at what a smart document might look like. On the slide you'll notice the screen shot of Microsoft Word. And on the left side of the screen are some XML elements that we have, Product and Quantity (Qty). What might happen here, when working within a smart document, let's say that the user comes in and they place the cursor inside the Product element where we see the word "Apple." The code inside the smart document assembly or .dll is responsible for loading the information that you see in the Document Actions task pane on the right side of the window. So when the user places the cursor inside the Product element, we see that in this case a display shows a Category drop-down list, which in this case we've selected Fruits, and a list box is shown for products, described here as Apple, Banana, and Orange.
How you could assist the user with this process is when they click inside of the Product element, they would have a drop-down list of available categories that they could pick from. In this case we select Fruits. Then you can populate the Product list box with available selections, such as Apples, Bananas, or Oranges. So you're basically guiding the user as to what options they have to pick from here and how they would be able to populate this element. So the user selects Fruits, then selects Apple, and then clicks the Enter button, and the word "Apple" gets populated inside of the Product element.
If they then move down to the Qty element, there may be some additional code within your smart document that would then change the display within the Document Actions task pane to assist them in entering a Quantity amount into that particular element. That's kind of a brief introduction of what a smart document is and what a smart document looks like.
We'll now discuss some information concerning the architecture (slide 6). There are basically four primary components of the smart document. At the core, as I mentioned before, is the Word document or Excel workbook. This is basically where you would start. You would open Word and create a document, or open Excel and create a workbook.
You would then attach an XML schema file that you have predefined, which would contain the XML elements that you would want to use within your smart document.
After you have created the XML schema, you can then proceed to creating your smart document assembly or .dll file. The smart document assembly or .dll will implement the ISmartDocument interface. And this .dll is responsible, as I mentioned before, for populating the Document Actions task pane, to assist the user within the smart document solution.
The fourth and final component is the XML expansion pack. The XML expansion pack is basically an XML file that you create that contains information concerning the files that are going to be necessary to implement your smart document solution. You can include XML schemas, transforms, dynamic link libraries, image files, and so on. That can all be a part of your smart document solution, and those are included within the XML expansion pack. The expansion pack also contains information such as where these files are located, version information, update frequency, and things like that to help assist the Office applications in loading and using your smart document.
The next topic we're going to look at is how a document becomes a smart document (slide 7). As I mentioned before, whenever you create the schema file that you're going to use, you go through a process, and Lori will cover this a little bit more in depth later on, of attaching the XML schema to your Word document or to your Excel Workbook. After that's attached, that gives you the XML elements that we see here in the Word document. Then you would attach the XML expansion pack to this document.
After the expansion pack is attached, you then get the Document Actions task pane, and the code would then load up whatever particular controls or components that you would show to the user as they navigate between elements within the document.
Again, the XML expansion pack is critical in telling the Office application where to go to get the particular components that it needs to load for this particular smart document that you've created.
When you attach a smart document assembly to a Word document or to an Excel workbook, there are some registry settings and document properties that are appended as well (slide 8). Most of the registry information is going to be written within the registry hive that's shown on the screen here, HKEY_CURRENT_USER\Software\Microsoft\Schema Library, or the corresponding key in the HKEY_LOCAL_MACHINE hive. The information written here includes manifest version, manifest location, update frequency, and things like that. That is stored within these registry keys.
In addition to that there are some document properties that are written, such as SolutionID and SolutionURL. These are written to the documents themselves. The SolutionID is the string that represents the SolutionID element of the XML expansion pack, and the SolutionURL is the string that represents the location of the XML expansion pack manifest file for the smart document.
In brief, there are really three options you have to create a smart document (slide 9). You can create a basic smart document, and this is a smart document that's simply based on the Microsoft Office Smart Tag List Schema. This particular type of smart document is useful if you want to quickly create a smart document, and you don't need to fully implement functionality that's provided by the smart document API. This option allows you, without writing any code, to quickly and easily create smart documents that can display labels, help text, document fragments, and so on.
The second option you have is a COM smart document, which would be created in Microsoft Visual Basic® 6.0 or Visual C++®.
Finally, the third option you have is creating a managed smart document. And you can use any of the programming languages included with Visual Studio .NET, such as Visual Basic .NET, C#, or Visual C++ .NET. One advantage you have with using this is that you can get a managed solution for your smart document. When building a managed smart document, you'll have to consider the security checks that are implemented within the .NET Framework.
To aid you in creating smart documents, I'd like to refer you to the Office 2003 Smart Document Software Development Kit. Included within the software development kit is some information concerning the ISmartDocument interface, a reference concerning the XML expansion pack, and there are also some tutorials included to get you started on creating a smart document that covers Visual Basic 6.0, Visual Basic .NET, C#, and C++ languages. There are also some samples included with the smart document in those particular languages that give you an idea of what a smart document would look like, as well as sample code that's included that you could look at to see how the smart document is implemented and how the controls are displayed within the Document Actions task pane.
Finally, the Smart Document SDK includes additional information that would be helpful with deployment. There are some deployment strategies included in there, as well as some common troubleshooting steps and common errors that we've encountered when building and deploying smart document solutions.
One other thing we want to discuss within the architecture realm here is security (slide 10). The XML expansion packs that you create for your smart document solution must be signed. Whenever you go to load a smart document into an Office application, the application performs a security pass on the expansion pack manifest file to ensure that the manifest is signed by a trusted source. If it determines that the XML expansion pack has not been signed, then Office does not load the expansion pack, and your smart document solution will not load.
To aid you with the signing of the smart document solution, included in the smart document SDK is a tool called Xmlsign.exe. This is a tool that will allow you to sign an XML expansion pack manifest file. However, you will still need to obtain a code-signing certificate from a certificate authority to be able to sign the file. But we do give you a tool that, assuming you have the certificates, you can use to sign the file.
Also included in the software development kit is a file called DisableManifestSecurityCheck. This is a registry file that's included solely for the purpose of testing and developing your smart document solution. If you execute this registry file, it basically turns off the security checking that the Office applications perform when loading the XML expansion pack, and it will allow you to load an unsigned expansion pack; however, again, we suggest this only be used for testing and development, because it is a global setting and it will disable the security check for any and all smart document solutions that might be loaded.
Finally, concerning code security, any COM .dll files, which would be .dll files you would build with Visual Basic 6.0 or C++, they follow the generic and standard Visual Basic for Applications macro security model. Any .NET-managed assemblies that you would create would follow the .NET security model, and are enforced by the Visual Studio Tools for Office loader, which is responsible for loading your managed smart document assembly.
This concludes the overview on the introduction and architecture for the smart document. I'm going to turn you over now to Lori Turner, who is going to go more in depth on developing your own smart document solution (slide 11).
Lori: Now that Ken has provided you with an overview of what a smart document is and how it works, our next task will be to walk you through the coding steps you might follow to begin creating your own smart document assembly in Visual Basic .NET.
In the next few slides I will walk you through creating a very basic smart document to illustrate how you lay out controls in the task pane, initialize those controls, and respond to user actions. The sample that we create in this presentation will be available for download (http://download.microsoft.com/download/A/B/B/ABB079A4-5F02-4A9D-8384-12052C154C1D/SmartDocSample.exe).
The first step in creating your smart document is to create the XML schema that will drive the data entry into the document or the workbook. The XML schema is important not only for marking up your documents with XML elements, but also for driving the smart document so that it knows what controls should appear in the task pane as the user selects various parts of the document.
For this example, you'll see that we have a schema. This is a schema that we develop for our smart document solution, as we proceed with the next few slides. In this schema you'll see that we have a complexType. The complexType has a name of OrderType. The OrderType contains two elements. It has a Product element and a Qty element. Last, at the very bottom of the schema, you'll see that we have one element, named example, and it uses our complexType order type.
Now, designing the XML schema is pretty important, because not only does it determine how your document will be designed, but it also is going to determine what sort of actions you're going to see in the Document Actions task pane. We'll see that as we proceed through the following slides.
So we've created our schema. Our next step is to start building our project (slide 12). All you need to do is start creating your project in Visual Studio .NET, and here we're going to be using Visual Basic .NET for this sample, is to create a new project using the Class Library template. After you've created the new project with the template, you reference what's known as the SmartTags 2.0 Primary Interop Assembly, or PIA.
Let me briefly just describe at this point what a PIA is, in case you may not know. Whenever you develop any managed code solution for Office 2003, you must use what's called a Primary Interop Assembly; at least that is our recommendation. You should understand that when a managed code client needs to interact with Office, it does so through what's called the COM Interop Layer. When managed code makes a call to a COM object, it will use what's known as a runtime callable wrapper, which is also known as an interop assembly. Now, there is only one interop assembly designated as the PIA for a particular COM object. When you install Office 2003, you also can install the PIAs if the .NET Framework 1.1 is present on the machine. So it is this PIA that is installed with Office 2003 for the Smart Tags library that you should reference when you start to build your smart document assembly project.
So after you have added the reference, the next point is going to be to add an Imports statement to simplify coding. The Imports statement here is Imports Microsoft.Office.Interop.SmartTag. The whole purpose of that really is to just shorten the amount of code that you actually have to write. I would certainly recommend it, every time you use anything in the SmartTag library, you would have to qualify it with Microsoft.Office.Interop.SmartTag. So Imports is definitely helpful here.
The next step is to implement the ISmartDocument interface. Visual Basic .NET has a very nice feature, in that as soon as you type implement ISmartDocument, right after you press ENTER, that class will be automatically filled with all of the methods that you need to implement for that interface.
The next section in our slides will talk about the methods that we will be using for this interface, and the types and sorts of code that you would use in each one.
So let's briefly talk about what is required for us to lay out the smart document solution (slide 13). And by lay out the smart document solution, I mean how do we determine which XML elements have document actions associated with them in the task pane, and what controls are going to be shown in each task pane?
First you indicate the count of XML elements with actions and the name and caption of each element. You do that with the three functions, SmartDocXMLTypeCount, SmartDocXMLTypeName, and SmartDocXMLTypeCaption.
Next you indicate the count of controls for each element. So you would supply properties for each control, like the Name, the ID, the Type, and the Caption, using the various control methods. Now, also, you can initialize the solution using SmartDocInitialize. You don't necessarily have to use SmartDocInitialize, but if you wanted to obtain a reference to the document or to the Word application when the smart document solution loads, then SmartDocInitialize is probably the event that you would use.
So SmartDocInitialize (slide 14) runs when a user attaches an XML expansion pack to a document or they open an existing document with a solution attached. Here I do illustrate how we could get the document reference so that we could store it as a global object or global variable, so that we might use it later on or elsewhere in our code. That is probably the most common purpose of SmartDocInitialize.
Let's talk once again, just to recap, because this is an important point, about controls and elements and their relationship to the schema (slide 15). In our final solution that we're going to build, we want to have two document actions. We want to have a document action for the Product element in our schema, and we want to have a document action for the Qty element in our schema. Now, each Document Actions task pane is associated with a particular element. But notice that each task pane, Document Actions, can have more than one control associated with it. For example, in the Product element we're going to have three controls. We have a drop-down list box, a list box, and a button; whereas, for the Qty element, we have two controls, a text box and a button.
After the smart document has been initialized, using SmartDocumentInitialize event, the next thing that we want to focus on is laying out the elements at run time (slide 16). The first thing we have to do is specify the namespace for the schema. Here you can see that we have a namespace constant called OrderSample. Then we have name constants for the two XML elements that we want to have document actions associated to. We have a PRODUCT element, so its name is in the form namespace # element name. The QTY element has the name with the syntax namespace # Qty. We have a constant that indicates the number of elements that will have associated actions, that's 2. Then for ease of coding, we are also going to create an array that has the captions and the names for these elements. So we have a two-element array, one for the Product element and one for the Qty element.
The next step is to determine what the element properties will be (slide 17). We have three methods that we want to focus on: SmartDocXMLTypeCount() — and we just return the number of elements. That's very straightforward. Here it would be 2.
The next step would be to return the type name for each XML element. And again, that would be in the form namespace#xmlelementname.
Then last, we would return the XmlTypeCaption. That is the caption for the task pane itself. So the element caption is what will appear as the caption for the task pane.
At this point we've decided that we're going to have two elements in the task pane. Our next step will be to determine and to figure out at run time what controls (slide 18) will be added into those task panes, or what controls will be associated with the elements. With controls in a smart document solution, you can have one or more per XML element. Every control has a unique identifier, a unique name, and optionally it can have a caption that will appear in the task pane.
Now, for control types, smart document solutions support a number of built-in controls. You could have a check box, a combo box, a list box, option buttons, a text box, a document fragment, help, image, hyperlink, label, and separator controls. Some of these you may be familiar with, but I'll touch briefly on the document fragment control because you may not have seen that before. A document fragment control allows you to create pieces of text or boilerplate text that your users can easily add to the document. The text for document fragments can be either hard-coded strings within your code or external documents that you reference from within your code.
Right beside built-in controls you can also use ActiveX® controls in a smart document solution. The advantage to using an ActiveX control in your smart document is if you need functionality that one of the built-in controls does not provide. A common example of that might be the calendar control. You'll see quite a few samples in the SDK where they implement a calendar control in the task pane, because there is no calendar control equivalent that's built into the smart document architecture. But we can always borrow from ActiveX controls to use that functionality.
So our first step is to decide how many controls are going to be associated with our elements (slide 19). We do that through the ControlCount property. Here in the ControlCount property one of the parameters that's passed in is called the XMLTypeName. The type name will either be, in our case, the type name for the Product element or the type name for the QTY element. We can use a Select Case statement to determine this based on what the XML type name is. If it's the PRODUCT element, we want a ControlCount of 3, and if it's the QTY element, we want a ControlCount of 2. Once again, as you may recall from our earlier screen shot, in our solution our product is going to have three controls. The PRODUCT element Document Actions pane will have three controls. They will have a combo box, a list box, and a button. In QTY we'll have a text box and a button. So here in the ControlCount property, all we have done at this point is decided how many controls are going to appear in each task pane.
The next point to bring up is the ControlID property (slide 20). The ControlID is the identifier for a control. Now, the ControlID property has a parameter called a ControlIndex. The ControlIndex value provides a number that represents a controlled position in the collection of controls for a given XML element. However, each control collection starts numbering the controls at 1, which means that if you have multiple elements that have multiple controls, you could have multiple controls with the same ControlIndex value. To resolve this problem, we use the ControlID property so that we can assign a unique number to our controls, and so that we can identify them at run time.
The best way to provide a unique ControlID value for each control is to add a number to the ControlIndex for each type. This new value becomes the value of the ControlID property, which is then passed into other methods and properties as the ControlID parameter. So essentially, in the ControlID property, what we're doing is taking a ControlIndex and computing or creating our own ControlID so that we can identify our controls later in our code. Here we've decided that if it's the PRODUCT element, it's going to start with a base of 100. If it's a control for the PRODUCT element, it has a base of 100. If it's a control for the QTY element, we'll have a base of 200. From that we can uniquely identify all of our controls.
The next thing is to specify control properties (slide 21). Now, I will add at this point that everything in the smart document solution is dynamic. And what that means is that, as you may have already figured out, there's no design environment for you to drag and drop controls onto a task pane. Everything for the task pane is created completely at run time. All of the control properties are specified at run time. They are created on the fly, and they are completely driven by code. So everything from the width, the height, the caption, and so forth is all driven by code.
Here we're specifying control properties for the ControlTypeFromID, and the ControlCaptionFromID. ControlTypeFromID is where we decide what kind of a control is this control with a given ID. For example, if the control ID were 101, I want the control type to be a C_TYPE_COMBO; for 102, I'd specify C_TYPE_LIST_BOX; for 103, a C_TYPE_BUTTON; and so forth. At this point we take a ControlID that we devised in the step on the previous slide. We take our ControlID, and then we tell it what kind of a control it is.
ControlCaptionFromID just provides a caption for the control, if you wish to have one.
At this point we've laid out our smart document. If we were to run it at the point to where we've created it so far, you would actually have a Smart Document task pane, and it would have controls in it. However, the controls probably wouldn't have any initial values, and they would not respond to actions. So we've pretty much completed the first part, which is to design the layout of the elements and controls.
Our next mission would be to initialize and populate those controls (slide 22). As I mentioned earlier, controls in a smart document solution are dynamic. They have to be initialized with common events. All of the controls for a smart document solution have Populate events that you use to populate various controls. When a Populate event is fired, a control identifier is passed in so that you know what control it is that you were supposed to populate at that moment.
Here I'll also point out that there is a RefreshPane method for each, the Excel and Word object models, that forces controls to update and that triggers another event, called OnPaneUpdateComplete.
Here let's take a look at some actual code to populate a text box (slide 23). As you can see, PopulateTextboxContent has a ControlID parameter. In our solution, we only have one text box, as you may recall. It was a text box for the Qty element. And it had a control identifier of 201. In the PopulateTextboxContent, we checked to see if this ControlID is 201. If it is, then we set the text, which is a parameter, which will be returned from this event, equal to the string, a value that we have specified.
Here's another Populate event (slide 24). This one in particular is PopulateListOrComboContent. This particular event will fire for any list boxes or any combo boxes in the smart document solution. Now, in our case we have a combo box and a list box, so we actually do have to check the ControlID to determine which one is triggering this event. Is it the Category ComboBox, or is it the Product ListBox? If it's the Category ComboBox, which has the ControlID of 101, then we just initialize the list for that combo box here. If it's the Product ListBox, which has the control identifier of 102, then we have two choices. If you remember, the Category drop down will dictate what selection the Product ListBox will be. So we do have to look at the category index here and say, "If the Category combo box has an index of 1, then I want to use one list, or if the index for the Category combo box is 2, I have another list I want to use." So on the fly we can tell it which list we want to show in the Product list box, and we can also set the initial value that is selected.
On the previous two slides we showed how to populate a text box. We showed how to populate the list box. And we showed how to populate the combo box. The only other controls that we haven't talked about are the buttons. And for buttons we really don't have anything we need to initialize, but we do want to respond to the user's actions. So that's our next focus, responding to user actions (slide 25). So if the user clicks a control, they change an item in a list box, they click a button, or they type text in a text box, then we'll have another event fire. And that's what you will see here on the slide.
When the user clicks or changes a control, a common event is fired. A control identifier is passed as a parameter to the event to identify the control at run time. This is similar to what we saw with all of the populate events. The various action events are OnTextBoxContentChange, OnListOrComboSelectChange, and so forth. You can certainly read those. In our case, we're probably going to be interested in InvokeControl the most. InvokeControl is what will fire when the user clicks one of the buttons.
Now, we will also use the OnListOrComboSelectChange event, because if the end user changes a value in our Category combo box, we want our Product list box to reflect that change. So we'll use the OnListOrComboSelectChange there as well.
Responding to user actions (slide 26). First, OnTextBoxContentChange fires when the Quantity text box is changed. And here we just want to retrieve the value that appears in the text box. For OnListOrComboSelectChange, if the user changes a value in the combo box for Category, we want to update the list in the list box. Here we use the RefreshPane method. For example, if the combo box for Category is changed and that's ControlID 101, and then we want to update our category index to indicate, did the user select a category of fruits or a category of produce? Based on the user selection, we'll fill in the category index appropriately. And then we call RefreshPane. RefreshPane will call back in to repopulate the controls. So after RefreshPane, our controls will be repopulated using any variables or any other information that we might have supplied at that time.
Now I will go over a couple of tips here or make note of a couple of points about RefreshPane. First of all, you should never use RefreshPane in any of the populate events. If you need to refresh the task pane, you should use the OnPaneUpdateComplete method instead. Now, if you do use RefreshPane and OnPaneUpdateComplete, then you need to be careful about not allowing your code to go into an infinite loop. So if you use RefreshPane and OnPaneUpdateComplete, you need to make sure that you have some way of issuing that RefreshPane and then stopping, rather than continually refreshing the pane and having a chance of getting yourself into a loop.
Responding to user actions (slide 27): the InvokeControl in our scenario is going to be fired when the user clicks one of the buttons, either the button that's in the Product element task pane, or the button that's in the Qty element task pane. When the user clicks a button, we want to take the values that we have already retrieved from the previous change events for the text box and the combo box, and the list box, take those values, and put them into our document.
Essentially, what we do with InvokeControl is we check to see if it's case 103, then the user has clicked the button in the Product element task pane. If that's the case, then we want to take their selection and take the value for the product and put that into the selected XML element. We do that through Target.XMLNodes(1).Range.Text, which you'll see at the bottom of this slide. A parameter to InvokeControl is a target parameter. The target parameter indicates what the target XML node is for this task pane. So from there you can actually drill down to the range so you know where to put the selected text.
Similarly, for the Qty element, if the user selects the button for the Qty element, which has a ControlID of 202, then we just take our quantity value and we put it into that range.
To this point you've completed all of the code. We've written all of the code that would be needed to build and run a smart document solution such that it lays out the controls, initializes and populates controls, and responds to user actions. That's a very basic example. Again, it will be available for download.
Now that we've created the code, we need to talk a little bit about the XML expansion pack (slide 28), which Ken did talk about in one of the earlier slides.
Recall that an XML expansion pack manifest file manages all of the components and files that are part of a smart document. The XML expansion pack manifest file specifies the location and name of the components that are required to make a smart document function. In addition, the XML expansion pack manifest file may specify setup information related to those files, including information Word or Excel might need to install and register COM components, and so forth.
On this current slide, this is by no means the complete XML expansion pack, but I just wanted to kind of highlight a few of the important parts of the XML expansion pack. You would want to reference the XML expansion pack manifest schema that's in the SDK for complete details. So let's just touch briefly on each of these elements.
First you'll notice that there is a manifest element at the root. Below the manifest element you have a Version element. The Version element specifies the version number for the manifest file and for files included with the XML expansion pack.
The URI specifies the uniform resource indicator that is associated with the XML expansion pack manifest file.
UpdateFrequency: this is the time that should elapse in minutes between client polls to the server to check for updates. For example, if you had a smart document solution that was running from a server, you could use update frequency of some given time to have the clients automatically poll your server to see if there is an update available.
Next you'll see that we have a Solution. And the solution is a wrapper element for a single solution in the schema library.
A solution has a SolutionID, which is a GUID or other unique identifier to identify the solution. It has a Type, so it could be smart document, a schema, a transform, and so on. It has a friendly name, which is an Alias. And of course, we also will have information about the File. So there could be information like the path, whether it's a managed component, whether or not it needs to be registered to function as a COM component, whether or not it would be run from the server, and so forth. So there's actually a whole lot of information that you will have in an XML expansion pack. My recommendation, when you're starting off creating smart document solutions, is to really borrow from some of the XML expansion packs that are already in the sample. That's usually the easiest way to approach those, until you become more familiar with them.
At this point we've created the code for our smart document solution. We've created the XML manifest or the XML expansion pack. The expansion pack was actually too large for me to show you on the screen. That's why I just simply provided you with an overview. But there will be an XML expansion pack in the download. So you have your assembly, you have your XML expansion pack, and we're going to assume that you have disabled the XML expansion pack security check using the registry key that Ken previously described for testing.
Given that the solution is ready to run, the first thing we do is create our document and attach our schema to the document and the markup (slide 29). Here we have the XML element with two child elements, Product and Qty. After the document is marked up, then we can attach the XML expansion pack. And at that point the smart document assembly will load. And if you select an element, either the Product or the Qty element, which we have document actions associated with, then those actions will appear in the task pane.
That's what you see in the next screen shot (slide 30). So if the user selects a product node within their document, then it's going to show the Document Actions task pane associated with the product. And if they select a Qty element in the document, it will show the document actions associated with the Qty element.
At that point our solution is pretty much complete. And of course this is a very simple example and we can build on it, but the few steps that we've gone through so far are at least enough to get a smart document solution up and running for you to test it, and you can then build on it further for your solutions.
So the next topic is some things that you should consider (slide 31) when you develop your own smart document solutions. The most important consideration is to keep in mind that task pane controls are dynamic, and as such, they do not maintain their state. Control state will revert to the value and the controls of the associated populate event. For example, text box, check box, radio button, combo box, and list box controls don't automatically maintain state when you use them in smart document solutions. So every time the task pane redraws a control, the state can revert to the value in an associated populate method. As a result, you should understand the various ways to maintain the state of these controls when planning and developing your smart document solution.
There are several ways that you could maintain state. One might be through global variables, which is what we've done in our example. There is a note there, and I will touch on that in a moment. Another way to maintain state might be to use the document itself to store your control values. So you could use the actual document variables, or you could use document properties to store your control values. Or at run time, in your .NET assembly, you could create your own custom collections to keep track of the various control states for each document action, for its associated document.
Let's go back and briefly just talk about using global variables, which is what I have done in the example that I just provided. When you use global variables to maintain state, you should be very careful about how you're handling those variables if you might have more than one document open with the same solution.
For example, let's consider the example that we've built. If I had one document associated, let's say I selected apples. Well, I would have a variable that stores that product for me as apples. So I start a new document, and at that point I have two documents open, with the same solution attached. I change the product to bananas. My global variable is updated to reflect bananas. But when I switch back to document 1, I'm still on bananas instead of apples, which is what you would probably expect, because apples is the last thing that you selected on that document.
Given that kind of a scenario, you really want to be careful. You can certainly use global variables, but you would want to be careful with them unless you're going to be certain that you will only have one document using your solution at any given time. Certainly, some of the other options might be better, particularly storing your control values in custom document properties, or actual document variables that would be stored with the document itself.
Another consideration is that you need to account for object model differences (slide 32). To this point we pretty much were just looking at it as a Word solution, but our smart document will actually run in Excel as well. There's only one thing that we would have to really change in the code, and that is in the InvokeControl event. As you recall, in an InvokeControl event we take the value out of a task pane and we insert it into our document. Well, if it were a workbook instead of a document, then the objects that we use in the Excel object model obviously are different than what we'd use in the Word object model. So, in our example, we really only have to make a couple of small changes here so that we can take our value and put it into a worksheet cell instead of a range in the document.
This takes us to troubleshooting (slide 33). There are a couple of things that you should check for troubleshooting, just to start off with. Now, troubleshooting is a very large topic, and I can't cover it all in one slide. But there is a document, which we will link to here shortly, where you can get more tips for troubleshooting your smart document solutions. Here I'll just give you some of the common things that people might run into.
First, you want to make sure that your XML in the XML expansion pack is valid and well formed. Although that might seem obvious, it's sometimes a very easy thing to overlook. But if your XML is not valid, then your solution will probably not run.
For managed code, we have to be sure to grant full trust to the assembly and restart the application. Now, I say here that we should restart the application because this is something that's also common to managed code extensions that you use with the Visual Studio tools for Office loader. Every time you update a .NET security policy, you need to be sure to restart all Office applications for those policy changes to take effect.
Now, I say all Office applications here because a common thing to trip you up would be if you're creating a smart document solution for Word, and you're also using Outlook, and Outlook is using Word as your e-mail editor. In this case you might have Word running and not realize it. So if you are using managed code extensions and you run into problems that you think could be associated with .NET security, then be sure to shut down all applications.
Another thing to check is that all of the dependent files are installed in the expected location and the location that's indicated in the XML expansion pack.
Then just a couple of tips here for debugging: Whenever you debug your Word smart document solution or your Excel smart document solution, there are basically three tips here that I would suggest. First of all, in your project properties, you want to set up WinWord or Excel.exe as the startup program for debugging. That way you can step through your code.
Second, in the Visual Studio .NET environment, under the Debug menu, there is an Exceptions option. There you can indicate for it to break on all errors. I would certainly recommend that you select that option for debugging.
Third, and I didn't mention it on the slide, but it's important for testing and development, is that it's probably easiest if you use the runFromServer option in your XML expansion pack. The reason for that is so that you don't have to worry about having your smart document solution built in one location and then cached and loaded from another. So for debugging purposes it's just easier to run it from the location from which you built it. And you can do that by using, I believe, the runFromServer element in the schema.
That pretty much concludes the presentation part of our WebCast. Here I do have some additional resources for you (slide 34). The download for the sample that we created will be available (http://download.microsoft.com/download/A/B/B/ABB079A4-5F02-4A9D-8384-12052C154C1D/SmartDocSample.exe). We have the link here to the SDK, which is definitely something you must have to develop these solutions.
Then we have three MSDN® articles that are very helpful. One is just kind of a hello world tutorial using ActiveX controls in smart documents (http://msdn.microsoft.com/library/en-us/dnofftalk/html/office09042003.asp). And then, of course, there is "Troubleshooting Smart Document Error Messages," (http://msdn.microsoft.com/library/en-us/dno2k3ta/html/odc_oftrsmartdocerrors.asp), which I previously referenced.
At this point, I believe we are open for questions.
Otto Cate: Thank you very much for the presentation.
Before we move on to the Q&A portion of the Support WebCast, I'd like to share a couple of quick program notes with our listeners. For more information on future events, or to review any of our sessions on demand, feel free to visit our main Support WebCast site at support.microsoft.com/webcasts/. There you'll also find the on-demand streaming media for this particular live session, within 24 hours, as well as a downloadable version of the PowerPoint® slides. And we also plan to have a full transcript posted there for you within two to three weeks' time.
We'd also like to ask you for any feedback you have about the events that we produce. Feel free to submit any feedback on today's event, subjects that you'd like to see in the future, or even the quality of the events that we produce. Anything is fair game there, and we'd certainly love to hear from you. You can use the URL support.microsoft.com/servicedesks/webcasts/feedback.asp. With that, let's answer some questions that were submitted during the presentation today.
When populating the section controls, I'm adding an object of a user-defined class — for instance, a customer — into a combo box within the PopulateListOrComboContent method. Is there a way for me to retrieve a reference to the selected item in the combo box in the InvokeControl method, just as I can in Windows Forms or Web Forms?
Lori: That's a good question. I think if I understand what your question is, it's that you want to programmatically acquire a reference to the combo box so that you can query the properties of that combo box at various points in your code.
The short answer to that is sort of no, because all of the controls, at least for the built-in controls, in a smart document solution are created on the fly. Anytime you need to query or set properties of those controls, it has to be handled in an event, kind of checking the control identifiers to determine if that's the control that you're looking for.
So if I understand the question here, you want to get to the control collection, and then from the control collection get a control and then the various properties. The short answer to that really is no.
What you would want to do is use the OnListOrComboSelectChange event to actually determine what is selected. If you are using your own custom classes for populating that list box, then you'd probably want to create a collection, and have that collection sync up with your list for your combo box. And then whatever index the user selects for the combo box, you could then use that same index to reference your custom collection.
Otto: Is there any public information available regarding the future plans for smart docs? For instance, ease of development or perhaps the UI?
Lori: I don't know of anything that I could really share at the moment. However, I will add that I would certainly recommend that you visit the Office development site on MSDN. Even well before Office 2003 released, there was all kinds of documentation and articles talking about these new features. So check the Office Developer Center on MSDN, and that will kind of give you ideas on what our forward directions for Office development will be.
Otto: The next question here: Are you aware of any EDMS vendors that are supporting the smart document technology within their document management environments that would actually help us build dynamic documents through user-selectable queries? For example, let's say a user opens a smart document that prompts the user for various information that would ultimately extract and import relevant elements from the EDMS to build a dynamic document. For instance, a scenario would be where a user needs to create a maintenance manual for specific assembly, and then is presented with a simple set of pull-down options that allow them to specify information such as "Include General Description," "Yes or No"; "Select product type" with a drop-down list; "Select model number" with a drop-down list; that kind of thing.
Lori: I don't know of an exact example that meets your specific requirements; however, just based on your description, it sounds like you might be interested in what's called the Proposals Accelerator, and that's something that's available for download from MSDN.
Proposals Accelerator is kind of a prepackaged or prebuilt end-to-end solution for building proposals. And the way that I think that it sort of matches what you're describing here is the proposals solution does use a smart document solution, and it allows users to build documents so they can take predetermined document fragments for various sections of the document and build documents. And then after they've completed it, at least for the proposals accelerator, they're stored on a SharePoint™ document library, I believe.
So you might want to just check out the proposals solution. While that may not meet your exact needs, it might at least give you an idea of how a similar solution might look.
Otto: The next question: How does this differ from or relate to using InfoPath™?
Lori: In a lot of ways I would say they're very similar. Actually, there would be some situations, like if you were building the small example that we created here, where I would probably say that InfoPath would be a better choice. However, if you have a situation where you need all of the formatting features that Word has available, that you're not going to get in InfoPath, then that's when you would want to decide if you need the features of Word. If you don't need the features of Word, then it's possible that InfoPath would be a good choice.
I'll give you one example a customer who we have worked with in the past who was creating a smart document solution for Word, and they were actually using a smart document solution to create an article. An article, obviously, has many different parts. It can have a summary, a resolution, a title, and things of that nature. And in that case they wanted to use Word formatting and have other Word features available. So in that case Word was the right choice for them. But it is possible that InfoPath can be a better choice. That really depends on your solution and what your requirements are.
Otto: The next question that we have here: Do you know some way that I can access ActiveX on the actionPertainsToEntireSchema section, either directly or indirectly?
Lori: I can't say that I know the answer to that right off. That's probably something I would have to take offline to see. I haven't tried that. So I will have to follow up offline with the person who asked that question.
Follow-up answer: The Smart Document SDK describes that the controls in an element with the name "#actionPertainsToEntireSchema" cannot be accessed through the object models for Word or Excel. Because you can only acquire an object reference to an ActiveX control by using the Range.XMLParentNode.SmartTag.SmartTagActions(<control>), you cannot acquire an object referencer to an ActiveX control in a #actionPertainsToEntireSchema element.
An alternative to using #actionPertainsToEntireSchema is to set the KeepAlive and ExpandToFill properties of the ActiveX control in the PopulateActiveXProps event:
Props.Write(Key:="KeepAlive", value:="true")
Props.Write(Key:="ExpandToFill", value:="true")
For more details on the KeepAlive and ExpandToFill properties, see the ISmartDocProperties Interface help topic (http://msdn.microsoft.com/library/en-us/sdsdk/html/sdobjISmartDocProperties.asp) in the Smart Document SDK.
Otto: Okay. Next question: I have been unable to get the managed SDK samples to work. I've been receiving the following error: "The XML expansion pack for the smart document program is missing or invalid." I've run the SetPolicy.bat file, as well as the .reg registry fix, and the issue still occurs. The unmanaged samples, however, run with no problems. Is this something that you've seen before?
Lori: First, I would definitely recommend that you look on our references slide. We had a link (http://msdn.microsoft.com/library/en-us/dno2k3ta/html/odc_oftrsmartdocerrors.asp) to an MSDN article for troubleshooting this error and other ones as well. So definitely use that as a resource.
I will mention you a couple of things that you might want to check. If you've used Setpolicy.bat, I would make sure that the policy is correct and that it's actually set up — that the policy is using the correct path to the .dll. The way that you get to that is you go through Control Panel, then double-click Administrative Tools, and in there you'll see an icon called Microsoft .NET Framework Configuration 1.1. And then from there you go to Runtime Security Policy, and you want to look at the security policies. If it's running from your local computer, you'd want to look at it at the user level. From there you'd want to check the policy and confirm that the path is valid. That's the first thing that I would check.
The second thing that you might want to check may not be an issue here. But just verify that the PIA for the Smart Tag type library is installed. By default, if you did a typical Office installation, the PIA is not installed. It's set to install on demand. On your development machine, you definitely do want to make sure that it's installed on the computer. You don't want it to be installed on demand, and you don't, obviously, not want it to be installed. So go through Windows, click Start, click Control Panel, double-click Add or Remove Programs, go through the Office setup, and just verify that setting for SmartTags 2.0, I believe it's listed as .NET Programmability Support. Make sure that's marked as Run from My Computer. That would be one thing to check.
Besides confirming that the policy is correct, if you're like me you may not have restarted your computer in a while. And you could have Word still running in the background. So whenever you change a security policy for .NET, you need to make sure that all instances of Word or Excel, or any other Office applications, have been shut down.
So there are a few things to check. But if that doesn't help, certainly you should take a look at the article on MSDN and follow some of its recommendations.
Otto: Are there any smart document samples available that use the XML configuration file instead of embedding the logic into the .dll file? This would actually help us facilitate deployment issues, and it might prevent .dll recompilation upon updates.
Lori: If I understand your question, you're looking at one of the Microsoft Office Smart Tag List (MOSTL) examples. There is an example on MSDN. I don't know what the article is offhand, but I believe that's your question. And we do have one example on MSDN, and there might even be one in the SDK that's just straight XML based and requires no code. However, if you use the MOSTL-based smart document, then it is a very, very basic smart document. You certainly don't have all of the flexibility that you have in code. But I can understand your question regarding deployment. That would certainly be an easier solution to deploy.
Follow-up answer: If your smart document implementation does not require the Smart Document API, you can build simple smart documents by writing an XML file that conforms to the MOSTL Schema. For an example, see the "MOSTL Smart Document Sample" topic in the Smart Document SDK. You can find another example of a MOSTL Smart Document at: "Smart Documents Development Overview."
Otto: Are there any off-the-shelf products available that would allow me to digitally sign solutions that are different than the one that ships with the SDK?
Lori: Not to my knowledge. Now, the one for the XMLSign tool that ships with the SDK, the XMLSign tool works perfectly fine for signing your XML expansion pack. But you certainly do need to have a certificate that has been issued by an authentication authority, such as a VeriSign. I'm sure there are plenty of others. But XMLSign should be fine, as long as you have a valid certificate.
Otto: With that, it appears that we've answered all of the questions that were submitted to the queue today, so I'm going to wrap up our session.
I wanted to thank our presenter for coming out and giving us a great presentation. And of course, as always, we'd like to thank you, our listeners, for attending today's event. We certainly hope that this information was useful to you and your business, and we look forward to seeing everyone again in the near future.
Thank you, everyone, and have a great day.
|