Storing custom XML in a Word document

K

Kevin M.

Hello,

I'm currently writing an add-in for word, and I'm trying to figure out
how I can store XML data pertaining to the add-in within the document.
I've looked into XML mapping a little, but that doesn't seem to be
exactly what I want.

Basically, my add-in has document-specific settings and the ability
for users to enter document-specific data. If two users are sending a
document back and forth, and assuming both have the add-in installed,
I'd like for them to be able to view the document with the same
settings preserved.

I know that a .docx file is really just a .zip file with a bunch of
XML files within. How can I programmatically add my own?

Thanks,
Kevin
 
P

Peter Jamieson

You could also consider using Word Document Variables for this.

However, here's a bit of code that shows you a small amount about using
custom XML - you don't actually need to do any Content COntrol mapping
to use it.

Sub CreateMyCustomXMLPart()
Dim objPart As Office.CustomXMLPart
' Let's remove any previously created
' custom XML parts
Call RemoveBuiltOutCustomXMLParts
' Create a part and set its XML.
' Or you can create, then .LoadXML from a string
' or .Load from a file. But you can only set the
' XML once
' Let's give it three namespaces (blank, mynsURI1 and mynsURI2)

Set objPart = ActiveDocument.CustomXMLParts.Add( _
"<myns1:MyXMLDoc xmlns:myns1=""mynsURI1"" xmlns:myns2=""mynsURI2"">" & _
"<Element0>E0value</Element0>" & _
"<myns1:Element1>E1value</myns1:Element1>" & _
"<myns2:Element2>E2value</myns2:Element2>" & _
"</myns1:MyXMLDoc>")


' Verify that the part is there
Debug.Print objPart.XML

' Word creates a GUID for the part
' So we can get that part by noting the GUID and hard-coding it
' into the line in the next Sub that starts
' Set objPart = ActiveDocument.CustomXMLParts.SelectByID
Debug.Print objPart.ID
' or we can use the Namespace to get it
Debug.Print objPart.NamespaceURI


Set objPart = Nothing

' Now ensure that you did this:
' Note the GUID and hard-code it
' into the line in the next Sub that starts
' Set objPart = ActiveDocument.CustomXMLParts.SelectByID

' Then save, close and re-open your document and
' try the next Sub
End Sub

Sub WorkWithMyCustomXMLPart()
Dim objCustomXMLPrefixMapping As Office.CustomXMLPrefixMapping
Dim objPart As Office.CustomXMLPart
Dim objParts As Office.CustomXMLParts

' Show that we can use a GUID to retrieve the part.
' But that's probably only a viable option if you
' always ensure that you use the same GUID, which you could
' probably do if you inserted your part "by hand" outside
' the Word object model. But if you ever have to set it up
' "on-the-fly", Word will assign a new GUID and you would have
' to store the GUID somewhere to be able to re-use it -
' probably more trouble than it is worth
Set objPart =
ActiveDocument.CustomXMLParts.SelectByID("{2C1B27A1-E739-4EE5-8C2E-9ADE72DD63B5}")

' Still there?
Debug.Print objPart.XML
' Namespace URI
Debug.Print objPart.NamespaceURI
Set objPart = Nothing

' Probably simpler to get the part using its Namespace, we we can define
' There could be more than one part with this namespace...
Set objParts = ActiveDocument.CustomXMLParts.SelectByNamespace("mynsURI1")
For Each objPart In objParts
Debug.Print objPart.XML
Debug.Print objPart.ID
Debug.Print objPart.NamespaceURI
Next
' I guess you need to be sure that there is only one, or
' take the first one if there are more. Or some such.
Set objPart = objParts(1)
Set objParts = Nothing

''Debug.Print objPart.ID

' Want to change the value of Element1?
' Let's find out what namespace prefixes Word
' is using
' Let's also see what namespace prefixes Word has decided
' to use

' We'll need these to reference elements using XPath
For Each objCustomXMLPrefixMapping In objPart.NamespaceManager
Debug.Print
Debug.Print objCustomXMLPrefixMapping.Prefix
Debug.Print objCustomXMLPrefixMapping.NamespaceURI
Debug.Print
Next

'Or we can look up a prefix given the NamespaceURI
Debug.Print
Debug.Print objPart.NamespaceManager.LookupPrefix("mynsURI2")

' or vice versa
Debug.Print
Debug.Print objPart.NamespaceManager.LookupNamespace("ns0")

' That would let you provide the correct prefixes
' but here I've just hard-coded them. And you can
' probably deduce them from your XML anyway

' Update a value
objPart.SelectSingleNode("/ns0:MyXMLDoc[1]/Element0[1]").text = "mynewtext"
Debug.Print objPart.XML
Set objPart = Nothing
End Sub

Sub RemoveBuiltOutCustomXMLParts()
' Clears out old custom XML Parts
Dim objPart As Office.CustomXMLPart
For Each objPart In ActiveDocument.CustomXMLParts
If Not objPart.BuiltIn Then
objPart.Delete
End If
Next
End Sub
Peter Jamieson

http://tips.pjmsn.me.uk
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top