Resting Anchor

The Anchorage

Personal website of Gregory K. Maxey, Commander USN (Retired)

Tinkering with CustomXMLParts
(A Microsoft Word Help & Tip page by Gregory K. Maxey)

DISCLAIMER/TERMS OF USE

The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.

If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!


I'm a tinkerer.  If you've spent any amount of time browsing my various tips pages, that should not come as a surprise.

Not long ago, I became interested in working with CustomXMLParts in VBA procedures and I published CustomXML "Helpful" Help for Word.  Of course I had been aware of CustomXMLParts since they were first introduced with Word 2007; but, with the exception of using them for simple Cntent Control Mapping, they had remained a bit of a mystery to me.

While I was learning more and more about what CustomXMLParts are animated icon, I kept asking myself what I might be able to use them for animated icon think and so, I started tinkering.

This tips page demonstrates three ideas and techniques that I developed for employing a CustomXMLPart in a Word document.

Basic Data Store animated icon idea

As explained in CustomXML "Helpful" Help for Word, a CustomXMLPart is basically:

This first technique is probably a more traditional use of XML data.  In this demonstration, I'm going to convert raw data stored in an external Word document table into XML data stored as a CustomXMLPart in the project template file.

Documents created from the project template can be sent to other users who do not have access to the external file. However, since the data in the external file is contained in a document CustomXMLPart, the document functions for these users just as it functions for you!

The project template for this demonstration consists of a single four column Word table with content controls as shown below.  The content controls in column 1 are "empty" dropdown content controls titled "Item."

custom xml tinkerings 1

custom xml tinkerings 2

The external raw data is extracted from a table contained in a separate Word document shown below.  This file can be named and stored anywhere on your PC or network.  For the purpose of this demonstration the file is named "External Table Data.docm" and stored in the root directory.

custom xml tinkerings 3
C:\External Table Data.docm

Site Note Icon Note: You can download the demonstration project document and sample "External Table Data" file using the demo package link located at the end of this page.  Be sure to save the "External Table Data.docm" file directly in the "C:\" root directory for your computer.

Document users select from items listed in the "Name" column content controls.  After a selection is made and the user tabs or clicks out of the content control, the content control OnExit event procedure fills in the remaining columns of the selected row using data from the CustomXMLPart.

custom xml tinkerings 4

custom xml tinkerings 5

When the users exits the "Item" content control in the last row, a prompt is generated to determine if an additional new row is required.

custom xml tinkerings 6

custom xml tinkerings 7

Perhaps you can employ this technique to create you own dynamic document template such as an invoice or purchase order?  Good luck! 

Picture Slide Show animated icon idea

After figuring out the basics, I started thinking out of the box a little.  I thought, "If I can map a single picture type content control to a single CustomXMLNode of a CustomXMLPart, why not map a whole collection of pictures to a whole collection of CustomXMLNodes?"

This way I can select a single picture that I want to display in my document, or I can display the entire collection of pictures as a Word document slide show!

The following illustrates a representative document employing this technique. The document consists of a single picture content control used to display an image and a dropdown content control used to caption the displayed image and to select the image to display from the collection of stored images.

custom xml tinkerings 8

Using custom controls on the Quick Access Toolbar (QAT), the document user can:

custom xml tinkerings 9

When a slide show is initiated, the use is prompted to set the slide interval (in seconds). The default interval is 1 second.

custom xml tinkerings 10

Clicking the QAT "Load Images" controls displays two dialogs to the user.  The first asks the user if the images to load are in the users default "My Pictures" folder.  This makes navigating to the image folder easier.  The second dialog asks the user to select the folder containing the images to load.

custom xml tinkerings 11

First prompt.



Second promt

After a momentary delay (length will be determined by your PC processor speed, file size and the number of images to load), the new collection will be ready for viewing in the document.

Site Note IconNote:  Due to the typically unnecessarily large file size of most digital images, this technique has the potential to produce documents of an extraordinarily large if not impractical file size.  The collection of semaphore flags used in the project demonstration document were small .gif format flags which produced a reasonable display quality and overall file size.  For practical applications, you will need to consider image size and display quality as compared to a practical document file size.  There are lots of software applications that you can use to resize digital images.

custom xml tinkerings 13
Are you a home inspector or realtor?  Perhaps you can employ this technique to create you own dynamic document such as an inspection report or property listing. Good luck!

Pseudo Building Blocks animated icon idea

This final technique is a limited to Word 2013 users (and Word 2013 compatible file formats) which has the capability to map rich text content controls.

Basically, a building block is the saved (or stored) content of a defined range.  See: Building Blocks & AutoText.  With the exception of the most basic text building blocks; a building block, in addition to the basic text, will contain a variety of text attributes (e.g., font size, color, spacing, etc.).  A building block may also contain, in addition to text, other objects such as charts, graphs, or shape objects.  All of these possibilities conspire to make a plain text building blocks rare and "rich text" building blocks common!

Building blocks are stored in templates.  This means that you can only use and employ building blocks when you have access to the template that they are stored in.  Once you send a document to someone else and the link with the template is broken, the new user is unable to use those building blocks.

However, in Word 2013 you can map rich text content controls to a CustumXMLPart.  Since  Building blocks are just a form of "rich text" content, it seems that we should be able to map a collection of building blocks to a collection of CustomXMLNodes in a CustomXMLPart.

If this is true, then our "pseudo" building blocks stored as mapped rich text content in a CustomXMLPart will be available to other users without access to the template!  Let's have a go at it.

I have created and saved five building blocks depicting signatures of five famous American political figures. These building blocks are stored in a custom category "Signatures" in the Custom 1 gallery of my Building Blocks.dotx template.

custom xml tinkerings 14

The project document for this demonstration consists of an empty drop-down content control used to list and select a pseudo building block and an empty rich text content control used to map and display the building block content.

custom xml tinkerings 15

The following VBA procedure is used to map a collection of building block content to a collection of CustomXMLNodes in a document CustomXMLPart:

VBA Script:
Sub StoreBuildingBlocksInCustomXMLPart()
Dim oCXPart As CustomXMLPart
Dim oCC_BuildingBlock As ContentControl, oCC_Select As ContentControl
Dim lngIndex As Long
Dim oTmp As Template
Dim oBBT As BuildingBlockType
Dim oBB As BuildingBlock
  
  'Load the built-in building block templates.
  Templates.LoadBuildingBlocks
  
  'Reload a fresh CustomXMLPart to store the building blocks.
  On Error Resume Next
  'Kill any existing CustomXMLPart used previously.
  Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace _
               ("http//buildingblocks@namespace.com").Item(1)
  If Err.Number = 0 Then
    oCXPart.Delete
  End If
  On Error GoTo 0
  'Create the new CustomXMLPart.
  ActiveDocument.CustomXMLParts.Add _
                 ("<BuildingBlocks xmlns='http//buildingblocks@namespace.com'/>")
  Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace _
                ("http//buildingblocks@namespace.com").Item(1)
  
  'Set up the document content controls.
  Set oCC_BuildingBlock = ActiveDocument.SelectContentControlsByTitle _
                          ("Building Block").Item(1)
  Set oCC_Select = ActiveDocument.SelectContentControlsByTitle("Select Content").Item(1)
  'Clear any existing entries in the drop-down content control.
  For lngIndex = oCC_Select.DropdownListEntries.Count To 2 Step -1
    oCC_Select.DropdownListEntries(lngIndex).Delete
  Next lngIndex
  
  'Get the collection of building blocks.
  For Each oTmp In Templates
    'Get the template that stores the building blocks.
    If oTmp.Name = "Building Blocks.dotx" Then
      Exit For
    End If
  Next
  'Get the gallery that stores the building blocks.
  Set oBBT = oTmp.BuildingBlockTypes(wdTypeCustom1)
  'Get the individual building blocks in the "Signatures" category.
  For lngIndex = 1 To oBBT.Categories("Signatures").BuildingBlocks.Count
    Set oBB = oBBT.Categories("Signatures").BuildingBlocks(lngIndex)
    'Add a CustomXMLNode to store the building block data.
    oCXPart.AddNode oCXPart.SelectSingleNode _ 
        ("ns0:BuildingBlocks"), "BuildingBlock", , , msoCustomXMLNodeElement
    'Map the rich text content control to the CustomXMLNode.
    oCC_BuildingBlock.XMLMapping.SetMapping _
         "ns0:BuildingBlocks/BuildingBlock[" & lngIndex & "]", , oCXPart
    'Insert the building block into the rich text content control.
    oBB.Insert oCC_BuildingBlock.Range, True
    'Break the mapping link between the rich text control and the CustomXMLNode.
    oCC_BuildingBlock.XMLMapping.Delete
    'Add the building block name to the drop-down content control list.
    oCC_Select.DropdownListEntries.Add oBB.Name, lngIndex, lngIndex + 1
  Next
  'Select the default drop-down list entry.
  With oCC_Select
    .DropdownListEntries(1).Select
    .Range.Select
  End With
  Selection.HomeKey
  Set oCC_BuildingBlock = Nothing
  Set oCC_Select = Nothing
  Exit Sub
lbl_Cancel:
  On Error Resume Next
  oCXPart.Delete
  On Error GoTo 0
End Sub

Once the building blocks are mapped to the CustomXMLPart, the list of building blocks is displayed in the drop-down content control.

custom xml tinkerings 16

When the user selects and exits the drop-down content control, the Document ContentControl_OnExit event is used to remap the rich text content control the appropriate CustomXMLNode used to store the building block content.

VBA Script:
Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, _
                                          Cancel As Boolean)
Dim oCXPart As CustomXMLPart
Dim oCC_BuildingBlock As ContentControl
Dim oLEs As ContentControlListEntries
Dim oLE As ContentControlListEntry
  
  Select Case ContentControl.Title
    Case "Select Content"
      'Get the CustomXMLPart used to store data.
      Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace _
                   ("http//buildingblocks@namespace.com").Item(1)
      Set oLEs = ContentControl.DropdownListEntries
      'Determine which drop-down list entry is selected.
      For Each oLE In oLEs
        If oLE = ContentControl.Range.Text Then
          Exit For
        End If
      Next
      'Configure the Building Block CC.
      Set oCC_BuildingBlock = ActiveDocument.SelectContentControlsByTitle _
                              ("Building Block").Item(1)
      If ContentControl.ShowingPlaceholderText Then
        'Clear the content if nothing is selected in the drop-down.
        oCC_BuildingBlock.Range.Text = ""
      Else
        'Otherwise, remap the CC to the CustomXMLNode storing the building block content.
        oCC_BuildingBlock.XMLMapping.SetMapping _
                     "/ns0:BuildingBlocks/BuildingBlock[" & oLE.Value & "]", _
                     , oCXPart
      End If
    Case Else
      'Do nothing.
  End Select
lbl_Exit:
  Set oCXPart = Nothing
  Set oCC_BuildingBlock = Nothing
End Sub

The Building Block content control remapped to the appropriate CustomXMLNode will display the stored building block content.

custom xml tinkerings 17

Conclusion

That's it! I hope the three techniques I've demonstrated here will help you to understand and employ CustomXMLParts in your document solutions.  You can download the three project demonstration files and external table data file used to create this tips page here:  Demo Pack

Share

PAYMENTS/DONATIONS

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

Do you want to make a payment for consulting work or donate to help support this site?

PayPal is a safe, easy way to pay online.

Use the appropriate currency "Donate" button to make a payment or donation.


Search my site or the web using Google Search Engine

Google Search Logo