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

Create a Dragon script with command variables

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

Dragon Professional® comes out of the box with what they call “advanced scripting,” and we can leverage Dragon’s speech recognition engine not only for dictation but also when invoking custom voice commands to automatically carry out many writing and editing tasks. We can edit our documents faster and trigger more detailed and specific commands than you’re probably envisioning at this moment.

Thanks for your interest

This content is part of a paid plan.

Create a Dragon Professional advanced script with list variables

In this article, we’ll incorporate “list variables” in an custom Dragon Professional script to create more general and somewhat more natural voice commands to control Word.

If you prefer to jump straight into the water, start below. This article makes necessary use of a previously covered function to run a Word macro from within a Dragon Professional script. Another article covers the basics of getting a simple Dragon script up and running to run macros with Microsoft Word using your voice.

Existing Dragon Professional features …

Today, we’re focusing on using advanced scripting with Visual Basic for Applications (VBA) to talk to Word, but Dragon Professional also allows step-by-step macros as well as AutoText-like substitutions if you’re interested in those options.

Dragon already includes some natural language commands built into the application, and they’re nice, but the details can be a little annoying at times. Plus, we’re building up to better scripts where you have more control over how they work. I mean, if they’re “custom,” they should be custom.

Leveraging Word VBA macros

More specifically, I want to leverage my own Word VBA macros that already perform many editing tasks the way I prefer. Make Word work your way, right? (Say that three times real fast.)

This article extends previous one, but this version is more akin to a tutorial on using list variables in Dragon Professional advanced scripting, so we can expand our voice command capabilities when working with Microsoft Word.

Dragon Professional features and price

Advanced scripting is only available in the Dragon Professional or more specialized editions like Legal or Medical One. Dragon Professional is a paid application, and I am specifically using Dragon Professional v16 for this content. Do not buy an older, discontinued version of Dragon Home if you wish to use any advanced scripting features.

As writers, we should make use of tools that enhance our productivity, especially one that offers as much of a potential boost as Dragon Professional. If you’re price sensitive (and I understand that, for sure), you may want to come back to this article later, but if you can afford it, making the paradigm shift toward “will this expense make me faster, better, and/or more productive” is a valuable asset for anyone who plans to or is already making money on their writing.

How’s it work?

The name “list variable” sounds obscure to me. I’ve been programming for years, but what in the world is that?

We’ll get into more detail below, but in practice, they provide a way to create more variability in our voice command phrasing, so we don’t have to create forty-eleven script variations for each target task to handle different ways of saying the command.

More specifically, we create “lists” of words valid at a particular position in a voice command. Then we connect the voice commands to the respective Word macros we’ve already created.

We won’t avoid all script duplications (assuming you like more varied natural language commands), but it will significantly expand our voice command possibilities.

What this article is …

Rather than give a simplified example, we’ll dive right into swimming waters and use three list variables to create a relatively natural and practical voice command. Specifically, we’ll create a voice command to invoke a Word VBA macro that moves the current paragraph up or down in the document by any number of paragraphs. The phrasing is something like:

"Move that paragraph down three"

Simple and intuitive. Just the way I like it.

What this article isn’t …

This article is focused on implementing list variables in a Dragon script. It isn’t a tutorial covering the Dragon Professional scripting editor nor advanced scripting in general, but we are significantly extending the possibilities of using your voice to control Word with your own customized macros.

If you don’t have many VBA macros in Word yet, you might first check out some of the dozens of articles already on this site. What are you waiting for?

Why?

Why go through the trouble of creating voice commands?

Speed.

Plus, it’s a little fun to just say the commands and watch the magic happen.

Good enough isn’t …

“Good enough” is usually too slow—at least if you’re making money with your brain and fingers … and soon to be voice if you keep following along.

Expand your editing macros

Keyboard shortcuts are great and still the best option for the most common editing tasks, but sometimes it’s easier to just say it.

There are an infinite variety of macros we can create for so many tasks, but you have to remember them when editing. I have a few dozen macros bound to various keyboard shortcuts or as buttons in the Quick Launch toolbar. I try to group them and even use a few pretty little icons on the Quick Launch bar to make them easier to remember, but even then I forget the ones I don’t use as often.

Easier than some keyboard shortcuts

It's a lot easier to remember, “Select heading,” than some obscure key combination. For me, it’s Command+Option+Numpad5 … see, a little awkward, but I had more reasonable key combinations already claimed by other, more important, keyboard shortcuts.

Easier variations

Also, sometimes small variations to macros exist where I like both versions. For instance, right now in this document I want to select just the heading content excluding the heading paragraph. With voice commands, I can have both with just a slight wording change, “Select the heading content.”

Principles

Voice commands allow a large variety of command phrasings, so I try to cover most reasonable editing tasks in my macro collection. I also try to make the phrasing of the command as natural as possible.

As humans we don’t speak like robots, so the natural command variations make working with them easier. It is frustrating to forget your precise phrasing when you’re in the middle of editing. “Did I include a ‘the,’ use ‘that,’ ‘this,’ or leave it out completely?”

What is a list variable in Dragon Professional advanced scripting?

List variables are Dragon Professional’s specialized version of VBA variables. Given we’re dealing with dictation software, they’re not the same a general purpose variable, but they provide some structure to allow for command variations.

Practically speaking for us, we can use the same script to invoke different Word macros with slightly different phrasings.

Customizable command word lists

More specifically, a list variable in a Dragon Professional script is just a plain text list of possible words at a given position in a custom voice command. For example, you might create a list variable called <direction> holding various literal directions in the document.

  • above
  • below
  • up
  • down
  • backward
  • back
  • forward
  • left
  • right

The list is completely customizable with the exception of no blank entries are allowed. That means we can’t use a list variable to spoof an optional (omitted) command word.

Using a list variable

A list variable in a voice command name is surrounded by angle brackets like <direction>. Yeah, literally type it with angle brackets as shown.

Move that paragraph <direction>

This command could be invoked using the command:

"Move that paragraph up"

We can mix and match words and phrases to make our voice commands roll off the tongue more naturally.

Awkward keyword editor

Unfortunately, it looks we must work through the Dragon advanced scripting interface to create or edit the lists for a variables, which is a little awkward, but it is functional.

We can create up to custom list variables, but more standard ones exist in the scripting editor.

What do list variables do for us?

While they are a little annoying, list variables reduce misidentification of words when invoking voice commands by restricting the phrase to a more limited set of words.

They also allow us to condense our collection of voice commands since we can combine similar variations, but we’ll still have to create some duplicates if we want more natural voice commands.

Any issues?

What should we watch out for?

Dragon doesn’t really care about the exact composition of your list variables, but to make your own life easier, you might …

Consistency

Keep the lists consistent, so they make sense. On the other hand, utility is more important than idealized list categorization. Just don’t go overboard with mix and match word lists.

Not too long

Avoid exceptionally long lists. In extreme cases, very long lists might slow down the command recognition, but any speed issues are usually dominated by the voice recognition engine. On the other hand, Dragon allows a maximum of 20 custom lists, so you may need to condense them some.

Variable tips

How can we use list variables smarter?

Include some simple word variations

I have a list called <which> which contains:

  • the
  • those
  • that

These and similar words allow some general phrasing differences since we naturally state things in context. For example, when moving more than one paragraph we might say “move those paragraphs” rather than “move that paragraph,” but the computer must be instructed about how the generalized phrases mean essentially the same thing. We also tend to vary our wording without thinking about it.

Include more than one word on a line

We can wring more utility our o list variables by using multiple words. For example, my <which> list also includes some multiple word variations

  • to the
  • to a
  • the first

It may take some simple parsing logic to detect words like “first” or “last,” but we’ll cover such improvements in upcoming articles. With these extra variations, we could additionally say:

"Move to the paragraph above"

Lists don’t have to be mutually exclusive, but …

When you give a voice command, Dragon looks for the best command match.

Okay …

The same word can exist in more than one list variable which helps us organize our voice commands with different flavors for different Word macros, but …

Don’t go crazy with overlapping list variables because it will muddle the lists and make remembering the commands more difficult. More importantly, it could also lead to different commands having the same phrasing while being hidden behind the list variables. Dragon might not recognize and properly assign a command to the intended script.

Dictation list variable

Dragon provides a unique list variable <dictation> that encompasses all text at the end of a voice command. It must be placed at the end of the command, and any text at the end is parsed as if it were dictated text. This treatment has some implications if you want to write more general natural language scripts (that’s a hint for some upcoming articles), but we won’t be using it in this script.

What’s the plan?

In principle, how do we create a simple voice command script in Dragon Professional?

  • Open the Dragon Professional advanced scripting editor
  • Tell the script what application we want to connect to it (really part of the previously covered function)
  • Create a command name which is also the voice command to use when invoking the script
  • Set up a new list variable or use an existing one by typing the angle brackets around the variable name
  • Tell the script which Word VBA macro to run based on the word combination using the mentioned function

In order to keep the decision logic simple, we’ll use a separate function to connect Dragon Professional to the Word application, so see that article for more information.

How do we control Word from a Dragon Professional script?

Create script skeleton

Since we covered this in a previous article, we’ll be brief here.

The advanced scripting editor is mostly a plain text editor where we type commands just like in Word VBA macros. The Dragon Professional script editor has fewer features than the already meager Word VBA editor, but it does the job with some idiosyncrasies.

What’s the difference between a macro or a script?

Let’s clarify some terminology.

A “script” in Dragon Professional is basically the same thing as a “macro” in Word VBA.

Generally speaking, macros tend to refer to automations for repetitive tasks in an application. Scripts will probably look more like programming where macros may look more like general steps, but significant overlap exists between the terms.

In Dragon Professional, a “macro” is a recorded or list of task steps, but a “script” is a set of VBA steps more like a Word VBA macro. In Word, we can record macros as a series of steps, or we can write our own steps as a macro directly using VBA. The same term macro is used for both in part because Word always creates a VBA macro even when recording steps.

Open the script editor

Open the command editor using the Dragon Bar menu: Tools → Command Center → Add new command …

Create a new Dragon script

In the middle, open the combo box for the Command Type and select Advanced Scripting. This will add some lines to the script editor below.

Baby script ...

After selecting the new command option, by default, it’ll create an empty VBA script like the following in the script editor.

'#Language "WWB-COM"
Option Explicit

Sub Main

End Sub

Any VBA script steps will begin on the empty line after Sub Main. Now to the meat for our current project. We covered these lines in more detail in a previous article, so we’ll get to the point here.

Type the command name

In the MyCommand edit box at the top of the script window, type the first part of the voice command name.

Move that paragraph

We now need to give a general direction as part of the command.

Define a list variable

To define a list variable, start and end the list variable name in the command with angle brackets <direction>. Our command name for the script now literally looks like:

Move that paragraph <direction>

Of course, you can shorten or extend the phrase to your preference.

List variable dialog

Dragon will pop up another dialog where you can either chose an existing list to modify, or the editor will recognize and create a new list variable with that name. Each word or phrase should be on a separate line.

MyCommand editor dialog

Double click the list variable name to open the list variable editor.

List variable editor

The words are simply listed as plain text on separate lines.

Accessing variable values

Invariably, you’ll want the variable value as stated by the user during a voice command. We’ll need to store it in a plain text variable called a String.

Dim sVariable As String
' Store the first list variable result
sVariable = UtilityProvider.ContextValue(0)

I wouldn’t call this opaque notation, but it’s definitely not obvious either. Still, that’s why you have the internet and this amazingly helpful and wonderful article to guide you.

The Dim variable declaration is only required if Option Explicit is used at the top of the script (which is the default). I like preceding any string variables with an “s” to remind myself what I’m storing in the variable, but that’s just my preference.

Context element 0 gives us the value of the first list variable used in the voice command name. Element 1 is the second, and so forth (indexing using zero as the first element is common in programming). In this script so far, there is only one list variable, so (0) gives us the correct the stated word(s) at that position in the voice command. There actually is a good reason for counting from zero in other contexts, but we’ll just have to get used to it here.

Using list variable values

All list variables will start out as plain text strings, so you need a string variable like above to store the voice command word at that position in the command. If you’re searching for text or just comparing to the value directly, that’s all you need. If you want a numerical value from the variable, you’ll need to convert it. We’ll cover both options below.

Direction example

Now we can specify a verbal direction to move our paragraph. Imagine invoking the command by saying:

"Move that paragraph above"

Adapting the above context value stuff, we get the direction variable value said by the user specifically using:

Dim sDirection As String
sDirection = UtilityProvider.ContextValue(0)

In a stated voice command, the variable sDirection could contain a plain text value of “above” or “below”, but I like to allow even more options, so I further include word options: “before” and “after” as well as “up” and “down” or even “forward” and “backward.”

Using a Select statement

How do we conveniently allow all these possibilities?

We could chain together a series of If statements (see this previous article for a brief introduction to conditional statements in VBA), but it gets unwieldy quick. A Select-Case statement is much more natural here.

Select Case SomeVariable
Case Value1, Value2
' Do something for these two values
Case Value3
' Do something for this third value
Case Else
' Do this if nothing else matches (optional)
End Select

The SomeVariable after Select Case should be a variable that we can compare against known values like a number or a string (plain text). Essentially, this is an extended If statement that is cleaner to read and thus easier to use when many options exist.

Case conditions

We chain a series of Cases together as shown where we list the values corresponding to that case.

Case Value1, Value2

More than one value can be specified for each Case just by using a comma to separate the values. We can also be fancier with ranges of values (like Case 1 To 3 and other variations), but we don’t need it here since we’re comparing the direction list variable result to specific words.

If no matches are found, we could optionally include a Case Else to catch any other unspecified conditions. In these voice command scripts, I usually only use this option to notify myself that something went wrong such as a word was misinterpreted by Dragon.

What happens?

When a match is found, only the commands up until the next Case line are run (this is different than some other languages where the execution can fall through into the following cases).

If no matches are found, the Case Else steps are run.

If no matches are found but no Case Else is included, nothing happens.

While not forbidden, it’s best to not include any overlap in the cases since only the steps corresponding to the first match will be run.

Back to our example

Let’s apply this in skeleton form to our specific voice command. For our direction example, “above” and then “below” are the two cases. We use the sDirection variable to pick between the Cases.

Select Case sDirection
Case "above", "up", "backward", "back"
' Run Word macro to move the paragraph up
Case "below", "down", "forward"
' Run Word macro to move the paragraph down
End Select

Looking at the Case options, I also added some other variations to provide flexibility in how we say our voice command. For example, we could also say:

Move that paragraph up

Or …

Move that paragraph back

But keep reading because we’re still building our command.

Only allowed keywords work

The above Select Case statement excluded the Case Else at the bottom, so no backup action is allowed.

That is, nothing happens if we don’t detect one of the specified direction keywords. The voice command will only work with the specified keywords even if they are included in the <direction> list variable, but this isn’t a bad thing. I’ve used this multiple times to enable only the word variations I want for a specific command while keeping my list variables more general within reason.

For example, my <direction> list variable also includes the word “left”, but this phrasing would be awkward.

Move that paragraph left

Huh?

It should do the same thing since left basically means before the current paragraph, but it doesn’t make English sense (at least to me), so I don’t enable that word for this command. I suppose one could argue the same thing about above or below since they’re prepositions with no object, but the object is implied clearly enough for me.

No optional command words

Unfortunately, we can’t include optional words in a voice command name as of Dragon Professional version 16.0. Omitting optional words is an unfortunate omission itself, but we can allow some flexibility as shown using list variables.

If you want some different phrasings for the same voice command, you can further duplicate the script and/or use some clever list variable values, but as of Dragon Professional v16, if your command includes a list variable, you must say something at that position in the command.

Running the Word macro

Candidate VBA commands to run the relevant Word macros might be:

WordApp.Run "MoveParagraphAbove"

Or …

WordApp.Run "MoveParagraphBelow"

I say candidates because these aren’t my actual macro names since we can be more concise if we use a subroutine with parameters (see previous article for a partial explanation). Also, these macros are probably more easily stored in your Word application (the VBA editor which usually stores the VBA in the Normal.dot Word template).

For me, I already have many stand-alone macros (no arguments are allowed on a Word macro if you assign it to a keyboard shortcut or a button), but I’ve also created many commands that include parameters just waiting for arguments. We can determine these values with the voice command within the Dragon script and then provide that information to the Word macro. These versions are often more convenient to use in Dragon Professional scripting.

Allowing for errors

Here is where is gets messier and why using a function to run the Word macro is probably better.

We are connecting two different applications, so what happens if the command encounters a problem when trying to run the macro?

The script would fail, but we don’t want it to crash. We’ll get a nasty message from Dragon Professional or Microsoft Word. We need some steps to handle the error and exit the script gracefully.

That’s where the function enters the picture. I think the easiest way to do this is to just make a separate function that just accesses the Word application and runs the macro. We can check for any errors there and quit a script gracefully if one occurs. That way all the extra stuff is in one place. Nice and tidy.

Call a macro function

The relevant function in this Dragon Professional script is long enough for its own article, so let’s use the result without much extra explanation here. To use this function, we’ll call it with the macro name.

Call RunWordMacro("MoveParagraphAbove")

Remember Call is used to run a function or subroutine when we have to provide arguments for the function parameters. Otherwise you can omit it.

The returned result from this function indicates whether it was successful or not, but we don’t need it, so I didn’t store it in separate variable. If we did, that would look like:

MyResult = RunWordMacro("MoveParagraphAbove") ' Not used

No library in Dragon Professional

Unfortunately, Dragon Professional advanced scripting doesn’t allow us to create libraries unless you want to store the function as a separate file.

Unfortunately, as far as I could tell through internet digging, the script then loads the file from the hard drive every time the script runs. I prefer not to open a file on my computer every time I give a voice command, so I copy and paste this function between scripts (which is generally bad when you need to make any changes).

I keep other common macros in a Word VBA module which makes sense since those actions are run within Word anyhow. Still, I would prefer to have script interpretation stuff inside a Dragon Professional script. That division just makes sense to me, but alas, the powers that be have said “No” (for now?).

However, Dragon Professional should allow our scripts to access or create a library since there will invariably be common functions between scripts (like the RunWordMacro function above). We need to work around this limitation for now. Fortunately, as long as we’re working with Microsoft Word, the latter solution of storing the common scripts in a Word VBA module is a good backup solution overall.

Running the Word macro with a function

So here is the snippet to pick the correct Word macro to run.

Select Case sDirection
Case "above", "up", "back", "backward", "back"
Call RunWordMacro("InsertNovelNoteAbove")
Case "below", "down", "forward"
Call RunWordMacro("InsertNovelNoteBelow")
End Select

Notice how the Case statement is automatically selecting the correct macro to run based on the direction variable value.

See the function RunWordMacro below.

Gotchas

Here’s the “what could go wrong?” section.

Voice recognition issues

Well, I hate to say it, but voice command recognition is dependent on the voice recognition engine, the work environment, the microphone, and your own pronunciation.

Ambient noise pollution

If you’re like me, and your intake vent for your air conditioner is literally twelve feet away (about 4 meters) from your computer desk, it can cause garbled commands (like it just did for me half a minute ago). Sometimes I may not even realize the AC is running since I tune the noise out. My microphone doesn’t.

Just misses a word …

Also, sometimes Dragon just misses a word, and I have a nice microphone setup (not professional but pretty good). The ambient noise just seems to take over, and while Dragon is powerful, it just isn’t as good as a human brain at filtering out all background noise or discerning between slightly different inflections when saying the same phrase.

Arghhh.

You could lean toward the microphone (annoying since I like to remain nice and slouched in my office chair) or just use keyboard shortcuts while the cacophony of apartment noise refuses to cooperate with the dictation software.

Not a silver bullet

I’m not telling you voice commands solve everything. They have their own issues, but overall, they’re a nice plus to our productivity.

More natural language commands later …

Later in upcoming articles, we’ll further account for some common spelling errors when we get more sophisticated with our natural language commands.

Initial Script

The final script looks messier than it is.

'#Language "WWB-COM"
Option Explicit
Sub Main
' Store direction as stated by user
Dim sDirection As String
sDirection = UtilityProvider.ContextValue(0)

Select Case sDirection
Case "above", "before", "backward", "back"
Call RunWordMacro("MoveParagraphAbove")
Case "below", "after", "forward"
Call RunWordMacro("MoveParagraphBelow")
End Select
End Sub
Function RunWordMacro(SMacro As String, Optional MyParameter As Variant) As Boolean
' Run any macro that exists in the Word application
' Works for standard Word commands also

' Returns True or False based on whether the command ran successfully
' True does not indicate the macro itself was successful

' Enable error tracking (jump to line below if so)
On Error GoTo WordMacroError

' Requires Microsoft Word 16.0 Object Library enabled
Dim WordApp As Word.Application

' Set WordApp application object
Set WordApp = GetObject(,"Word.Application")
If IsMissing(MyParameter) Then
WordApp.Run SMacro
Else
WordApp.Run SMacro, MyParameter
End If

' Assign return value and exit
RunWordMacro = True ' Exit with success
Set WordApp = Nothing ' Tell VBA you are done with the object
Exit Function

WordMacroError:
' There is an error
RunWordMacro = False ' Exit with failure
Set WordApp = Nothing ' Tell VBA you are done with the object
Err.Clear
End Function

The function will catch an error when trying to execute the macro, so the script doesn’t crash. See the previous article for directions on how to enable the Word 16.0 Object Library.

This script can be readily extended to include more complex scenarios. This function also allows a single parameter such as the number of paragraphs. A later implementation will allow more parameters.

Improvements

What about even better phrasing?

Ahhh, someone after my own efficient heart.

This or that?

What if I accidentally said this?

Move this paragraph up

It won’t work.

Arghhh.

Yeah, notice “this” instead of “that” given in the name of the original command.

We could just get mad and throw the computer and microphone out the window, but you already paid for the everything, so just rein your horse in.

Is this compared to that really a problem?

Yep. Computer can be finicky that way.

This small variation is why I created a <which> list variable which includes the following words (among others):

  • that
  • the
  • these
  • this
  • those
  • to the

and more, but here several words allow me to use different phrasing without too much extra thought.

New command name

The new command name is:

Move <which> paragraph <direction>

The only negative side is the command phrasing starts to look muddled. Later, you might wonder exactly which words were included in the <which> list variable, but now we can say:

Move this paragraph backward

Or …

Move the paragraph down

It won’t win any user-interface awards, but it’s nicer with barely any extra work.

Getting the which word used

We don’t really need to access the word in the <which> position of the command, but if you just really want it, it is now the first list variable of the command.

' Not really needed and not used below
Dim sWhich As String
sWhich = UtilityProvider.ContextValue(0)

Remember the first context value is the zeroth (0) index position.

Direction changes its index

Since <which> is now the first list variable, the <direction> becomes the second list variable in the command. The direction word is now stored in the element 1 context value, not 0 as before because <which> took that spot.

' Store direction as stated by user (updated)
Dim sDirection As String
sDirection = UtilityProvider.ContextValue(1)

Just one paragraph?

So now this command will move the current paragraph up by 1. Wonderful.

The sun shines brighter now. Rainbows are more vibrant.

But …

Do we really have to move the paragraph up (or down) one at a time in the era of talking to computers? That seems—

No. We don’t.

We need a number

It would be more useful if we could specify a number of paragraphs in the command. Suppose we wanted to use the voice command:

Move that paragraph up 3

Now we’re getting even more useful.

New voice command name

Now my re-updated voice command name is:

Move <which> paragraph <direction> <number>

We now have a much more general command; however, one small disadvantage of this approach is we must now say “1” at the end if we’re only moving by one paragraph. The single paragraph move is no longer implicit. If this bothers you (it kinda does me), stay tuned for upcoming articles on more natural language commands.

How does it work?

If you have a list variable with text numbers, you can convert it to a variable number using some standard VBA functions.

A common list variable uses whole numbers: 0, 1, 2, 3, …, up to some maximum value (my maximum was 20). Dragon calls it <1to10>, but I prefer to create my own called <number> and include only Arabic numerals (see why below) from 1 to 20 on my list.

Store the number from the list variable

Store the string that corresponds to the <number> list variable.

Dim sNumber As String
sNumber = UtilityProvider.ContextValue(2)

Don’t forget the (index) should correspond to one less than the variable number order in the voice command, so the <number> word position is the third list variable in the name, so it uses index (2) when counting from zero.

Here sNumber is a text string holding the number, say “5”. Let me emphasize that this is a character “5” not a number 5. We could then use the CInt() function to convert the string to a number.

Converting the number … but hold on

Computers see numbers and text as different things (kind of … mostly but not exactly), so we need to convert the text number to a computer Integer.

Dim MyNumber As Integer
MyNumber = CInt(sNumber) ' but watch out!

Another common whole number data type is Long which is basically just a larger integer.

' Alternative allowing larger numbers
Dim MyNumber As Long
MyNumber = CLng(sNumber) ' but watch out!

VBA in both Dragon Professional and Word is picky with exact type matches when running a macro. The arguments you provide must be exactly the same type, so be sure of it!

For example, Integers won’t translate into Long values automatically (called casting in computer speak). I won’t embarrass myself by telling you I lost a whole day of work relearning this simple lesson.

Check for a number

We do have other problems though.

Unfortunately, this will still cause an error if sNumber is not actually a text form of an Arabic numeral: “1”, “2”, … , and so on. I do not mean “one”, “two”, etc. These noun forms would need to be converted some other way.

In this case, we have some control over the text stored in sNumber since we’re using a list variable holding only text numbers, but in general, if sNumber is not an actual number, your script will crash and pop up a nasty reminder. We should definitely check whether it is a valid number before trying to convert it. Specifically, we can use the IsNumeric function:

IsNumeric(sNumber) ' True if sNumber is a number

The function IsNumeric(sNumber) results in a True-False(Boolean) value if the given string sNumber is indeed a valid number. We can use it in a conditional statement (see previous article for a brief review).

If IsNumeric(sNumber) Then
MyNumber = CInt(sNumber)
End If

If sNumber is valid as a numeric value then convert it using Cint() and store the numeric result a new variable MyNumber. Since the command is so short, I like this more compact notation.

If IsNumeric(sNumber) Then MyNumber = CInt(sNumber)

Now we can use the MyNumber variable as an argument for say a move count in a Word macro, and we don’t have to worry about the script crashing and ruining all our editing fun.

Something to think about …

I like even more variability in my command phrasing. For example, what if I could say:

Move that paragraph before the previous paragraph

Or more ...

Move that down to the third paragraph
Move that forward by 3 paragraphs

Sometimes the command just comes out different as we’re editing, so why not let the Dragon interpret what I say, but alas, that is an adventure for another day.

New macro call

This version includes the MoveParagraphs function from another article.

Now we have a number, we can give (called “passing”) that Integer to our Word macro as a second argument separated by a comma.

Call RunWordMacro("MoveParagraphs", SomeNumber)

Based on the MoveParagraphs function, SomeNumber should be negative for paragraph moves up but positive for moves down in the document. Since MyNumber is always positive, we get a negative of it using -MyNumber.

Call RunWordMacro("MoveParagraphs", -MyNumber) ' For move up
Call RunWordMacro("MoveParagraphs", MyNumber) ' For move down

Again, we don’t need the returned result, so we ignore it by not storing it in a variable.

Final Improved Script

The final extended script is:

'#Language "WWB-COM"
Option Explicit
Sub Main
' Store direction as stated by user
Dim sDirection As String, sNumber As String
' We do not need the first list variable value
' Dim sWhich As String ' not needed
'sWhich = UtilityProvider.ContextValue(0) ' not needed
sDirection = UtilityProvider.ContextValue(1)
' Store text version of the paragraph move number
sNumber = UtilityProvider.ContextValue(2)

' Check and store a numeric value for the spoken number
If IsNumeric(sNumber) Then MyNumber = CInt(sNumber)

' Decide which macro to run based on the direction
Select Case sDirection
Case "above", "before", "up", "backward", "back"
' Need a negative number for move up, so use -MyNumber
Call RunWordMacro("MoveParagraphs", -MyNumber)
Case "below", "after", "down", "forward"
Call RunWordMacro("MoveParagraphs", MyNumber)
End Select
End Sub
Function RunWordMacro(SMacro As String, Optional MyParameter As Variant) As Boolean
' Run any macro that exists in the Word application
' Works for standard Word commands also

' Returns True or False based on whether the command ran successfully
' True does not indicate the macro itself was successful

' Enable error tracking (jump to line below if so)
On Error GoTo WordMacroError

' Requires Microsoft Word 16.0 Object Library enabled
Dim WordApp As Word.Application

' Set WordApp application object
Set WordApp = GetObject(,"Word.Application")
If IsMissing(MyParameter) Then
WordApp.Run SMacro
Else
WordApp.Run SMacro, MyParameter
End If

' Assign return value and exit
RunWordMacro = True ' Exit with success
Set WordApp = Nothing ' Tell VBA you are done with the object
Exit Function

WordMacroError:
' An error occurred
RunWordMacro = False ' Exit with failure
Set WordApp = Nothing ' Tell VBA you are done with the object
Err.Clear
End Function

Remember the variable MyNumber must exactly match the expected data type of the paragraph in the called Word macro.

My version has a few more tweaks to simplify things, but they require extra lines with more explanation, so we’re done here.

Have fun expanding and extending your Dragon scripts.

Now go forth and edit faster!

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.