HOWTO: Use Automation to Run a Word 97 Macro with Arguments
ID: Q183369
|
The information in this article applies to:
-
Microsoft Visual C++, 32-bit Enterprise Edition, versions 5.0, 6.0
-
Microsoft Visual Basic for Applications version 5.0
-
The Microsoft Foundation Classes (MFC)
-
Microsoft Word 97 for Windows
SUMMARY
This article discusses how to use version 4.2 of the Microsoft Foundation
Class (MFC) library installed with Microsoft Visual C++ to automate Word 97
and run a macro that requires argument(s).
MORE INFORMATION
You can copy the code in this article to the message handler function of an
event defined in an MFC .cpp file. However, the purpose of the code is to
illustrate the process of using the IDispatch interfaces and member
functions defined in the Msword8.olb type library. The primary benefit
comes from reading and understanding the code so that you can modify the
example, or write code from scratch to automate sending an argument to a
Microsoft Word 97 VBA macro.
This example presents two methods for passing arguments to Word 97 VBA
macros:
- The first method calls a macro that is defined in the class module for
the "ThisDocument" object. The macro definition specifies a parameter.
- The second method uses Word variable objects. The macro definition does
not specify any parameters; however, the macro code accesses the value
of a variable stored within the document. The macro is called using the
Run method.
NOTE: This method will not work for a document that is protected.
Step-by-Step Example
- In Microsoft Word, create a new document and press ALT+F11 to display
the Visual Basic Editor.
- In the Word Visual Basic Macro Editor "Project" box (usually located at
the upper-left of the Visual Basic Window), double-click the
tree node for "ThisDocument" to display its module window. Add the
following code:
Public Sub testmacro(x As String)
MsgBox "First Method" & vbcr & x
End Sub
- On the Insert menu, click Module to insert a new module and add the code
below to the module:
Sub GetSetVarVals()
For Each myVar In ActiveDocument.Variables
If myVar.Name = "VarVal" Then
ActiveDocument.Variables("VarVal").Delete
End If
Next myVar
ActiveDocument.Variables.Add Name:="VarVal", _
Value:=ActiveDocument.Variables("FullName").Value
' Retrieve the contents of the document variable.
MsgBox "Second method" & _
vbcr & ActiveDocument.Variables("VarVal").Value
End Sub
Sub DelVariables() 'Delete the variable "FullName".
For Each myVar In ActiveDocument.Variables
If myVar.Name = "FullName" Then
ActiveDocument.Variables("FullName").Delete
End If
Next myVar
End Sub
- Save the document as C:\Test.doc. Close the document and exit Word.
- Follow steps 1 through 12 in the following Microsoft Knowledge Base
article to create a sample project that uses the IDispatch interfaces
and member functions defined in the MSWord8.olb type library:
Q178749 HOWTO: Create an Automation Project Using MFC and a Type Library
- To the dialog box created in steps 4 and 5 of the parent article
Q178749, add an "Edit Box" control from the Controls toolbar (if that
is not visible, right-click the gray area of the Visual Studio
command bar. From the context pop-up menu, select "Controls.")
This control will display the ID of IDC_EDIT1 in the General tab page of
the Edit Properties dialog box.
- On the View menu, click ClassWizard (or press CTRL+W). On the Member
Variables tab of the MFC ClassWizard dialog, select IDC_EDIT1 and click
Add Variable. Type "m_Argument" (without the quotation marks) for the
Member Variable Name, and click Ok. Click OK to close the ClassWizard
Dialog box.
- At the top of the AutoProjectDlg.cpp file, add the following line:
#include "msword8.h"
- Add the following code to CAutoProjectDlg::OnRun() in the
AutoProjectDlg.cpp file:
UpdateData(TRUE); // Transfers data from edit box
// on opening dialog box
// to the member variable m_Argument.
// Convenient constants.
COleVariant covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND,
VT_ERROR);
// Objects.
_Application objWord;
Range objRange;
objWord.CreateDispatch("Word.Application.8");
objWord.SetVisible(TRUE);
Documents oDocs(objWord.GetDocuments()); // Use the Constructor
// for Documents.
_Document oDoc;
oDoc.AttachDispatch(oDocs.Open(COleVariant("C:\\Test.doc",VT_BSTR),
covFalse, //Confirm Conversions.
covFalse, // Not read only.
covTrue, // Add to recent documents.
covOptional, // PassWordDocument.
covOptional, // PassWordTemplate.
covFalse, // Revert.
covOptional, // WritePasswordDocument.
covOptional, // WritePasswordTemplate.
covOptional) // Format, e.g., WordOpenFormat.
);
// Here is code for the method that passes an argument to a Word
// VBA macro defined in the ThisDocument class. The macro specifies
// a string parameter. Such a macro won't appear in the document's
// macro list.
// The macro is not declared in the Word typelib, so the code
// retrieves the dispid at run time from the IDispatch interface
// for the Document object. It uses that dispid in the call to
// InvokeHelper.
OLECHAR FAR* szMember = OLESTR("testmacro");
DISPID dispid;
if(FAILED(oDoc.m_lpDispatch->GetIDsOfNames ( IID_NULL,
&szMember, //Function name.
1, //Number of functions.
LOCALE_SYSTEM_DEFAULT,
&dispid)))
{
AfxMessageBox("Unable to get dispID for testmacro");
}
COleVariant result;
UCHAR *parmStr = (BYTE *)( VTS_VARIANT );
COleVariant x;
x = COleVariant(m_Argument);
oDoc.InvokeHelper( dispid,
DISPATCH_METHOD | DISPATCH_PROPERTYGET,
VT_VARIANT,
(void *)&result,
parmStr,
&x);
// Here is code that passes an argument using Word variables.
// This method won't work on a protected document, because that
// won't let the user--in this case your MFC client--set
// variable values.
AfxMessageBox("Next, pass an argument using a Variable");
Variables oVariables = oDoc.GetVariables(); // Create Variables
// collection for current doc.
objWord.Run("DelVariables"); // Word Macro to purge the variable
// "FullName".
VARIANT *v = new VARIANT; // Creating pointer to a VARIANT.
v->vt = VT_BSTR; // Variant type = VT_BSTR
v->bstrVal = m_Argument.AllocSysString(); //The string from Edit Box.
oVariables.Add("FullName", v); // "FullName" is the Word Variables
// item.
objWord.Run("GetSetVarVals"); // Word Macro to show the contents of
// "FullName".
delete v; // Release the memory block for the Variant.
objWord.Quit(covFalse, covOptional, covFalse);
// The parameters mean Save Changes, Original Format, RouteDocument.
- You may need to modify the code in CAutoProjectDlg::OnRun() to indicate
the correct path for your document Test.doc. The document is referenced
in the following line:
oDoc.AttachDispatch(oDocs.Open(
COleVariant("C:\\Test.doc",VT_BSTR)...
- Compile your VC++ project, then run it.
- The dialog box will appear. Enter a string, such as "George Washington"
(without the quotation marks) in the edit box.
- Click Run in the dialog box. Word will appear, then the Message Box of
the macro "GetSetVarVals()" will appear. The argument you entered in the
MFC edit box has been passed to the Word VBA macro.
REFERENCES
For more information about automating Microsoft Word using MFC, please
refer to the following articles in the Microsoft Knowledge Base:
Q178784 Use Automation to Open and Print a Word 97 Document
Q180312 HOWTO: Use Automation to Set the Printer from an MFC Project
Additional query words:
IDispatch Word 8.0 Word8 Word97
Keywords : kbinterop kbole kbAutomation kbMFC KbVBA kbVC500 kbVC600 kbWord
Version : WINDOWS:5.0,6.0,97; winnt:
Platform : WINDOWS winnt
Issue type :
|