HOWTO: Embed and Automate a Word Document with MFC

ID: Q238611


The information in this article applies to:
  • Microsoft Word 97 for Windows
  • Microsoft Word 2000
  • Microsoft Visual C++, 32-bit Professional Edition, versions 5.0, 6.0


SUMMARY

Documents that are embedded in other application documents, using OLE embedding, can be modified by automation without double-clicking the embedded document to activate it in "edit" or "open"' mode.

This article demonstrates how to embed and automate a Microsoft Word 2000 document in an MFC Single Document Interface application. The same approach works with a Microsoft Word 97 document. The distinction is not which version of Word created the document, but rather, which version of Word you use in the automation process.

The difference in the use of the Word 2000 type library instead of that of Word 97. The different files containing the two different type libraries are MSWord9.olb for Microsoft Word 2000, and MSWord8.olb for Word 97. The default location for either file is ...\Program Files\Microsoft Office\Office.


MORE INFORMATION

Create a Sample Project

  1. Using Microsoft Visual Studio, start a new MFC AppWizard (exe) project named EmbedWord. In AppWizard, choose "Single Document" as the application type in step 1 and choose "Container" as the type of compound document support in step 3. You can accept all other defaults.


  2. Press the CTRL+W key combination to invoke the Class Wizard. Select the Automation tab. Click the Add Class button and choose From a Type Library. Browse to locate the Microsoft Word 2000 type library (MSWord9.olb).


  3. In the Confirm Classes dialog box, select all of the members listed, and click OK.


  4. Click OK again to close ClassWizard.


  5. Modify EmbedWordView.cpp so that it includes the header file ClassWizard generated from the Word type library:


  6. 
    #include "msword9.h" 
  7. Replace the code in CEmbedWordView::OnInsertObject() with the following:


  8. 
    void CEmbedWordView::OnInsertObject()
    {
       EmbedAutomateWord();
    } 
  9. Add a CEmbedWordView::EmbedAutomateWord() member function to EmbedWordView.cpp:


  10. 
    void CEmbedWordView::EmbedAutomateWord()
    {
    
         /*******************************************************************
          This method encapsulates the process of embedding a Word document
          in a View object and automating that document to add text.
         *******************************************************************/ 
    
        //Change the cursor so the user knows something exciting is going
             //on.
             BeginWaitCursor();
    
             CEmbedWordCntrItem* pItem = NULL;
             TRY
             {
                //Get the document associated with this view, and be sure it's
                //valid.
                CEmbedWordDoc* pDoc = GetDocument();
                ASSERT_VALID(pDoc);
    
                //Create a new item associated with this document, and be sure
                //it's valid.
                pItem = new CEmbedWordCntrItem(pDoc);
                ASSERT_VALID(pItem);
    
                // Get Class ID for Word document.
                // This is used in creation.
                CLSID clsid;
                if(FAILED(::CLSIDFromProgID(L"Word.Document",&clsid)))
                   //Any exception will do. You just need to break out of the
                   //TRY statement.
                   AfxThrowMemoryException();
    
                // Create the Word embedded item.
                if(!pItem->CreateNewItem(clsid))
                   //Any exception will do. You just need to break out of the
                   //TRY statement.
                   AfxThrowMemoryException();
    
                //Make sure the new CContainerItem is valid.
                ASSERT_VALID(pItem);
    
                // Launch the server to edit the item.
                pItem->DoVerb(OLEIVERB_SHOW, this);
    
                // As an arbitrary user interface design, this sets the
                // selection to the last item inserted.
                m_pSelection = pItem;   // set selection to last inserted item
                pDoc->UpdateAllViews(NULL);
    
                //Query for the dispatch pointer for the embedded object. In
                //this case, this is the Word document.
                LPDISPATCH lpDisp;
                lpDisp = pItem->GetIDispatch();
    
                //Add text to the first line of the document
                _Document doc;
                Selection selection;
                _Application app;
                PageSetup pagesetup;
                _Font font;
    
                //set _Document doc to use lpDisp, the IDispatch* of the
                //actual document.
                doc.AttachDispatch(lpDisp);
                
                //Then get the document's application object reference.
                app = doc.GetApplication();
    
                // From there, get a Selection object for the insertion point.
                selection = app.GetSelection();
                selection.SetText(
                      "This is a good place to say \"Hello World\"");
    
                // Automate setting the values for various properties.
                font = selection.GetFont();
                font.SetName("Tahoma");
                font.SetSize(16);
                selection.SetFont(font);
             }
    
             //Here, you need to do clean up if something went wrong.
             CATCH(CException, e)
             {
                if (pItem != NULL)
                {
                   ASSERT_VALID(pItem);
                   pItem->Delete();
                }
                AfxMessageBox(IDP_FAILED_TO_CREATE);
             }
             END_CATCH
    
             //Set the cursor back to normal so the user knows exciting stuff
             //is no longer happening.
             EndWaitCursor();
    } 
  11. Open EmbedWordView.h and add the declaration of this new method to the "implementation" region:


  12. 
       void EmbedAutomateWord(); 
  13. Open CntrItem.cpp and add a new CEmbedWordCntrItem::GetIDispatch member function:


  14. 
    LPDISPATCH CEmbedWordCntrItem::GetIDispatch()
    {	
    
         /****************************************************************
          This method returns the IDispatch* for the application linked to 
          this container.	
         *****************************************************************/ 
    
             //The this and m_lpObject pointers must be valid for this function
             //to work correctly. The m_lpObject is the IUnknown pointer to
             // this object.
             ASSERT_VALID(this);
             ASSERT(m_lpObject != NULL);
    
             LPUNKNOWN lpUnk = m_lpObject;
    
             //The embedded application must be running in order for the rest
             //of the function to work.
             Run();
    
             //QI for the IOleLink interface of m_lpObject.
             LPOLELINK lpOleLink = NULL;
             if (m_lpObject->QueryInterface(IID_IOleLink,
                (LPVOID FAR*)&lpOleLink) == NOERROR)
             {
                ASSERT(lpOleLink != NULL);
                lpUnk = NULL;
    
                //Retrieve the IUnknown interface to the linked application.
                if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
                {
                   TRACE0("Warning: Link is not connected!\n");
                   lpOleLink->Release();
                   return NULL;
                }
                ASSERT(lpUnk != NULL);
             }
    
             //QI for the IDispatch interface of the linked application.
             LPDISPATCH lpDispatch = NULL;
             if (lpUnk->QueryInterface(IID_IDispatch, (LPVOID FAR*)&lpDispatch)
                !=NOERROR)
             {
                TRACE0("Warning: does not support IDispatch!\n");
                return NULL;
             }
    
             //After assuring yourself that it is valid, return the IDispatch
             //interface to the caller.
             ASSERT(lpDispatch != NULL);
             return lpDispatch;      
    } 
  15. Open CntrItem.h and add the following declaration to the "implementation" region:


  16. 
    LPDISPATCH GetIDispatch(); 
  17. In CntrItem.cpp, change the last line of code in CEmbedWordCntrItem::OnGetItemPosition from:


  18. 
    rPosition.SetRect(10, 10, 210, 210); 
    to:
    
    rPosition.SetRect(20, 20, 630, 420); 
  19. Press the F7 key to build EmbedWord.exe. Then press the CTRL+F5 key combination to run the application. When the frame Untitled - EmbedWord appears, click Insert New Object on the Edit menu. The new embedded Word document appears, and the Word menu and Command button bar are merged with the menu of the EmbedWord application.

    Your code embedded the new document, added text to it, and set the typeface and font size.


(c) Microsoft Corporation 1999, All Rights Reserved. Contributions by Chris Jensen, Microsoft Corporation.


REFERENCES

For additional information about automating an embedding Office document, please click the article number below to view the article in the Microsoft Knowledge Base:

Q184663 HOWTO: Embed and Automate a Microsoft Excel Worksheet with MFC

(c) Microsoft Corporation 1999, All Rights Reserved. Contributions by Chris Jensen, Microsoft Corporation.

Additional query words:

Keywords : kbole kbMFC kbVC500 kbVC600 kbWord kbGrpDSO kbDSupport kbWord97 kbword2000
Version : WINDOWS:2000,97; winnt:5.0,6.0
Platform : WINDOWS winnt
Issue type : kbhowto


Last Reviewed: October 21, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.