Word Automation C++ Class

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

More by Author

Must Read