Automate Microsoft Word to Perform a Mail Merge from Visual C++ .NET

Article translations Article translations
Article ID: 308338 - View products that this article applies to.
For a Microsoft C# .NET version of this article, see 301659.
For a Microsoft Visual Basic .NET version of this article, see 301656.
Expand all | Collapse all

On This Page

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 article demonstrates how to create and manipulate a Word document from Visual C++ .NET and Microsoft Foundation Classes (MFC) by using Automation.

More information

Automation is a process that allows applications that are written in languages such as Visual C++ .NET to programmatically control other applications. Automation to Word allows you to perform actions such as creating new documents, adding text to documents, and formatting documents. With Word and other Microsoft Office applications, virtually all of the actions that you can perform manually through the user interface can also be performed programmatically by using Automation.

Word exposes this programmatic functionality through an object model. The object model is a collection of classes and methods that serve as counterparts to the logical components of Word. For example, there is an Application object, a Document object, and a Paragraph object, each of which contain the functionality of those components in Word. To access the object model from Visual C++ .NET, you can set a project reference to the type library.

Building the Automation Sample

  1. Follow the steps in the "Create an Automation Client" section of the following Microsoft Knowledge Base article to create a basic Automation client:
    307473 HOWTO: Use a Type Library for Office Automation from Visual C++ .NET
    In step 4 of the article, select the Microsoft Word type library. The default location for Word 2000 is C:\Program Files\Microsoft Office\Office\Msword9.olb, the default location for Word 2002 is C:\Program Files\Microsoft Office\Office10\Msword.olb, and the default location for Word 2003 is C:\Program Files\Microsoft Office\Office11\MSWord.olb. Select the following Word interfaces:
    • _Application
    • _Document
    • Cell
    • Cells
    • Column
    • Columns
    • Documents
    • Hyperlinks
    • MailMerge
    • MailMergeFields
    • Paragraphs
    • Range
    • Row
    • Rows
    • Selection
    • Shading
    • Table
    • Tables

    In step 6, add the following #include statements at the beginning of Autoprojectdlg.cpp:
    #include "CApplication.h"
    #include "CDocument0.h"
    #include "CDocuments.h"
    #include "CSelection.h"
    #include "CParagraphs.h"
    #include "CTable0.h"
    #include "CTables0.h"
    #include "CRange.h"
    #include "CColumns0.h"
    #include "CColumn.h"
    #include "CRow.h"
    #include "CRows.h"
    #include "CCells.h"
    #include "CCell.h"
    #include "CShading.h"
    #include "CHyperlinks.h"
    #include "CMailMerge.h"
    #include "CMailMergeFields.h"
    					
  2. In the IDD_AUTOPROJECT_DIALOG dialog box, right-click Run and select Add event handler. In the Event Handler Wizard, select the BN_CLICKED message type, and then click Add and Edit.
  3. Replace the following code
    void CAutoProjectDlg::OnBnClickedRun()
    ( With Visual Studio .NET 1.1 you may not be able to rename the button to anything other than "IDC_Button1". In that case 
    the method will be named CAutoProject::OnBnClickedButton1.)
    {
    	// TO DO: Add your control notification handler code here.
    }
    					
    with:
    void InsertLines(CSelection *pSelection, int NumLines)
    {
    	int iCount;
    
    	// Insert NumLines blank lines.
    	for (iCount = 1; iCount <= NumLines; iCount++)
    		pSelection->TypeParagraph();
    }
    
    void FillRow(CTable0 *pTable,int Row, CString Text1, 
    			 CString Text2, CString Text3, CString Text4)
    {
    	CCell oCell;
    	CRange oRange;
    
    	// Insert data into the specific cell.
    	oCell = pTable->Cell(Row,1);
    	oRange = oCell.get_Range();
    	oRange.InsertAfter(Text1);
    	oCell = pTable->Cell(Row,2);
    	oRange = oCell.get_Range();
    	oRange.InsertAfter(Text2);
    	oCell = pTable->Cell(Row,3);
    	oRange = oCell.get_Range();
    	oRange.InsertAfter(Text3);
    	oCell = pTable->Cell(Row,4);
    	oRange = oCell.get_Range();
    	oRange.InsertAfter(Text4);
    }
    
    void CreateMailMergeDataFile(CApplication *pApp,CDocument0 *pDoc)
    {
      CDocument0 oDataDoc;
      CMailMerge oMailMerge;
      CDocuments oDocs;
      CTables0 oTables;
      CTable0 oTable;
      CRows oRows;
      int iCount;
      COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR),
    				vtFalse((short)FALSE);
      
      // Create a data source that contains the field data at C:\DataDoc.doc.
      oMailMerge = pDoc->get_MailMerge();
      oMailMerge.CreateDataSource(COleVariant("C:\\DataDoc.doc"), 
            vtOptional,vtOptional,
            COleVariant("FirstName, LastName, Address,CityStateZip"),
            vtOptional, vtOptional,vtOptional,vtOptional,vtOptional);
      // Open the file to insert data.
      oDocs = pApp->get_Documents();
    
      //WORD9:
      oDataDoc = oDocs.Open(COleVariant("C:\\DataDoc.doc"), 
           vtOptional,vtOptional,vtOptional,vtOptional,
           vtOptional,vtOptional,vtOptional,vtOptional,
           vtOptional,vtOptional);
    
      //WORD10:
      //oDataDoc = oDocs.Open(COleVariant("C:\\DataDoc.doc"), 
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //	   vtOptional,vtOptional);
    
      //WORD11:
      //oDataDoc = oDocs.Open(COleVariant("C:\\DataDoc.doc"), 
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //     vtOptional,vtOptional,vtOptional,vtOptional,
      //	   vtOptional,vtOptional, vtOptional);
    
      oTables = oDataDoc.get_Tables();
      oTable = oTables.Item(1);
      oRows = oTable.get_Rows();
      for (iCount=1; iCount<=2; iCount++)  
        oRows.Add(vtOptional);
    
      // Fill in the data.
      FillRow(&oTable, 2, "Steve", "DeBroux", 
            "4567 Main Street", "Buffalo, NY  98052");
      FillRow(&oTable, 3, "Jan", "Miksovsky", 
            "1234 5th Street", "Charlotte, NC  98765");
      FillRow(&oTable, 4, "Brian", "Valentine", 
            "12348 78th Street  Apt. 214", "Lubbock, TX  25874");
      // Save and close the file.
      oDataDoc.Save();
      oDataDoc.Close(vtFalse,vtOptional,vtOptional);
    } 
    
    void CAutoProjectDlg::OnBnClickedRun() // It may be OnBnClickedButton1()
    {
    	CApplication oWord;
    	CDocuments oDocs;
    	CDocument0 oDoc;
    	CSelection oSelection;
    	CParagraphs oParagraphs;
    	CTables0 oTables;
    	CTable0 oTable;
    	CRange oRange;
    	CColumns0 oColumns;
    	CColumn oColumn;
    	CRows oRows;
    	CRow oRow;
    
    	CCells oCells;
    	CCell oCell; 
    	CShading oShading;
    	CHyperlinks oHyperlinks;
    	CMailMerge oMailMerge;
    	CMailMergeFields oMailMergeFields;
    
    	COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR),
    		        vtTrue((short)TRUE),
    				vtFalse((short)FALSE);
    	CString StrToAdd;
    
    	// Create an instance of Word.
    	if (!oWord.CreateDispatch("Word.Application")) {
    		AfxMessageBox("Word failed to start!");
    	} else {
    	// Set the visible property.
    	oWord.put_Visible(VARIANT_TRUE);
    	// Add a new document.
    	oDocs = oWord.get_Documents();
    
    	//WORD9:
    	oDoc = oDocs.Add(vtOptional,vtOptional,vtOptional);
    
    	//WORD10 & WORD11:
    	//oDoc = oDocs.Add(vtOptional,vtOptional,vtOptional,vtOptional);
    
    	CreateMailMergeDataFile(&oWord,&oDoc);
    
    	// Add the address header.
    	StrToAdd = "State University\r\nElectrical Engineering "  
    		       "Department";
    	oSelection = oWord.get_Selection();
    
    	oParagraphs = oSelection.get_Paragraphs();
    	oParagraphs.put_Alignment(1);  // 1 = wdAlignParagraphCenter  
    	oSelection.TypeText(StrToAdd);
    
    	InsertLines(&oSelection,4);
    
    	oParagraphs.put_Alignment(0);  // 0 = wdAlignParagraphLeft
    
    
    	oMailMerge = oDoc.get_MailMerge();
    	oMailMergeFields = oMailMerge.get_Fields();
    	oMailMergeFields.Add(oSelection.get_Range(),"FirstName");
    	oSelection.TypeText(" ");
    	oMailMergeFields.Add(oSelection.get_Range(),"LastName");
    	oSelection.TypeParagraph();
    	oMailMergeFields.Add(oSelection.get_Range(),"Address");
    	oSelection.TypeParagraph();
    	oMailMergeFields.Add(oSelection.get_Range(),"CityStateZip");
    
    	InsertLines(&oSelection,4);
    	// Set the paragraph alignment to Right justified.
    	oParagraphs = oSelection.get_Paragraphs();
    
    	oParagraphs.put_Alignment(2);  // 2 = wdAlignParagraphRight
    	// Insert the current date.
    
    	//WORD9:
    	oSelection.InsertDateTime(COleVariant("dddd, MMMM dd, yyyy"), 
    		 vtFalse,vtOptional);
    
    	//WORD10 & WORD11:
    	//oSelection.InsertDateTime(COleVariant("dddd, MMMM dd, yyyy"), 
    	//	 vtFalse,vtOptional,vtOptional,vtOptional);
    
    	InsertLines(&oSelection,2);
    
    	// Reset the justification to Justify.
    
    	oParagraphs = oSelection.get_Paragraphs();
    	oParagraphs.put_Alignment(3);  // 3 = wdAlignParagraphJustify
    
    	oSelection.TypeText("Dear ");
    	oMailMergeFields.Add(oSelection.get_Range(),"FirstName");
    	oSelection.TypeText(",");
    
    	InsertLines(&oSelection,2);
    
    	// Add the body of the message.
    	StrToAdd = "Thank you for your recent request for next "  
    	       "semester's class schedule for the Electrical "  
    	       "Engineering Department.  Enclosed with this letter "  
    	       "is a booklet containing all the classes offered "  
    	       "next semester at State University.  Several new "  
    	       "classes will be offered in the Electrical "  
       	       "Engineering Department next semester.  These "  
    	       "classes are listed below.";
    	oSelection.TypeText(StrToAdd);
    
    	InsertLines(&oSelection,2);
    	
    	// Add a new table with 9 rows and 4 columns.
    	oRange = oSelection.get_Range();
    	oTables = oDoc.get_Tables();
    	
    	//WORD9:
    	oTable = oTables.Add(oRange,9,4,vtOptional);
    
    	//WORD10 & WORD11:
    	//oTable = oTables.Add(oRange,9,4,vtOptional,vtOptional);
    
    	// Set the width of each column.
    	oColumns = oTable.get_Columns();
    
    	//BEGIN WORD9:
    	oColumn = oColumns.Item(1);
    	oColumn.put_Width(60.0,0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(2);
    	oColumn.put_Width(182.0,0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(3);
    	oColumn.put_Width(100.0,0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(4);
    	oColumn.put_Width(111.0,0); // 0 = wdAdjustNone
    	//END WORD9
    
            /*
    	//BEGIN WORD10 & WORD11:
    	oColumn = oColumns.Item(1);
    	oColumn.put_Width(60.0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(2);
    	oColumn.put_Width(182.0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(3);
    	oColumn.put_Width(100.0);  // 0 = wdAdjustNone
    	oColumn = oColumns.Item(4);
    	oColumn.put_Width(111.0);  // 0 = wdAdjustNone
    	//END WORD10 & WORD11
            */ 
    
    	// Set the shading for row 1 to wdGray25.
    	oRows = oTable.get_Rows();
    	oRow = oRows.Item(1);
    	oCells = oRow.get_Cells();
    	oShading = oCells.get_Shading();
    	oShading.put_BackgroundPatternColorIndex(16); // 16 = wdGray25
    
    	// Turn on bold formatting for the first row.
    	oRange = oRow.get_Range();
    	oRange.put_Bold(TRUE);
    
    	// Set the alignment for cell (1,1) to Center.
    	oCell = oTable.Cell(1,1);
    	oRange = oCell.get_Range();
    	oParagraphs = oRange.get_Paragraphs();
    	oParagraphs.put_Alignment(1);  // 1 = wdAlignParagraphCenter
    
    	// Fill in the class schedule data.
    	FillRow(&oTable,1,"Class Number","Class Name", 
    		"Class Time","Instructor");	
    	FillRow(&oTable,2, "EE220", "Introduction to Electronics II",  
    		"1:00-2:00 M,W,F", "Dr. Jensen");
    	FillRow(&oTable,3, "EE230", "Electromagnetic Field Theory I",  
    		"10:00-11:30 T,T", "Dr. Crump");
    	FillRow(&oTable,4, "EE300", "Feedback Control Systems",  
    		"9:00-10:00 M,W,F", "Dr. Murdy");
    	FillRow(&oTable,5, "EE325", "Advanced Digital Design",  
    		"9:00-10:30 T,T", "Dr. Alley");
    	FillRow(&oTable,6, "EE350", "Advanced Communication Systems",  
    		"9:00-10:30 T,T", "Dr. Taylor");
    	FillRow(&oTable,7, "EE400", "Advanced Microwave Theory",  
    		"1:00-2:30 T,T", "Dr. Lee");
    	FillRow(&oTable,8, "EE450", "Plasma Theory",  
    		"1:00-2:00 M,W,F", "Dr. Davis");
    	FillRow(&oTable,9, "EE500", "Principles of VLSI Design",  
    		"3:00-4:00 M,W,F", "Dr. Ellison");
    
    	// Go to the end of the document.
    	oSelection.GoTo(COleVariant((short)3), // 3 = wdGoToLine
    	COleVariant((short)-1),vtOptional,vtOptional);  // -1 = wdGoToLast
    
    	InsertLines(&oSelection,2);
    
    	// Add closing text.
    	StrToAdd = "For additional information regarding the "  
                 "Department of Electrical Engineering, "  
                 "you can visit our website at ";
    	oSelection.TypeText(StrToAdd);
    
    	// Add a hyperlink to the home page.
    	oHyperlinks = oSelection.get_Hyperlinks();
    
            oHyperlinks.Add(oSelection.get_Range(),
                COleVariant("http://www.ee.stateu.tld"),vtOptional,
                vtOptional,vtOptional,vtOptional);
    
    	// Finish adding closing text.
    	StrToAdd = ".  Thank you for your interest in the classes "  
                 "offered in the Department of Electrical "  
                 "Engineering.  If you have any other questions, "  
                 "please feel free to give us a call at (999) "  
                 "555-1212.\r\n\r\n"  
                 "Sincerely,\r\n\r\n"  
                 "Kathryn M. Hinsch\r\n" 
                 "Department of Electrical Engineering\r\n";
    	oSelection.TypeText(StrToAdd);
    
    	// Perform mail merge.
    	oMailMerge.put_Destination(0); // 0 = wdSendToNewDocument
    	oMailMerge.Execute(vtFalse);
    
    	// Close the original form document.
    	oDoc.put_Saved(TRUE);
    	oDoc.Close(vtFalse,vtOptional,vtOptional); 
    	}
    }
    					
    NOTE: As written, this code uses the Word 9.0 object library. When you added references to your project, if you selected the Word 10.0 object library or Word 11 instead of the Word 9.0 object library, search the code for comments that contain "//WORD10" or "//WORD11, or //WORD10 & WORD11and uncomment the line or lines of code to which the comment refers. Likewise, search the code for comments that contain "//WORD9" and comment the line or lines of code to which the comment refers.

  4. Be sure to implement step 5. in the list under the heading "Create Automation Client" from the article mentioned above, i.e.
    Article ID 307473 "HOWTO: Use a Type Library for Office Automation from Visual C++ .NET.
  5. Press F5 to build and run the program.
  6. Click Run. The Automation client starts Word and creates a set of form letters from a mail merge.

References

For more information, see the following Microsoft Developer Network (MSDN) Web site:
Microsoft Office Development with Visual Studio
http://msdn2.microsoft.com/en-us/library/aa188489(office.10).aspx

Properties

Article ID: 308338 - Last Review: June 19, 2014 - Revision: 6.0
Applies to
  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft Word 2000
  • Microsoft Word 2002
  • Microsoft Visual C++ .NET 2003 Standard Edition
  • Microsoft Visual Studio .NET 2003 Professional Edition
Keywords: 
kbautomation kbhowto KB308338

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com