none
Word Mail Merge - How to save result ? RRS feed

  • Question

  • Hi, I have a problem saving the result of a Mail Merge to disk.

    My code:

    Object[] objParam = new Object[1];
    Type WordType;
    Object WordApp = null;
    Object WordDoc = null;
    Object WordMailMerge = null;
    Object WordSource = null;
    
    WordType = Type.GetTypeFromProgID("Word.Application");
    WordApp = Activator.CreateInstance(WordType);
    WordDoc = WordApp.GetType().InvokeMember("Documents", System.Reflection.BindingFlags.GetProperty, null, WordApp, null);
    
    objParam[0] = MyDot;
    WordDoc = WordDoc.GetType().InvokeMember("Add", System.Reflection.BindingFlags.InvokeMethod, null, WordDoc, objParam);
    
    // MAIL MERGE	
    WordMailMerge = WordDoc.GetType().InvokeMember("MailMerge", System.Reflection.BindingFlags.GetProperty, null, WordDoc, null);
    
    objParam[0] = MyData;
    WordSource = WordMailMerge.GetType().InvokeMember("OpenDataSource", System.Reflection.BindingFlags.InvokeMethod, null, WordMailMerge, objParam);
    WordMailMerge.GetType().InvokeMember("Execute", System.Reflection.BindingFlags.InvokeMethod, null, WordMailMerge, null);
    
    
    // Close DOT file
    objParam[0] = 0; //wdDoNotSaveChange
    WordDoc.GetType().InvokeMember("Close", System.Reflection.BindingFlags.InvokeMethod, null, WordDoc, objParam);
    
    // Show Word
    objParam[0] = true;
    WordType.InvokeMember("Visible", System.Reflection.BindingFlags.SetProperty, null, WordApp, objParam);

    Now Word is visible with the result of the Mail Merge, but if I try to save the DOC, I need to specify the path, while I want to save it to disk before showing so that Word saves automatically to the pre-existent path.

    How can I do ?

    • Changed type Nazza Tuesday, November 20, 2012 4:08 PM this is a question
    Tuesday, November 20, 2012 4:07 PM

Answers

  • Hi Nazza

    You're invoking the method on the wrong object. The MailMerge object has no SaveAs method - it can be used only on a Document object.

    It would, indeed, be useful if executing MailMerge would return a Document object. Unfortunately, that is not the case. But since your code creates a new instance of Word and closes the main merge document, there should be only one document left that's open in the WordApplication. So you can use the ActiveDocument property to return that document, then save it. Something like this:

                // Close DOT file
                objParam[0] = 0; //wdDoNotSaveChange
                WordDoc.GetType().InvokeMember("Close", System.Reflection.BindingFlags.InvokeMethod, null, WordDoc, objParam);
    
                object mergeDoc = WordApp.GetType().InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, WordApp, null);
                objParam[0] = @"C:\Test\TestMergeLateBinding.docx";
                mergeDoc.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, mergeDoc, objParam);
    
                // Show Word
                objParam[0] = true;
                WordType.InvokeMember("Visible", System.Reflection.BindingFlags.SetProperty, null, WordApp, objParam);


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by Nazza Wednesday, November 21, 2012 2:37 PM
    Wednesday, November 21, 2012 2:20 PM
    Moderator

All replies

  • Hi Nazza,

    Thanks for posting in the MSDN Forum.

    In my opinion, that you can invoke the Documents.Save(Type.missing,Type.missing) method to save your document due to you don't have a clearly goal for the Save method in your description. This method will prompt a SaveAs dialog to finish Save method. I don't know whether it can hit your goal. I tried to retrieve Document entry from Document via Reflection to approach your goal, however it beyond my ability.

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, November 21, 2012 6:02 AM
    Moderator
  • Hi Tom, thank you for your reply.

    I don't want to prompt a SaveAs dialog, this is my main goal, so I thought to save the document before opening. In this way Word doesn't ask for a path while closing and saving.


    • Edited by Nazza Wednesday, November 21, 2012 9:38 AM
    Wednesday, November 21, 2012 9:36 AM
  • HI Nazza

    If you use the SaveAs method you can save to a file on disk without displaying a prompt - your code decides on the file path and name.

    Please note that, since you're not working with the VSTO technology I'm moving the discussion to the Word for Developers forum.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, November 21, 2012 10:49 AM
    Moderator
  • HI Nazza

    If you use the SaveAs method you can save to a file on disk without displaying a prompt - your code decides on the file path and name.

    Please note that, since you're not working with the VSTO technology I'm moving the discussion to the Word for Developers forum.


    Cindy Meister, VSTO/Word MVP, my blog

    Hi, this is exactly what I mean !

    However I don't know the syntax the save the MergeMail result to disk.

    Shouldn't be something like:

    objParam[0] = MyPath;
    WordMailMerge.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, WordMailMerge, objParam);

    I receive an exception

    C# Reflection - "(Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"

    PS: thank you for moving the thread.
    • Edited by Nazza Wednesday, November 21, 2012 11:13 AM
    Wednesday, November 21, 2012 11:11 AM
  • Hi Nazza

    You're invoking the method on the wrong object. The MailMerge object has no SaveAs method - it can be used only on a Document object.

    It would, indeed, be useful if executing MailMerge would return a Document object. Unfortunately, that is not the case. But since your code creates a new instance of Word and closes the main merge document, there should be only one document left that's open in the WordApplication. So you can use the ActiveDocument property to return that document, then save it. Something like this:

                // Close DOT file
                objParam[0] = 0; //wdDoNotSaveChange
                WordDoc.GetType().InvokeMember("Close", System.Reflection.BindingFlags.InvokeMethod, null, WordDoc, objParam);
    
                object mergeDoc = WordApp.GetType().InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, WordApp, null);
                objParam[0] = @"C:\Test\TestMergeLateBinding.docx";
                mergeDoc.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, mergeDoc, objParam);
    
                // Show Word
                objParam[0] = true;
                WordType.InvokeMember("Visible", System.Reflection.BindingFlags.SetProperty, null, WordApp, objParam);


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by Nazza Wednesday, November 21, 2012 2:37 PM
    Wednesday, November 21, 2012 2:20 PM
    Moderator
  • Thank you Cindy, it worked perfectly !
    Wednesday, November 21, 2012 2:48 PM