Microsoft Word Automation Class

Introduction

Often, the main challenge in developing C++ automation solutions for Microsoft Office is the lack of detailed technical documentation for Office's OLE interface. At the same time, ample automation information for Visual Basic applications can be acquired by using Office macros and the Office Help Wizard. It would be natural to come with a tool that can be used to "translate" or "convert" Office's macros into code executable from C++. This approach was previously implemented in an MSVC Excel automation project and is described in the recent article on CodeGuru (see "Microsoft Excel Automation Class" by V. Golovlev).

In this article, the approach is modified for executing Microsoft Word functions from an MSVC application. The CWordAutomation class that implements this approach includes a small collection of OLE functions and also contains examples of code for some MS Office operations. Also, a CEzWordAutomation wrapper class is provided; it exposes a set of methods from CWordAutomation to perform basic access to MS Word documents.

The MSWordDemo project provides an example of using CWordAutomation and CEzWordAutomation to read and write text from and to MS Word documents, open and save Word files, and use the Word spell function to check word spelling in an MSVC application.

The CWordAutomation has two groups of methods: 1) to access OLE interface, and 2) to implement selected macros. The most essential methods from the first group include WordDispatch(...), AddArgumentCString(...), AddArgumentInt2(...), and ClearAllArgs(). The second group includes an example of implementating Word macros to create a new Word document, adding and reading text from the Word document, and opening/saving Word files:

  • CreateBlankDocument()
  • AppendText(CString szText)
  • GetLine(int nLine)
  • OpenWordFile(CString szFileName)
  • SaveWordFileAs(CString szFileName)
  • and some others.

The MSWordDemo project gives an example of using CWordAutomation and CEzWordAutomation. In this project, a Word document is viewed as a collection of lines (strings) that can be read from or written to the document. Each Word line can be accessed in the document by its line number (see CWordAutomation::GetLine(int nLine)). The total number of lines in the document is retrieved by GetLinesCount(). The user can add a new string (line) to the document by using the AppendText(...) method. The new text is appended at the end of the document. To move a large amount of data and copy text between Word documents, the CopyLinesToClipboard(...) method is available. Text is copied to a clipboard and subsequently can be pasted into the document by using the PasteText(...) method.

A Word application can be started in one of two modes: with the user interface exposed (bVisible = TRUE) or hidden (bVisible = FALSE). In the first mode, the document and Word interface are visible and available to the user. In the second mode (bVisible = FALSE), Word runs in the background with no interface exposed, but Word functions can be executed by MSVC code.

Adding a Word Automation Function to a MSVC Project

Add CWordAutomation and CEzWordAutomation classes to your project (see also "Microsoft Excel Automation Class" on how to add automation classes to the project). To start a new Word document, use this code in your application:

CEzWordAutomation MsWord;

To start Word in the background with no interface exposed to the user:

CEzWordAutomation MsWord(FALSE);

To release the document and close the Word application, call:

MsWord.ReleseWord.

To open a Word file and get/create szFileName, call:

MsWord.OpenWordFile(szFileName);

Also, see the WordDemo project for examples of implementating the CWordAutomation and CEzWordAutomation classes.

The WordDemo project provides examples of using the CWordAutomation and CEzWordAutomation classes to start a new Word document and add new text to the document by entering a single line (AppendText(...)) or by copying multiple lines by the copy/paste clipboard function. Other examples include methods to open and save Word files. Also included in this project is an example of using Word's spell engine to check word spelling from a C++ application.

To run the WordDemo application, Microsoft Word must be installed on your computer!

To run the demo program, compile and run the project.The WordDemo interface has two sections: one to demonstrate Word functions and the other to demonstrate spell checking using the Word speller:

Functions of the DemoProject Buttons

  • "Open New Word Doc": Opens a new Word document and enters text using the AppendText(...) method. The Word interface is visible.
  • "Paste to Word Doc": Opens a new Word document and enters text using clipboard functions CopyTextToClipboard(...) and PasteText(...). The Word interface is visible.
  • "Save Word File": start Word in background (i.e., interface is not visible), enter text to the document, open file dialog and save Word file.
  • "Open Word File": Starts a Word application, opens file dialog and the Word file. The Word interface is visible.
  • "Get Text": Starts a Word application in the background, opens the file dialog, reads the number of lines in the Word file selected by user, reads the first and last lines in the file, releases the Word application, and reports the number of lines in the file and contents of the first and last line to the user.
  • "Exit": Releases WordDemo.
  • "Spell check": Uses Word's spell engine to check spelling of the word the user entered. Word is started in the background mode after the user enters the word and clicks the "Check spelling" button. If Word's speller reports one or more alternative spellings, the very first entry from the collection of the alternative spellings replaces the word in the Edit box. After completion, the Word application is released.

Writing Code to Add a New Word Function

The first step is to write a macro that performs the user's function. For instance, the following macro returns the first entry from a collection of alternative spellings for the user's word szUserWord:

szNewSpelling = Application.GetSpellingSuggestions(Word:=
   szUserWord).Item(Index:=1).Name
Note: To use this in MSVC method, the parameters MUST be named whenever possible. In a VB project, this macro works just fine:
Application.GetSpellingSuggestions(szUserWord).Item(1)

But, to use it in MSVC, it has to be used with all parameters spelled out:

Application.GetSpellingSuggestions(Word:=
   szUserWord).Item(Index:=1).Name

The next step is to add a new method to the CWordAutomation class and write the code. Each macro object, for instance MyMacroObject, is called in MSVC by a block of code as shown in the following code snippet:

{ClearAllArgs();
if (!WordInvoke(vargParentObject.pdispVal,
   L" MyMacroObject ", &vargMyChildObject, DISPATCH_METHOD, 0))
   return FALSE;}

Observe the use of vargParentObject B and vargMyChildObject here. In this example, MyMacroObject is the child of the ParentObject, and it has also its own child object MyChildObject: ParentObject.MyMacroObject.MyChildObject

If MyMacroObject requires a parameter to be used: MyParameter:=wdParamValue, the MSVC code has to be modified to this:

{ClearAllArgs();
AddArgumentInt2(L" MyParameter ", 0, wdParamValue);
if (!WordInvoke(vargParentObject.pdispVal, L" MyMacroObject ",
   &vargMyChildObject, DISPATCH_METHOD, 0))B return FALSE;}

In the above speller's example, the macro uses four objects. The corresponding code will consist of three blocks of {ClearAllArgs... WordInvoke}(in other words, N-1 of the number of objects used, see CWordAutomation::SpellWord(CString szWord) for details). If the macro returns a value, that value can be retrieved from the VARIANTARG returned by the last WordInvoke(...) call. To see a detailed example of retrieving value from a macro, please refer to the CWordAutomation::GetLine(int nLine) method in the MSWordDemo project.

Additional examples of MSVC codes for Office macros can be found in discussions posted on CodeGuru for "Microsoft Excel Automation Class."

The last step is to add the corresponding new method to EzWordAutomation. In most cases. it consists of a single line of code (see EzWordAutomation methods).

Thank you! Your comments are highly valuable!



About the Author

Val Golovlev

Physicist, now is working in life science research. Fan of C++ for six years; have used C++ in various projects for interfacing instruments, data processing; image acquisition and analysis, internet applications, databases, etc.

Downloads

Comments

  • How do export pdf file in word doc?

    Posted by amber on 09/15/2014 06:29am

    how do export the pdf file in word doc

    Reply
  • How do I insert a merge field object

    Posted by Charles Aghedo on 09/19/2012 01:23pm

    Using your Microsoft Word Automation Class, id there a way I can insert a mail merge field into the Word document?

    Reply
  • Thanks a lot

    Posted by vaibhavbvp on 09/04/2012 04:17am

    thanks for such a nice piece of work... i have a small query how to find the page number of a image??e.g suppose i have a document of 10 pages,which contains image on page 3,5,8.. now the problem is how can we know about these page numbers???

    Reply
  • Extracting table data present in a section of MS word

    Posted by gb on 08/03/2012 03:48am

    How to get data from a table present in section of word doc?

    Reply
  • How to get number of lines per page?

    Posted by dpreznik on 02/24/2011 09:54am

    Deer Val, Could you please tell me how I can get number of lines of a random page? Or at worst, how I can get number of document's pages to divide the number of lines in the document by it and get the average number of lines per page? Thanks.

    • Figured it out

      Posted by dpreznik on 02/24/2011 10:37am

      Never mind, I figured it out based on your GetLinesCount() method. Thanks!

      Reply
    Reply
  • how to change word doc's background color?

    Posted by ship1912 on 01/28/2011 04:20am

    Thank you!

    Reply
  • Tracking SaveAs events in MS Word using Automation class

    Posted by dinakara on 08/26/2010 05:56am

    Dear Val Golovlev
     
      Thanks for for posting two interesting articles on  Automation Class of Microsoft Word and Excel in Codeguru.  After going through your article, I was wondering, would it be possible to track certain events like Save As events in Microsoft Office word/Excel/powerpoint  from my MSVC application.
    
    Basically, I would like to trace the source and Destination Paths of the files that is being saved using "Save As" menu option in the MS Word/Excel from my MSVC application 
    
    
    I appreciate your valuable suggestions/ help or sample code...
    
    
    Thanks in advance
    
    Dinakara K

    Reply
  • how to print the word doc?

    Posted by Mike Pliam on 10/05/2009 11:28pm

    Wonderful article.  Cannot thank you enough.  I need to print an MsWord doc using your method.  I have been unable to do so.  Get APPCRASH.
    
    Here's my attempt to print using the Ms Word macro:
    [code]
    // Print the current document using MS Word macro:
    // Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
    // wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
    // ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
    // False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
    // PrintZoomPaperHeight:=0
    BOOL CWordAutomation::Print()
    {
    	if(NULL  == m_pdispWordApp)
    		return FALSE;
    
    	VARIANTARG vargPrintOut;
    
    	// MsWord constants (see: http://msdn.microsoft.com/en-us/library/aa211923(office.11).aspx)
    	int wdPrintAllDocument = -1;		// MsWord constant
    	int wdPrintDocumentContent = -1;	// MsWord constant
    	int wdPrintAllPages = -1;			// MsWord constant
    
    	ClearAllArgs();
    	if (!WordInvoke(m_pdispWordApp, L"Application", &vargPrintOut, DISPATCH_PROPERTYGET, 0))
    		return FALSE;
    
    	ClearAllArgs();
    	AddArgumentCString(L"FileName", 0, "");
    	AddArgumentInt2(L"Range", 0, wdPrintAllDocument);
    	AddArgumentInt2(L"Item", 0, wdPrintDocumentContent);
    	AddArgumentInt2(L"Copies", 0, 1);
    	AddArgumentCString(L"Pages", 0, "");
    	AddArgumentInt2(L"PageType", 0, wdPrintAllPages);
    	AddArgumentBool(L"ManualDuplexPrint", 0, FALSE);
    	AddArgumentBool(L"Collate", 0, TRUE);
    	AddArgumentBool(L"Background", 0, TRUE);
    	AddArgumentBool(L"PrintToFile", 0, FALSE);
    	AddArgumentInt2(L"PrintZoomColumn", 0, 0);
    	AddArgumentInt2(L"PrintZoomRow", 0, 0);
    	AddArgumentInt2(L"PrintZoomPaperWidth", 0, 0);
    	AddArgumentInt2(L"PrintZoomPaperHeight", 0, 0);
    
    	if (!WordInvoke(vargPrintOut.pdispVal, L"PrintOut", NULL, DISPATCH_METHOD, 0))
    		return FALSE;
    
    	return TRUE;
    
    }// Print(CString szFilename)
    [/code]
    
    Please help :)

    • Re: How to print document?

      Posted by golovlev on 10/06/2009 05:43pm

      Mike, you are pretty much on target. 
      Please notice m_pdispWordApp points to "Application" object, so there is no need in vargPrintOut in your code. Also, there is no need to set up default variables unless you are planing to change them. Below two examples of print methods are given. The first and the  simplest print method uses MS Word default settings for printing. The second method allows to set the number of copies and select pages to print. Here they are:
       
      //Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
      //        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
      //        ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
      //        False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
      //        PrintZoomPaperHeight:=0
      
      BOOL CWordAutomation::PrintDoc()
      {
      	if(NULL  == m_pdispWordApp)
      		return FALSE;
      
      	ClearAllArgs();
      	if (!WordInvoke(m_pdispWordApp, L"PrintOut", NULL, DISPATCH_METHOD, 0))
      		return FALSE;
      
      	return TRUE;
      }
      
      //This method allows to set the number of copies and selecti pages to print 
      BOOL CWordAutomation::PrintDoc(int nCopies, CString szSelectedPages)
      {
      	if(NULL  == m_pdispWordApp)
      		return FALSE;
      
      	ClearAllArgs();
      	AddArgumentInt2(L"Copies", 0, nCopies);
      	if(!szSelectedPages.IsEmpty())
      		AddArgumentCString(L"Pages", 0, szSelectedPages);
      	if (!WordInvoke(m_pdispWordApp, L"PrintOut", NULL, DISPATCH_METHOD, 0))
      		return FALSE;
      
      	return TRUE;
      }

      Reply
    Reply
  • how to export/extrace image in word doc?

    Posted by jauming on 04/12/2009 09:28am

    how to export/extrace image in word doc?
    thanks

    • Re: how to export/extrace image in word doc

      Posted by golovlev on 04/13/2009 09:03am

      There are two ways to do it:
      1. Copy image to clipboard and past it by executing: Application.Selection.Paste. For more information see copying text by CWordAutomation::PasteText(...) and incerting picture to Excel worksheet in Excel automation class at http://www.codeguru.com/cpp/data/mfc_database/microsoftexcel/article.php/c11745/
      2. Use "Insert picture from File" by executing: Application.Selection.InlineShapes.AddPicture FileName:= szFileName.  User must provide file name for the image file (jpg, tif, etc.) 
      Here is an example: 
      //Insert picture from file using MS Word Insert Picture from File macro:
      //Application.Selection.InlineShapes.AddPicture FileName:= szFileName
      BOOL CWordAutomation::InsertPicture(CString szFileName)
      {
      	if(NULL  == m_pdispWordApp)
      		return FALSE;
      	//Insert picture at the end of the document
      	GoToEndOfDocument();
      	VARIANTARG vargSelection, vargInlineShapes, varg1;
      	//Get Application.Selection
      	ClearAllArgs();
      	if (!WordInvoke(m_pdispWordApp, L"Selection", &vargSelection, DISPATCH_PROPERTYGET, 0))
      		return FALSE;
      //Get Application.Selection.InlineShapes	
      ClearAllArgs();
      	if (!WordInvoke(vargSelection.pdispVal, L"InlineShapes", &vargInlineShapes, DISPATCH_PROPERTYGET, 0))
      		return FALSE;
      	//Execute Application.Selection.InlineShapes.AddPicture FileName:= szFileName
      	ClearAllArgs();
      	AddArgumentCString(L"FileName", 0, szFileName);
      	if (!WordInvoke(vargInlineShapes.pdispVal, L"AddPicture", &varg1, DISPATCH_METHOD, 0))
      		return FALSE;
      
      	return TRUE;
      }

      Reply
    Reply
  • Thank you!

    Posted by Sebastien B on 02/05/2008 09:19am

    Thank you Mister Golovlev! I've been looking for this kind of COM wrapper for years! What is missing is an event sink connected to callbacks, or virtual methods (to detect when a document is closed for example). Anyway thank you again for your work. Sebastien

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds