Friday, June 24, 2011

Word Automation Using C# and Visual Studio 2010

I have been engaged with Word Automation using C# for some time and I thought to share the basic steps of doing it. Word Automation is simply generating Word Documents programmatically. Lets take a simple scenario. Let's say that you have a common document which you want to address to different personals. And you are storing Person's details in an database. Since I want this example to be simple, I will assume that there will not be two Persons which have the same name which inheritingly means I can say the Person's name is unique.

So in my database I will have a Table called 'RECEIVER_DETAILS' which has following Fields.
  1. RECEIVER_TITLE
  2. RECEIVER_NAME
  3. ADDRESS_LINE1
  4. ADDRESS_LINE2
  5. ADDRESS_LINE3
  6. ADDRESS_LINE4
I have created a simple Windows Forms Application with a simple Windows Form like this.


Now what I want is when I typed the Name and press enter other fields should be automatically filled. Since this post is mainly about Word Automation I will not describe how to do that, and I think for you all it's a simple piece of work. Now what I want is when I clicked Generate button I want all address details to be written back in a Word Document. And that is a simle Word Automation. Since it's always better to use Step by Step approach, I will start from Step 01.

Step 01.

Open a Microsoft Word Document. I am using Microsoft Office 2010.


Now go to Insert tab, under that go to Quick Parts and under that click Field.


Then the following screen will appear.


From Categories drop down list select Mail Merge.


And from Mail Merge select MergeField, under Field Name type "To Title" and select "(none)" as Format.


Click OK and you will get something like this.


Likewise I have created some fields to store Person's address details.


Now you should save this document as a Word Template.


Now you have successfully created a Word Template and this template will be used to create new documents with Person's address details.

Step 02.

Now it's the programming part. I assume you all can write the part of code to fill text boxes, when you have typed the Name and hit Enter. Now open the solution which you have created the Windows Form in and add the following references to the Project.
  • Microsoft.Office.Tools.Word
  • Microsoft.Office.Interop.Word
In the Form code, add following lines to the using section.

using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Tools.Word;
using Microsoft.Office.Interop.Word;

Declare global type objects before Form Constructor.

Object oMissing = System.Reflection.Missing.Value;

// if you want your document to be saved as pdf
Object format = Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF;

Word.Application oWord = new Word.Application();
Word.Document oWordDoc = new Word.Document();

In btnGenerate_Click event write the following.

// path of the Word Template document
Object oTemplatePath = @"C:\Users\Jaliya\Desktop\Temp\Word Automation.dotx";
oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
int iFields = 0;

foreach (Word.Field myMergeField in oWordDoc.Fields)
{
     iFields++;
     Word.Range rngFieldCode = myMergeField.Code;
     String fieldText = rngFieldCode.Text;

     if (fieldText.StartsWith(" MERGEFIELD"))
     {
          Int32 endMerge = fieldText.IndexOf("\\");
          Int32 fieldNameLength = fieldText.Length - endMerge;
          String fieldName = fieldText.Substring(11, endMerge - 11);
          fieldName = fieldName.Trim();
          if (fieldName == "\"To Title\"")
          {
                myMergeField.Select();
                // check whether the control text is empty
                if (cboTitle.Text == "")
                {
                      oWord.Selection.TypeText(" ");
                }
                else
                {
                      oWord.Selection.TypeText(cboTitle.Text);
                }
          }
          if (fieldName == "\"To Name\"")
          {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtName.Text == "")
                {
                      oWord.Selection.TypeText(" ");
                }
                else
                {
                      oWord.Selection.TypeText(txtName.Text);
                }
         }
         if (fieldName == "\"To Address Line 1\"")
         {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtAddressLine1.Text == "")
                {
                      oWord.Selection.TypeText(" ");
                }
                else
                {
                      oWord.Selection.TypeText(txtAddressLine1.Text);
                }
         }
         if (fieldName == "\"To Address Line 2\"")
         {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtAddressLine2.Text == "")
                {
                     oWord.Selection.TypeText(" ");
                }
                else
                {
                     oWord.Selection.TypeText(txtAddressLine2.Text);
                }
          }
          if (fieldName == "\"To Address Line 3\"")
          {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtAddressLine3.Text == "")
                {
                     oWord.Selection.TypeText(" ");
                }
                else
                {
                     oWord.Selection.TypeText(txtAddressLine3.Text);
                }
          }
          if (fieldName == "\"To Address Line 4\"")
          {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtAddressLine4.Text == "")
                {
                     oWord.Selection.TypeText(" ");
                }
                else
                {
                     oWord.Selection.TypeText(txtAddressLine4.Text);
                }
          }
     }
}

string s = @"C:\Users\Jaliya\Desktop\Temp";

// if you want your document to be saved as pdf
object savePath = s + "\\Temp Word.pdf";

oWordDoc.SaveAs(ref savePath, ref format, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);


// if you want your document to be saved as docx
object savePath = s + "\\Temp Word.docx";

oWordDoc.SaveAs(ref savePath, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

In the FormClosing event add the following code. If you are not using this part in the Form Closing event, after generating the document if you check Processes under Task Manager, you will see a Process called"WINWORD.EXE". To close that Process I am writing this tiny piece of code.

object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
oWordDoc.Close(ref doNotSaveChanges, ref oMissing, ref oMissing);
oWord.Quit(ref doNotSaveChanges, ref oMissing, ref oMissing);


After clicking "Generate" button, here is the screen shot of what I got. I created a ".pdf" document.




And that's the basics of Word Automation Using C# and Visual Studio 2010. Feel free to ask any question and to give me your feedback.

Happy Coding.

Regards,
Jaliya

1 comment: