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

Get main key from shortcut text

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

We can simplify some keybinding assignments by allowing the user to provide the full keyboard shortcut as text. This function translates a single alphanumeric character to a standard Word key value to facilitate creating other shortcut assignment macros.

Thanks for your interest

This content is part of a paid plan.

Get main key value from shortcut text

When assigning keyboard shortcuts in Word VBA, it is convenient to allow shortcut formats like “Control+Shift+A” where “A” is the “main key” of the shortcut. Toward that end, we need a way to convert the last character to a numeric constant consistent with the key codes used by VBA key binding methods. Fortunately, Word’s WdKey enumeration corresponds to the known standard “Ascii” value for uppercase alphabetic or numeric text, and we can utilize standard Word functions to make the conversion.

This article is part of a series of mostly member articles:

Get main key ascii value function skeleton

The function skeleton to covert an alphanumeric character to its corresponding WdKey constant is:

Function GetAlphanumericKey(SKey As String) As WdKey
' Returns a WdKey constant corresponding to the number or uppercase letter
' in the last character of SKey
' Returns wdNoKey if no valid alphanumeric character was found

End Function

For simplicity, we will assume “alphanumeric” for the remainder of the article when referring to the main key character.

Parameter

The function requires the main key text for the keyboard shortcut as a string. We name it SKey where the last character in it is assumed to be the main key, but anything other text is ignored. This is useful if the user wants to provide the full shortcut text description to this function.

Return value

The function returns the WdKey value corresponding to the main key character including uppercase letters or a single digit text number. We use a WdKey enumeration type because ascii values differ between upper and lowercase characters. Fortunately, letters in the WdKey table match the corresponding uppercase ascii character values, but any WdKey constants are automatically converted to Long numbers by VBA when used in keycode calculations.

If no matching WdKey constant is found, the function returns wdNoKey  (technically a value of 255).

WdKey or Long number type?

The WdKey enumeration contains constants corresponding to physical keys on a typical US keyboard. It would be easier and seemingly more general to just return a Long number type since it’s used for keycode values elsewhere in VBA key binding, but using a WdKey return type communicates the function’s purpose more clearly.

This function is focused on doing some grunt work for key binding macros, so accounting for lowercase letters does not make sense. For shortcuts, the “A” key is the “a” key, and Shift acts as a separate modifier key rather than controlling capitalization. Moreover, lowercase alphabetic ascii values actually overlap the WdKey table in the range of the numeric keypad and function keys.

VBA doesn’t actually constrain the return value to lie within the enumeration constants, but it is clearer to return a WdKey number type, and VBA converts between these number types automatically anyhow.

Why not allow any key?

We could allow any valid single key, such as a semicolon character “;”, but the non-alphanumeric keys in the WdKey table are scattered through the enumeration compared to their corresponding ascii values—

But it’s just a few extra simple—

Hold on and listen a little bit longer.

To reliably parse the extra keys, we would need a whole additional section of the function to check them almost individually. Plus, do we allow “ ” as well as the word form “space”, and if we allow the latter, do we distinguish between cases like “backspace” and “space” in Word for Windows but not Word for Mac? Doing so would require some text searches, and if so, how do we determine the extent main key characters in the shortcut text? Do we look for a typical plus + or hyphen - as a separator character?

See how a “simple” generalization expands faster than you might think?

It’s a lot extra for a function that was initially meant to simplify some shortcut assignments, not provide a comprehensive solution. It’s a compromise based on what’s needed and how much work is required to get it. Sometimes simplicity beats generality.

What we’re not talking about

The WdKey table strangely leaves out some physical keys like the arrows, but these are nevertheless included in the VBA KeyCode table. The WdKey table also does not include characters accessed with the Shift key like an exclamation point “!” or a colon “:”, but any of these keys are outside the scope of this function anyhow.

We also exclude command keys like Control, Shift, Alt in Word for Windows or Command, Control, Shift, or Option on a Mac since these are all handled as shortcut modifier keys.

What is ASCII?

Here’s where we get slightly technical but hold your tomatoes.

ASCII is an old computer numbering system for some plain text and some non-printing characters. Printable character values range from about 32 to 126. Technically, the name is an acronym, but we’ll drop the capitalization, and we won’t worry about any “extended ascii” tables since many variations exist. The lower portion of the table (up to 127) is mostly standard, but any other keys have a multitude of definitions across various reference tables.

Comparison to the WdKey table

For alphabetic and numeric characters, the WdKey enumeration overlaps the ascii table with the same numerical values. The WdKey table has many other key constants, but we won’t use them in this utility function.

Quick error check

If SKey is an empty string, one of the text functions below will crash the function, so we need to catch this. Fortunately, doing so is straightforward. We literally, just check whether SKey is equal to an empty string “”.

SKey = ""

Remember, this is a True or False (Boolean) condition when used with an If statement.

If SKey = "" Then
' Shortcut text is empty and invalid
End If

What do we do?

Since we're returning a value from the WdKey table, the relevant invalid return result is wdNoKey. We set that first.

GetAlphanumericKey = wdNoKey

Then we exit the function since we already know there was a problem.

Exit Function

Putting it together, we get:

' Check for empty shortcut text
If SKey = "" Then
' Invalid shortcut text so exit function
GetAlphanumericKey = wdNoKey
Exit Function
End If

Get the single numeric or text character

We need to identify the main key for the shortcut. Our parameter for the shortcut is SKey. How do we isolate the tentative last character? Was it A, B, …, Z, 0, …, 9, or something else?

A standard VBA function called Right(SomeText) does just that.

Right(SomeText, NumberOfCharacters)

It literally gives us the rightmost NumberOfCharacters in the string represented here by the SomeText variable. Right(…) does not change SomeText directly unless we store the result back into the same variable.

Single character variable

We create a new variable named sMainKey which stores the last character of SKey. It these happen to end up the same as SKey, it doesn’t matter.

Dim sMainKey As String

We want one character from the end of the SKey parameter using the Right(…) function, and we store the result in sMainKey.

sMainKey = Right(SKey, 1)

It is a rather short string with only one character, but that’s okay. Just to be extra clear, even if sMainKey is anything "0" through "9", it is text not an explicit numerical value.

Uppercase restriction

Computers consider upper and lower case characters to be different, and the WdKey table only includes “uppercase” constant values, so we need to account for this. The easiest thing to do is just force the character to be uppercase. VBA has a standard function UCase(…) to do this.

UCase(SomeText)

It literally converts all alphabetic characters in SomeText to uppercase and returns that text. It has no effect on characters that are already uppercase or on non-alphabetic characters. The latter effect will allow us to extend the function to conveniently allow some non-alphabetic characters like numbers 0 through 9.

Since UCase(…) does not change the text directly, we need to store the result back into the same variable.

sMainKey = UCase(sMainKey)

Get the key value

How do we interpret the main key character in the context of assigning keyboard shortcuts?

The keybinding command we’re working toward in an upcoming article in part requires a numerical value for the main key from the WdKey constants table. We need to convert our identified main key text currently stored in sMainKey to the corresponding WdKey constant.

The old ascii table is our bridge. Fortunately for us, uppercase letters or text numbers 0 through 9 correspond to the same constant values in both tables.

Ascii conversion

VBA includes a standard function Asc(…) to convert a plain text character to its ascii number.

Asc(SomeCharacter)

We provide the character we need to convert, and it returns the corresponding ascii number. We’ll store this in another variable as a Long value (essentially a big counting number). Technically, Asc(…) returns an Integer, but we’ll store it as a bigger Long value. VBA handles this conversion for us automatically.

Dim myKey As Long

Now store the numeric value corresponding to the sMainKey character in the myKey variable.

myKey = Asc(sMainKey)

More concise version

If you prefer to be more concise, we could just cut out the in-between assignments and convert the last shortcut character to an ascii value in one step. Collecting the working steps, we have:

' Get last character of SKey and covert it to uppercase
Dim sMainKey As String
sMainKey = Right(SKey, 1)
sMainKey = UCase(sMainKey)

' Get ascii value of sMainKey character
Dim myKey As Long
myKey = Asc(sMainKey)

These steps can be reduced to two lines, and we can also omit the sMainKey variable since we do not use it in this condensed version.

' Interpret ascii value of last SKey character
Dim myKey As Long
myKey = Asc(UCase(Right(SKey, 1)))

It depends on your preference for concise code for whether you’re willing to read such things. When it’s clear, I probably lean toward this version in my personal macros.

Dig a little deeper (for practice)

It’s a little messy to read if you’re not used to it, but let’s think about it a little more for practice. We evaluate it from the inside out kind of like the old parentheses rules in mathematics.

  • The innermost Right(…) function picks the last character of the SKey variable.
  • This single character is then “passed” to the uppercase function.
  • Finally, this possibly modified single character is passed to the Asc(…) function.
  • The resulting number is then stored in the myKey variable.

I’ll stick with the step-by-step version for clarity in this function.

Validations

This function is specialized to our task of identifying an alphanumeric character for the main key of a potential keyboard shortcut, so we can add some extra validation steps to catch potential problems early.

We allow text numbers which have valid ascii values between 48 and 57 for characters “0” to “9”, respectively. If the character is an uppercase letter, the ascii value should be between 65 and 90 for “A” to “Z”.

Our rough conditional statement is something like:

If ascii number corresponds to an uppercase alphabetic or a number character Then
' Accept key ...
Else
' Reject key ...
End If

Lowercase letter validation not needed

Lowercase letters range from 97 to 122 for “a” to “z”, inclusive, but we do not need to test this range since we previously converted our letter, if appropriate, to uppercase.

Uppercase letter validation

To check if myKey is in the numeric range between 65 and 90, inclusive, for uppercase letters, we use two inequalities. First, myKey must be greater than or equal to 65 to be in the uppercase letter range.

myKey >= 65

Then myKey must also be less than or equal to 90.

myKey <= 90

The And operator is required because both conditions are required to be True if myKey lies within the uppercase letter range.

myKey >= 65 And myKey <= 90

Numeric digit validation

Given the context of the function, we also need to check numeric characters, but the same logic applies. Numbers 0 through 9 in the ascii table correspond to values in the range 48 to 57, so we add a second range validation check:

myKey >= 48 And myKey <= 57

Compound condition

We can accept the myKey value in either of the ranges above. Allowing either of them to be True to get an overall valid key constant corresponds to an Or operator, so we put them together into a longer compound condition.

Is key in range 1 Or is key in range 2

Using the actual range conditions from above, we have the messier compound condition:

(myKey >= 65 And myKey <= 90) Or (myKey >= 48 And myKey <= 57)

Technically the And operators are evaluated first since they have a higher precedence than Or much like multiplication precedes addition in mathematics, but it’s clearer if we include parentheses.

Validation conditional statement

We insert the compound condition into the earlier If statement.

' Validate uppercase alphanumeric ascii value
If (myKey >= 65 And myKey <= 90) Or _
(myKey >= 48 And myKey <= 57) Then
' Accept key and return valid value
Else
' Reject key with invalid value
End If

An underscore _ is a line continuation character, so VBA treats everything there as if it is on the same line. It just makes the statement easier for us humans to read.

Valid result

If the key is valid, we assign myKey as the return value to the function name.

GetAlphanumericKey = myKey

VBA automatically converts the Long value of myKey to a WdKey type.

Invalid result

If myKey does not correspond to an uppercase letter ascii value or a numeric character from 0 to 9, we return an invalid “no key” value using the wdNoKey constant.

GetAlphanumericKey = wdNoKey

This technically has a value of 255, but we will always refer to it by name to make it easier to remember which is the point of enumeration tables.

Conditional statement

We finally insert the respective return values using the function name.

' Validate alphanumeric ascii value
If (myKey >= 65 And myKey <= 90) Or _
(myKey >= 48 And myKey <= 57) Then
' Number is uppercase alphabetic or a numeric character
GetAlphanumericKey = myKey
Else
' Reject key with invalid value
GetAlphanumericKey = wdNoKey
End If

Since our return type is WdKey, we want to be consistent and return a corresponding invalid value of wdNoKey. Returning a negative value such as -1 would work. VBA would allow it, but technically, no negative values exist in the WdKey table, so that could be a little confusing down the road.

Final get main key value function

Putting it all together, the final function to get the alphanumeric WdKey value for the last character of some shortcut text is:

Function GetAlphanumericKey(SKey As String) As WdKey
' Returns a WdKey constant corresponding to the number or uppercase letter
' in the last character of SKey
' Returns wdNoKey if no valid alphanumeric character was found

' Check for empty shortcut text
If SKey = "" Then
' Invalid shortcut text so exit function
GetAlphanumericKey = wdNoKey
Exit Function
End If

' Interpret ascii value of last SKey character
' Ascii value is equivalent to WdKey constant for uppercase letters
' and text numbers
Dim sMainKey As String, myKey As Long
sMainKey = Right(SKey, 1) ' Get last character
sMainKey = UCase(sMainKey) ' Convert to uppercase character
myKey = Asc(sMainKey) ' Convert character to ascii value

' Validate alphanumeric WdKey value
If (myKey >= 65 And myKey <= 90) Or _
(myKey >= 48 And myKey <= 57) Then
' Number is uppercase alphabetic or a numeric character
GetAlphanumericKey = myKey
Else
' Reject key with invalid value
GetAlphanumericKey = wdNoKey
End If
End Function

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.