MS Office COM Basics

Helpful script writing tricks and HowTo's
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

MS Office COM Basics

22 Jul 2015, 17:47

1 Introduction
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.

Image

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.

Image

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」
  1. 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.
  2. 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.
    1. 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.
    2. If the object member selected is a method, press Space and a tooltip will be displayed showing the method's parameters.
  3. You can keep peeling back layers of the onion in this manner until the desired member is reached.
Note: Hit F1 at any time to be shown the Help topic of the item next to the cursor. More info on how to set up and use Help below.

2.3 Object Browser
Press F2 to open the Object Browser.

Image

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.

Image

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

Image

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 .
An example of a property that returns an object is the Application.ActiveDocument property in MS Word. In VBA, Set MyDoc = ActiveDocument stores a reference to the Document object which is currently active. The AHK equivalent would be MyDoc := wdApp.ActiveDocument. Note that in AHK we use := for the assignment operator. We also need to specify the Application object (wdApp). We must have stored a reference to an Application object in the wdApp variable previously.

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.
Application.ActiveWorkbook wrote:Returns a Workbook object that represents the workbook in the active window (the window on top).
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."

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
4.2 Methods
In this example we will add a comment to a cell in Excel. Start by using the Macro Recorder. 「Demo GIF」
  1. Begin recording a macro.
  2. Right-click on a cell and select Insert Comment.
  3. Press Escape to dismiss the comment and then stop recording the macro.
  4. Edit the macro to view the code created.
Your macro should look similar to the following.

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
Now we can easily find the documentation by placing our cursor next to the various properties and methods and pressing F1. It appears that three things are happening:
  1. 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.
  2. 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.
  3. 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.
As always, unlike VBA, with AHK we need to specify an Application object. If a reference to an Application object has been obtained previously in the script, the simplest AHK version of this macro could be one line long. This AHK hotkey will add the comment "Hello world!" to cell A1 when the F4 key is pressed.

Code: Select all

F4::xlApp.Range("A1").AddComment("Hello world!")
Testing the script quickly reveals a problem. The second time the hotkey is pressed it generates an error. Apparently a comment cannot be added to a cell which already has one. We could decide to tolerate this limitation, but there are ways to allow for preexisting comments. If we would like to suppress the error message so that the method silently fails, we could use try. Or, as in the following script, we could see whether a comment exists by testing if Range.Comment returns an object or not (It will return a Comment object if a comment exists). If a comment exists, overwrite it with the Comment.Text method. Else add a comment with the Range.AddComment method.

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
In practice, hard-coding cell A1 into a script is probably not desirable. If we replaced Range("A1") with ActiveCell our script would be a lot more useful. Note: Range("A1") and ActiveCell both return a Range object, which is why they are interchangeable here.

4.3 Events
To listen for a COM object's events we will need to do two things:
  1. 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.
  2. 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.
ComObjConnect Pseudo-Code Example: ComObjConnect(MyVar, "MyPrefix")
  • 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.
If ComObjConnect is called as above, every time the COM object fires the MyEvent event, our script will look for a function named MyPrefixMyEvent and attempt to call it.

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
}
When the event fires, the two variables within the function, Doc and App, will contain a reference to the newly created Document object, and a reference to the Word Application object which fired the event.

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
}
Our finished script will display a message box showing the name of the new document. Then it will type the text, "Hello world".

Note: Prior to AHK v1.1.24.02 there is an additional problem:
Spoiler
NewDocument Event (Word) Example - Class Version: The ComObjConnect docs page contains a small note with some interesting implications:
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.
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.

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
We can use a for-loop to enumerate a collection. Just keep in mind that normal for-loops usually store the value separately from the key: for key, val in obj. But, COM objects of this type store the value in what would normally be the key: for val, in obj.

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.
Application.ActiveCell Property (Excel) wrote:

Code: Select all

Worksheets("Sheet1").Activate
With ActiveCell.Font
    .Bold = True
    .Italic = True
End With
The following is equivalent.

Code: Select all

Worksheets("Sheet1").Activate
ActiveCell.Font.Bold = True
ActiveCell.Font.Italic = True
We can do something similar in AHK by saving a reference to the child object in a variable.

Code: Select all

xlApp.Worksheets("Sheet1").Activate
MyFont := xlApp.ActiveCell.Font
MyFont.Bold := true
MyFont.Italic := true
5.4 Named Parameters
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:
4.2 Methods wrote:

Code: Select all

Range("A1").Comment.Text Text:="kon:" & Chr(10) & ""
Note: "Text" is the name of the method and also the name of the first parameter of the method.

Using named parameters allows VBA coders to omit any optional parameters without accounting for them.

The Comment.Text docs show the prototype:
Comment.Text wrote: expression .Text(Text, Start, Overwrite)
expression A variable that represents a Comment object.
In practice, AHK code is going to resemble the prototype more closely than it will resemble the code using named parameters.

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:
expression .SomeMethod(Param1, Param2, Param3, Param4)
expression A variable that represents an Application object.
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.

Code: Select all

MyComObj.SomeMethod("abc",, 123)
5.5 Typed Values
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.
5.6 Searching Online
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 6.2 Examples 6.3 Tutorials 6.4 COM Object Reference
I have inevitably been inaccurate or flat out wrong, or I have left out important information. Comments, suggestions, and corrections are appreciated! :D

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.
Last edited by kon on 13 May 2017, 17:15, edited 42 times in total.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: Basic MS Office COM

22 Jul 2015, 17:48

-
User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Re: Basic MS Office COM

23 Jul 2015, 03:26

Nicely done :) kon

I did not closely read all of it but it seems very informative

note in the Ahk example of 5.3 you assign with = instead of :=
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: Basic MS Office COM

23 Jul 2015, 15:55

Thanks Blackholyman!
Fixed.
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Basic MS Office COM

23 Jul 2015, 20:36

I've just begun reading through this but it rocks so far! I've been using COM for years but really didn't understand much of what I was doing. I'm already getting a clearer understanding which will help me save a lot of time and frustration in the future! Thank you for your time!
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: Basic MS Office COM

24 Jul 2015, 11:49

Thank you, that's great! I'm glad you are enjoying it so far!
danotto94
Posts: 14
Joined: 11 Aug 2015, 10:32

Re: Basic MS Office COM

11 Aug 2015, 10:40

To delete columns in Excel, type for example:

Code: Select all

x1.Range("A:H").EntireColumn.Delete
To cut/paste/move cells:

Code: Select all

x1.Range("A1:C6").Select
x1.Selection.Cut
x1.Range("A10").Select
x1.ActiveSheet.Paste
Is there an easier way to do this?
User avatar
sinkfaze
Posts: 616
Joined: 01 Oct 2013, 08:01

Re: Basic MS Office COM

13 Aug 2015, 11:18

xl.Range["A1:A6"].Cut(xl.Range["A10"])
autocart
Posts: 214
Joined: 12 May 2014, 07:42

Re: MS Office COM Basics

30 Aug 2016, 09:16

Hi kon,
Thx for this fine post.

One question. You write: "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."

I am working with MS Publisher 2007. It seems to me that with the application object I can only use the items in the "Publisher" library. Can I also use other libraries through the COM interface with ahk, like e.g. "Office", or is this really not possible?

Thx, Stephan
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: MS Office COM Basics

30 Aug 2016, 13:55

Thanks autocart. Glad to see interest in this tutorial. :D
The following is my basic understanding, but if someone more knowledgeable on the subject wants to jump in with more info, feel free :)

Yes, if you are working with Publisher you will mostly only use the items in the Publisher library. I did say, "We can generally just leave <All Libraries> selected." That was an oversimplification. You usually won't be accessing the other libraries programmatically. If I need to use a member of the "Office" library, it's usually a constant. In which case I would look up its value in the object browser and write the value in my script.

You can access some members of the "Office" library if you go through the Publisher.Applicaiton object. For example, in the following code oPub.CommandBars returns a CommandBars object which is a collection of CommandBar objects. CommandBar objects are derived from the CommandBar Class, which is a member of the "Office" library.

Code: Select all

oPub := ComObjCreate("Publisher.Application")
MsgBox, % oPub.CommandBars.Count
I've been playing with ImportTypeLib to get the values of constants; and there's probably more that can be done that I am unaware of. As an example, this gets the value of msoAfterLastSibling:

Code: Select all

; https://autohotkey.com/board/topic/78201-ahk-l-importtypelib-extended-com-support/
#Include %A_ScriptDir%\maul-esel-ImportTypeLib-28e9e8b
#Include Main.ahk

; The following path varies depending on your system and Office version.
TLOffice := ImportTypeLib("C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE14\MSO.DLL")  
MsgBox, % TLOffice.MsoRelativeNodePosition.msoAfterLastSibling  ; 4
User avatar
lmstearn
Posts: 681
Joined: 11 Aug 2016, 02:32
Contact:

Re: MS Office COM Basics

14 Sep 2016, 02:01

@Kon: Thanks- having never worked with COM, this provides a working overview, that of which is not included in the current AHK docs.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: MS Office COM Basics

14 Sep 2016, 10:02

Great! :D You're welcome.
User avatar
JoeWinograd
Posts: 2166
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: MS Office COM Basics

27 Sep 2016, 10:06

Hi kon,
First, great tutorial! Thanks for taking the time to create it and then sharing it with all of us. I took a quick spin through it and am now going through it in detail (and will provide feedback for you), but I have an immediate issue that I haven't been able to figure out yet from the tutorial, namely, how to close a Word doc without saving the changes. The problem is described thoroughly in this post:
https://autohotkey.com/boards/viewtopic ... 28#p111428
If you (or anyone else reading this) have the answer, I'd be very grateful. Thanks, Joe
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: MS Office COM Basics

27 Sep 2016, 11:06

Hi! :)

wdDoNotSaveChanges, msoTrue, and msoFalse are constants. See section 5.1 and then 2.3 above. Most of the time you don't need to use VT_Bool_True := ComObject(0xB, -1). Simply passing -1 works in most cases.
Document[/url].[url=https://msdn.microsoft.com/en-us/library/office/ff196343.aspx]Close wrote:SaveChanges
Specifies the save action for the document. Can be one of the following WdSaveOptions constants: wdDoNotSaveChanges, wdPromptToSaveChanges, or wdSaveChanges.
So try:

Code: Select all

InputFile:=A_ScriptDir . "\test.docx"
oDoc := ComObjGet(InputFile)
oDoc.ShowRevisions := 0
MsgBox, % oDoc.Content.Text
oDoc.Close(0)
Side note:
JoeWinograd wrote:I found the MSDN doc for it and attempted to translate it into AHK as follows:

Code: Select all

oDoc.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
...fails with Error 0x800A107A.
^^That page is written for C# and VB. I suggest finding pages written for VBA, or use the Word Help and Object Browser as explained in section 2 above.

You can't directly access constants from AHK, although it is possible if you use ImportTypeLib. I wrote a script that makes it easier to use ImportTypeLib with MS Office constants: OfficeInfo. With it, you could do something like this:

Code: Select all

; ImportTypeLib: https://autohotkey.com/board/topic/78201-ahk-l-importtypelib-extended-com-support/
#Include %A_ScriptDir%\maul-esel-ImportTypeLib-28e9e8b
#Include Main.ahk
#Include %A_ScriptDir%\OfficeInfo.ahk  ; OfficeInfo: https://autohotkey.com/boards/viewtopic.php?f=6&t=23164
SetBatchLines, -1
c := new OfficeInfo

InputFile:=A_ScriptDir . "\test.docx"
oDoc := ComObjGet(InputFile)
oDoc.ShowRevisions := c.msoFalse
MsgBox, % oDoc.Content.Text
oDoc.Close(c.wdDoNotSaveChanges)
^^This just uses two constants so using OfficeInfo here is probably overkill, but this shows the general idea.

Another side note: When looking into your original question about tracked changes, I found the following page which seems useful: https://blogs.msdn.microsoft.com/office ... word-2013/
User avatar
ahkDustVorteX
Posts: 47
Joined: 14 May 2014, 12:08

Re: MS Office COM Basics

27 Sep 2016, 14:39

Hey Kon,

Very good job. This is a great compilation to help understand COM

Thanks a lot!

:clap:
Editor: Notepad++
"Those who wait and persist, always achieve."
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: MS Office COM Basics

27 Sep 2016, 14:47

You're welcome. :)
Thanks for the feedback and the kind words.
User avatar
JoeWinograd
Posts: 2166
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: MS Office COM Basics

27 Sep 2016, 15:04

Hi kon,
Thanks for that detailed explanation — extremely helpful! When you say that "Most of the time you don't need to use..." the VT_Bool trick, I presume that means some of the time you do need to use it. So for someone like me, with mediocre knowledge of COM, is it safer to stick with using VT_Bool_True and VT_Bool_False all the time? Any downside to it? Thanks, Joe
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: MS Office COM Basics

27 Sep 2016, 15:59

In my experience, you sometimes need to force at Type (ie: the "VT_Bool trick") when a parameter can accept more than one type of value. See section 5.5 above. Here's an example of when forcing a Type was required: AHK + Excel COM / MSDN - FitToPagesWide

It's OK to force a Type every time you use true and false. But, why only force a Type for true and false? You could specify a Type for other values passed to methods or properties... But this would amount to a lot of unnecessary work and maybe a tiny bit of extra overhead.

I suggest forcing a Type only when passing the bare value doesn't work. You will get a "Type Mismatch" error (or a similar error) if you pass the wrong Type of value to a method or property. You should be able to find these errors as soon as you try running the code, so there isn't much risk in trying to use the bare value first.
User avatar
JoeWinograd
Posts: 2166
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: MS Office COM Basics

27 Sep 2016, 16:19

You should be able to find these errors as soon as you try running the code, so there isn't much risk in trying to use the bare value first.
Makes perfect sense! Thanks again, Joe
imustbeamoron
Posts: 44
Joined: 18 Aug 2016, 22:56

Re: MS Office COM Basics

07 Oct 2016, 19:16

wow. I just came across this post. This didn't get nearly enough love.. i just started reading through all of the info you provided, but wanted to stop to say thank you kon for taking the time to put this very informative, well done tutorial together.

Return to “Tutorials (v1)”

Who is online

Users browsing this forum: No registered users and 25 guests