Personal website of Gregory K. Maxey, Commander USN (Retired)
Do you have ad-blocking software enabled? While I respect your right to do so, your donations and the minimal advertisements on this site help to defray internet and other costs of providing this content. Please consider excluding this website from blocking or turning off the blocker while browsing this site.
The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.
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 , I kept asking myself what I might be able to use them for and so, I started tinkering.
This tips page demonstrates three ideas and techniques that I developed for employing a CustomXMLPart in a Word document.
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."
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.
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.
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.
Perhaps you can employ this technique to create you own dynamic document template such as an invoice or purchase order? Good luck!
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.
Using custom controls on the Quick Access Toolbar (QAT), the document user can:
When a slide show is initiated, the use is prompted to set the slide interval (in seconds). The default interval is 1 second.
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.
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.
Note: 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.
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.
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.
The following VBA procedure is used to map a collection of building block content to a collection of CustomXMLNodes in a document CustomXMLPart:
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 _ ("email@example.com").Item(1) If Err.Number = 0 Then oCXPart.Delete End If On Error GoTo 0 'Create the new CustomXMLPart. ActiveDocument.CustomXMLParts.Add _ ("<BuildingBlocks firstname.lastname@example.org'/>") Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace _ ("email@example.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.
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.
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 _ ("firstname.lastname@example.org").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.
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
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.