When working with Dragon Professional advanced scripting, you will inevitably encounter repetitive steps. Such is the case when we run Word macros using Dragon. You probably have boat load of macros, and when you open up the possibility of invoking them using voice commands, you’ll want to buy a bigger boat.
Thanks for your interest
This content is part of a paid plan.
Dragon Scripting Function to Run a Word Macro
This article has some overlap with a previous simplified script, but we’ll take it up a level as we extract the relevant steps. In the end, the effort to create a function to run a Word macro will simplify more complex Dragon Professional scripts when interacting with Word.
If you don’t have many VBA macros in Word yet, check out the dozens of articles already on this site. What are you waiting for? Go forth and edit faster.
Warning: Rubber ducky in the road ahead!
As a brief warning, this one gets a little bumpy if you’re new to scripting, so skip it if you’re happy with the previous simple Dragon Professional script. Alternatively, just jump to the end and take the function as a black box, but I don’t recommend you do that every time.
Features and pricing
Advanced scripting is only available in the Dragon Professional® edition or above (specialized editions like Legal or Medical One). Dragon Professional is a paid application, and I am specifically working with 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 (I understand), 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.
What’s the plan?
How do we create a function in a Dragon Professional script to invoke a Word VBA macro by voice?
So how do we control Word from a Dragon Professional script?
The number of arguments given should agree with the number and type of parameters expected by the macro being called.
In this function, we’re not concerned with any other decisions normally made inside the Dragon Professional script. We’re just focused on running the Word macro.
Create function skeleton
The advanced scripting editor is mostly a plain text editor where we type commands just like in Word VBA macros. This will be a function, so it will not stand alone like a Dragon Professional script, but we’ll use it to make invoking Word VBA macros easier and allow us to create better Dragon scripts.
Open a text editor
We can create this function in any text editor since it does not stand alone. A popular powerful, and yet free, text editor for Windows is Notepad++.
If you wish to work in Dragon Professional, open the command editor using the Dragon Bar menu: Tools → Command Center → Add new command … or open an existing script. Your regular script steps go inside the Main subroutine, but we won’t be making a complete script here.
Instead, will be creating a function. Add the following function skeleton (above or below the Main subroutine in whatever script you’re working if you're in Dragon).
Let’s break down the different elements.
What is the return value?
We added “As Boolean” on the end of the function declaration to tell the script this function will return a True or False value based on whether it ran the Word macro successfully.
Then we assign the result to the function name sometime during macro execution. Often this is done at the end, but that’s not required. We’ve temporarily assigned True since we don’t have a result yet.
A True result doesn’t ensure the macro did exactly what you expect in Word. It just indicates there was no error when trying to run it from within your Dragon Professional script.
What parameters?
Our function has parameters which includes the macro name but also any macro parameters, if needed.
Macro name
We need the name of the Word macro to run which we’ll call SMacro. I prefer to prefix my string (plain text) variables with an “S”, but it isn’t required. It needs to be a plain text String variable type to work properly with the Application’s Run method later.
Are there macro parameters?
If the macro requires a parameter, we allow a second parameter for this function which we’ll call MyParameter. Here is where it gets a little confusing if you’re not used to VBA.
Don’t know the data type
We can’t give a specific data type for the parameter because we don’t know it yet.
Is the parameter some text for a novel note, the number of paragraphs to move, or a True-False (Boolean) value? These are different, and we won’t know until the user actually uses the function.
Arghhh.
Use a Variant type
With that in mind, we give it a “Variant” type meaning we’re not being specific, and VBA should allow essentially any type of data. It can even hold object-like values such as document Ranges.
We won’t use object types much in Dragon Professional scripting since more complex editing tasks are probably easier to implement directly inside a Word VBA macro. There is no compelling reason so far to tinker with Word directly from within Dragon Professional.
Use an Optional parameter
What if we don’t have a parameter for the macro?
We further declare MyParameter as “Optional” because we want to allow the user to run the macro even if it has no parameters.
Single function (almost)
Between the Optional parameter and the Variant data type, we are able to use a single function to run many Word macros rather than creating many variations of the function only differing by the parameter type we accept. A follow up article will cover more general macros that allow more parameters.
Declare the Object
If you leave Option Explicit in the header section of the Dragon Professional script (above Sub Main), we need to specify the type of variable we’re using to access the Word application. This is the lazy way, but we all like wearing jogging pants and our favorite ragged shirt at home.
WordApp is just a variable name that makes it easy to remember what we’re referencing later.
In fancy terms, this is called “late binding,” because we’re not actually giving the variable type. We’re just saying it’s an “Object” and letting the script interpreter decide what kind of object WordApp is when the interpreter eventually knows. Like many other things in life, this approach has pros and cons. It feels a little like cheating, but here it makes the script easier to write.
For clarity, this line just specifies the variable type, but WordApp currently holds Nothing because it has not been connected to anything yet.
Or be specific …
I prefer to be more specific when I can, so if you’ve enabled the special Word object library for a script (see extended content below), use this WordApp declaration instead.
The Word object library isn’t available by default, and it must be enabled for each Dragon Professional script. This a second reason I copy and modify scripts rather than create them from scratch.
This statement is less ambiguous than just calling it an “Object” if you ever revisit the function. Plus, the editor will give you hints via context menus about any methods or properties as you work (called IntelliSense in Microsoft apps). It’s not a dramatic improvement when creating scripts and macros, but it’s nice when you need it.
Get Word application
Now we need to tell Dragon we’re connecting this variable to the Word application.
GetObject is a stock VBA function that will retrieve identifying information for the object you specify.
We used Set because the Word application here is an object not just a plain value like a number or character. Most objects have multiple data (properties) and possible actions (methods) associated with them.
That annoying comma …
Unfortunately, the application name is the second argument in GetObject, so the comma in front of it indicates a skipped argument. Specifically, the first parameter is the path name of the object, but we don’t know what that is. Fortunately, we don’t need to know it to connect it to Word (although ignorance is not always bliss).
I don’t like how the comma makes the command look messy and unfinished, but it’s easier to just leave the first argument out since the focus is on telling Dragon the object we’re connecting to the variable.
What if Word is not open?
If Word is not open, we’ll get an error message with GetObject(…), and I mean it will crash your script. Can we say bad? Like flipping your boat while fishing.
Just exit?
We could possibly open Word using the CreateObject function, but in most cases, it probably doesn’t make sense to run a macro on an empty document. Another issue is it takes some time for the application to load, but how much time will depend on the computer as well as how bogged down with other tasks it might be. We don’t want to run any more function steps until Word is open.
There are ways to wait until the application is finished opening, but that’s at least two reasons to just quit the function by letting the error handling take over if Word isn’t open (see below). In this function, the extra complexity just isn’t necessary for the majority of use cases. We almost always want to run a macro on some document content.
Run the macro now?
Well, it’s a little premature, but it’s the next logical step, so let’s talk about it. Suppose we run a macro with a command something like:
We need to use “Call” here because the function has an argument. This particular way ignores any return result from the function because we don’t store it in a variable. See the explanation of the Final Function below for an example of that.
How do we run the macro inside this function?
Using the WordApp variable, our VBA commands is:
We don’t use double quotes here because SMacro is already a plain text string that holds the name of the macro to run. Our macro isn’t called “SMacro”.
But what if we have a parameter?
What if the macro requires a parameter? That is, what if the user ran our function with a command something like this instead:
Right now, I don’t care what the 5 means, but it sits in the second place correspond to the function’s MyParameter. The naïve approach would be to just use a Run command like:
And … it’s almost correct, but this command would need to also run the previous example where no parameters were given … but it won’t. The command will cause an error since SomeMacro in the first example does not expect a parameter.
Number of arguments and macros parameters must match
The number of extra arguments we give to the Run command after the macro name must exactly match the number of parameters expected by the macro, and we need to know in advance. The application’s Run method requires any macro parameters to be given, and it will also not ignore an extra parameter if it isn’t needed.
Arghhh.
However, we can still take advantage of Optional parameters that have default values in our Word macros. These arguments can be omitted when using the Application Run method.
Use consistent data types when running Word macros
Argument and macro parameter data types must match exactly when using the Run method (see previous article for more explanation). For example, even a discrepancy of Long and Integer between the Run argument data type and the expected parameter type in the Word macro will cause the script to crash. If most numbers are a Long data type, then we have fewer chances for type clashes between the Dragon script and any Microsoft Word macro. We’ll never be able to tell a practical difference when the script runs, so we essentially lose nothing.
Detecting a missing parameter?
Recall we declared MyParameter as Optional, so it doesn’t have to be given. Otherwise the first example would not have been a valid use of the function. Fortunately, we can detect whether the user gave us something in the MyParameter or not.
Now we’re talking. This is easy (not that we’ll get away with avoiding error handling). We just need to set up a condition to check for the missing parameter and run the appropriate version.
Now we can do either case with a parameter or not.
Setup error handling
However, we could still get an error. For example, what if the parameter had the wrong type? Or the user gave a parameter when the macro didn’t want one? The function won’t know the difference.
Ughhh. Does it ever end?
There’s no avoiding some error handling unless you don’t mind your scripts shouting at you.
Allow for a macro error
If the command has a problem, the macro screams at us—well it just complains and gives us an error, but it feels like screaming. Do you know the programmer equivalent of road rage. Obviously, I didn’t do anything wrong because—
Oh, am I distracted? Let’s get back to it.
What do we do if there is an error?
At this point, we just assume something is wrong and exit since there’s no reason to keep going, but we want to get out gracefully. We add a few steps at the end of the function to reset things back to normal and let the user know there was a problem.
Check for errors
First we tell VBA to look for any possible errors.
If placed at the top of the function, it will catch any error that occurs either when trying to switch to the open Word application or when trying to run the Word macro.
Error line
On any error, VBA will jump to the line we label by WordMacroError.
Often these extra steps are placed at the end of the function. So what do we do after an error is detected by VBA?
Exiting after an error
Since we’re taking care of the error, we should clear the error before we exit the function to be nice.
Then we should set the function result to False to indicate that the function did not run the macro successfully.
Finally, we should be nice and tell VBA we’re done with the WordApp variable by setting it to Nothing.
Then we just let the function finish assuming we put the error steps at the end of the function.
Finish the macro
If the macro runs successfully, we let the user know by setting the function result to True.
We tell VBA we’re done with the WordApp variable by setting it to Nothing.
Then we just exit the function.
This last line is necessary because VBA would continue into the following error steps (see function below). Granted there are similarities between these steps and those when ending on an error, but the return value is different between the two cases.
Final Function
Putting it all together, our Dragon Professional VBA function to run a general Word macro with up to one parameter is:
Works with standard Word commands
This function will also work with standard Word commands like SentLeft or ParaUpExtend. These can be run with VBA or manually through the View dialog (via the View → Macros → View Macros; then select “Word commands” in the “Macros in:” combo box near the lower middle of the dialog).
How to use it?
To use this function, call it with either just the macro name or with a single parameter if needed.
Call is often used in VBA to execute a function or subroutine when we provide arguments. It's only technically required in VBA if parentheses are used for the arguments, but it is commonly used otherwise as well. In this example, the return result from the function (whether it was successful or not) is not used, so the result is just discarded.
If you want to store the result to use for some other decision in the script, you could use:
Then you could use bResult in a conditional statement for whatever decision you need. I like to add a "b" before True-False variables to remind me what data they store.
Where to put it?
In Dragon Professional advanced scripting, the above function should be copied into each script where it will be used. I tend to just copy it into one of several types of scripts and make copies as I need them.
No library?
This isn’t the best solution for a professional application in my opinion, but it appears Nuance’s design philosophy is for each script to be independent. I understand the notion, but I think it’s a mistake. This function is an example because if I make any changes, such as adding CreateObject functionality to open Word if it’s not already running, I now have a few dozen places to add the change. Not the best solution.
Unfortunately, to my knowledge Dragon Professional advanced scripting does not allow a library of functions other than using an external file. In my research, the external file would be loaded each time the macro runs. I don’t like this approach either for interpreted scripts. If the scripts were compiled once it would be fine, but Dragon Professional scripts are interpreted each time the script is used.
Enable Word scripting library
To enable the library that gives us access to the Word.Application. Press Alt+Enter when inside script editor and click the checkbox for Microsoft Word 16.0 Object Library.
Previous versions of Dragon Professional (or equivalent in earlier versions) allowed access via the right-click context menu, but that menu option no longer seems to be present in v16.0. You’ll have to scroll down the long alphabetical list to somewhere in the middle.
Handles errors
The function catches any errors when trying to run a Word macro and gracefully returns control back to the Main script subroutine.
Even nicer than VBA in Word
One nice thing about this function and Dragon Professional scripts is we can easily run macros with parameters. Let me explain.
In Word VBA, any macro you assign to a keyboard shortcut, a Ribbon button, a Quick Access Toolbar button, or run through the macro dialog (via the View → Macros → View Macros) cannot have any parameters. Not even one. Functions and subroutines with parameters are very useful in VBA, but we just can’t assign them to any of the above. However, we can assign them to voice commands in Dragon Professional scripting. Yay!
That’s nice and almost makes up (mentally) for the lack of being able to create a custom Dragon Professional scripting library.