0
votes

I'm trying to automate mailmerge using a .net program. There's a one page letter in word document addressed to a particular person with a mailmerge field by name 'Person'. Our database has got multiple persons and each person name has to go into a copy of the letter. We want the one-page letters to be concatenated one after the other. Currently this code tries to use two persons with - name1 & name2. The code below opens a separate instance of word for every person name.

        object oMissing = System.Reflection.Missing.Value;
        //CREATING OBJECTS OF WORD AND DOCUMENT
        Word.Application oWord = new Word.Application();
        Word.Document oWordDoc = new Word.Document("C:\\Test\\AddressTemplate.docx");


        //SETTING THE VISIBILITY TO TRUE
        oWord.Visible = true;
        //THE LOCATION OF THE TEMPLATE FILE ON THE MACHINE
        Object oTemplatePath = "C:\\Test\\AddressTemplate.docx";

        oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);

        foreach (Microsoft.Office.Interop.Word.Field field in oWordDoc.Fields)
        {
            if (field.Code.Text.Contains("Person"))
            {
                field.Select();
                oWord.Selection.TypeText(name1);
            }
        }

        oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);

        foreach (Microsoft.Office.Interop.Word.Field field in oWordDoc.Fields)
        {
            if (field.Code.Text.Contains("Person"))
            {
                field.Select();
                oWord.Selection.TypeText(name2);
            }
        }

Question: How can I change the code to open just one instance of word, fill in the mailmerge field and concatenate one letter at the end of the other?

2
In this code, you are not adding "instances" of Word - you are adding a document each time you do Documents.Add. To match your description of your requirement, what you really need to do is change your second ".Add" use something like .Insertfile to insert a new copy of template at the end of the existing document, then replace the next "Person" field (unless you take steps to narrow the range you are searching, that will become slower as you add template copies). But the standard MailMerge already does what you are describing - it might be better to describe what you need to do differently.user1379931
Thanks, Bibadia. Yes, I see that ".Add" is adding a document each time. How do I insert a new copy of the template at the end of the existing document, in order to replace the next "Person" field? The standard mailmerge does this. However, I am trying to automate this functionality from a c# program. In my program, on the click of a button, persons will be fetched from the database(say 100). And then this template is replicated 100 times to fill the name of the person each time, all in the same document , concatenated one after the other. Hope the goal is clear now. Look forward to inputs.Vaishali Bulusu
Such stuff is easily researched, and that is the expectation here. SOme hints, though: you can't insert a document into itself. You should probably create a new one, then use InsertFile (as I mentioned) to append each copy at the end. But the point I am making is that if your "set of persons" can be retrieved via a SQL query from an external data source, all you need do is issue a MailMerge.OpenDataSource with that query, set the merge type to be Letters and the Destination to be a new Document, execute the merge and take it from there. With a proper database you can create a temp table...user1379931
Thanks, Bibabia. Using the article: support.microsoft.com/kb/301659 and replacing the template file with mine. I got the desired result.Vaishali Bulusu

2 Answers

1
votes

If you call new Word.Application you're creating a new instance, if what you want is to create a new instance if there is none, but reuse one if there is already one open you can do the following:

        Application app;
        try
        {
            app = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
        }
        catch
        {
            app = new Application();
        }

Based on your comment i think you actually only have 1 instance of word open, it just opens both documents in different Windows (but a single application). Windows aren't the same as applications.

If you want it all in a single window you could reuse the previous document or else close it before you open a new one

0
votes

Ronan's code above did the trick for me. I was doing new Application() every time, adding WINWORD instances (I know, should've known better). I speak both C# and VB, but here's the VB version I used in this project:

        ' Use same winword instance if there; if not, create new one
    Dim oApp As Application
    Try
        oApp = DirectCast(Runtime.InteropServices.Marshal.GetActiveObject("Word.Application"), Application)
    Catch ex As Exception
        ' Word not yet open; open new instance
        Try
            ' Ensure we have Word installed
            oApp = New Application()
        Catch eApp As Exception
            Throw New ApplicationException(String.Format("You must have Microsoft Word installed to run the Top Line report"))
        End Try
    End Try
    oApp.Visible = True