Logo: TechTrax...brought to you by MouseTrax Computing Solutions

Customizing Word: A Roadmap for the Professional Developer

by Bill Coan, MVP

This article is protected by Copyscape! DO NOT COPY without permission!

Skill rating level 9.

Microsoft Word can be customized in a variety of ways to suit almost any word processing need.

Note! When we say that Word can be customized, we aren’t talking about changing the definitions of paragraph styles (or other styles) in a template. Nor are we talking about storing elements of content as AutoText entries or creating AutoCorrect entries. These things can have a tremendous impact on a user’s productivity, and they can change a user’s experience of Word, but they don’t change the way Word itself works. They are merely expressions of Word’s built-in capabilities. Customizations go beyond built-in capabilities, actually changing the way Word works.

Customizations can include any combination of the following:

  • Event handlers that alter the way Word responds to the opening or closing of a document, the changing of the selection within a document, or a variety of other events. Since event handlers are triggered automatically by the events they handle, the user needn’t take any explicit action to invoke them. For more information about event handlers, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnword2k2/html/odc_wdappevnt.asp.

  • Macros that run in place of (and can alter the operation of) Word’s built-in commands. Such macros, when present, are invoked via the built-in menus, toolbars, and/or keystrokes that would otherwise invoke Word’s built-in commands.

  • Macros that carry out specialized operations beyond those possible or convenient with Word’s built-in commands. Such macros can be invoked by the user via custom menus, toolbars, and/or keystrokes.

  • Menu, toolbar, and keyboard customizations that control how macros and Word’s built-in commands are invoked by a user.

Customizations can be stored in any combination of the following locations:

  • The active document.

  • The template “attached” to the active document.

  • A “global” or “add-in” template.

  • Word’s default global template (Normal.dot).

  • A component object model (COM) add-in, also known as a dynamic link library (DLL) add-in. To create a COM add-in, you must have access to a development tool capable of creating *.dll files, such as the tools available in Visual Studio and Visual Studio.NET.

Important! Although menu, toolbar, and keyboard customizations can be generated by code stored in any of these locations, the customizations themselves can be permanently stored only in the first four locations. Since COM add-ins can’t store customizations, developers of such an add-in must exercise special care when choosing where to permanently store customizations generated by the add-in. Otherwise, the customizations could have greater or less scope than intended, with serious consequences for the user. For more information, see “Scope of Customizations” and “Design-Time vs. Run-Time Customizations” below.

Scope of Customization

Customizations Stored in the Active Document

Customizations stored in the active document take effect as soon as the document becomes active and remain in effect only so long as the document remains active.

Customizations Stored in the Template Attached to the Active Document

Customizations stored in the template attached to the active document take effect as soon as the document becomes active or as soon as it becomes attached to the template (whichever comes last) and remain in effect only so long as the document remains active and attached to that template. If the document is detached from the original template and attached to some other template, or if the document loses focus to another document that is attached to some other template, the customizations in the original template will cease to be in effect and will be replaced by the customizations (if any) stored in the other template.

Customization Stored in a *.dot Add-in File

Customizations stored in a *.dot add-in file take effect as soon as the add-in file is loaded into Word’s memory space and remain in effect until the add-in file is unloaded from Word’s memory space.

A *.dot add-in file stored in Word’s Startup folder or the Office Startup folder will automatically be loaded into Word’s memory space when Word starts and unloaded when Word exits. Therefore, the customizations stored in such a file will be in effect throughout the entirety of every Word session for as long as the add-in file remains stored in the Startup folder (unless the user explicitly unloads the add-in file at some point).

Regardless of where it is stored, a *.dot add-in file can be manually loaded into Word’s memory space and unloaded from Word’s memory space by the user or from code run from a template, another *.dot add-in or a COM add-in.

To manually load a *.dot add-in file into Word’s memory space, the user chooses Tools > Templates and Add-Ins and then either places a checkmark next to an available add-in file or else clicks Add… and selects a new add-in file. To manually unload an add-in file from Word’s memory space, the user chooses Tools > Templates and Add-Ins and then removes the checkmark next to that add-in file.

Customizations Stored in Word's Global Default Template (Normal.dot)

Customizations stored in Word’s default global template (Normal.dot) are automatically loaded into Word’s memory space when Word starts and unloaded when Word exits. Therefore, any customizations stored in this template will be in effect throughout every Word session.

Customizations Stored in the COM Add-in File

Customizations stored in a COM add-in file take effect as soon as the add-in file is loaded into Word’s memory space and remain in effect until the add-in file is unloaded from Word’s memory space.

Customizations stored in a COM add-in file and registered as a bootloading add-in for Word will automatically be loaded into Word’s memory space when Word starts and unloaded when Word exits. Therefore, the customizations stored in such a file will be in effect throughout every Word session for as long as the add-in file remains so registered.

Note: In the Windows Registry, COM add-in files for Word are listed in the following locations:

  • HKEY_CURRENT_USER\Software\Microsoft\Office\Word\Addins\<ProgID>\LoadBehavior.

  • HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Word\Addins\<ProgID>\LoadBehavior.

Files listed under HKEY_CURRENT_USER can be loaded only by the current user. Files listed under HKEY_LOCAL_MACHINE can be loaded by any user. The “LoadBehavior” value reveals whether the file is currently loaded and also determines when the file loads.

  • 0 = Disconnect—Is not loaded.

  • 1 = Connected—Is loaded.

  • 2 = Bootload—Load on application startup.

  • 8 = Demand Load—Load only when requested by user.

  • 16 = Connect First Time—Load only once (on next startup).

For example, a value of 3 indicates that the add-in file is currently loaded and that it loads on application startup (1 + 3 = 3). A value of 9 indicates that the add-in file is currently loaded and that it loads only when requested by the user (1 + 8 = 9).

Customizations stored in a COM add-in file and registered under HKEY_CURRENT_USER also can be manually loaded into Word’s memory space and unloaded from Word’s memory space by the user. The command for loading and unloading such add-ins doesn’t appear on Word’s menus by default, but it can be added to the Tools menu as follows:

  1. In Word choose Tools > Customize and then choose the Commands Tab.

  2. Under Categories, choose “Tools.”

  3. Under Commands, choose “COM Add-Ins” and drag it to the Tools menu and wait for the menu to drop down, then position it just below the “Templates and Add-ins” command, and then release the mouse.

To manually load a *.dll add-in file into Word’s memory space, the user chooses Tools > Com Add-ins and then either places a checkmark next to an available add-in file or else clicks Add… and selects a new add-in file. To manually unload an add-in file from Word’s memory space, the user chooses Tools > Com Add-ins and then removes the checkmark next to that add-in file.

Note! Customizations stored in a COM add-in file and registered under HKEY_LOCAL_MACHINE cannot be manually loaded into Word’s memory space and unloaded from Word’s memory space by the user, because they don’t show up in the COM add-ins dialogs box.

Conflicts Among Customizations

Since customizations can be stored in multiple locations, and since the scope of customizations in one location can overlap the scope of those in another location, conflicts can arise. To resolve such conflicts, Word assigns precedence to customizations based on where the customizations are stored, in the following order:

  1. The active document. Customizations stored in the active document take precedence over any other customizations that may be present.

  2. The template attached to the active document. Customizations stored in the template attached to the active document take precedence over customizations stored in add-in files or in Word’s default global template (Normal.dot).

  3. Add-in files, in order of loading. The most recently loaded add-in file takes precedence over add-in files loaded earlier.

    Note! Since add-in files can be loaded automatically from Word’s Startup folder, automatically from the Office Startup folder, and manually from any location at any time, there is no way for the developer of any particular add-in file to assure that his or her file will load before or after any other particular add-in file.

  4. The default global template (Normal.dot).

Limiting the Scope of Customization to What is Actually Required

Although customizations can help users to be more productive, even well-thought-out customizations have the potential to interfere with the user’s productivity in unexpected ways. Therefore, the first rule when customizing Word is to limit the scope of customizations to what is actually required.

If the goal of the customizations is to help the user work with a particular document, then the customizations should be stored in that document. This will assure that the customizations will be present only when that document is being worked on.

Note! Keyboard customizations stored in a document are more fragile than other customizations, and they can disappear if the user switches to a different document and then switches back to the document containing the customizations. For this reason, customizations shouldn’t be stored in a document if while working on the document the user is likely to switch temporarily to a different document and then return to the original document.

If the goal of the customizations is to help the user work with an entire class of documents, then the documents should all be attached to a single template, and the customizations should be stored in that template. This will assure that the customizations will be present only when documents attached to that template are being worked on.

If the goal of the customizations is to help the user perform a particular task regardless of which document (or class of documents) is being worked on, then the customizations must of necessity be stored in an add-in file.

If the user performs a particular set of tasks infrequently or at very predictable times, then the add-in file that stores the customizations for that set of tasks should be loaded into Word’s memory space only when needed, and it should be unloaded when no longer needed. This will assure that the customizations will be present when needed but only when needed.

If the user performs a particular set of tasks frequently or at unpredictable times, then the add-in file that stores the customizations for that set of tasks might need to be kept in Word’s Startup folder or in the Office Startup folder or, in the case of a COM add-in, registered as an autoloading file, so that it will be loaded into Word’s memory space when Word starts and remain there until Word exits (unless the user explicitly unloads it before then). This will assure that the customizations will be present throughout every Word session.

It is almost never a good idea for a developer to store customizations in Normal.dot, for the following reasons:

  • Normal.dot is the default location for user customizations. Users who know very little about Word can quickly accumulate in Normal.dot various customizations of great value to them. Any interference with these customizations by a developer will be viewed (rightfully) as an intrusion on the user’s workspace.

  • Normal.dot can become corrupt, at which point it must be deleted so that Word can generate a fresh copy. When this happens, any customizations stored in Normal.dot by a developer will be lost.

  • In some corporate environments, Normal.dot is overwritten daily by a network logon policy. In addition to being an affront and an aggravation to users, this practice will interfere with a developer’s efforts to store customizations in Normal.dot.

Design-Time vs. Run-Time Customizations

When a developer stores customizations in a file before the file is distributed to the user, the customizations are referred to as design-time customizations. When a user receives a file from a developer and the file triggers customizations while Word is running under user control, the customizations are referred to as run-time customizations.

Event Handlers and Macros

The vast majority of event handlers and macros are written by a developer at design time. Although the Visual Basic for Applications Integrated Development Environment can be automated to produce event handlers and macros at run time, such automation is very seldom required and lies outside the scope of this article.

When a developer writes an event handler or a macro and saves the code in a *.doc file, a *.dot file, or a *.dll file at design time, there is no ambiguity about where the macro or event handler will be stored or what its scope will be. It will be stored in the file that the developer chooses, and its scope will be dictated by when the file is loaded into Word’s memory space, by when the file is unloaded from Word’s memory space, and by the rules of precedence regarding conflicts among customizations.

Menu, Toolbar, and Keyboard Customizations

Customizations to Word’s menus, toolbars, and keyboard can usually be handled in the same way as most macros and event handlers are handled. That is, the customizations are created by the developer at design time and saved in a *.doc or *.dot file. Thereafter, the scope of the customizations will be dictated by when the file is loaded into Word’s memory space, by when the file is unloaded from Word’s memory space, and by the rules of precedence regarding conflicts among customizations.

In the case of COM add-ins, it isn’t possible to create customizations of Word’s menus, toolbars, and keyboard at design time, because COM add-in files have no way to store such customizations. The most that a COM add-in can do is to store at design time the code needed to carry out the customizations at run time.

In some cases, the exact nature of customizations needed (whether of the menus, toolbars, and/or keyboard) might not be knowable until run time. In such cases, the developer has no choice but to consider run-time customizations.

Design-Time Customizations of Menus, Toolbars, and Keyboard

When creating menu, toolbar, and keyboard customizations in a *.doc or *.dot file at design time, the developer has two options: create the customizations via Word’s user interface or create them via macro code.

To create design-time customizations via the user interface, the developer chooses Tools > Customize or  Tools > Customize > Keyboard. The dialog boxes that appear when these commands are given allow the developer not only to create the customizations but also to select in which file the customizations will be stored, such as the active document or its attached template, the active template (if the active document is a template), or Word’s default global template (Normal.dot). That file can then be saved in the normal way. Thereafter, the scope of the customizations will be dictated by when the file is loaded into Word’s memory space, by when it is unloaded from Word’s memory space, and by the rules of precedence regarding conflicts among customizations.

To create design-time customizations via macro code, the developer writes and then immediately runs a macro such as the following:

Option Explicit
Sub CustomizeWord()
'***************************************************************************
'***************************************************************************
'***************************************************************************
'This macro customizes Word’s user interface by assigning a macro called
'”TemplateVersion” to run when the user presses F10. This macro also creates
'a custom toolbar and then places a control button on that toolbar and sets
'the button’s “OnAction” property to the TemplateVersion macro.
'NOTE: The TemplateVersion macro is listed below, immediately after the code
'for the CustomizeWord macro.
'***************************************************************************
'***************************************************************************
'***************************************************************************
'declare some variables for a custom toolbar
    Dim oCB As CommandBar
    Dim oControl As CommandBarButton
     'set the customization context in such a way that the
     'customizations will be stored in the same file as this code
     CustomizationContext = ThisDocument
     'clear any keyboard customizations left over from previous
     'executions of this macro
     KeyBindings.ClearAll
     'Assign the F10 key to the "TemplateVersion"
     'macro stored in the modCustomization module of the WordCustomizationProject.
     KeyBindings.Add _
         KeyCode:=BuildKeyCode(wdKeyF10), _
         KeyCategory:=wdKeyCategoryMacro, _
         Command:="WordCustomizationProject.modCustomization.TemplateVersion"

  'NOTE: "WordCustomizationProject.modCustomization.TemplateVersion" (see above) is a
  'fully qualified macro name. Using the fully qualified name helps make sure
  'that Word will run the proper macro. If there are two or more "TemplateVersion"
  'macros, Word will run only the one stored in the modCustomization module of the
  'project called WordCustomizationProject. (Project names and module names
  'can be changed in the Properties pane of the VBA integrated development environment
  'IMPORTANT: Always assign unique names to your code projects and code modules,
  'so that Word will know exactly which macro you want it to run.
  'Delete the existing Custom Toolbar, if present.
  'ignore errors, in case the toolbar doesn't yet exist

  On Error Resume Next
  CommandBars("Custom Toolbar").Protection = msoBarNoProtection
  CommandBars("Custom Toolbar").Delete
  On Error GoTo 0
  'Create a new command bar called Custom Toolbar
  Set oCB = _
  CommandBars.Add( _
            Name:="Custom Toolbar", _
            Position:=msoBarFloating)
  'set the new command bar to be visible and position it, for now,
  '100 pixels from the left edge and 200 pixels from the
  'top edge of the Word application window.
  With oCB
    .Visible = True
    .Left = 100
    .Top = 200
  End With
  'add a control button to the new command bar
  Set oControl = oCB.Controls.Add(Type:=msoControlButton)
  'set the control button to display its caption,
  'then set its caption to "Version" and
  'set the button's "OnAction" property to the "TemplateVersion"
  'macro stored in the modCustomization module
  With oControl
    .Style = msoButtonCaption
    .Caption = "Version"
    .OnAction = "modCustomization.TemplateVersion"
  End With

  'NOTE: "modCustomization.TemplateVersion" (see above) is NOT a fully
  'qualified macro name, but it is the closest we can come to one.
  'Ideally, we would include the project name ("WordCustomizationProject")
  'when specifying which macro we want Word to run, but unfortunately
  'there's a bug in the OnAction property that prevents this. The best we can
  'do is to include the module name along with the macro name, to help
  'distinguish the desired macro from an identically named macro in some other
  'module.
  '(Module names can be changed in the
  'Properties pane of the VBA integrated development environment.)
  'IMPORTANT: Always assign unique names to your code modules,
  'so that Word will know exactly which macro you want it to run.
  'protect the custom command bar to make sure it stays visible and
  'also to make sure that it isn't further customized by the user

  With oCB
    .Protection = msoBarNoChangeVisible + msoBarNoCustomize
  End With
  'release variables from memory
  Set oCB = Nothing
  Set oControl = Nothing
  'force the customization context to return to the active document's
  'attached template, or to Normal.dot if no document happens to be open
  'this helps assure that Word will continue to properly display
  'all customizations currently in force.
  If Documents.Count > 0 Then
    CustomizationContext = ActiveDocument.AttachedTemplate
  Else
    CustomizationContext = NormalTemplate
  End If
End Sub

Sub TemplateVersion()
  MsgBox "Word Customization Code" & vbCr & _
         "Version 1.0"
End Sub

Notice that the macro sets the “customization context” before implementing its customizations. The customization context specifies where the customizations are to be stored. In the macro, the customization context is set to ThisDocument, which refers to the file where the macro code itself is stored.

Also notice that the code explicitly resets any earlier customizations stored in the same customization context. This helps prevent successive customizations from piling up on top of one other, with an additional new toolbar (for example) appearing alongside older ones created during previous executions of the code.

Note! Resetting earlier customizations doesn’t reduce the file size of *.doc and *.dot files. On the contrary, all customizations and resettings tend to increase the file size. The problem seems to be that Word doesn’t actually delete the old customizations, but allows them to accumulate within the file even though they aren’t being used. For more information, see http://word.mvps.org/faqs/macrosvba/TemplateBloat.htm.

Other possible customization contexts include:

  • ActiveDocument

  • ActiveDocument.AttachedTemplate

  • Templates(<filespec for a currently loaded add-in template>)

  • NormalTemplate

Note! Setting the CustomizationContext to NormalTemplate will “dirty” the Normal template and cause Word either to save changes to the Normal template without prompting the user or else to prompt the user to save the changes (depending on whether the user has checked “Prompt to save Normal template” under Tools > Options > Save). As a general rule, this is a very bad programming practice, since Normal.dot is the user’s file and shouldn’t be changed by anyone other than the user. Also, since Normal.dot is sometimes overwritten upon network logon, and since many users delete Normal.dot when troubleshooting a problem with Word, customizations stored in Normal.dot can be lost unexpectedly. For further information about add-ins and Normal.dot, see http://office.microsoft.com/en-us/assistance/HA011514521033.aspx.

Finally, notice that the code explicitly sets the customization context to a known value after the customizations have been completed. This is a good practice, especially for code that might one day be used at run time rather than design time. If the customization context has been set at the start of the macro to, say, an add-in template, Word’s user interface might temporarily reflect only the customizations stored in that template, rather than continuing to reflect other customizations that may also be in force. By explicitly setting the customization context to a known value upon completion, you can help assure that Word’s user interface will immediately reflect all customizations of interest to the user.

Note! In most cases, a customization macro should end by setting the customization context to the active document’s attached template or to Normal.dot. The most notable exception occurs when the customization macro is storing customizations in the active document. In that case, the customization context should remain set to the active document, because setting it to some other value will hide any toolbars added to the active document, defeating the purpose of the customization code.

After the above code is executed and the customizations have been created, the file where the customizations have been stored can be saved in the normal way. Thereafter, the scope of the customizations will be dictated by when the file is loaded into Word’s memory space, by when it is unloaded from Word’s memory space, and by the rules of precedence regarding conflicts among customizations.

A Word of Caution about Design-Time Customizations

For best results, it’s important to create design-time customizations on a “plain vanilla” instance of Microsoft Word. That is, no add-ins should be loaded and the default global template (Normal.dot) should be a fresh copy generated by Word with no modifications by the developer. (To generate a fresh copy of Normal.dot, quit Word and Outlook, rename all existing instances of Normal.dot to Normal.old, then restart Word.)

The reason for this requirement is that customizations can be subtractive as well as additive. Here’s an example of how this can lead to unintended results:

Suppose that an instance of Word is running, that the active document is a *.dot file, and that you are creating some customizations via the user interface. Further suppose that the DataPrompter® add-in has been loaded into this instance of Word.

In this scenario, if you choose Tools > Customize, drag Word’s Table menu off the menu bar and then drag the DataPrompter menu off the menu bar, the results will be “subtractive” customizations. When the *.dot file is distributed to users, the customizations will tell Word not to display Word’s Table menu and not to display the DataPrompter menu. Users who haven’t installed the DataPrompter add-in won’t notice the lack of the DataPrompter menu, because they aren’t used to seeing it on the menu bar, but users who have installed the DataPrompter add-in will wonder why the DataPrompter menu has gone missing from Word’s menu bar.

It’s worth noting that the DataPrompter menu will disappear even though no change has been made to the DataPrompter add-in itself. The DataPrompter add-in will still contain an add-in menu for the menu bar, just as it always has. The difference is that Word chooses not to display the add-in menu, because your *.dot file contains a subtractive customization telling Word not to display it.

Needless to say, no developer of an add-in can offer users a predictable experience if other developers distribute subtractive design-time customizations that override their work. For this reason, it behooves all developers to familiarize themselves with the scope of customizations, the rules of precedence that govern conflicts, and the potential for one developer’s design-time customizations to interfere with those of another.

The good news is that the potential for these problems can be minimized by making sure that customizations are carried out on a plain vanilla instance of Microsoft Word. In such an instance, customizations from other developers won’t be present and therefore won’t be at risk of inadvertent subtraction.

Run-Time Customizations of Menus, Toolbars, and Keyboard

To customize menus, toolbars, and the keyboard at run time, the developer relies on code created at design time that runs at run time. In most cases, the code can be nearly identical to what would be run at design time to accomplish design-time customizations. In fact, in most cases the only real difference, if any, is the customization context.

Since run-time code could be running in the presence of customizations stored in a variety of contexts, it’s absolutely critical to start by setting the customization context to the desired context (typically ThisDocument) and end by setting the customization context to a known value (typically ActiveDocument.AttachedTemplate or NormalTemplate, unless the customizations are being stored in the active document, in which case the context must remain set to the active document). Otherwise, after the code runs, Word’s interface in some cases might temporarily reflect only the latest customizations and fail to continue reflecting other customizations that are also in force.

In the case of code stored in a COM add-in (a *.dll file), the customization context must be set to an appropriate *.doc or *.dot file, because the *.dll file itself can’t store customizations to menus, toolbars, or the keyboard. Many developers of COM add-ins automatically assume that their only choice is to set the run-time customization context to NormalTemplate, which causes the customizations to be stored in Normal.dot. As noted earlier, customizations stored in Normal.dot can interfere with user customizations, and they may be lost if Normal.dot becomes corrupt or if a network logon script overwrites it.

For developers who insist on storing their customizations in Normal.dot, it’s important to make very precise references to the menus, toolbars, or keybindings being customized, so that the customizations will have no impact on the user’s own customizations or on those stored in Normal.dot by some other developer’s add-in.

A more foolproof approach is to distribute a *.dot file along with the COM add-in, and to store all customizations in the *.dot file. The *.dot file can be placed into Word’s Startup folder or the Office startup folder if desired, but technically it needn’t be. Instead, it can be stored in a convenient location selected by the developer and loaded into Word (as a global template add-in) by the developer’s COM add-in before the run-time customizations are carried out.

After customizations have been created at run time, the file where the customizations have been stored (i.e., the customization context) can be saved, if desired, with one of the following statements:

  • ThisDocument.Save

  • ActiveDocument.Save

  • ActiveDocument.AttachedTemplate.Save

  • Templates(<filespec for a currently loaded add-in template>).Save

  • NormalTemplate.Save

Alternatively, the customization context can be marked as already saved, so that Word won’t try to save the associated file upon exit, with one of the following statements:

  • ThisDocument.Saved = True

  • ActiveDocument.Saved = True

  • ActiveDocument.AttachedTemplate.Saved = True

  • Templates(<filespec for a currently loaded add-in template>).Saved = True

  • NormalTemplate.Saved = True

Note! Setting the Normal template’s “Saved” property to True will prevent Word from saving changes to the Normal template (or prompting the user to do so) even if the Normal template contains changes made by the user. As a general rule, this is a very bad programming practice, since changes made by the user can be lost without notice.

A Word of Caution about Run-Time Customizations

Unlike code for design-time customizations, which is usually executed explicitly by the developer, code for run-time customizations is more typically triggered by an event. For example, a COM add-in might rely on its OnLoad event, or a *.dot file loaded as a global add-in might rely on an AutoExec macro, to trigger the execution of run-time customizations.

There are two problems with triggering run-time customization code by events.

First, the timing of events is outside of the developer’s control (and outside of the user’s control, as well). For example, if two different *.dot files are stored in Word’s Startup folder, and each of them contains an AutoExec macro, it’s hard to predict in which order they will run.

Second, event code isn’t necessarily executed all at once. Instead, if multiple events have taken place, or if an event occurs while an OnLoad event handler or AutoExec macro is executing, Word switches back and forth among all of the queued processes and tries to make a little bit of progress on each one before carrying any individual routine to completion.

In some cases, Word can loop through all of the events several times before a particular customization routine is executed to completion. Worse yet, changes in customization context can take place without warning as Word loops through the various events, either because the code in each event handler explicitly sets the customization context to a different value or because Word itself temporarily switches the customization context as it loads various files into memory. In too many cases, the customization context can be switched so often and so suddenly that a customization intended for one context is instead applied to a different context.

Testing under a variety of conditions (with and without other add-ins present, with and without Outlook running, with and without Outlook using Word as its email editor, with and without other Windows processes running) can help reveal some of the problems that can occur with run-time customizations. Unfortunately, other problems might not show up until after testing has been completed and an add-in has been released for distribution.

One way to avoid run-time problems is to rely completely on design-time customizations. In the case of a COM add-in, this means preparing and distributing a *.dot add-in along with the COM add-in, with customizations stored in the *.dot add-in.

Run-time problems can be minimized by limiting run-time customizations to those carried out when a user clicks a popup control (i.e. a menu). Like other command bar controls, popup controls have an OnAction property that allows them to run a macro when clicked.

Since a popup control’s OnAction macro could be running in the presence of customizations stored in a variety of contexts, it’s absolutely critical that such a macro start by setting the customization context to the desired context (typically ThisDocument) and end by setting the customization context to a known value (ActiveDocument.AttachedTemplate or NormalTemplate, unless the customizations are being stored in the active document, in which case the context must remain set to the active document.) If this precaution is neglected, Word’s interface might temporarily reflect only the latest customizations and fail to continue reflecting other customizations that are also in force.

The following macro shows how a popup control’s OnAction property can be used to configure the menu that pops up when the user clicks the control:

Option Explicit
Sub DynamicallyAdjustMenu()
'***************************************************************************
'***************************************************************************
'***************************************************************************
'This macro customizes Word’s user interface by enabling or disabling
'the first control found on a popup control. Whenever the user clicks the
'the popup control, Word evaluates how many documents are open and then
'either enables or disables the first control on the popup menu.
'***************************************************************************
'***************************************************************************
'***************************************************************************
'declare a boolean variable
'to store the "saved" status of the
'file containing this code
  Dim blnSaved As Boolean
  'store the saved status of the file
  'containing this code
  blnSaved = ThisDocument.Saved
  'set the customization context in such a way that the
  'customizations will be stored in the same file as this code
  CustomizationContext = ThisDocument
  'if more than one document is open,
  'then enable the first control on the menu
  'that called this routine. Otherwise
  'disable the first control on the menu
  With CommandBars.ActionControl
    If Documents.Count > 1 Then
      .Controls(1).Enabled = True
    Else
      .Controls(1).Enabled = False
    End If
  End With
  'since the above customization will "dirty"
  'the file containing this code,
  'set the file's Saved bit to what it was
  'before the customization was made.
  'this will prevent Word from prompting the
  'user to save the file
  ThisDocument.Saved = blnSaved
  'force the customization context to return to the active document's
  'attached template, or to Normal.dot if no document happens to be open
  'this helps assure that Word will continue to properly display
  'all customizations currently in force.
  If Documents.Count > 0 Then
    CustomizationContext = ActiveDocument.AttachedTemplate
  Else
    CustomizationContext = NormalTemplate
  End If
End Sub

First, Do No Harm

Customizing Word can be as easy as writing a single macro or event handler or as complicated as desired. No matter how modest or ambitious the project, a responsible developer must start by confronting the issues of storage location and scope and the potential for conflicts among customizations, plus the question of whether to rely exclusively on design-time customizations or a mixture of design-time and run-time customizations. Beyond these principles, the developer’s primary design goal should be to do no harm to Word itself or to any other templates or add-ins that may be present.

Bill Coan would like to thank fellow MVPs, Jay Freedman, Suzanne Barnhill, Shauna Kelly, Doug Robbins and Steve Hudson for providing technical validations of this article.

Click to rate this article.

Go up to the top of this page.
This site powered by the Logical Web Publisher™: Content management by Logical Expressions, Inc.