Using OLE Automation with Word

OLE Automation is a protocol intended to replace DDE. As with DDE, an application can use OLE Automation to share data or control another application.

In OLE Automation, Word provides another application (called the "container" application) with an object — a unit of information similar to a topic in DDE. Word supports a single object called "WordBasic" for OLE Automation. You use the "WordBasic" object to send WordBasic instructions to Word. The technique is similar to sending commands to Word through DDE, but with OLE Automation, WordBasic instructions can return numbers or strings directly to the container application. This makes it possible to use WordBasic instructions as an extension of the container application's macro or programming language.

Note that Word can provide an object to another application for OLE Automation, but it cannot use OLE Automation to access objects in other applications. In other words, applications that support OLE Automation, such as Microsoft Excel or a Visual Basic application, can use OLE Automation to access Word, but Word cannot use OLE Automation to access them. (In DDE terms, Word can act as a server for another application but cannot act as the client.)

Microsoft Visual FoxPro version 3.0 includes an OLE Automation client example. For information about how to run and view the code associated with the OLE Automation example, see "OLE Automation Sample" in Microsoft Visual FoxPro Help.

Note

Throughout this section, the term "Visual Basic" is used to refer to either Visual Basic version 3.0 or later (Windows) or Visual Basic in Microsoft Access version 7.0 (Windows) and Microsoft Excel version 5.0 or later (Windows or Macintosh), unless otherwise indicated.

Accessing Word

The first step toward making Word available to a container application is to define an object variable that will reference the "WordBasic" object in Word. In Visual Basic, you declare a variable of type Object. For example:


Dim WordObj As Object

You then make the "WordBasic" object available to the container application by "creating" it for the application and assigning it to the object variable. In Visual Basic, you use the CreateObject function to create an object and the Set keyword to assign to the object variable. Here is the syntax:

Set ObjectVar = CreateObject("Application.ObjectType")

For example, in Visual Basic you could use the following instruction:


Set WordObj = CreateObject("Word.Basic")

This instruction makes the "WordBasic" object in Word available to the container application for OLE Automation.

If Word version 6.0 is not running when another application needs to access it, OLE Automation starts a visible instance of Word. You don't need to include a separate instruction to start Word, as you do with DDE. An error occurs if Word cannot be found. While a visible instance is useful for debugging a Visual Basic procedure, you may want to hide the instance in the final macro. To do so, use the WordBasic AppHide statement:


Set WordObj = CreateObject("Word.Basic")
WordObj.AppHide

If Word version 7.0 is not running when another application needs to access it, OLE Automation starts a hidden instance of Word. While a hidden instance is useful for the final macro, you may want to make the instance visible while debugging the Visual Basic procedure. To do so, use the WordBasic AppShow statement:


Set WordObj = CreateObject("Word.Basic")
WordObj.AppShow

Applications that fully support OLE Automation make their documents available as objects. Since Word supports only the "WordBasic" object for OLE Automation, you cannot use OLE Automation to directly access a Word document as an object (unless the document is embedded in the container application; see "Accessing an Embedded Word Object" later in this chapter). For example, you cannot use the GetObject function in Visual Basic to access a Word document. Instead, you use WordBasic instructions to access Word and to act on Word documents, as described in the following section.

If OLE Automation starts a Word session, OLE Automation will close Word when the object variable that references the "WordBasic" object expires — when either the procedure ends or the container application is closed. In Visual Basic, you can use the Set statement with the Nothing keyword to clear an object variable, which has the same effect as closing the container application.

Note that the "WordBasic" object does not support a method to close itself. That is, if Word is running when OLE Automation starts, you cannot close Word through OLE Automation; you can only close a Word session if you also used OLE Automation to start it.

Using WordBasic Statements and Functions

Once you have made the "WordBasic" object available to the container application, you can use most WordBasic statements or functions to act on Word and Word documents. You use WordBasic instructions in OLE Automation in the same way you use them in Word macros.

WordBasic statements and functions not available to OLE Automation include the following: control structures, such as While¼Wend and If¼Then¼Else; declaration statements such as Dim; statements associated with custom dialog boxes; the FileExit statement; and statements or functions that require array variables as arguments.

WordBasic functions that return strings end in a dollar sign ($). When using these functions in OLE Automation, you can either leave off the dollar sign or enclose it in brackets. The following instruction shows the GetBookmark$() function as it might appear in a WordBasic macro:


mark$ = GetBookmark$("Address")

In Visual Basic, the same instruction might be specified as either of the following two instructions, where mark is a string variable:


mark = WordObj.[GetBookmark$]("Address")
mark = WordObj.GetBookmark("Address")

Note

The following WordBasic functions that return strings require the dollar sign and must be enclosed in brackets: Font$(), GetSystemInfo$(), and Language$(). These WordBasic functions have the same keywords as WordBasic statements (for example, there is a Font statement as well as a Font$() function); without the dollar sign WordBasic has no way to distinguish them from WordBasic statements.

The following example opens the Word document LETTER.DOC and then uses a WordBasic GetBookmark$() instruction to retrieve the text of the "Address" bookmark in LETTER.DOC and display it in a message box:


Dim mark As String
Dim WordObj As Object
Set WordObj = CreateObject("Word.Basic")
WordObj.FileOpen Name:= "LETTER.DOC"
mark = WordObj.GetBookmark("Address")
MsgBox mark

The following example retrieves the list of bookmarks from the active document and displays their contents in a series of message boxes. These instructions use WordBasic instructions just as if they were part of the Visual Basic language. In effect, these instructions extend the functionality of Visual Basic. The only difference is that since WordBasic is not an object-oriented language with methods and properties like those of Visual Basic, the syntax of the WordBasic instructions does not match Visual Basic syntax.


Dim WordObj As Object
Set WordObj = CreateObject("Word.Basic")
Dim count As Integer, countmarks As Integer
countmarks = WordObj.CountBookmarks()
If countmarks <> 0 Then
ReDim bmarks$(1 To countmarks)
For count = 1 To countmarks
    bmarks$(count) = WordObj.BookmarkName(count)
Next count
For count = 1 To countmarks
    MsgBox bmarks$(count)
Next
End If

In the following example, the instructions toggle the bold formatting of the selected paragraph in Word:


Dim WordObj As Object
Set WordObj = CreateObject("Word.Basic")
WordObj.EditGoto "\Para"        'Select the current paragraph
If WordObj.Bold() <> 0 Then
    WordObj.Bold 0            'Remove bold from the selected text
Else
    WordObj.Bold 1            'Apply bold to the selected text
End If

What Does the Instruction Act On?

A significant difference between Visual Basic and WordBasic is that in Visual Basic, whatever a statement (or "method") acts on is specified in the statement itself. In WordBasic, however, that is not always the case. For example, an EditCut WordBasic instruction might cut anything from a single character to an entire document: it cuts whatever is selected in the active document when the instruction runs. Most WordBasic formatting and editing instructions work this way. If you're used to the Visual Basic way of doing things, keep in mind that when using WordBasic instructions, you usually need to be aware of the current selection or location of the insertion point.


Accessing an Embedded Word Object

So far, this section has described accessing Word as a separate application. But you can also access a Word object such as a Word document or Word picture embedded in the container application. In Visual Basic, you use the Object property to access the document or picture and to use WordBasic statements and functions to act on it. Here is the syntax for Visual Basic version 3.0 or later (not available on the Macintosh):

Set ObjectVar = OLEControlName.Object.Application.WordBasic

ObjectVar is a previously declared object variable; OLEControlName is the name of the OLE control in which the Word object is embedded. For example, you could use the following instructions to access a document embedded in an OLE control called OLE1:


Dim WordObj As Object
Set WordObj = OLE1.Object.Application.WordBasic

In Microsoft Excel Visual Basic, you use the OLEObjects method to return the embedded Word object. The following example accesses a Word document object with the name Picture 1 (the name given to the object in Microsoft Excel, not a document filename) in the active worksheet:


Dim WordObj As Object
Set WordObj = ActiveSheet.OLEObjects("Picture 1")

In Microsoft Access Visual Basic, you use the Object property to access an embedded Word document. For example, you could use the following instructions to access a document embedded in an OLE control called OLE1:


Dim WordObj As Object
Set WordObj = Me!OLE1.Object.Application.WordBasic

The embedded object must be activated before it can be accessed. You can either include an instruction to activate the OLE control, or you can assume the object is activated in some other way (for example, the user double-clicks it). In Visual Basic version 3.0, you can use the Action property to activate OLE control. For example:


OLE1.Action = 7

In this instruction, OLE1 is the name of the OLE control in which the Word object is embedded.

In Visual Basic version 4.0, you can activate an OLE control using the Action property or the DoVerb method. For example, the following two instructions are equivalent:


OLE1.DoVerb(vbOLEShow)
OLE1.Action = 7

In Microsoft Excel Visual Basic, you use the Activate method to activate the Word object. In the following example, WordObj is an object variable in which the Word document object is stored:


WordObj.Activate

In Microsoft Access Visual Basic, you use the Action property to activate the Word object. For example:


Me!OLE1.Action = acOLEActivate

The following example accesses a Word object embedded in a Visual Basic version 4.0 container application. Then it uses the WordBasic EditSelectAll statement to select all the text, and the WordBasic Bold statement to format it as bold. The Check1.SetFocus instruction deactivates the embedded Word object and returns the focus to a checkbox named "Check1."


Dim WordObj As Object
OLE1.DoVerb(vbOLEShow)
Set WordObj = OLE1.Object.Application.WordBasic
WordObj.EditSelectAll
WordObj.Bold
Check1.SetFocus
Set WordObj = Nothing

Here is the same example using Microsoft Excel Visual Basic. The final instruction, Range("B6").Activate, deactivates the embedded Word object and activates cell B6 in the active worksheet.


Dim WordObj As Object
Set WordObj = ActiveSheet.OLEObjects("Picture 1")
WordObj.Activate
With WordObj.Object.Application.WordBasic
    .EditSelectAll
    .Bold
End With
Range("B6").Activate

Here is the same example using Microsoft Access Visual Basic. The final instruction, DoCmd.GoToControl "Check1", activates the check box named "Check1."


Dim WordObj As Object
Set WordObj = Me!OLE1.Object.Application.WordBasic
Me!OLE1.Action = acOLEActivate
WordObj.EditSelectAll
WordObj.Bold
DoCmd.GoToControl "Check1"
Set WordObj = Nothing

Retrieving Word Dialog Box Settings

You can retrieve Word dialog box settings when you're using OLE Automation to access either Word itself (through the "Basic" object) or an embedded Word document. To do so, you first create an object variable to hold the settings, and then place the settings in the object variable. For example:


Dim TOVvar As Object
Set TOVvar = WordObj.CurValues.FileOpen

The first instruction defines an object variable to hold the dialog box settings. The second instruction assigns the variable the current settings of the dialog box — in this case, the settings of the Open dialog box (File menu). WordObj is the object variable defined to access WordBasic. CurValues returns the dialog box settings from the dialog box specified. To specify a dialog box, you use the name of the WordBasic statement that corresponds to a Word dialog box. For example, FileOpen is the name of the WordBasic statement that corresponds to the Open dialog box (File menu). If you don't know the name to use for a dialog box, see "Language Summary" and "Statements and Functions" in Part 2, "WordBasic Reference."

Once you have placed the dialog box settings in an object variable, you use the following syntax to access them:

DialogObjectVar.DialogBoxSettingName

DialogBoxSettingName is the name of an argument for the WordBasic statement that corresponds to the dialog box whose settings are stored in DialogObjectVar. For the list of valid arguments, see the entry for the WordBasic statement in Part 2, "WordBasic Reference."

The following Visual Basic example toggles the Draft Font setting on the View tab in the Options dialog box (Tools menu). Note that if you are using Visual Basic version 3.0, you cannot use the instruction WordObj.ToolsOptionsView DraftFont := 0 since DraftFont is a named argument. Instead, you specify the argument positionally, as described in "Using Positional Arguments in Visual Basic Version 3.0" later in this chapter.


Dim WordObj As Object
Dim TOVvar As Object
Set WordObj = CreateObject("Word.Basic")
Set TOVvar = WordObj.CurValues.ToolsOptionsView
If TOVvar.DraftFont = 1 Then
    WordObj.ToolsOptionsView DraftFont := 0
Else
    WordObj.ToolsOptionsView DraftFont := 1
End If

Running Word Macros and Displaying Dialog Boxes

You can run a Word macro through OLE Automation, just as you can from within another Word macro. After the macro runs, control returns to the procedure that called it. You use the WordBasic ToolsMacro statement to run a macro. For example, the following instruction runs a macro called CountOpenWindows:


WordObj.ToolsMacro "CountOpenWindows", True

Word must be the active application if the macro displays a dialog box, message box, input box, or anything that requires a response from the user before the macro can continue. If Word is not the active application, the macro comes to a halt and eventually an OLE Automation error occurs. To make Word the active application, you can use an instruction similar to the WordBasic AppActivate statement in the container application's macro or programming language.

You can't directly define and display a dialog box through OLE Automation, but you can run a Word macro to display the dialog box. If the dialog box is a dialog box built into Word, you can then use the CurValues method to retrieve its settings. If the dialog box is a custom dialog box, the macro that displays the dialog box can save the dialog box settings so that they remain after the macro is finished. For example, the macro could save the settings in a settings file. For information on settings files, see "Using Settings Files and Document Variables" in Chapter 9, "More WordBasic Techniques."

Passing Values to a Word Macro

You cannot directly pass arguments to a Word macro or macro subroutine through OLE Automation. Within WordBasic, you can use the syntax MacroName.Subroutine [(ArgumentList)] to call subroutines in other macros and pass arguments to them, but this syntax is not supported by OLE Automation. If you want your Visual Basic code to run a WordBasic macro and to pass values to that macro, you must store those values in a location the macro can access. For example, you could store values in a settings file or in Word document variables. For information on settings files and document variables, see "Using Settings Files and Document Variables" in Chapter 9, "More WordBasic Techniques."


The following Visual Basic example runs a Word macro called CreateAndSaveNewDoc and displays a message when the macro is finished. The Visual Basic AppActivate statement is used to activate Word before the macro runs, since the macro will display the Save As dialog box.


Dim WordObj As Object
Set WordObj = CreateObject("Word.Basic")
AppActivate "Microsoft Word"
WordObj.ToolsMacro "CreateAndSaveNewDoc", True
MsgBox "The CreateAndSaveNewDoc macro is done."

You can also run this example in a Visual Basic version 3.0 application, but the Visual Basic version 3.0 AppActivate statement requires as an argument the same text that appears in the Word application window title bar. This text may change if a document window is maximized, so you need to add an If conditional to check whether this is the case and change the text specified in AppActivate accordingly. The following conditional uses the WordBasic functions CountWindows, DocMaximize(), and WindowName$() to accomplish this task:


If WordObj.CountWindows() > 0 Then
    If WordObj.DocMaximize() = True Then
        AppActivate "Microsoft Word - " + WordObj.WindowName()
    Else
        AppActivate "Microsoft Word"
    End If
Else
    AppActivate "Microsoft Word"
End If

Here is the CreateAndSaveNewDoc macro:


Sub MAIN
AppMaximize "Microsoft Word"
On Error Goto bye
FileNew
FileSave
AppActivate "Microsoft Excel"
bye:
End Sub

This macro maximizes the Word window (in case Word is minimized when the macro is called), then creates a new file and uses the FileSave statement to display the Save As dialog box (File menu). (This dialog box is displayed because the file has never been saved.) The AppActivate instruction at the end of the macro activates Microsoft Excel so that control returns to the routine that called the macro. If you are using Visual Basic version 4.0, you can use the AppActivate statement with the text from the application title bar (i.e. AppActivate "Form1")

Using Positional Arguments in Visual Basic Version 3.0

WordBasic statements that correspond to Word dialog boxes use named arguments — arguments whose values are associated with names. For example, .Font is the named argument in the following instruction:


FormatDropCap .Font = "Arial"

In Visual Basic version 4.0, Microsoft Excel Visual Basic, and Microsoft Access Visual Basic, you can call WordBasic instructions using named arguments, as shown in the following example:


WordObj.FormatDropCap Font:="Arial"

You cannot call a WordBasic instruction from Visual Basic version 3.0 using named arguments. Instead, you identify arguments by position. The following example shows a WordBasic instruction as it could appear in a Word macro:


FormatDropCap .Position = 1, .Font = "Arial", .DropHeight = 3, .DistFromText = 6

To use this instruction in a Visual Basic version 3.0 procedure, you would write the following:


WordObj.FormatDropCap 1, "Arial", 3, 6

In this instruction, WordObj is an object variable that refers to WordBasic. If you want to leave out an argument, you must indicate the missing argument with a comma, as shown in the following instruction:


WordObj.FormatDropCap , "Arial", , 6

Trailing commas can be omitted (for example, WordObj.FormatDropCap 1, "Arial" is valid; it isn't necessary to specify WordObj.FormatDropCap 1, "Arial", , ,).

Boolean "true" and "false" values are used to specify command buttons. For example, the following WordBasic instruction runs the macro CountOpenWindows:


ToolsMacro .Name = "CountOpenWindows", .Run

where .Run is the named argument equivalent to the Run button in the Macro dialog box. In a Visual Basic version 3.0 procedure, the instruction might appear as follows:


WordObj.ToolsMacro "CountOpenWindows", True

A true value is equivalent to choosing a command button; false is equivalent to not choosing it. The following instruction opens the CountOpenWindows macro for editing:


WordObj.ToolsMacro "CountOpenWindows", False, True

In WordBasic, the third argument is .Edit, so in Visual Basic version 3.0 a true value in the third position is equivalent to choosing the Edit button. Omitting a command button argument is equivalent to giving it a value of false.

Note

The syntax line for most statement and function entries in WordBasic Help describes the correct positional order of arguments. There are some exceptions, however. For a complete list of these exceptions and the correct order of their arguments, see POSITION.TXT on the Microsoft Word Developer's Kit disk (Windows).