|


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:
- In Word choose Tools > Customize and then choose the
Commands Tab.
- Under Categories, choose “Tools.”
- 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:
- The active document. Customizations stored in the
active document take precedence over any other customizations that may be
present.
- 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).
- 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.
- 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.

|