User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    Word Automation C++ Class

    • 1
    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
    • 1

    IT Offers





    Partners

    • Partner With Us














    Top Authors


    The Network for Technology Professionals

    Search:

    About Internet.com

    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers