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

Parsing command phrase numbers in a Dragon Professional script

Word • Macros • Dragon • Voice Commands
Peter Ronhovde
32
min read

When creating custom natural language voice command scripts in Dragon Professional, we’ll eventually need to interpret numbers of document elements to act on such as in command phrases “delete five words” or “move that selection up three paragraphs”. Identifying the number allows more general command scripts. A previous article covered identifying relevant text keywords using the Like operator in VBA, but the process is a little more complicated when identifying numbers. We create a function to facilitate the process.

Thanks for your interest

This content is part of a paid plan.

Parsing numbers from a command phrase in a custom Dragon Professional script

A previous article parsed document related keywords. The next step in customizing our own natural language voice commands is detecting any spoken numbers. While Dragon Professional already includes list variables for such tasks, they aren’t general enough unless we create a long list. We're extending the idea to allow any whole number.

Using keywords in command parsing

Identifying keywords is a simple form of parsing text. There are better ways to interpret general text, but voice commands are often relatively simple where keywords can adequately summarize the instructions. Thus, we gain a lot of phrasing flexibility with a much easier approach.

Our number parsing goal

We’re imagining a voice command something like:

"Move that paragraph up two"

That doesn’t seem too bad, right?

A previous article talked about how to get the “paragraph” document element and the “up” direction parts of the command, but now we need to interpret the number.

Uhhh …

And it needs to work with any reasonable number (up to ten would be practical for most use cases but probably too restrictive in general), but we get bonus points if we allow any whole (non-negative) number.

Hold on.

I need some iced tea before we continue. Go ahead and get yourself a coffee and maybe a donut. I’ll be back in a minute.

Okay, Here we go.

We’ll start with interpreting numbers up to 10, but that is a little restrictive, so we’ll backtrack and add larger numbers in the extended content.

Function Skeleton

Checking for the same number matches over and over in various command scripts is repetitive, so it’s convenient to extract the steps into a function. When we need to interpret a number in a script, we just “pass” the voice command phrase to the function (generally referred to as "calling" the function). Then we store whatever result the function returns in a variable for later use.

Most of our keyword parsing functions are similar in structure, so we’ll use the following function skeleton:

Function GetPhraseNumber(sPhrase As String) As Long
' Include steps to interpret any command phrase number ...
' Only returns whole number (non-negative) values
' Assign a returned number result ...
End Function

Let's break down the details a little bit.

What parameter?

The function receives the command phrase as a plain text String variable sPhrase.

sPhrase As String

An upcoming article will cover how to get the command phrase from the Dragon Professional voice command script, but for now we’ll assume it’s stored in the sPhrase text variable.

Return result

To return the value, we assign any determined result to the function name anywhere within the function. For example, we might assign a function result by the following somewhere inside the function:

GetPhraseNumber = 1 ' Tentative function return value

Default value

The document direction is already determined by a previous parsing function, so we will not interpret negative numbers in this function. Therefore, zero makes a reasonable default value when no number is stated explicitly in the command.

Data type

The return type of the function is given As Long as opposed to As Integer since Integers in VBA have a maximum value around 32,000. In practice for a voice command when writing, even this large of a number would probably never be needed, but we might as well be general about it (perhaps for character or word commands in a novel). Long values require slightly more computer memory than Integer values, but in practice, we would almost never notice the difference in a script or macro.

Store the detected number

We need to store the number for later use if it is present in the command text. As mentioned above, two of the basic number types are Integers and a larger number Long. To keep things simple and general, we’ll use Long.

Dim nElements As Long

Long and Integer data types are actual numbers in VBA as opposed to text versions of numbers like “two” or “2”.

I like to precede any variable names for numbers with an “n” as a reminder of what type of data it stores. We’re calling the variable “nElements” rather than something like “nParagraphs” since we plan to use the number function with different document elements across several scripts.

Using Like in text searches

“Text? I thought we were checking for—”

Just hold on.

We’re building something. Plus, we can write numbers as words also, right?

Search expressions using Like embrace VBAs inclination toward easily understandable commands (speaking of VBA macro steps not a Dragon voice command). They are usually clean and easy to read, and they allow a few wildcard characters in the search patterns to match varied text. Wildcard characters provide some flexibility, but we’ll stick with simpler search patterns for keywords or numbers.

The previous article covers some elementary concepts in more detail when using Like to parse a short command phrase, so we’ll swim out into deeper water a little more quickly in this article.

If you’re interested in more comprehensive search techniques, look up regular expressions including our brief introduction to using them in VBA.

Basic syntax when searching with Like

As a brief review, the basic syntax using Like is:

sPhrase Like "*two*"

The text variable to search comes first followed by the Like VBA reserved word (meaning we can’t declare a variable in VBA named Like). Lastly, we add a plain text match pattern in double quotes. We could also use a String variable for the search pattern if it helps, but we’ll just stick with explicit search patterns.

Asterisk wildcard characters

The asterisks on either side of “two” indicate that Like should allow any or no characters on either side of the word. If one were omitted, such as “two*”, this pattern would require “two” to begin the sPhrase string, so we need both asterisks.

Like statement result

A search expression using Like will result in a True-False (Boolean) value. For example, our test expression “*two*” is True if the word “two” is found anywhere within the sPhrase text variable.

Using Like in conditional statements

Since Like gives us a True or False result, we can use them directly in conditional statements to make decisions in the script (see previous article for a brief introduction).

If sPhrase Like "*two*" Then
' Do these steps if "two" is anywhere in the sPhrase text ...
End If

We’re checking against the noun form of “2” since Dragon Professional will automatically convert spoken text in a <dictation> list variable (see below) to the word form when the number is less than or equal to ten.

Storing the numerical result

Like only tells us whether a match was found, so we need to manually store the intended number inside the If statement.

If sPhrase Like "*two*" Then
nElements = 2
End If

The variable nElements stores the actual number value not a text version of it.

Using Like for text numbers as digits

In Dragon Professional scripts, the command phrase will be all text even if any numbers are stated explicitly. The number “2” will probably be automatically transcribed as the noun form “two” for any values ten or below (customizable in Dragon settings), but we should also interpret the text number version just in case.

Incidentally, even a “2” in a text variable is still text even though it looks like a number to human eyes. In VBA, it’s not a number 2 in the conventional sense until we convert it to a numerical value. We’ll work on number conversions from text in the extended content.

Numerical text search pattern

How do we match numerical digits as text?

We’re already checking for the noun form "two", so we explicitly add a check for the digit form “2” as text. If either condition is a match, then we know the stated number and can assign the value to nElements.

When matching “2”, our search pattern is literally “*2*”.

Not using “#” in the search pattern (yet)

If you’re familiar with the search patterns, you may notice that I omitted the more generic numerical digit match “*#*”. I don’t want to match a single-digit number because Like doesn’t tell me what number was matched. It only indicates that a match occurred, and I also need to test for noun forms like “*two*” anyhow. See the extended content below where we leverage the general match pattern for larger numbers.

Compound conditions

We’re matching both the noun “two” as well as the number “2” as text.

When several conditions are equivalent

Since either match could be True and still indicate a numerical value of 2 for the voice command, we use an Or operator.

Condition A Or Condition B

The Or operator gives us a True result is either condition A or B is True. Applying it to our Like searches, we have:

sPhrase Like "*two*" Or sPhrase Like "*2*"

In this compound condition, we won’t know which match was True (or both), just that one of the matches was successful; but in this statement, both matches are equivalent to the same numerical value.

Our number conditional statement

We put this compound condition into a conditional statement.

If sPhrase Like "*two*" Or sPhrase Like "*2*" Then
' Assign a known value of two
End If

In one sense, it’s a little clunky, and it will get even longer below, but it’s not as awkward as it seems at first. No matter what, we would need to interpret any usage of “two” in a command phrase as a noun whether it is done directly or as part of a separate function.

Other solutions?

Alternatively, we could get more detailed information on a match using another string function InStr(…). It detects the presence of a search text and tells us where it’s located in the string.

In principle, we could then extract the number and convert it to a value from the string, but InStr(…) looks for a specific text with no wildcards possible. If we knew what text number to search for, we wouldn’t need to search for it.

A regular expression could easily capture which value the user said at a given position in the command using a “group”, called a “submatch” in VBA parlance. We could use that information somewhere else in the script, but that is a subject of a later article.

Solving with Like

Fortunately, if we’re willing to sacrifice conciseness in our script, Like provides an easy and clear solution.

Detect which number matches using ElseIf

How do we distinguish between numbers one through ten?

We can extend what we did for the number “two” to the numbers one through ten. If we find a match, we assign the appropriate number to our nElements variable.

The direct approach is to chain the necessary conditional matches together using ElseIf statements. An ElseIf statement is basically a continued If statement, so we chain ten of them together to handle whole numbers ten or less.

If either match condition for "one" is True Then
' Do these steps for match condition one ...
ElseIf either match condition for "two" is True Then
' Do these steps for match condition two ...
'
' Include other matches up to ten ...
'
End If

Each ElseIf statement tests the condition and runs the code below it if the condition is True. If the condition is False, it checks the next ElseIf statement until none are left or until it finds an Else statement. After any match in the chain is found and the corresponding steps are run, the overall If statement ends. See this previous article for more explanation about conditional statements in VBA.

Default value

We need a way to set a default value since a number may not be stated in some cases. If no numbers are found, we assume a value of zero and assign it in the Else part of the long If statement.

' ... previous part of the If statement
Else
' Do these steps if no other matches were found ...
End If

Getting the number

Now the initial solution.

As we did with search for “*two*” above, we use Like to check for a series of specific numbers in either the text or numerical form and then assign the known value to the nElements repeating for all numbers up to ten.

Including ordinal numbers

You could add ordinal numbers such as “*first*” by tacking on an additional check.

sPhrase Like "*one*" Or sPhrase Like "*1*" Or sPhrase Like "*first*"

We only need to consider the unique ordinal forms like “first”, “second”, “third”, “fifth”, or “ninth”. The others like “fourth” will be matched by “*four*” since “four” is a substring of “fourth”.

Number parsing conditional statement skeleton

Repeat the compound conditional statements for “one”, “two”, up to “ten”. That’s why we sacrificed conciseness if we use Like directly. If no number matches are found, we’ll assume a value of 0.

An abbreviated set of steps to interpret the move number is:

If sPhrase Like "*one*" Or sPhrase Like "*first*" Or SomeText Like "*1*" Then
nElements = 1
ElseIf sPhrase Like "*two*" Or sPhrase Like "*second*" Or SomeText Like "*1*" Then
nElements = 2
'
' And other number conditions up to ten ...
'
Else
' No matches found, so assume zero
nElements = 0
End If

Now that we have the skeleton, let’s create our function.

Basic numbers phrase function

We’ve been storing the identified numerical value in the nElements variable, but now we’ll return the number as our function result by storing it in the function name GetPhraseNumber instead.

Function GetPhraseNumber(sPhrase As String) As Long
' Check given phrase for (text) numbers up to ten
' Ordinal numbers are included up to ten
' Returned values are any single-digit whole number up to 10
' with zero 0 as a default value for no matched number

' Determine if a whole number is in sPhrase
If sPhrase Like "*one*" Or sPhrase Like "*1*" Or sPhrase Like "*first*" Then
GetPhraseNumber = 1
ElseIf sPhrase Like "*two*" Or sPhrase Like "*2*" Or sPhrase Like "*second*" Then
GetPhraseNumber = 2
ElseIf sPhrase Like "*three*" Or sPhrase Like "*3*" Or sPhrase Like "*third*" Then
GetPhraseNumber = 3
ElseIf sPhrase Like "*four*" Or sPhrase Like "*4*" Then
GetPhraseNumber = 4
ElseIf sPhrase Like "*five*" Or sPhrase Like "*5*" Or sPhrase Like "*fifth*" Then
GetPhraseNumber = 5
ElseIf sPhrase Like "*six*" Or sPhrase Like "*6*" Then
GetPhraseNumber = 6
ElseIf sPhrase Like "*seven*" Or sPhrase Like "*7*" Then
GetPhraseNumber = 7
ElseIf sPhrase Like "*eight*" Or sPhrase Like "*8*" Then
GetPhraseNumber = 8
ElseIf sPhrase Like "*nine*" Or sPhrase Like "*9*" Or sPhrase Like "*ninth*" Then
GetPhraseNumber = 9
ElseIf sPhrase Like "*ten*" Or sPhrase Like "*10*" Then
GetPhraseNumber = 10
Else
' No matches found, so assume zero (no negative values allowed)
GetPhraseNumber = 0
End If
End Function

Really? That’s clunky

Yeah, that’s … kind of long. We stopped at ten just to keep it shorter, but we still need to account for numbers bigger than ten.

Arghhh.

Can you say regular expressions, please?

Yeah, I agree, it really is easier if we switch, so we could—

Excuse me?

Oh, sorry. You’re right. I suppose we shouldn’t get ahead of ourselves. Yeah, let’s save regex for another article and stick with Like for now [sad face].

Example use

When using the above function, we store the result in the nElements variable we defined earlier. We “pass” the command phrase sPhrase as an argument in parentheses, then set the returned result equal to nElements.

nElements = GetPhraseNumber(sPhrase)

Given the function, we know we get a Long value from 0 up to 10. See the extended content below if you want to allow any whole number up to about two billion, but the process is more programmy.

Gotchas?

Where could all this go wrong?

Ambiguous numbers

There are some issues with more colloquial phrasings like “this one”.

"Move that three paragraphs above this one"

I admit the wording is a little awkward, but “one” in this phrase is a pronoun referring to the current paragraph rather than a numerical value. The above function would not be able to distinguish between “three” and “one” without some additional validation checks. Solving this issue is left to later articles.

Just don’t say it like that

One could argue, “just don’t say it like that.”

I suppose you could enforce that restriction on yourself, but you’ll be surprised how much your spoken command varies as you try to conveniently give command.

It’s happened to me more than once. You’re writing, and you need to instruct the computer to do something. Your brain knows what you want to say and the meaning of the command, but your verbal processing doesn’t quite get the command out correctly, at least not without some additional effort.

Writing and speech use different parts of the brain. It’s not that you can’t train yourself to efficiently give the voice command in a specific way, but why not let the command script make that process easier? We’ll expand more on natural language voice commands in upcoming articles at two different levels.

Improved Number Phrase Function Using Like

Let’s tackle interpreting numbers larger than ten.

Like with numbers

The wildcard character to find numbers with a Like search pattern is “#”. Assuming it is part of a larger search pattern, the hashtag symbol specifically matches a single number digit at the given location in the search pattern.

Detecting one-digit numbers

How do we get a general one-digit number anywhere in a text string using Like?

Using our previous command phrase variable sPhrase, we could try a pattern match such as:

sPhrase Like "*#*"

This pattern asks Like to match any single-digit number in the text regardless of what is on either side (numbers, spaces, or other text). For example, “This is a 1” would work fine but so would “How about 23” and “Your ID is A4X”. We can take advantage of the former and correct for the latter below.

However, using Like only tells us if a number is present. We don’t get the numeric value or even its position in the sPhrase text variable.

Ughhh, can’t they ever make it easy for us?

What do we do?

Leave single-digit numbers explicit

We can detect whether a single digit number exists in the text, but in practice when parsing voice commands, using a pattern “*#*” doesn’t solve our problem of interpreting numbers.

We don’t get the specific number or even its position in the phrase, and we would still need to account for noun forms of the numbers “one” through “ten” (and the unique ordinal forms if you wish to include them). Most <dictation> list variable results in Dragon Professional scripting will automatically convert spoken numbers ten or below into their noun form, so we can’t leave them out.

It’s easier to just use explicit matches “*1*”, “*one*”, “*first*”, etc. with single-digit numbers, and tackle larger numbers with the hashtag wildcard character.

Aside from a different solution entirely (like regex … yeah, I’ll shut up about it for now), we can still solve this problem for larger numbers, but we will need to lean on some additional tools to generalize our solution.

Detecting two-digit numbers

For larger numbers, we need to know if at least two consecutive numerical digits appear together anywhere in the text. Using Like, we can detect them with more than one hashtag in the search pattern such as “##”, but we need the wildcard characters “*”. Each asterisk * allows for any or no character in that position, so a search pattern “*##*” using Like will match any two number digits side by side anywhere in the searched text. A few examples include:

"Move that paragraph up 12" Like "*##*" ' Match is True
"Move that down by 103 paragraphs" Like "*##*" ' Match is True
"Move the selection left by 5 words" Like "*##*" ' Match is False

The first two examples work because they include at least a two-digit number, “12” or “103”, respectively. The pattern also matches “… 103 …” because the “3” in the number falls into the second asterisk * wildcard character since a "3" counts as any character. The last example only includes a single digit number “5”, so it is not matched by “*##*” which requires at least two digit characters side by side.

Not quite enough …

What’s the problem?

Again, Like only tells us whether a match was found. It returns no information about the match, so we still need to dig deeper to extract the stated number from the command.

Match conditional statement

So we can detect a general two or more digit number in the command phrase using the Like search pattern “*##*”. Using our assumed command phrase sPhrase, the conditional statement looks like:

sPhrase Like "*##*"

Combining this with our previous conditional statement from the basic script above, we get:

' ... other prior number cases from one to ten
' Now check for at least a two-digit number
ElseIf sPhrase Like "*##*" Then
' Do these steps if at least a two-digit number exists ...
Else
' Default case if nothing else matches ...
End If

Are we done?

Oh. That’s all? That was easy—

Uh …

Probably not if you scroll down and see how much of the article is left.

What’s wrong?

As previously mentioned, we don’t know which number was stated. The above Like expression only tells us if a two or more digit number is present.

Ughhh.

This is why regex really is a better solution for more complicated text searches, but let’s trudge ahead.

Test each word of the command phrase

We can split the command text up into individual words and check whether each word is a number.

Yeah, it’s clunky, but it’s completely general for any whole number mentioned in the command.

Store the command words

We need a variable to store all the words in sPhrase. We’ll call it AllWords.

Dim AllWords As Variant

We’re being lazy with the return type because we haven’t talked about arrays (basically a sequential list of values in computer memory) yet, and the Split function below will give us an array of words. Using a Variant type for AllWords allows VBA to handle the details for us. I don’t like being sloppy like this, but I do not want to introduce arrays now.

Using the Split function

The Split function is a standard VBA function that takes a plain text string and splits it based on any desired separation character such as commas, spaces, dashes, etc. The string to split is the first argument, and the character used to break it into pieces (generally called “substrings”) is the second argument.

Split(SomeText, SplitCharacter)

In our case, we need to split the command phrase sPhrase into individual words, so we specify the split character as a space “ ” in double quotes (remember plain text strings must be set off by double quotes). The spaces are discarded in the splitting process, but this doesn’t matter for our solution.

' Split sPhrase into individual words based on spaces
AllWords = Split(sPhrase, " ")

The return type for the Split function is an array of text strings, but we’re not interested in the gritty details more than what was stated above. The AllWords words variable just holds a sequence of words for us.

Checking for numbers using IsNumeric

We’ve split sPhrase into its individual words. Presumably most of them will be regular words and not numbers; so if I select a given word, say “the”, from command phrase, how do I determine whether it is a number? And when I find a text number, how do I convert it to an actual number?

Let’s assume our word is stored in a variable named sWord (see below). The IsNumeric function is a standard VBA function that tests whether a text string is a possible number in disguise.

IsNumeric(sWord)

The function does not convert the word to a number for us. It just checks whether sWord has a possible numerical value and gives us a True or False (Boolean) result.

Using IsNumeric in a conditional statement

Since IsNumeric returns a Boolean value, we can immediately use it in a conditional statement.

If IsNumeric(sWord) Then
' Convert sWord to a number ...
End If

Presumably inside the If statement, we would convert the validated number into its corresponding numerical value.

Converting numerical text into a number

We can convert a known text number to a VBA Long number type using the standard VBA function CLng(…). We apply it to sWord and then store the result in our previous variable nElements.

nElements = CLng(sWord)

This function only works if we know sWord is a text form of a numerical value such as “1”, “25”, etc. Otherwise, VBA will give an error and crash your script which isn’t fun.

If you prefer to use Integer numbers, there is a corresponding VBA function CInt(sWord).

CLng only works for numbers

Unfortunately, neither IsNumeric nor CLng will work with noun forms of numbers “one”, “twelve”, etc., but we’ve already manually accounted for these numbers at least up to “ten” in the basic script above.

Number conversion

Putting it together, our numerical test along with the number conversion is:

If IsNumeric(sWord) Then
nElements = CLng(sWord)
End If

But since the command is so short, I prefer the more compact form:

If IsNumeric(sWord) Then nElements = CLng(sWord)

Unfortunately, this does start looking more like programming than a typical VBA macro or script.

Check all command words

We now want to check each word in the AllWords variable and convert the spoken number. A For Each loop will iterate over each item in an array or collection and allow us to run checks (or whatever else we wish to do) on it.

General For Each loop structure

A general For Each loop has the structure:

' Loop over any array or collection of items
For Each SomeLoopVariable In SomeCollection
' Do these steps for each item in SomeCollection ...
Next

The reserved words “For”, “Each”, and “In” are required. SomeLoopVariable must be a Variant type for an array like we're using, but it can be an Object type if you're looping over object-like things such as Ranges, Paragraphs, etc. This variable changes its value as we loop over the items in SomeCollection.

The SomeCollection variable can be any array or collection VBA understands natively. Word or Dragon automatically detects how many items are in the collection and loops over them one by one.

The loop must be ended by Next. If you prefer to be extra clear, the loop variable name can be placed after the Next, but it is optional.

Next SomeLoopVariable ' Including the loop variable is optional

All steps inside the loop will be repeated for each item in the collection. If SomeCollection contains no items, then the loop does nothing. A nice thing about a For Each loop is we don’t need to know how many items are in the collection.

Define a loop variable for each command word

We need a loop variable which we’ll name sWord. This variable will take on the value of each individual word in the command phrase as the For Each loop iterates over each word stored in the AllWords variable.

Dim sWord As Variant

You might consider declaring sWord as a String type since we know the words from the command phrase are plain text, but VBA requires the Loop variable of a For Each loop to be a Variant type because we’re looping over an array.

Loop over the command words

Now loop over all the words in AllWords and perform the number check. Following the For Each loop structure above, we use:

' Loop over identified words to detect a number
For Each sWord In AllWords
If IsNumeric(sWord) Then nElements = CLng(wWord)
Next sWord

sWord must be the loop variable, and AllWords must be the array of words where we’re looping over.

Allows (almost) any size number

Split separated our command phrase into words based on the spaces “ ” between them. Even though we initially matched a two-digit number using Like, the Split function automatically separates out the whole number (no pun intended), so the conversion works for any size number up to the maximum size of a Long variable (over two billion).

Final improved get number function

Combining the earlier basic function results with our new multi-digit number parser, we the following improved script. Again, we replace references to nElements mentioned above with the function name GetPhraseNumber to assign the return value of the function.

Function GetPhraseNumber(sPhrase As String) As Long
' Check given phrase for (text) whole numbers
' Ordinal numbers are included up to ten
' Returned value is any whole number up to about two billion
' with zero 0 as a default value for no matched number

' Determine if a whole number is in sPhrase
If sPhrase Like "*one*" Or sPhrase Like "*1*" Or sPhrase Like "*first*" Then
GetPhraseNumber = 1
ElseIf sPhrase Like "*two*" Or sPhrase Like "*2*" Or sPhrase Like "*second*" Then
GetPhraseNumber = 2
ElseIf sPhrase Like "*three*" Or sPhrase Like "*3*" Or sPhrase Like "*third*" Then
GetPhraseNumber = 3
ElseIf sPhrase Like "*four*" Or sPhrase Like "*4*" Then
GetPhraseNumber = 4
ElseIf sPhrase Like "*five*" Or sPhrase Like "*5*" Or sPhrase Like "*fifth*" Then
GetPhraseNumber = 5
ElseIf sPhrase Like "*six*" Or sPhrase Like "*6*" Then
GetPhraseNumber = 6
ElseIf sPhrase Like "*seven*" Or sPhrase Like "*7*" Then
GetPhraseNumber = 7
ElseIf sPhrase Like "*eight*" Or sPhrase Like "*8*" Then
GetPhraseNumber = 8
ElseIf sPhrase Like "*nine*" Or sPhrase Like "*9*" Or sPhrase Like "*ninth*" Then
GetPhraseNumber = 9
ElseIf sPhrase Like "*ten*" Or sPhrase Like "*10*" Then
GetPhraseNumber = 10
ElseIf sPhrase Like "*##*" Then
' At least a two-digit number exists, so convert it
Dim sWord As Variant, AllWords As Variant

' Split sPhrase into its individual words
AllWords = Split(SomeText, " ")

' Loop over identified words to detect a number
For Each sWord In AllWords
If IsNumeric(sWord) Then GetPhraseNumber = CLng(sWord)
Next sWord
Else
' No matches found, so default to zero
GetPhraseNumber = 0
End If
End Function

This version will not catch noun forms of numbers above ten, but it catches them for ten or below because we explicitly test for them.

The way the two or more digit number check and conversion is done, only the last number mentioned in the command phrase will be returned. Any other numbers mentioned are ignored.

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.