Microsoft KB Archive/316207

= Embed and Automate a Word Document by Using C++ .NET and MFC =

Article ID: 316207

Article Last Modified on 1/17/2007

-

APPLIES TO


 * Microsoft Visual C++ .NET 2002 Standard Edition
 * Microsoft Word 2000 Standard Edition
 * Microsoft Word 2002 Standard Edition
 * Microsoft Visual C++ .NET 2003 Standard Edition
 * Microsoft Office Word 2003

-



This article was previously published under Q316207





For a Microsoft Visual C++ 6.0 version of this article, see 238611.

IN THIS TASK

 * SUMMARY
 * Create an MFC Application that Embeds a Word Document
 * Test the Application
 * Troubleshooting
 * REFERENCES



Note Microsoft Visual C++ .NET (2002) supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code.



SUMMARY
This step-by-step article describes how to embed a Word document in a View object in a single-document interface (SDI) Microsoft Foundation Classes (MFC) application by using Visual C++ .NET.

back to the top

Create an MFC Application that Embeds a Word Document
The following steps demonstrate how to embed a Word document and automate the document to add data to a cell.  Start Microsoft Visual Studio .NET. On the File menu, click New, and then click Project. Under Project types click Visual C++ Projects, and then click MFC Application under Templates. Name the project Embed_Word. When the MFC Application Wizard appears, follow these steps:  Click Application Type and then select Single Document. Click Compound Document Support and then select Container. Click Finish to accept all other default settings.</ol> </li> Add interfaces from the Word object library. To do this, follow these steps: <ol style="list-style-type: lower-alpha;"> On the Project menu, click Add Class.</li> Select MFC Class From TypeLib from the list of templates and click Open. The Add Class From TypeLib Wizard appears.</li> In the list of available type libraries, locate Microsoft Word  Object Library. For Word 2000, the version is 9.0. For Word 2002, the version is 10.0. For Word 2003 the version is 11.</li> Add the following interfaces: <ul> _Document</li> Range</li></ul> </li> Click Finish.</li></ol> </li>  Add the following line to Cntritem.h as a public member function of the CEmbed_WordCntrItem class: LPDISPATCH GetIDispatch; </li>  Add the GetIDispatch method to Cntritem.cpp, as follows: /******************************************************************* LPDISPATCH CEmbed_WordCntrItem::GetIDispatch {   //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);
 * This method returns the IDispatch* for the application that is linked to
 * this container.

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(&quot;Warning: Link is not connected!\n&quot;); 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(&quot;Warning: does not support IDispatch!\n&quot;); return NULL; }

//After you verify that it is valid, return the IDispatch //interface to the caller. ASSERT(lpDispatch != NULL); return lpDispatch; }                   </li>  Add the following line to Embed_wordview.h as a public method of the CEmbed_WordView class: void EmbedAutomateWord; </li>  Add the following lines to Embed_wordview.cpp:
 * 1) include &quot;CDocument0.h&quot;
 * 2) include &quot;CRange.h&quot;

/******************************************************************** void CEmbed_WordView::EmbedAutomateWord {  //Change the cursor so that the user knows that something exciting is going //on. BeginWaitCursor;
 * This method encapsulates the process of embedding an Word
 * document in a View object and automating that document to add
 * some text.

CEmbed_WordCntrItem* pItem = NULL; TRY {   //Get the document that is associated with this view, and be sure that it is    //valid. CEmbed_WordDoc* pDoc = GetDocument; ASSERT_VALID(pDoc);

//Create a new item associated with this document, and be sure that it is   //valid. pItem = new CEmbed_WordCntrItem(pDoc); ASSERT_VALID(pItem);

// Get the Class ID for the Word document. // This is used in creation. CLSID clsid; if(FAILED(::CLSIDFromProgID(L&quot;Word.document&quot;,&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 that the new CContainerItem is valid. ASSERT_VALID(pItem);

// Start 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 the 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 embedded Word document. CDocument0 wdDoc; CRange wdRange;

//set CDocument0 wdDoc to use lpDisp, the IDispatch* of the //actual document. wdDoc.AttachDispatch(lpDisp);

//Get a CRange object for the document. wdRange = wdDoc.Range(COleVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ),        COleVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ) );

//Fill the range with the string &quot;Hello, World!&quot; wdRange.put_Text( &quot;Hello, World!&quot; ); }

//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; }                   </li>  Replace the code for CEmbed_WordView::OnInsertObject in Embed_wordview.cpp with the following: void CEmbed_WordView::OnInsertObject {   EmbedAutomateWord; } NOTE: EmbedAutomateWord is merely a special case of OnInsertObject, which allows the user to select from a list of available OLE objects to insert into the application. You will override this behavior because it is not needed for this demonstration. </li></ol>

back to the top

Test the Application

 * 1) Press F5 to build and run the application.
 * 2) On the Edit menu of the application, click Insert New Object.
 * 3) Examine the results. A new Word document is embedded into the View object, with the text &quot;Hello, World!&quot;.

back to the top

Troubleshooting
If you add class wrappers for the Word object library by using the File option in the Add Class From TypeLib Wizard, you may receive an error message when you browse to the object library. To avoid this problem, type the full path and file name for the object library instead of browsing to the file. For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

311408 BUG: 'Read-Only' Warning When Adding MFC Class From Library

back to the top

<div class="references_section">