was working on an internal project a bit ago and one of the requirements was to implement
a fancy Word document. The idea was that all of the editing of the text/code
samples/etc. would be done in the application and then the user could just export
it to Word to put any finishing touches and send off to the customer. The final
report needed to include section headers, page breaks, a table of contents, etc.
There are a number of ways we could have accomplished the task. There’s
the Word automation stuff that relies upon a COM based API, there’s the method
of just creating an HTML document and loading that into Word and then finally there’s
the Open XML API. Now, someone had hacked up a version of this export functionality
previously using the Word automation stuff but considering we’re often dealing with
1,000+ page documents – it turned out to be a little slow. Also,
there are some restrictions around using the automation libraries in a server context.
Lastly, since my OpenXML kung-fu is strong, I thought I would take the opportunity
to implement a better, more flexible and much faster solution. For
those just starting out, Brian and Zeyad’s excellent blog on the topic is invaluable.
One of the requirements for the export operation was to have Word automagically refresh
the table of contents (and other fields) the first time the document is opened.
This was something that took a bit of time to research but you really end up with
– A document-level element that will refresh all of the fields when the document is
– A field-level attribute that will refresh ONLY the field you specify when the document
The “w:updateFields” element is a document-level element that is set in the document
settings part and tells Word to update all of the fields in the document:
If you’re wondering what the document settings part is – just rename a Word doc from
“blah.docx” to “blah.docx.zip” and extract it to
a folder on your computer. In the new folder is a directory called “word”.
In that directory, you should see a file called “settings.xml”:
that file are all of the document level settings for your docx. There’s
some really great stuff in here.
If you’d like to use the OpenXML
SDK to set that value (and you’d be crazy not to), here’s some sample code:
This attribute is applied to the field you would like to have refreshed when the document
is opened in Word. It tells Word to only refresh this field the next time the
document is opened. For example, if you want to apply it to a field like your
table of contents, just find the w:fldChar and add that attribute:
For a simple field, like the document author, you’ll want to add it to the w:fldSimple
element, like so:
A caveat or two
Both of these methods will work just fine in Word 2010.
In Word 2007, though, you need to clear out the contents of the field before the user
opens the document. For example, with a table of contents, Word will normally
cache the contents of the TOC in the fldChar element. This is good, normally,
but here it causes a problem.
For example, in a very simple test document, you would see the following cached data
(i.e.: Heading 1, Heading 2, etc.):
After you clear out the schmutz,
you end up with just the begin element, the definition of the TOC and the end element:
Once you’ve made the updates, you can safely open up your file in Word 2007 and your
fields will update when the document opens.
Just to stress, this is improved in Word 2010 and you no longer need to clear
out the cached data in your fields.