There are several tutorials on the forums for specific Microsoft (MS) Office programs, and many more Ask For Help topics about specific tasks. They provide AutoHotkey (AHK) examples demonstrating the use of MS Office commands (methods), setting or retrieving values (properties), or listening for events.
After reading those threads, AHK users may still have questions. How did the author know the name of the method, property, or event? How did they know which parameters to use, and in which order? This tutorial will try to answer those questions for all MS Office programs in general.
We will briefly introduce VBA, discuss how to find and use the MS Office documentation, and how to translate the code found there into AHK. The concepts discussed here will help a user start to learn how to do anything in MS Office that is accessible via the Component Object Model (COM), all without any preexisting AHK code. Although, some basic knowledge of AHK expressions and objects is required.
Note that this is just an introduction. There are many more VBA tutorials and other learning resources out there.
2 VBA
Visual Basic for Applications (VBA) is a programming language built into MS Office programs for the purpose of macro creation and scripting. Many users will have seen VBA code in the past. For example, if you have ever recorded a macro and viewed the resulting code. Through COM, AHK can use the same objects a VBA script would.
It is important to note that VBA and Visual Basic (VB) are not the same language. VBA is a dialect of VB. If you are searching online for code examples or documentation, you may find yourself on an MSDN page with VB, C#, or C++ examples. This is a sign you are not on the right page. The MSDN pages most useful for creating AHK code are the ones written for VBA. These are the same pages found in the MS Office docs (see the Help File section below).
The following tools will be present in most MS Office programs, with a few exceptions.
2.1 VBA Editor
In an MS Office application, press Alt+F11 to open the VBA Editor.
From the VBA Editor we will access other key components like the Object Browser, Code Window, and Help.
2.2 Code Window
Open a Code Window by pressing F7.
This is where we can experiment writing VBA code. Before we start, select Tools > Options from the menu. Make sure Auto List Members and Auto Quick Info are checked.
The following briefly describes one way to explore an MS Office Application object. 「Demo GIF」
- Type Application. in a Code Window. A list of all the members of the Application object should appear when you press the .. Each item in this list is either a method, property, event, or object belonging to the Application object.
- Use the arrow keys to select an item from the popup list. Once you have selected a member of the Application object, press tab to autocomplete it. Items can also be selected using the mouse.
- If the object member selected is an object with members of its own: Press . and another popup menu will be shown with all the members of the child member.
- If the object member selected is a method, press Space and a tooltip will be displayed showing the method's parameters.
- You can keep peeling back layers of the onion in this manner until the desired member is reached.
2.3 Object Browser
Press F2 to open the Object Browser.
Libraries: The drop down list in the top left of the window allows us to select which libraries to explore. We can generally just leave <All Libraries> selected. 「More Info」
Search: Directly below the Libraries drop down list is the Search box. Search terms can be typed here and the results will be shown in the list view directly below.
Classes: The Classes list box contains an alphabetical list of classes. Notably, constants are listed here too.
Members of: When a class is selected, either in the Search Results list view or the Classes list box, its members will be displayed in this list box. The icon to the left of each member indicates their type. The icon that looks like a hand pointing at a piece of paper is for properties. The green flying brick means it is a method. The lightning bolt is for events.
Select an item in either the Search Results, Classes, or Members of areas and press F1 to view the related docs (if they exist).
2.4 Help
Press F1 to open Help.
Search Scope: The search scope is displayed on the left side of the status bar at the bottom of the Help window. We do not want to search the general Help. To get search results relevant to VBA we need to switch the search scope to Developer Reference. The scope should already be set correctly if you launched Help from the VBA Editor. The scope can be set using the drop down list to the right of the search box.
Connection Status: The connection status is shown on the right side of the status bar at the bottom of the Help window. We want to use Offline mode. Left-click on the connection icon in the status bar and select Show content only from this computer.
2.5 Macro Recorder
The Macro Recorder is a useful tool if you don't know which method or property to use. The VBA code it creates can be viewed, although usually it includes a lot of irrelevant info too. Unfortunately, the Macro Recorder is not present in some MS Office applications; notably Outlook, PowerPoint, and Publisher.
3 Objects
3.1 Application Object
All MS Office programs we will be interacting with have an Application object. This object is AHK's gateway into the program. Think of this object as being synonymous with the program as a whole.
You could think of each MS Office Application object as being similar to a tree. To access a specific part of the application we will always start at the tree's base. Then, depending on what it is we wish to access, we will navigate our way up the tree into smaller and smaller branches of the application.
VBA code examples often omit the Application object. This is because VBA code run within an application knows to use its own application by default. In AHK we always have to specify which Application object to use, because an AHK script can have any (reasonable) number of Application objects at one time.
3.2 Properties
Properties represent a single characteristic belonging to an object. Properties can be any type of value. For example, many objects have a Name property. This property will usually return a String.
AHK Pseudo-Code Example: MyVar := MyObj.Name
- MyObj is an AHK variable containing a reference to a COM object. This object has a property called Name.
- Name returns the name of the object.
- MyVar variable now contains the name of MyObj .
3.3 Methods
A method executes code. If you are familiar with functions in AHK, methods work in a similar manner except they belong to an object. (If you are familiar with methods in AHK, that's even better.) A method belonging to an object will do something to the object. For example, a Workbook object in Excel has these methods which will all do something to the workbook itself.
3.4 Events
Events are generated because of a user action. We can connect our scripts to COM objects in order to listen for their events and respond to them.
4 Examples
In this section we will explore how to go from not knowing where to start, to finding the appropriate documentation, to creating working code in AHK. We will apply the tools and principals that were described in the previous sections. There are many ways to approach a task. We could start with the Macro Recorder to figure out which commands to use. We could simply search online for a VBA code example; MS Office is ubiquitous so VBA code is easy to find. Or we could search the Help and Object Browser. Sometimes one technique is enough to solve a problem, but other times we could hit a wall.
Each technique has its own strengths and weaknesses. You can probably guess that Help is extremely useful, but sometimes it may not provide an example of the specific task we want to accomplish. An online search could provide code that does exactly what we want, but there is no guarantee the code we find will be the best way to do a given task.
More Examples: Additional examples are available on github here. Also see Section 6 of this tutorial, and don't forget about searching the AHK forum as Section 5.6 describes.
4.1 Properties
Let's look at some of the "Active" properties in Excel. Open the Object Browser and select Application with your mouse in the Classes area. All the members of the Application object should be shown in the Members of area. There are several properties near the top that all begin with "Active." ActiveCell, ActiveChart, ActiveSheet etc. Based on their names, it's probably easy to guess what each of these properties returns. To verify, select a property with your mouse and press F1. 「Demo GIF」
We'll use ActiveWorkbook as an example. Our AHK script will display a message box with the name of the active workbook.
We can follow the link to the Workbook object docs page. From there we can verify that Workbook objects have a property called Name and it, "Returns a String value that represents the name of the object."Application.ActiveWorkbook wrote:Returns a Workbook object that represents the workbook in the active window (the window on top).
As always, we start with an Application object. We will use the Application.ActiveWorkbook property to get a reference to the active workbook, then use the Workbook.Name property to retrieve the name.
Code: Select all
xlApp := ComObjActive("Excel.Application") ; get a reference to the active Excel Application object
MsgBox, % xlApp.ActiveWorkbook.Name ; display the name of the active workbook
In this example we will add a comment to a cell in Excel. Start by using the Macro Recorder. 「Demo GIF」
- Begin recording a macro.
- Right-click on a cell and select Insert Comment.
- Press Escape to dismiss the comment and then stop recording the macro.
- Edit the macro to view the code created.
Code: Select all
Sub Macro1()
'
' Macro1 Macro
'
'
Range("A1").AddComment
Range("A1").Comment.Visible = False
Range("A1").Comment.Text Text:="kon:" & Chr(10) & ""
End Sub
- Range.AddComment adds a comment to the Range. The docs tell us that this method has an optional parameter which sets the comment text. The Macro Recorder chose not to use this parameter.
- The Comment.Visible property is set to False. Some testing (running some modified versions of the macro) revealed that comments are not visible by default anyway, so we will not bother to include this line in our AHK script.
- Comment.Text is used to set the comment text. Notice that this method has a text parameter just like the AddComment method, but it also has two additional parameters. The extra parameters seem to make Comment.Text a more versatile method than Range.AddComment. Perhaps that is why the Macro Recorder chose to use it instead.
Code: Select all
F4::xlApp.Range("A1").AddComment("Hello world!")
Code: Select all
xlApp := ComObjActive("Excel.Application") ; Get a reference to an existing Excel Application object
return ; End of Auto-execute section [https://autohotkey.com/docs/Scripts.htm#auto]
F4:: ; F4 hotkey
if IsObject(xlApp.Range("A1").Comment) ; Did 'Range.Comment' return an object?
xlApp.Range("A1").Comment.Text("Hello world!") ; Change the comment text
else
xlApp.Range("A1").AddComment("Hello world!") ; Add a comment
return
4.3 Events
To listen for a COM object's events we will need to do two things:
- Define a function that will be called when the event is fired. The function will have the same number of parameters as the event plus one final parameter. The extra parameter will contain a reference to the COM object we passed to ComObjConnect.
- Connect our COM object to the function using ComObjConnect. ComObjConnect accepts two parameters, ComObject and optionally Prefix. ComObject is the object whose events we want to listen for. Prefix is a String that all of our function names will start with.
- MyVar is an AHK variable containing a reference to a COM object. This object has an event called MyEvent.
- "MyPrefix" is a string to prefix to the event name.
NewDocument Event (Word) Example: The Application.NewDocument docs show that it, "Occurs when a new document is created." The event passes our function one parameter, a Document object. This Document object represents the new document that caused the NewDocument event to fire. Also remember that our function can accept one additional parameter, which will contain a reference to the COM object that fired the event. So our function definition will look like this:
Code: Select all
wd_NewDocument(Doc, App)
{
; Do stuff here
}
Now that we have defined our function, we can connect it to a COM object. The NewDocument event docs tell us it is fired by an Application object. So we need to pass an Application object to ComObjConnect. We used wd_ as the prefix when defining our function, so that's what we will pass as the Prefix parameter.
Our basic working example can be:
Code: Select all
#Persistent
wdApp := ComObjCreate("Word.Application") ; Create an application object
wdApp.Visible := true ; Make the application visible
ComObjConnect(wdApp, "wd_") ; Connect to the application's events
return ; End of Auto-execute section
wd_NewDocument(Doc, App) ; This function responds to Word's 'NewDocument' event
{
MsgBox, % Doc.Name ; Show the name of the new document
App.Selection.TypeText("Hello world") ; Type text at the current selection
}
/*
wd_Quit(App) ; This function responds to Word's 'Quit' event
{
MsgBox, % App.Name ; Show the name of the application
ComObjConnect(App) ; Disconnect from App events
}
Note: Prior to AHK v1.1.24.02 there is an additional problem:
Basically this means that instead of passing a String prefix to ComObjConnect, we can pass it an instance of an AHK class. Instead of calling a function, it will call the class methods. And defining a __Call meta-function will allow us to respond to all events without defining a method first.ComObjConnect() wrote:[v1.1.01+]: This parameter can be an object defined by the script. When an event is raised, the corresponding method is called. The first parameter, which is usually the hidden this parameter, refers to the script-defined object, not the COM object. To catch all events without defining a method for each one, define a __Call meta-function.
Code: Select all
#Persistent
wdApp := ComObjCreate("Word.Application") ; Create an application object
wdApp.Visible := true ; Make the application visible
ComObjConnect(wdApp, new EventsClass) ; Connect to the application's events
return ; End of Auto-execute section
class EventsClass
{
__Call(Event, Args*)
{
if !IsFunc(this[Event]) ; If this event does not correspond to a method
ToolTip, % Event
}
NewDocument(Doc, App)
{
MsgBox % Doc.Name
Doc.Activate ; Activate the document because 'Selection' is used next
App.Selection.TypeText("Hello world") ; Type text in the new document
}
Quit(App)
{
MsgBox, % App.Name
ComObjConnect(App) ; Disconnect from App events
ExitApp ; Exit this script
}
}
5 Miscellaneous
5.1 Constants
Constants are similar to AHK's built-in variables except their value will not change. Constants are not directly accessible to AHK, so we need to look up the value they represent and use that in our script instead of their name. The Object Browser is an excellent tool to find the values of constants.
Just like in AHK, where built-in variables (almost) always start with A_, MS Office constants within a given application will start with the same prefix. Ex: Word constants start with Wd, Excel constants start with Xl, VB constants start with Vb, and general MS Office constants start with Mso. 「More Info」
5.2 Enumerating Collections
The name "collections" is quite self-explanatory: a collection is a group of things (usually objects). Documentation for some properties says, "Use the Xs property to return the Xs collection." (Replace Xs with the property name.) Here is a pseudo-code AHK example:
Code: Select all
MyApp := ComObjCreate("SomeProgram.Application")
MyCollection := MyApp.Xs ; Xs is a property belonging to the application object which will return a collection of all X objects
for X, in MyCollection ; for each X in the collection...
MsgBox, % X.Value ; display the "Value" property of this X
More: 5.3 Saving References
Once you have drilled down into an object, you may find it useful to save a reference to a child object. This eliminates the need to "drill down" each time you want to access it. Take this VBA example which changes the font formatting in the active cell. The With statement signifies that the next two lines will both use ActiveCell.Font.
The following is equivalent.Application.ActiveCell Property (Excel) wrote:Code: Select all
Worksheets("Sheet1").Activate With ActiveCell.Font .Bold = True .Italic = True End With
Code: Select all
Worksheets("Sheet1").Activate
ActiveCell.Font.Bold = True
ActiveCell.Font.Italic = True
Code: Select all
xlApp.Worksheets("Sheet1").Activate
MyFont := xlApp.ActiveCell.Font
MyFont.Bold := true
MyFont.Italic := true
AHK does not have named parameters, but VBA does. We saw an example of named parameters previously in section 4.2 when using the Comment.Text method:
Note: "Text" is the name of the method and also the name of the first parameter of the method.4.2 Methods wrote:Code: Select all
Range("A1").Comment.Text Text:="kon:" & Chr(10) & ""
Using named parameters allows VBA coders to omit any optional parameters without accounting for them.
The Comment.Text docs show the prototype:
In practice, AHK code is going to resemble the prototype more closely than it will resemble the code using named parameters.Comment.Text wrote: expression .Text(Text, Start, Overwrite)
expression A variable that represents a Comment object.
The rules we must follow in AHK for omitting parameters are similar to the rules for omitting parameters in AHK functions. Take this fictional example prototype:
If all of the parameters are optional, and we want to use Param1 and Param3, we can omit Param4 but we still need to account for Param2 with a comma.expression .SomeMethod(Param1, Param2, Param3, Param4)
expression A variable that represents an Application object.
Code: Select all
MyComObj.SomeMethod("abc",, 123)
Unlike AHK, VBA variables and parameters have distinct Types. The MS Office documentation usually lists a Type for each property or method parameter. Various Types include Boolean, Object, String, Variant, and many more.
When passing a parameter to a method or assigning a value to a property, AHK usually handles the decision of which type of value to use. A problem will occur when it is possible to pass more than one Type of value to a parameter or property, and AHK attempts to use the wrong Type. For example, if a method was able to accept both a Boolean and String, but AHK attempted to pass it the String "asdf" as a Boolean. This is not a problem users will encounter regularly, but it may cause headaches in some specific cases. 「More Info」
We can specify a Type by using the ComObject function: ParamObj := ComObject(VarType, Value)
- VarType is a number representing the Variant type desired. See ComObjType for a list of Variant types and their corresponding numbers.
- Value is the data we want to store.
- ParamObj is the object representing a typed value we will pass to a method or property.
The following are some basic suggestions to help improve results when searching online.
The AHK forum is usually the best place to start looking. For example: To search for a documentation page, try the following format: Object.PropertyMethodEvent AppName "MSDN" "VBA" To search for for VBA examples, include a brief task description and the name of the application and/or "VBA."
6 Links
6.1 External Links
- Getting to grips with VBA basics in 15 minutes
- VBA Variables & Constants
- Why is TRUE equal to -1 and not 1
- Microsoft Technet script repository
- Excel - Get the value of cells in a column one by one
- Excel - Import data from a text file (QueryTables.Add). This is a 1:1 translation of VBA code generated by the Excel Macro Recorder.
- Word - Create a document from a template and insert script-generated text (using bookmarks). The text formatting of the template is preserved.
- Word - Find and replace anywhere (In headers, textboxes, etc.). This is a 1:1 translation of this VBA sub.
- Events - Change the value of a ByRef parameter
- More on github...
- COM Object Reference (archived forum)
- COM Object Reference [Index]
I have inevitably been inaccurate or flat out wrong, or I have left out important information. Comments, suggestions, and corrections are appreciated!
Source code for this tutorial is now on github: https://github.com/ahkon/MS-Office-COM-Basics
Feel free to make a pull request or start an issue if you have a suggestion; I will merge it and update this tutorial if I agree with the changes.