Word Automation C++ Class

Thursday Feb 1st 2001 by Poonam Bajaj
Share:

Wrapper class that enables C++ applications to automate Microsoft Word

Environment: VC++ 6.0, Windows 2000 with MS-Office installed.

In this article, I will describe the implementation of a C++ class that automates Microsoft Word application. The class uses low-level COM and is quite handy in its usage. The idea came into my mind when I answered two queries on this topic on a discussion forum in just one day!

I named the class 'CAutoWord'. It can open a Word documment file and print its contents on the default printer. Everything works in the background. A typical application can be an NT service which generally runs without any UI. It has following exposed methods.

1. CAutoWord() : Constructor function that initializes COM.
2. int InitAutomation() : Initializes the automation. In case of failure, it returns -1 else 0 is returned.
3. int PrintDocument() : This function will load the file and print the contents on the default printer. Negative return value indicates that an error occurred.

More functions can be added using the same framework.

Usage Scenario

The code snippet given below demonstrates its usage.
#include "AutoWord.h"

int PrintWordDocument(CString szFilePath)
{
 // Instantiate an object of CAutoWord
 CAutoWord	AutoWord;

 // Set filepath 
 int iRetVal = AutoWord.InitAutomation();
 if (iRetVal != 0)
 {
  printf("LoadDocument operation failed.");
 }

 // Set filepath 
 char* strFilePath = szFilePath.GetBuffer(szFilePath.
                                          GetLength));

 // Print the WORD document
 iRetVal = AutoWord.PrintDocument(strFilePath);
 if (iRetVal == 0)
 {
  AfxMessageBox(szFilePath+" was sent to printer.");
 }
 else
 {
  AfxMessageBox("Print operation failed.");
 }

 return iRetVal;
}

Implementation

Following is CAutoWord class declaration :
#include <oaidl.h>

class CAutoWord  
{
 void Destroy(); // Cleaup function

public:
 // Opens, Prints and closes a document
 int PrintDocument(char* strFilepath); 

 // Initializes the automation class and prepares 
 // it for use.
 int InitAutomation(); 

 // Constructor : Initializes COM libraries
 CAutoWord();      
 
 // Destructor : Calls Detroy() and UnInitializes COM.
 virtual ~CAutoWord(); 

private:
 // Keeps value of Dispatch pointer to 
 // 'Word.Application' instance
 IDispatch* m_pDispApp;    

 // Keeps a pointer to 'Documents' property of 
 // m_pDispApp interface.
 IDispatch* m_pDocuments;  
};

Most of the work is done InitAutomation() and PrintDocument() functions.

InitAutomation() creates an instance of the 'Word.Application' object and obtains the pointer to the instance's IUnknown interface.

IUnknown* pUnk;
HRESULT hr = ::CoCreateInstance( clsid, 
                                 NULL, 
                                 CLSCTX_LOCAL_SERVER, 
                                 IID_IUnknown, 
                                 (void**) &pUnk);
Calling QueryInterface() on IUnknown gives a pointer to the IDispatch interface (m_pDispApp).
hr = pUnk->QueryInterface(IID_IDispatch, 
                          (void**)&m_pDispApp);
Using GetIDsOfNames(), we get Dispatch Id of 'Documents' property of m_pDispApp interface.
LPOLESTR szDoc = L"Documents";   
hr = m_pDispApp->GetIDsOfNames(IID_NULL, 
                               &szDoc, 
                               1, 
                               LOCALE_SYSTEM_DEFAULT, 
                               &dispID);
Now, Invoke() function is called that gives us Dispatch pointer to its 'Documents' property. The pointer is saved in m_pDocuments member variable.
hr = m_pDispApp->Invoke(dispID, 
                        IID_NULL, 
                        LOCALE_SYSTEM_DEFAULT, 
                        DISPATCH_PROPERTYGET, 
                        &dp, 
                        &varRetVal, 
                        NULL, 
                        NULL);
...
m_pDocuments = varRetVal.pdispVal;

PrintDocument() method gets the Dispatch Id of 'Open' method of m_pDocuments interface. Then the invoke function is called with the Word Document's filepath as a parameter. This returns a pointer to the Dispatch interface to this Word document. We call it pDocument.

LPOLESTR szOpenDoc = L"Open";
HRESULT hr = m_pDocuments->GetIDsOfNames(IID_NULL, 
                                         &szOpenDoc, 
                                         1, 
                                         LOCALE_SYSTEM_DEFAULT, 
                                         &dispOpenID);
hr = m_pDocuments->Invoke(dispOpenID, 
                          IID_NULL, 
                          LOCALE_SYSTEM_DEFAULT, 
                          DISPATCH_METHOD, 
                          &dpOpen, 
                          &varRetVal, 
                          &excepInfo, 
                          NULL);
...
IDispatch* pDocument = varRetVal.pdispVal;
After pDocument is obtained, it's 'PrintOut' method is called. This actually prints out the contents of the Word Document on the default printer and the document is closed.
LPOLESTR szPrintDoc = L"PrintOut";
hr = pDocument->GetIDsOfNames(IID_NULL, 
                              &szPrintDoc, 
                              1, 
                              LOCALE_SYSTEM_DEFAULT, 
                              &dispPrintID);
hr = pDocument->Invoke(dispPrintID, 
                       IID_NULL, 
                       LOCALE_SYSTEM_DEFAULT, 
                       DISPATCH_METHOD, 
                       &dpPrint, 
                       &varRetVal, 
                       NULL, 
                       NULL);
...
LPOLESTR szCloseDoc = L"Close";
hr = pDocument->GetIDsOfNames(IID_NULL, 
                              &szCloseDoc, 
                              1, 
                              LOCALE_SYSTEM_DEFAULT, 
                              &dispCloseID);
hr = pDocument->Invoke(dispCloseID, 
                       IID_NULL, 
                       LOCALE_SYSTEM_DEFAULT, 
                       DISPATCH_METHOD, 
                       &dpClose, 
                       &varRetVal, 
                       &excepInfo, 
                       NULL);

The Destroy() method simply quits the Word Application's instance.

LPOLESTR szQuit = L"Quit";
HRESULT hr = m_pDispApp->GetIDsOfNames(IID_NULL, 
                                       &szQuit, 
                                       1, 
                                       LOCALE_SYSTEM_DEFAULT, 
                                       &dispQuit);
hr = m_pDispApp->Invoke(dispQuit, 
                        IID_NULL, 
                        LOCALE_SYSTEM_DEFAULT, 
                        DISPATCH_METHOD, 
                        &dpQuit, 
                        &varRetVal, 
                        &excepInfo, 
                        NULL);
The Demo project uses CAutoWord class to print the Word files.

Downloads

Download source - 2 Kb
Download demo project - 4 Kb
Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved