2 Replies - 971 Views - Last Post: 17 December 2013 - 01:27 PM Rate Topic: -----

#1 AnalyticLunatic   User is offline

  • D.I.C Lover

Reputation: 239
  • View blog
  • Posts: 1,073
  • Joined: 25-June 12

Hide template Word Doc while displaying executed Word Doc?

Posted 13 December 2013 - 09:18 AM

In my code below, I start up 2 word instances. One instance I set to my "template", the file for a Mail Merge document that hasn't been run. The other Instance is for a blank document I will use to copy/paste each page from the executed mail merge document into, and then individually save the document.

I make both Word instances visible, then open up my "template" and the blank document for individual saving using each instance. Next I open the Data Source for the MailMerge operation.

Once I Execute the Mail Merge operation, I am left with 3 documents visible on my screen:

  • The original "template" for the Mail Merge
  • The blank document I was using for individual file saving when copy/pasting the Mail Merge sections.
  • The executed mail merge document titled "Form Letters1".


My code processes a while() loop going through and copies each section of "Form Letters1" and pasting it into my document titled "Newdocument.doc". My foreach() loop then updates a database tracking table before generating the filename of "Newdocument.doc" and saving it.

Once the individual section from "Form Letters1" has been saved, I select everything in the newly saved document and clear it out for processing the next section in "Form Letters1".

When all individual sections of "Form Letters1" have been copy/pasted and saved as their own document I hide my "Newdocument.doc" with oNewWord.Visible = false;.

My issue here is that on screen I am still showing both the the "template" document for the Mail Merge, and also the "Form Letters1" executed Mail Merge document.

Is there any way for me to hide the template and keep "Form Letters1" visible? I tried setting oWord.Visible = false; before my message box appears, but that hides both the "template" AND "Form Letters1" (the executed Mail Merge document I need to let users review and print).

public void MergeSplitAndReview()
    {
        try
        {
            //MergeDocLibrary mdl = new MergeDocLibrary();
            //mdl.mergeDocument(docSource, docLoc);

            // Mail Merge Template
            Word.Application oWord = new Word.Application();
            Word.Document oWrdDoc = new Word.Document();
            // New Document Instance
            Word.Application oNewWord = new Word.Application();
            Word.Document oNewWrdDoc = new Word.Document();

            object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;

            // Documents must be visible for code to Activate()
            oWord.Visible = true;
            oNewWord.Visible = true;

            Object oTemplatePath = docLoc;
            Object oMissing = System.Reflection.Missing.Value;

            // Open Mail Merge Template
            oWrdDoc = oWord.Documents.Open(oTemplatePath);

            // Open New Document (Empty)
            // Note: I tried programmatically starting a new word document instead of opening an exisitng "blank",
            //       bu when the copy/paste operation occurred, formatting was way off. The blank document below was
            //       generated by taking a copy of the FullMailMerge.doc, clearing it out, and saving it, thus providing
            //       a kind of formatted "template".
            string newDocument = projectDirectory + "\\Newdocument.doc";
            oNewWrdDoc = oNewWord.Documents.Open(newDocument);

            // Open Mail Merge Datasource
            oWrdDoc.MailMerge.OpenDataSource(docSource, oMissing, oMissing, oMissing,
               oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);

            // Execute Mail Merge (Opens Completed Mail Merge Documents Titled "Letters1")
            oWrdDoc.MailMerge.Execute();

            // Save the processed Mail Merge Document for Archiving
            // oWord.Activedocument.SaveAs2(docTempDir + "FullMailMerge.doc");

            int docCnt = oWord.Activedocument.Sections.Count - 1;
            int cnt = 0;
            while (cnt != docCnt)
            {
                cnt++;
                string newFilename = "";

                // Copy Desired Section from Mail Merge
                oWord.Activedocument.Sections[cnt].Range.Copy();
                // Set focus to the New Word Doc instance
                oNewWord.Activate();
                // Paste copied range to New Word Doc
                oNewWord.Activedocument.Range(0, 0).Paste();

                foreach (ListViewItem lvI in lvData.Items)
                {
                    if (lvI.Checked) // Get first checked lvI in lvData to use for generating filename
                    {
                        updateAddrChngHistory(lvI.SubItems[16].Text);

                        string fileSys = lvI.SubItems[12].Text.ToUpper();
                        string memNo = lvI.SubItems[0].Text;

                        newFilename = fileSys + "%" + memNo + "%" + "" + "%" + "" + "%" + "CORRESPONDENCE%OUTGOING - ACKNOWLEDGEMENT%" + DateTime.Now.ToString("yyyy-MM-dd-hh.mm.ss.ffffff") + ".doc";

                        lvI.Remove(); // Delete from listview the lvI used for newFilename
                        break;        // Break out of foreach loop
                    }
                }

                // Save New Word Doc
                oNewWord.Activedocument.SaveAs2(docTempDir + newFilename);
                // Clear New Word Doc
                oNewWord.Activedocument.Content.Select();
                oNewWord.Selection.TypeBackspace();
            }
            // Show only the Full Mail Merge Doc. Have user press OK when finished to close documents.
            // Set 'False' in PROD, 'True' in DEV
            // oWord.Visible = false;
            // Hides my new word instance used to save each individual section of the full Mail Merge Doc
            oNewWord.Visible = false;
            MessageBox.Show(new Form() { TopMost = true }, "Click OK when finsihed.");

            oNewWord.Activedocument.Close(doNotSaveChanges); // Close the Individual Record Document
            oNewWord.Quit();                                 // Close Word Instance for Individual Record
            oWord.Activedocument.Close(doNotSaveChanges);    // Close the Full Mail Merge Document (Currently ALSO closes the Template document)
            oWord.Quit(doNotSaveChanges);                    // Close the Mail Merge Template
            MessageBox.Show("Mail Merge Completed, Individual Documents Saved, Instances Closed.");
        }
        catch (Exception ex)
        {
            LogException(ex);
            MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
            // Close all Word processes
            Process[] processes = Process.GetProcessesByName("winword");
            foreach (var process in processes)
            {
                process.Close();
            }
        }
        finally
        {

        }
    }



Is This A Good Question/Topic? 0
  • +

Replies To: Hide template Word Doc while displaying executed Word Doc?

#2 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6833
  • View blog
  • Posts: 28,345
  • Joined: 12-December 12

Re: Hide template Word Doc while displaying executed Word Doc?

Posted 13 December 2013 - 10:25 AM

oWord.Visible = false;

This hides the Word instance so, of course, will hide all documents open within this instance.

I've said this before but.. here goes, you only need one instance of Word.

Why does your user need to review the process? You are automating it. Mixing automation with user interaction is, IMO, always likely to be problematic. Is the user has to interact with the process then this would be more suitable for a Word Add-In.

As you are automating I would automate the full process, with nothing visible (after testing). If the user subsequently wants to open or print a generated document then I would make this a separate step, with a Button that is Enabled when the automation is complete.



Anyway, if you are struggling to make a particular document visible, or invisible, then you might close all documents and re-open the one(s) you need.
Was This Post Helpful? 1
  • +
  • -

#3 AnalyticLunatic   User is offline

  • D.I.C Lover

Reputation: 239
  • View blog
  • Posts: 1,073
  • Joined: 25-June 12

Re: Hide template Word Doc while displaying executed Word Doc?

Posted 17 December 2013 - 01:27 PM

View Postandrewsw, on 13 December 2013 - 05:25 PM, said:

Why does your user need to review the process? You are automating it. Mixing automation with user interaction is, IMO, always likely to be problematic. Is the user has to interact with the process then this would be more suitable for a Word Add-In.


User does not need to review the process. The only reason they SEE the copy/pasting is due to needing the word docs visible in order for them to be Activated(). Being Visible = false cause an error when code tries to Activate(). With the way Business Flow is set-up, I need to present the users with the final mail merge document on screen, allow them to print, and after they have pressed OK, update the database as to what (individually saved) documents have been printed.

My updated code is below (modified to fix some other errors). Still trying to figure out how to hide the Template when user is given the OK dialogue.

*Updated Code:
public void MergeSplitAndReview()
        {
            try
            {
                MessageFilter.Register();

                //MergeDocLibrary mdl = new MergeDocLibrary();
                //mdl.mergeDocument(docSource, docLoc);

                // Mail Merge Template
                Word.Application oWord = new Word.Application();
                Word.Document oWrdDoc = new Word.Document();
                // New Document Instance
                Word.Application oNewWord = new Word.Application();
                Word.Document oNewWrdDoc = new Word.Document();

                object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;

                // Documents must be visible for code to Activate()
                oWord.Visible = true;
                oNewWord.Visible = true;

                Object oTemplatePath = docLoc;
                Object oMissing = System.Reflection.Missing.Value;

                // Open Mail Merge Template
                oWrdDoc = oWord.Documents.Open(oTemplatePath);

                // Open New Document (Empty)
                // Note: I tried programmatically starting a new word document instead of opening an exisitng "blank",
                //       bu when the copy/paste operation occurred, formatting was way off. The blank document below was
                //       generated by taking a copy of the FullMailMerge.doc, clearing it out, and saving it, thus providing
                //       a kind of formatted "template".
                string newDocument = projectDirectory + "\\Newdocument.doc";
                oNewWrdDoc = oNewWord.Documents.Open(newDocument);

                // Open Mail Merge Datasource
                oWrdDoc.MailMerge.OpenDataSource(docSource, oMissing, oMissing, oMissing,
                   oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
                
                // Execute Mail Merge (Opens Completed Mail Merge Documents Titled "Letters1")
                oWrdDoc.MailMerge.Execute();

                // Save the processed Mail Merge Document for Archiving
                // oWord.Activedocument.SaveAs2(docTempDir + "FullMailMerge.doc");
                string[] SSNsArray = new string[lvData.Items.Count];
                x = 0;
                int docCnt = oWord.Activedocument.Sections.Count - 1;
                int cnt = 0;
                while (cnt != docCnt)
                {
                    cnt++;
                    string newFilename = "";
                    
                    // Copy Desired Section from Mail Merge
                    oWord.Activedocument.Sections[cnt].Range.Copy();
                    // Set focus to the New Word Doc instance
                    oNewWord.Activate();
                    // Paste copied range to New Word Doc
                    oNewWord.Activedocument.Range(0, 0).Paste();

                    foreach (ListViewItem lvI in lvData.Items)
                    {
                        if (lvI.Checked) // Get first checked lvI in lvData to use for generating filename
                        {
                            // Store SSN (lvI.SubItems[18]) in Array. 
                            SSNsArray[x] = lvI.SubItems[18].Text;
                            x++;

                            //updateAddrChngHistory(lvI.SubItems[18].Text);

                            string fileSys = lvI.SubItems[14].Text.ToUpper();
                            string memNo = lvI.SubItems[0].Text;

                            newFilename = fileSys + "%" + memNo + "%" + "" + "%" + "" + "%" + "CORRESPONDENCE%OUTGOING - ACKNOWLEDGEMENT%" + DateTime.Now.ToString("yyyy-MM-dd-hh.mm.ss.ffffff") + ".doc";

                            lvI.Remove(); // Delete from listview the lvI used for newFilename
                            break;        // Break out of foreach loop
                        }
                    }

                    x = 0; // Reset value of 'x' (Global Variable) to 0.

                    // Save New Word Doc
                    oNewWord.Activedocument.SaveAs2(docTempDir + newFilename);
                    // Clear New Word Doc
                    oNewWord.Activedocument.Content.Select();
                    oNewWord.Selection.TypeBackspace();
                }
                // Show only the Full Mail Merge Doc. Have user press OK when finished to close documents.
                // Set 'False' in PROD, 'True' in DEV
                // oWord.Visible = false;
                // Hides my new word instance used to save each individual section of the full Mail Merge Doc
                oNewWord.Visible = false;
                // MessageBox.Show(new Form() { TopMost = true }, "Click OK when finsihed.");
                MessageBox.Show(new Form() { TopMost = true }, "Click OK when finsihed.");

                // Do not update Change History Table until user has compelted and "theoretically" printed.
                foreach (string ssn in SSNsArray)
                {
                    if (ssn != null && ssn.Length > 0)
                    {
                        updateAddrChngHistory(ssn);
                    }
                }

                oNewWord.Activedocument.Close(doNotSaveChanges); // Close the Individual Record Document
                oNewWord.Quit();                                 // Close Word Instance for Individual Record
                oWord.Activedocument.Close(doNotSaveChanges);    // Close the Full Mail Merge Document (Currently ALSO closes the Template document)
                // oWord.Documents.Open(docTempDir + "FullMailMerge.doc");
                
                oWord.Quit(doNotSaveChanges);                    // Close the Mail Merge Template
                MessageFilter.Revoke();
                MessageBox.Show("Mail Merge Completed, Individual Documents Saved, Instances Closed.");
            }
            catch (Exception ex)
            {
                LogException(ex);
                MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
                // Close all Word processes
                Process[] processes = Process.GetProcessesByName("winword");
                foreach (var process in processes)
                {
                    process.Close();
                }
            }
            finally
            {
                
            }
        }


EDIT:

I took your suggestion of closing the documents when processing finished and then just open the Full Mail Merge from a saved location. Not quite what I was after, but as a Temp Application Solution, this may work. Thanks Andrew.

Updated Code:
public void MergeSplitAndReview()
        {
            try
            {
                MessageFilter.Register();

                //MergeDocLibrary mdl = new MergeDocLibrary();
                //mdl.mergeDocument(docSource, docLoc);

                // Mail Merge Template
                Word.Application oWord = new Word.Application();
                Word.Document oWrdDoc = new Word.Document();
                // New Document Instance
                Word.Application oNewWord = new Word.Application();
                Word.Document oNewWrdDoc = new Word.Document();

                object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;

                // Documents must be visible for code to Activate()
                oWord.Visible = true;
                oNewWord.Visible = true;

                Object oTemplatePath = docLoc;
                Object oMissing = System.Reflection.Missing.Value;

                // Open Mail Merge Template
                oWrdDoc = oWord.Documents.Open(oTemplatePath);

                // Open New Document (Empty)
                // Note: I tried programmatically starting a new word document instead of opening an exisitng "blank",
                //       bu when the copy/paste operation occurred, formatting was way off. The blank document below was
                //       generated by taking a copy of the FullMailMerge.doc, clearing it out, and saving it, thus providing
                //       a kind of formatted "template".
                string newDocument = projectDirectory + "\\Newdocument.doc";
                oNewWrdDoc = oNewWord.Documents.Open(newDocument);

                // Open Mail Merge Datasource
                oWrdDoc.MailMerge.OpenDataSource(docSource, oMissing, oMissing, oMissing,
                   oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
                
                // Execute Mail Merge (Opens Completed Mail Merge Documents Titled "Letters1")
                oWrdDoc.MailMerge.Execute();

                // Save the processed Mail Merge Document for Archiving
                oWord.Activedocument.SaveAs2(docTempDir + "FullMailMerge.doc");

                string[] SSNsArray = new string[lvData.Items.Count];
                x = 0;
                int docCnt = oWord.Activedocument.Sections.Count - 1;
                int cnt = 0;
                while (cnt != docCnt)
                {
                    cnt++;
                    string newFilename = "";
                    
                    // Copy Desired Section from Mail Merge
                    oWord.Activedocument.Sections[cnt].Range.Copy();
                    // Set focus to the New Word Doc instance
                    oNewWord.Activate();
                    // Paste copied range to New Word Doc
                    oNewWord.Activedocument.Range(0, 0).Paste();

                    foreach (ListViewItem lvI in lvData.Items)
                    {
                        if (lvI.Checked) // Get first checked lvI in lvData to use for generating filename
                        {
                            // Store SSN (lvI.SubItems[18]) in Array. 
                            SSNsArray[x] = lvI.SubItems[18].Text;
                            x++;

                            //updateAddrChngHistory(lvI.SubItems[18].Text);

                            string fileSys = lvI.SubItems[14].Text.ToUpper();
                            string memNo = lvI.SubItems[0].Text;

                            newFilename = fileSys + "%" + memNo + "%" + "" + "%" + "" + "%" + "CORRESPONDENCE%OUTGOING - ACKNOWLEDGEMENT%" + DateTime.Now.ToString("yyyy-MM-dd-hh.mm.ss.ffffff") + ".doc";

                            lvI.Remove(); // Delete from listview the lvI used for newFilename
                            break;        // Break out of foreach loop
                        }
                    }

                    x = 0; // Reset value of 'x' (Global Variable) to 0.

                    // Save New Word Doc
                    oNewWord.Activedocument.SaveAs2(docTempDir + newFilename);
                    // Clear New Word Doc
                    oNewWord.Activedocument.Content.Select();
                    oNewWord.Selection.TypeBackspace();
                }
                // Show only the Full Mail Merge Doc. Have user press OK when finished to close documents.
                // Set 'False' in PROD, 'True' in DEV
                // oWord.Visible = false;
                // Hides my new word instance used to save each individual section of the full Mail Merge Doc
                oNewWord.Visible = false;
                oNewWord.Activedocument.Close(doNotSaveChanges); // Close the Individual Record Document
                oNewWord.Quit();                                 // Close Word Instance for Individual Record
                oWord.Activedocument.Close(doNotSaveChanges);    // Close the Full Mail Merge Document (Currently ALSO closes the Template document)
                oWord.Activedocument.Close(doNotSaveChanges);
                
                oWord.Documents.Open(docTempDir + "FullMailMerge.doc");

                // MessageBox.Show(new Form() { TopMost = true }, "Click OK when finsihed.");
                MessageBox.Show(new Form() { TopMost = true }, "Click OK when finsihed.");

                // Do not update Change History Table until user has compelted and "theoretically" printed.
                foreach (string ssn in SSNsArray)
                {
                    if (ssn != null && ssn.Length > 0)
                    {
                        updateAddrChngHistory(ssn);
                    }
                }
                oWord.Quit(doNotSaveChanges);                    // Close the Mail Merge Template
                MessageFilter.Revoke();
                MessageBox.Show("Mail Merge Completed, Individual Documents Saved, Instances Closed.");
            }
            catch (Exception ex)
            {
                LogException(ex);
                MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
                // Close all Word processes
                Process[] processes = Process.GetProcessesByName("winword");
                foreach (var process in processes)
                {
                    process.Close();
                }
            }
            finally
            {
                
            }
        }

This post has been edited by AnalyticLunatic: 17 December 2013 - 01:44 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1