Heading

This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
min read

Assign a special key shortcut

Word • Macros • Functions • Organization
Peter Ronhovde
28
min read

As our list of editing macros in Microsoft Word grows, we’ll invariably want to automate the process of assigning the keyboard shortcuts in part because they are occasionally reset by Word.

Thanks for your interest

This content is part of a paid plan.

Automatically update custom keyboard shortcuts

Our productivity gets a boost when our most common editing macros are at our fingertips, so we can wring more work out of our most used macros when we assign them to keyboard shortcuts.

Most shortcuts use some combination of modifier keys along with one main key. While we can assign many keys individually, this is usually reserved to just the function keys.

Assigning our own custom keyboard shortcuts to macros or commands is called “keybinding.” Unfortunately, the keybinding command in Word VBA is a little awkward (see previous article), but we can simplify the process with our own macros and functions.

Only so many reasonable key combinations exist, so if you want more customization options, you can also assign macros to custom buttons on the ribbon or the Quick Launch bar. Also, two-key shortcuts can be set with a similar command as covered in this article, but we’re not covering them today. For those willing to invest in voice recognition software, Dragon Professional scripting also uses VBA, and it allows us to connect to Word and run our macros by voice command (see previous introductory article to get started).

This article is part of a series of mostly member articles to automatically assign our own keyboard shortcuts in VBA. Each article covers different aspects of the small project.

Why do we need it?

While we can manually assign custom shortcuts in both Word for Mac and Windows, it quickly becomes tiresome beyond only a handful of macros, and your library of editing macros will grow faster than you think. Also, issues occasionally arise with custom shortcuts in Microsoft Word which require us to reset them.

Reassign shortcuts when reset by Word

If you rename a macro or even just copy and paste it somewhere else inside the VBA editor, Word detects the change and invalidates the assigned shortcut or resets it back to the default if one exists. You would need to reassign it manually … again. Worse, Word will sometimes automatically reset all keyboard shortcuts to defaults if the Normal.dot template becomes corrupted. Fortunately, the latter case is rare but troublesome when it happens. Either way, it’s handy to be able to reset all your shortcuts with a single button press or however you choose to invoke the reassignment macro.

Better shortcut organization

Organizing shortcut assignments also helps with remembering which ones you have at your disposal and in setting up useful shortcut patterns.

Macro skeleton

We’re creating a “special key” shortcut assignment macro that requires a keycode constant to assign the shortcut, but it is actually the more general case and the easier one to implement. The macro skeleton is:

Sub AddShortcutSpecialKey(ByVal sModifierKeys As String, MainKey As Long, _
SMacro As String, MyKeyCategory As WdKeyCategory = wdKeyCategoryMacro)
' Add or update a keyboard shortcuts for a Word macro

End Sub

This macro isn’t a function, so it returns no value.

Depending on our preferences, we need about four slight variations of this macro for the different cases. Some other programming languages make this easier with “overloaded” functions that use the same function name but different parameters, but we must use distinct names in VBA.

Parameters

The macro requires three arguments from the user with an optional fourth. The first two are identical by design to the GetKeyCode function in an earlier article.

I often precede plain text variables with an “s” or “S” to identify the variable type as a String, and a capital first letter implies the variable value will not change inside the macro. VBA does not care about nor enforce either “rule” as long as we don’t try to use one of its reserved words.

Modifier keys text string

The first parameter requires a plain text string telling the macro what modifier keys are used for the keyboard shortcut. We’ll call this variable sModifierKeys where we imagine input something like “Control+Shift”. For simplicity, we’re requiring the words to be spelled out in full, but it could be implemented with abbreviations as well.

We convert any alphabetic characters in sModifierKeys to lowercase inside the function, but any changes to String arguments in VBA can leak back outside the macro. The ByVal keyword tells VBA not to change the argument value given by the user.

The main key such as “A” or “9” should not be included in the sModifierKeys text, but any main key given as text will just be ignored by the previous GetKeyCode function. As far as this macro is concerned, modifier key texts “Control+Shift” and “Control+Shift+A” will result in the same keyboard shortcut provided the next MainKey constant is correct. An upcoming article will allow us to interpret a shortcut assignment in this more convenient pattern “Control+Shift+A”.

Main key

The second parameter requires a standard Word key constant. These are usually found in the WdKey enumeration table, but to keep it general, the MainKey variable value is stored as a Long number type (just a bigger Integer).

In VBA, enumerations are mostly just constant lists with names that are easier to read and remember. The WdKey table includes all text characters as well as most special keys like Home or Delete. Word automatically converts between WdKey values to a Long number type for the MainKey variable, so for example, we could specify an “A” key for the shortcut by passing the function a value of wdKeyA.

Arrow keys are omitted from the WdKey table for some reason, but they are defined in the VBA KeyCode constants table, and they are used in the same manner.

VBA automatically converts the key constants to Long numbers when necessary.

Macro name

We also need the plain text name of the macro or Word command to run which we’ll call SMacro. We cannot assign shortcuts to macros with any parameters, nor can we assign shortcuts to functions.

Optional key binding category

Unfortunately, the key binding command has a tiny variation between assigning shortcuts to our own macros or standard Word commands. While I don’t like making this macro seem more complicated, it’s annoying to have such a small difference force us to copy the same macro over with only one tiny change and another dozen or so identical steps.

Optional parameter review

We’ll make the parameter Optional since a macro is the most common use case by far.

Optional MyKeyCategory ' ... but what is the type?

We’ve covered the Optional keyword for parameters before, so let’s do a whirlwind review.

Optional tells VBA the variable does not need to be given when the function is called. If not, VBA uses a default value given with the parameter.

Key category type

We still need to specify a variable type which must be one of the “intrinsic” types such as numbers or a string. The type of our MyKeyCategory variable is WdKeyCategory.

Optional MyKeyCategory As WdKeyCategory ' ... not quite done

Yep, it’s like they make up new enumerations for everything, but that’s better than all numbers being a Long number type, and we have to refer to tables to know what anything is. At least it’s descriptive but see the Gotchas below.

Default value

There are several key category types in the enumeration, but we mainly need the macro and standard Word command constants which are wdKeyCategoryMacro and wdKeyCategoryCommand, respectively.

The default value for our optional category parameter is literally assigned right after the parameter type with = SomeValue where SomeValue must match the data type used (e.g., a number for a Long parameter, True-False for a Boolean parameter, etc.). For us, assigning a shortcut to a macro is the most common case by far, so we’ll set wdKeyCategoryMacro as the default value.

Optional MyKeyCategory As WdKeyCategory = wdKeyCategoryMacro

Getting the keycode

The keycode identifies the unique key combination for a shortcut we’re attempting to assign. Getting the keycode requires several steps including a pair of supplementary key validation functions, so it was relegated to its own function.

Define keycode number variable

We start by defining a numeric variable myKeyCode which will store the unique key code.

Dim myKeyCode As Long

It has a Long number type since the KeyCode option of the KeyBindings Add method later wants a Long number for the unique key combination.

Call key code function

The previous GetKeyCode function (or the improved version) requires two arguments which are identical to the first two parameters of the current function. The work to create the earlier function pays off since we simply call it using the same two arguments.

GetKeyCode(sModifierKeys, MainKey)

We store the numerical keycode result in the previous myKeyCode variable.

myKeyCode = GetKeyCode(sModifierKeys, MainKey)

Some key combinations just don’t work in Word, but specifics depend on whether you’re in Word for Windows or Mac. The GetKeyCode function performs some validations on the potential key combination, but we still have some error checking to do later just in case.

Setup the keyboard shortcut (“keybinding”)

We’ve interpreted the modifier keys text and main key value and stored the result in the myKeyCode variable. We need to bind the key combination to the intended macro.

KeyBindings property

We introduced the KeyBindings object in a previous article which belongs to the Application object in VBA.

Application.KeyBindings ... ' Can omit Application

When not specified, VBA assumes the Application object, so we can just omit it.

KeyBindings ' Reference any needed property or method ...

In addition to some other data (properties) and actions (methods) defining what it can do, KeyBindings stores a collection of all active and inactive key bindings in Word.

Clear key binding

It’s good practice to clear an existing key binding. Probably nothing bad would happen if we ignore this step. It makes the macro more complicated, but it is safer and definitely clearer.

Get the Key

There are several ways to access the specific KeyBinding corresponding to the given keyboard shortcut. I prefer to use the Key method.

' Example key reference using a common function BuildKeyCode(...)
KeyBindings.Key(BuildKeyCode(wdKeyControl, wdKeyShift, wdKeyA))

As shown, many examples in the Microsoft documentation use the BuildKeyCode function to refer to the proper shortcut, but we’ve already stored our keycode in the myKeyCode variable earlier.

KeyBindings.Key(myKeyCode)

This Key purportedly refers to a KeyBinding object which stores information about the key binding information corresponding to myKeyCode.

Clear the key binding

Now we can clear the key binding—

Hold on … better watch out for trouble.

Does the key binding even exist?

The problem is the upcoming Clear method will cause an error if the referenced Key does not exist. Meaning, this step could easily cause the macro to crash.

KeyBindings.Key(myKeyCode).Clear ' May crash the macro!

Hmmm.

We now need to ensure the referenced Key gives us a valid KeyBinding object before trying to clear it. Probably the cleanest way to proceed is to store the Key result, so we first declare a new KeyBinding variable.

Dim myKey As KeyBinding

Now we can Set the key binding to whatever result is returned by the Key method for our keycode.

Set myKey = KeyBindings.Key(myKeyCode)

We need to use Set because a KeyBinding is a VBA object with its own properties (data) and actions (methods) not just a value like a number. This assignment to a new variable isn’t strictly necessary, but it makes the following steps a little clearer.

Validate whether key binding exists

The Key method literally returns Nothing if the Key shortcut does not exist in Word, so we just check for it.

myKey Is Nothing ' Does myKey result exist?

Since it’s a True or False (Boolean) value, we can directly use it in a conditional statement.

If Not myKey Is Nothing Then
' Clear the key binding ...
End If

Since a KeyBinding is an object, we use “Is” rather than an equals = sign to compare it to Nothing. I wish VBA supported IsNot from Visual Basic, so the line reads better, but we’re stuck with this Yoda-esque form.

Finally clear the key binding

Now we can clear the key binding if it exists, but we’ll use the more compact notation with the If statement on one line.

If Not myKey Is Nothing Then myKey.Clear

Clearing an existing key binding isn’t strictly necessary. I know this in part because I’ve been just “adding” existing keyboard shortcuts for years in VBA, but I felt remiss to omit it from a public version, and it is a tidier approach.

Do not exit function

As a brief aside, we do not additionally exit the function if the key binding does not exist since we might be setting a new shortcut. Nothing wrong with that.

KeyBindings property

Now we return to binding macro to the shortcut. The KeyBindings object has a convenient (but messy) method to Add a new key binding.

Most common add key binding options

We have several options when referencing the KeyBindings.Add method:

  • The KeyCategory constant is usually either set to macros or Word commands. We’ll focus on macros until the end of this article.
  • The Command option is the literal name of the macro we want to run given in plain text within double quotes or with a string variable storing the name.
  • The KeyCode option needs the numeric value corresponding to the unique key combination we want to use to trigger the macro.

Typical command

The options make the command a little cumbersome, but a typical new keybinding command looks like:

KeyBindings.Add KeyCategory:=wdKeyCategoryMacro, Command:="MyMacroName", _
KeyCode:=BuildKeyCode(wdKeyControl, wdKeyShift, wdKeyA)

Each option is separated by a comma, and assigning option values in a VBA command requires a colon equals := not just an equals = sign. Unfortunately, the Add method requires a long line, so we add an underscore _ to stretch it across two lines and make it more readable. VBA does not care.

Shortcut category

Our MyKeyCategory parameter for the current macro assigned a default KeyCategory of wdKeyCategoryMacro.

Assigning a shortcut to a standard Word command rather than our own macros requires a different keybinding category wdKeyCategoryCommand. Everything else about the process is the same, and you won’t notice a difference when using them in Word.

Other interesting secondary categories in the table include wdKeyCategoryAutoText, wdKeyCategoryFont, wdKeyCategoryStyle, and wdKeyCategorySymbol; but we do not use them in this article. Word assigns several standard shortcuts related to these types, but I do not to use them.

Command name?

The current macro requires the macro name which is stored as SMacro.

Build keycode?

VBA provides a BuildKeyCode(…) function to make generating the key code easier, but we went through the work of creating our own slightly more general GetKeyCode function in a previous article. We provided the various modifier keys as text and the main key as a constant and stored the result in the myKeyCode variable.

Add method with our macro variables

Our version will look a little simpler than the above example since we directly use our parameter variables.

KeyBindings.Add KeyCategory:=MyKeyCategory, Command:=SMacro, _
KeyCode:=myKeyCode

Two-keys option?

Another option exists KeyCode2 to specify a second key. Standard Word two-key shortcuts access menu commands and such. We could generalize and apply them to our own macros, but we’re not covering them in this article.

String parameter?

An awkward system exists to provide a single String as a CommandParameter when adding a key binding, but I wouldn’t use it unless it was forced on me. The only exception might be for simple parameters like a paragraph spacing value, but even then accessing it inside the macro makes me want to proverbially but forcefully defenestrate anyone responsible for this programming atrocity (a.k.a., yeet them out a window in modern parlance).

No macro arguments

Any keyboard shortcut assigned in Word cannot have an argument (such as the number of paragraphs to move) which is unfortunate. We can, however, cheat the system if we use voice commands in Dragon Professional. See this article to get started if you’re interested in this route, but it is a paid application.

Testing keyboard shortcuts

Assuming you’ve done everything else correctly, some key combinations just don’t work.

Yep. That’s right … even if you really want it to.

It’s a limitation of Word, the physical keyboard, and/or how the operating system interprets the keyboard input. We can’t do much about it except mope and work around the missing key combinations. We can, however, test whether a given key combination will work.

Windows

In Word for Windows, use: File → Options → Customize Ribbon and click the Customize … button (see older video for Windows). It’s not the friendliest user interface, but inside this dialog, click into the Press new shortcut key: edit box, and you can test various combinations. I’m not sure they could’ve hidden it much better, but at least it’s available.

Mac

Testing shortcuts is much easier in Word for Mac, use the Tools → Customize keyboard … menu option. Test any key combinations in the dialog (see early part of a previous article on another topic).

What if a key binding error occurs?

The previously used GetKeyCode function already does some validation on the keycode value, but what if something else goes wrong?

We really should add an error step to catch a VBA “runtime” error (literally an error that occurs while the macro is running). If we don’t catch the error, the macro will crash and pop up a nasty message that we don’t know what in the world we’re doing with macros or writing—well, it’ll just let us know there was a problem, but it feels personal.

We’ve covered this in other articles, but let’s review the concept as it’s used in VBA.

Track errors

Let VBA know we want to track possible errors using On Error.

' Check for errors on the key binding
On Error GoTo KeyBindError

KeyBindError is just a made-up line label we add somewhere, but it’s usually placed at the end of the macro. After it, we include any error-specific steps we want to run if an error occurs.

Exit the macro

But first … we need to tell VBA not to proceed into the error steps when a shortcut assignment is successful. We simple exit the subroutine.

Exit Sub ' Do not run any error steps below

Otherwise, VBA would just mosey on through the rest of the macro steps running everything.

Error steps line label

We label a line using the same name as above just ending it with a colon:

KeyBindError:

The VBA editor insists the line is not indented. A little annoying but whatever.

Line labels are just that. VBA doesn’t do anything else with them other than store the line position. We always use them in the context of marking a line to goto if an error occurs. Technically, we could utilize them in regular macros with a GoTo statement, but programmers kind of quit doing that about 40 years ago since it made programs hard to follow. The tongue-in-cheek term was “spaghetti code” but the cooked kind with a mass of sticky noodles in a bowl.

Error message

I like to include an error message that gives additional information about the problem. The standard Word function is MsgBox.

MsgBox "A key binding error occurred ..." ' Some error message ...

Here we used a dummy error message for brevity, but the macro below includes a real error message including the key information (pun intended).

MsgBox works in both Mac and Windows. Other spiffy options exist like giving the dialog a title or a fancy icon beside our message, but our examples just report a basic error message.

Clear the error

We need to tell VBA we took care of the error, so it doesn’t get passed up the line to the calling macro. The standard Word VBA error object is Err, and we just need to reference the Clear method.

Err.Clear

Then we just let the macro end.

Gotchas

What might go wrong that we haven’t already solved?

My keyboard shortcut isn’t working!

Word may have disabled the shortcut for some reason, so try reassigning it. See comments at the top with a few reasons why this might happen.

Unfortunately, both Windows and Mac have idiosyncrasies with certain key combinations, but we just have to work around them. Available keyboard shortcuts differ between Word for Windows and Mac for multiple reasons. For example, I have issues using shortcuts involving punctuation keys on a Mac. Macs don’t seem to recognize them in combination with most modifier keys. This works better in Windows, but it’s not perfect there either.

Optional key category parameter

Since VBA doesn’t actually check values assigned to enumeration type variables, what if someone gives a general number to the MyKeyCategory parameter?

Rather than validate this value manually and further stretch out the function, I chose to let this fall under the umbrella of a generic error which would be caught by the On Error handling when the key binding is attempted.

Final general version with special keys

The special key version for assigning a shortcut to a macro or Word command is:

Sub AddShortcutSpecialKey(ByVal sModifierKeys As String, MainKey As Long, _
SMacro As String, MyKeyCategory As WdKeyCategory = wdKeyCategoryMacro)
' Add or update a keyboard shortcut for a Word macro or command
' sModifierKeys should be the keys as plain text such as "Control+Shift",
' but do not include the main key
' MainKey is a single key constant from the WdKey enumeration or VBA KeyCodes tables
' SMacro is the name of the macro or command to assign to the shortcut
' MyKeyCategory is the appropriate constant from the WdKeyCategory enumeration

' Get keycode using modifier keys and main key
Dim myKeyCode As Long
myKeyCode = GetKeyCode(sModifierKeys, MainKey)

' Check for errors on the key binding
On Error GoTo KeyBindError

' Check and clear an existing key binding with the same key code
Dim myKey As KeyBinding
Set myKey = KeyBindings.Key(myKeyCode)
If Not myKey Is Nothing Then myKey.Clear

' Assign keyboard shortcut to key combination
KeyBindings.Add KeyCategory:=MyKeyCategory, Command:=SMacro, _
KeyCode:=myKeyCode

Exit Sub ' Do not run any error steps below

KeyBindError:
' Invalid keyboard shortcut assignment attempt
MsgBox "Invalid keybinding assignment using " + _
sModifierKeys + vbCr + _
"with keycode = " + CStr(myKeyCode) + vbCr + _
"Main key = " + CStr(MainKey) + vbCr + _
"Category = " + CStr(MyKeyCategory) + vbCr + _
"For macro " + SMacro
Err.Clear
End Sub

If you’re using Word for Mac, use the GetKeyCodeMac function instead.

The previous GetKeyCode function or its improved version did the heavy lifting for us, so most of the effort here is spent taking care of possible errors. It's a little messy, but it would almost certainly bite us somewhere down the road if we had not included it.

The underscores just make it easier to read in the VBA editor. VBA doesn’t care unless it’s over 26 lines which is rarely needed.

Final simple Word macro version with special keys

Adding a macro shortcut is the most common case, so it’s nice to have a direct macro to do this. The advantage of creating the more general version above is we can just call it for our more specific cases. Now we apply it to a macro shortcut.

Sub AddMacroShortcutSpecialKey(sModifierKeys As String, MainKey As Long, SMacro As String)
' Just call the base key binding macro with a macro category
Call AddShortcutSpecialKey(sModifierKeys, MainKey, SMacro, wdKeyCategoryMacro)
End Sub

We had to use a unique macro name since VBA doesn’t allow repeated names.

Since the MyKeyCategory is optional with a default value of wdKeyCategoryMacro, we could have left that argument out, but I chose to be explicit just for the extra clarity.

Why make the parameter optional then? Well, someone else may want to omit it, and I probably will sometime also.

One could argue we now have two macros rather than one, but this one is just for convenience and prettification (it’s a real word). Obviously, you could just leave this one out and use the more general version if you prefer.

Example uses

When we set up our keyboard shortcuts, we “call” the function once for each (re)assigned shortcut.

Let’s pretend we want to assign a macro named ApplySceneStyle to the keyboard shortcut Control+Shift+A. The appropriate modifier keys text is “Control+Shift” and the key constant from the WdKey table is wdKeyA. Inserting these into the function call, we have:

Call AddMacroShortcutSpecialKey("Control+Shift", wdKeyA, "ApplySceneStyle")

That’s not too bad.

We needed the initial keyword Call since the macro required arguments.

The ApplySceneStyle macro name was passed as plain text in double quotes. We specified wdKeyA from the standard key constants table.

Most relevant key constants are listed in the standard Word WdKey enumeration. It allows regular text characters as well as any special keys like Home or Delete, thus the “special key” part of the macro name.

Of course, we could’ve instead used the earlier general macro:

Call AddShortcutSpecialKey("Control+Shift", wdKeyA, "ApplySceneStyle")

In this case, they are almost the same, but we’ll shorten this in an upcoming article.

What don’t I like?

The above function call is a little clunky for simple shortcut assignments like Control+Shift+A. Why can’t I just use that same shortcut text instead of the clumsy wdKeyA for the main key?

I’d prefer to just call a simpler function with something like:

' Upcoming version ...
Call AddMacroShortcutKey("Control+Shift+A", "ApplySceneStyle")

That’s easier to use, but we'll have to wait for it since this usability improvement is the subject of the next version.

I like letting VBA interpret the “A” for me without needing to explicitly type wdKeyA. Admittedly, it’s splitting hairs when the above version works just fine, but I like my macros to be simple when possible and reasonable. Kind of like my VBA version of keeping the kitchen counter clean. It just … should be.

Word command version with special keys

Binding a shortcut to a standard Word command requires a slightly different key binding command, but we created the earlier assignment macro to allow an optional key category parameter. Now we use it to create a more specific macro to assign a Word command to a shortcut.

Change parameter name

I also made an aesthetic change in the third macro parameter from SMacro to SCommand just to be clearer if someone else ever reads it.

Final simple Word command version with special keys

In this macro, we tell the more general AddShortcutSpecialKey macro that we’re adding or modifying a standard Word command shortcut by providing the wdKeyCategoryCommand constant for the MyKeyCategory parameter.

Sub AddCommandShortcutSpecialKey(sModifierKeys As String, MainKey As Long, _
SCommand As String)
' Just call the base key binding macro with a command category
Call AddShortcutSpecialKey(sModifierKeys, MainKey, SCommand, wdKeyCategoryCommand)
End Sub

Again, this is just for convenience, so we don’t need to explicitly give the wdKeyCategoryCommand category.

Example uses

One Word command I use regularly is OutlinePromote. I prefer to assign it to “Control+Shift+O”, so with this macro, the assignment looks like:

Call AddCommandShortcutSpecialKey("Control+Shift", wdKeyO, "OutlinePromote")

Or we could use the slightly longer, messier version with the more general assignment macro:

Call AddShortcutSpecialKey("Control+Shift", wdKeyO, "OutlinePromote", _
wdKeyCategoryCommand)

I like the tidier look of the former version, but we’ll make it even easier in an upcoming article.

Use cases

OutlinePromote and OutlineDemote are very useful, so I reassigned both commands. I also reassigned several other standard commands like Redo via EditRedoOrRepeat to Control+Shift+Z to mimic the more standard Redo shortcut on a Mac. I also remapped CopyFormat, PasteFormat, as well as PasteTextOnly since I wanted the standard shortcuts for my own macros.

Word commands

The names of standard Word commands can be found in the macro dialog under the View menu or in the same dialog used for manually assigning shortcuts. Unfortunately, the respective command actions aren’t documented well, but the most useful ones are probably already assigned to a standard Word shortcut.

Affiliate Links

If you're interested in using Word or another tool related to the article, check out these affiliate links. I may make a small commission if you purchase when using them, but there is no increase in cost for you, and it helps to support this site and associated content.

I've been using Microsoft for Business for commercial use (that's us writers) on one of the lower pricing tiers for years. I get to use my macros, have online storage, and don't have to worry about software updates.