How to safely update a document's styles from its template without using the Organizer (and how to make the Tools + Templates and Add-ins dialog safe)

Article contributed by Dave Rado, Margaret Aldis, Ian Sharpe and Beth Melton

Overview of updating styles and template strategy

If you want to update the style definitions of a document with the style definitions in its attached template, you can manually select Tools + Templates and Add-ins, check the box which says Automatically update document styles, click OK; and then, because that setting is sticky (and most of the time, undesirable), immediately select Tools + Templates and Add-ins again, deselect the Automatically update document styles box, and click OK.

If the attached template is Normal.dot, this doesn't work in Word 97; but it works for all other attached templates in Word 97; and it works for all templates, including Normal.dot, in later versions of Word. (It can be made to work in Word 97, even if the attached template is Normal.dot, with a little programming – this is covered below).

It is important to realise that the only styles that are updated when you update a document's styles from its  template are the ones listed in the template itself under Styles in use (in the Style dialog, where it says List). So if a user modifies the definition of a built-in style in their document, but that style was not listed under Styles in use in the template, then updating their styles from the template will have no affect on that particular style definition. Because of this, if you are a template designer, you must ensure that any built-in styles which you want control over are listed under Style in use.

The best way to add a built-in style to the In use list is to insert it in the template (first redefining it if required). You could use a dummy paragraph for the purpose, and delete it again once you have finished applying your styles. The styles, having been applied once, will remain in the In use list for ever more.

When should styles be updated?

The Automatically update document styles setting is document-specific, and if left switched on when a particular document is saved, will update that document's styles whenever it is opened by anyone (until the document is saved again with the setting switched off).

This is usually undesirable, because, whereas one would want a document's styles to be updated whenever a style in its template is redefined while a document is being revised, once the document is live, one would definitely not.

Also if emailing to an external reviewer who does not have access to the template, the setting should emphatically not be switched on.

So in a corporate context, it's best never to save a document with its Automatically update document styles setting switched on. Instead, assuming you have a version control strategy, store the draft/live status of a document in a document variable (or document property); and by using an AutoOpen macro to read the variable or property, update the styles if it's in Draft mode, but not if it's Live.

In addition, your users may want to update a document's styles using the dialog, if their style definitions have been mangled. Updating a document's styles from its template is a lot faster than using the Organizer (and subject to the qualifications below, seems to be more reliable, as well).

Gotchas to be aware of, and their workarounds

As has already been mentioned, updating styles from the template doesn't work in Word 97 if the attached template is Normal.dot.

More seriously, in all versions of Word, updating styles can sometimes mangle your style definitions, especially in the case of numbering styles, where it can sometimes destroy the link between the styles and their List Templates.

But the good news is that updating styles can be made reliable, as follows.

1.

For it to be reliable, your numbering styles must use named List Templates. See the links at How to cure Word's List Numbering with a dose of VBA for more details.

2.

All the styles in the Styles in Use list need to have been physically applied to text  in the template once (but they do not need to have been applied in documents based on the template). What the difference is, in terms of the flags stored inside a template file, between a style that is listed in the In use list but has never been applied to text, and one that has been applied, is a mystery; but it seems there is a difference.

Unfortunately, it is all too easy to add a style to the Styles in Use list without ever applying the style to any text. In the case of built-in styles, you can do this manually by selecting Format + Style, where it says List, select All styles, and click Modify + OK + Close. Or programmatically, you can add it to the In use list by running code that defines the style.

In the case of custom styles, you can add them to the In use list without applying them to text by selecting Format + Style + New + OK + Close; or programmatically, by defining a new style without applying it.

Styles (especially numbering styles) that are listed in the In use list of a template, but have never physically been applied to text, will not be stable if you update your styles from the template. So if in doubt, it is a good idea to insert a dummy paragraph in each of your templates, cycle it through all the styles in the template's In use list, delete the dummy paragraph, and save the template. And if you subsequently need to redefine any of the styles in the template, it is again a good idea to apply the redefined style to a dummy paragraph.

3.

Sometimes, you have to do the update twice or occasionally even three times in order preserve your List Template names and their links to your numbering styles:

Dim oLT As ListTemplate
ActiveDocument.UpdateStyles
ActiveDocument.UpdateStyles
On Error Resume Next
For Each
oLT In ActiveDocument.AttachedTemplate.ListTemplates
    If Not oLT.Name = "" Then
        If Not ActiveDocument.ListTemplates(oLT.Name).ListLevels(1) _
                .LinkedStyle = oLT.ListLevels(1).LinkedStyle Then
            ActiveDocument.UpdateStyles
            Exit For
        End If
    End If
Next
oLT

No theories as to why this might be; it's a bug; but at least there is a workaround.

You can make the Tools + Templates and Add-ins dialog safe for users to use by intercepting the Word command as follows:

Sub FileTemplates()

With Dialogs(wdDialogToolsTemplates)
    .Show

    If .LinkStyles = 1 Then
        ActiveDocument.UpdateStyles
        Dim oLT As ListTemplate

        On Error Resume Next
        For Each
oLT In ActiveDocument.AttachedTemplate.ListTemplates
            If Not oLT.Name = "" Then
                If Not ActiveDocument.ListTemplates(oLT.Name).ListLevels(1) _
                        .LinkedStyle = oLT.ListLevels(1).LinkedStyle Then
                    ActiveDocument.UpdateStyles
                    Exit For
                End If
            End If
        Next
oLT
        ActiveDocument.UpdateStylesOnOpen = False
    End If
End With

End Sub

[The ActiveDocument.UpdateStylesOnOpen = False line in the above code sample prevents the user from being able to save the document with the Automatically update document styles setting switched on; and means they don't have to immediately go back to the dialog every time they update their styles, simply in order to deselect that setting. If that's not what you want, though, you can remove that line. But if you do remove that line, then you will also need to have an AutoOpen macro that checks whether the setting is switched on, and if it is, that updates the styles again if need be; otherwise the numbering styles will sometimes be broken when the document is reopened.]

But unfortunately, the Dialogs(wdDialogToolsTemplates) object is buggy – the dialog it displays doesn't show the list of add-ins, and half the buttons on it are greyed out. This is well worth contacting http://support.microsoft.com/contactus/ about.

You can get round this as follows:

a)

Instead of intercepting the FileTemplates command, create the following macro:

Sub ReplacementToolsTemplatesAndAddins()

'Execute the built-in button
CommandBars.FindControl(ID:=751).Execute
If Dialogs(wdDialogToolsTemplates).LinkStyles = 1 Then
    Dim oDoc As Document, oLT As ListTemplate
    Set oDoc = ActiveDocument
    oDoc.UpdateStyles

    On Error Resume Next
    For Each oLT In oDoc.AttachedTemplate.ListTemplates
        If Not oLT.Name = "" Then
            If Not oDoc.ListTemplates(oLT.Name).ListLevels(1) _
                    .LinkedStyle = oLT.ListLevels(1).LinkedStyle Then
                oDoc.UpdateStyles
                Exit For
            End If
        End If
    Next
oLT
    oDoc.UpdateStylesOnOpen = False
End If

End Sub

(Again, remove the ActiveDocument.UpdateStylesOnOpen = False line if you don't want it.)

b)

Create a new toolbar, name it Hidden, and move the built-in Templates and Add-ins button to the new toolbar. This is in order that the above macro can execute the built-in button (doing so avoids the bugs that you get if you use Dialogs(wdDialogToolsTemplates)), without the built-in button being visible to the user.

c)

Go to Tools + Customize, select the Commands tab; in the left pane, select All macros, in the right pane select the ReplacementToolsTemplatesAndAddins macro, and drag it onto the Tools menu, to where the Templates and Add-ins button used to be. Right-click the new button and rename it:
Templates and Add-&Ins...

d)

Disable the new toolbar (which makes it invisible to the user), as follows:

CommandBars("Hidden").Enabled = False

e)

If you've made the above customisations in an add-in, create an AutoExec macro as follows:

Sub AutoExec()
    CommandBars("Hidden").Enabled = False
End Sub

Or if you've customized a template rather than an add-in, create an AutoNew and AutoOpen macro in the template, containing the same code.

If you have already disabled the Web toolbar, of course, one could use that for this purpose, rather than creating a new Toolbar called Hidden. See also: How to stop the web toolbar from jumping up at you whenever you click on a page number in the table of contents.

With one qualification, your users should now be able to update their styles from their template(s) safely.

That one qualification is this: the above macro will safely update styles if their definitions have been changed in the attached template, and will safely revert them to the attached template's definitions if they have been redefined in the document. It will also safely update styles that are defined in the attached template but not in the document. But if there are broken list numbering styles in the document, it will sometimes, but not always, fix those. In other words, it is not a complete substitute for a Fix numbering macro (although it should greatly reduce the frequency with which you'll need to run the latter). For details of the latter, see the links at How to cure Word's List Numbering with a dose of VBA.

If you want to be able to update the styles of Word 97 documents that are attached to Normal.dot

If instead of using the UpdateStyles method, you use CopyStylesFromTemplate, then you can update your document's styles even in Word 97, when the attached template is Normal.dot. However, using CopyStylesFromTemplate is significantly slower than using UpdateStyles; so the following variation on the above macro only uses the slower method when necessary, and uses UpdateStyles when possible:

Sub ReplacementToolsTemplatesAndAddins()

Dim Word97Normal As Boolean, oDoc As Document, oLT As ListTemplate

'Execute the built-in button
CommandBars.FindControl(ID:=751).Execute

If
Dialogs(wdDialogToolsTemplates).LinkStyles = 1 Then
    Set oDoc = ActiveDocument

    If Left$(Application.Version, 1) = "8" And _
            oDoc.AttachedTemplate = NormalTemplate Then
        Word97Normal = True
    End If

    If Word97Normal Then
        oDoc.CopyStylesFromTemplate NormalTemplate
        oDoc.CopyStylesFromTemplate NormalTemplate
    Else
        oDoc.UpdateStyles
    End If

    On Error Resume Next
    For Each oLT In oDoc.AttachedTemplate.ListTemplates
        If Not oLT.Name = "" Then
            If Not oDoc.ListTemplates(oLT.Name).ListLevels(1) _
                    .LinkedStyle = oLT.ListLevels(1).LinkedStyle Then
                If Word97Normal Then
                    oDoc.CopyStylesFromTemplate NormalTemplate
                Else
                    oDoc.UpdateStyles
                End If
                Exit For
            End If
        End If
    Next
oLT
    oDoc.UpdateStylesOnOpen = False
End If

End Sub