Browse DevX
Sign up for e-mail newsletters from DevX


Designing Smart Documents in Office 2003 : Page 8

Today, most organizations have a wealth of Office documents that contain critical information, but finding, extracting, and reusing that information programmatically remains a largely unrealized goal. Fortunately, that's changing as XML processing in Microsoft Office 2003 grows up.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Rendering and Populating Controls
The API now calls the ControlCaptionFromID for each XMLType registered in the current context. You have the documentRoot applied at the entire document level and registered as a SmartNode with the API. Therefore, under the current context ControlCaptionFromID initially receives the ControlID 101 as a parameter. Some crucial things about this property are:

  • It defines a caption if the Control type is one defined in the Office API, for example, C_TYPE_BUTTON, C_TYPE_LINK, etc.
  • If the control defined for this ControlID is an ActiveX type, you use this property to return the GUID of the ActiveX Control.
  • This method is called twice for each control; therefore you should minimize any logic or complex operations performed here.
Consider the DocumentRoot implementation in SmartControls.vb as shown below:

Public Overrides Function ControlCaptionFromID( _ ByVal ControlID As Integer) As String ControlID = DocumentUtils.GetRealControlID( _ ControlID) Select Case ControlID Case 1 Return "{" + Controls.CustomerList.CLASSID + "}" Case 2 Return "Select" End Select End Function

The method returns the ClassID of the ActiveX control configured for the specified ControlID, while for a Link control (case 2) it returns "Select." However, remember that the actual ControlCaptionFromID has an enriched signature (see CustomerDocument.vb). It has parameters of the target range, xml associated for this control and the text contained in the XMLNode.

After executing the preceding property for case 1, the API makes a call to PopulateActiveXControl method. This call initializes the CustomerList ActiveX control. You can see this control developed in managed code and later registered as ActiveX. The control lists the existing customers in the database and is rendered on the task pane while you are in a documentRoot context. On selection of a customer, the name is applied within the customerName tag. This control is displayed as seen in Figure 4 and exposes the important methods shown in Table 5:

Table 5. CustomerList ActiveX Control Methods: The table shows the list of methods exposed by the CustomerList ActiveX control.
Method Description
BindData Takes an optional XMLNode that is used to populate the associated ListBox of the user control.
SelectedCustomerID Returns the ID of the selected customer.
SelectedCustomerName Returns the Name of the selected customer.

A full discussion of the implementation of this user control is outside the scope of this article. This control was added to provide you with a sample of how to display user controls on the task pane; look at the enclosed template for the exact functionality. Note that you have to register the control, so you could see the ComClass attribute. For the documentRoot type here's the PopulateActiveXProps implementation.

Public Overrides Sub PopulateActiveXProps( _ ByVal ControlID As Integer, _ ByVal ApplicationName As String, _ ByVal LocaleID As Integer, _ ByVal Text As String, _ ByVal Xml As String, _ ByVal Target As Object, _ ByVal Props As Microsoft.Office.Interop. _ SmartTag.ISmartDocProperties, _ ByVal ActiveXPropBag As Microsoft.Office.Interop. _ SmartTag.ISmartDocProperties) ControlID = DocumentUtils.GetRealControlID( _ ControlID) Select Case ControlID Case 1 With Props .Write("W", "136") .Write("H", "136") End With documentNode = CType(Target, _ Word.Range).XMLNodes(1) End Select End Sub

The Props argument specifies a set of predefined as well as custom properties using the Write method. This method has a key/value parameter. In the above case the width (W) and height (H) of the control are set to 136. For a list of available properties refer to this documentation. Further note that you can set the context of the current node by using the target parameter.

Table 6 provides a list of the populate methods that the API calls based on the assigned Control type.

Table 6. The table contains a list of the populate methods called by the Office API for the assigned Control type.
Method Description
PopulateActiveXProps Called when the control type for the corresponding ControlID is C_TYPE_ACTIVEX
PopulateCheckbox Called when the control type for the corresponding ControlID is CHECKBOX
PopulateHelpContent Called when the control type for the corresponding ControlID is C_TYPE_HELP or C_TYPE_HELPURL. In the case of later a URL is specified and for the former you can set the content as string
PopulateImage Called when the control type for the corresponding ControlID is C_TYPE_CHECKBOX
PopulateListOrComboContent Called when the control type for the corresponding ControlID is C_TYPE_LISTBOX or C_TYPE_COMBO.
PopulateOther Called when the control type for the corresponding ControlID is other than those for which there are already specific Populate methods. E.g. C_TYPE_LINK, etc.
PopulateRadioGroup Called when the control type for the corresponding ControlID is C_TYPE_RADIOGROUP
PopulateTextboxContent Called when the control type for the corresponding ControlID is C_TYPE_TEXTBOX
PopulateDocumentFragment When the control type is C_TYPE_DOCUMENTFRAGMENT or C_TYPE_DOCUMENTFRAGMENTURL for the associated ControlID this method is invoked. You can specify a text or URL for this.

Going back to the sample application, there are two controls defined in the current context—in the documentRoot—an ActiveX control, and a Link. The first call renders only the ActiveX control. During the second call, the API calls ControlCaptionFromID again using the ControlID 102 for the Link control. Because the control is a C_TYPE_LINK, it then executes the PopulateOther method, as defined in Table 6, since that's categorized to the populate event for this method.

When the process described above is complete the API executes the OnPaneUpdateComplete method. At this point you could access all the controls and perform actions, for example, updating all the controls for the document action pane. So far, you've assigned the ActiveX control to render using the W and H properties but have not loaded the data. In the OnPaneUpdateComplete method you can get a reference to the control and load data as shown below:

Private customerListCtl As Controls.CustomerList Public Overrides Sub OnPaneUpdateComplete( _ ByVal Document As Object) If Not documentNode Is Nothing Then customerListCtl = CType( _ documentNode.SmartTag.SmartTagActions(1). _ ActiveXControl, Controls.CustomerList) customerListCtl.BindData() End If End Sub

The important line in the snippet is:

documentNode.SmartTag.SmartTagActions(1). _ ActiveXControl

The documentNode.SmartTag returns the context of the XMLType, such as http://Officesamples/Customer/2004#documentRoot. Then you can either specify an index or the name used in ControlNameFromID on the SmartTagActions object. The sample gets the ActiveX control using the index. In addition, you can use other properties/methods to check the state of the controls. The final line uses the BindData method to bind the data within the controls.

Author's Note: It is important to understand that you can do an explicit refresh on the document actions pane, for example: CType(Document,Word.Document).SmartDocument.RefreshPane()

If you're using the above snippet inside the OnPaneUpdateComplete method after doing some actions be aware that you might cause an infinite loop. So have the method execute only under specific conditions.

That completes the implementation for the root node of the template. To rehash, Figure 4 provides an overall view of properties and their influence on the document actions task pane.

Figure 4. How ISmartDocument Properties Map to the Implementation: The figure provides an overall view of how the properties for the ISmartDocument interface map to the documentRoot implementation.
The documentRoot context makes it possible for a user to select a customer and click the "Select" link to apply the value. The following code snippet shows the method executed when a user clicks the link.

Public Overrides Sub InvokeControl( _ ByVal ControlID As Integer, _ ByVal ApplicationName As String, _ ByVal Target As Object, _ ByVal Text As String, _ ByVal Xml As String, _ ByVal LocaleID As Integer) ControlID = DocumentUtils.GetRealControlID( _ ControlID) Select Case ControlID Case 2 If Not documentNode Is Nothing Then Dim selectedValue As String = _ customerListCtl.SelectedCustomerName() If Not selectedValue Is Nothing Then DocumentUtils.document.Range. _ XMLNodes(4).Text = selectedValue End If End If End Select End Sub

The InvokeControl method gets called whenever a user clicks a control of type C_TYPE_BUTTON, C_TYPE_LINK, C_TYPE_DOCUMENTFRAGMENTURL or C_TYPE_DOCUMENTFRAGMENT. Again you need to distinguish the appropriate control using the ControlID. The preceding code retrieves the user-selected customer name and assigns it to the fourth node of the document which is the customername node.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date