从选定的Word Doc部分复制一个额外的空白页面?

时间:2013-11-26 19:45:55

标签: c# .net winforms interop mailmerge

我编写了以下代码,允许用户根据将要打印的word文档和数据源(不同系统)查询数据,他们可以选择SOURCE1,SOURCE2或BOTH。查询数据,将其放入ODBC DataReader中,然后循环以填充ListView控件。

然后,我允许用户选择要打印的记录,并将这些记录作为邮件合并操作处理到选定的Word文档中。

我现在要做的是将每个单词文档页面(邮件合并的每个记录)保存到具有自己名称的特定文件夹位置。

代码

private void btnSearch_Click(object sender, EventArgs e)
        {
            lvData.Clear();
            string qryCmd = "";

            createColumns();

            switch (cmbLetterType.SelectedIndex)
            {
                case 0:
                    qryCmd = chkSystem("oldAddr");
                    break;
                case 1:
                    qryCmd = chkSystem("newAddr");
                    break;
                case 2:
                    qryCmd = chkSystem("nameChg");
                    break;
            }

            // If the option for BOTH is selected, qryCmd is a long string containing the individual queries for SOURCE1 and SOURCE2.
            // Here I check if a semicolon (;) exists, denoting that there are 2 cmd queries in the string.
            // If so, I split the query calling GetiSeriesData() with the first query string, then assigning qryCmd the second 
            // strings value and continuing processing as normal.
            if (qryCmd.Contains(";"))
            {
                char[] delimitChar = { ';' };
                string[] splitQueries = qryCmd.Split(delimitChar);
                qryCmd = splitQueries[0];
                GetiSeriesData(qryCmd);
                qryCmd = splitQueries[1];
            }

            GetiSeriesData(qryCmd);

            // Display message if no records found.
            if (lvData.Items.Count == 0)
            {
                MessageBox.Show("No records found.");
            }
            lblRecCnt.Text = lvData.Items.Count.ToString();
            this.lvData.CheckBoxes = true;
         }

public void GetiSeriesData(string query)
        {
            OdbcDataReader dr;
            try
            {
                //Set value of system based on table being looked at in ConnectionString
                string sysValue = "";
                if (query.Contains("lib1"))
                {
                    sysValue = "P";
                }
                if (query.Contains("lib2"))
                {
                    sysValue = "N";
                }

                MergeDocLibrary mdl = new MergeDocLibrary();
                dr = mdl.GetData(query);

                Int16 x = 0;
                string gndr = "";

                // Fill ListView Control lvData
                while (dr.Read())
                {
                    lvData.Items.Add(dr["MEMNO"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["NAME"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ADDR1"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ADDR2"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["STATE"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["ZIP"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ADDR1"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ADDR2"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_CITY"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_STATE"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["OLD_ZIP"].ToString().Trim());

                    lvData.Items[x].SubItems.Add(sysValue.ToString().Trim());
                    lvData.Items[x].SubItems.Add(DateTime.Today.ToString("d"));
                    lvData.Items[x].SubItems.Add(dr["SEX"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["LNAME"].ToString().Trim());
                    if (dr["SEX"].ToString().Trim() == "M")
                    {
                        gndr = "Mr.";
                    }
                    else // (dr["SEX"].ToString().Trim() == "F)
                    {
                        gndr = "Ms.";
                    }
                    lvData.Items[x].SubItems.Add(gndr + dr["LNAME"].ToString().Trim());
                    lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim() + ", " + dr["STATE"].ToString().Trim() + " " + dr["ZIP"].ToString().Trim());
                    x += 1;
                }

                mdl.closeConn();

            }
            catch (Exception ex)
            {
                MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
            }
            finally
            {

            }
        }

public void OpenAndReview()
    {
        try
        {
            string docSave = @"C:\Users\NAME\Desktop\Test.doc";

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

        // Original Mail Merge Document
        Word.Range rng;
        object start = 0;
        object end = 0;
        Word.Range newWrdRng;
        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();

        // Set 'False' in PROD, 'True' in DEV
        oWord.Visible = true;
        oNewWord.Visible = true;
        Object oTemplatePath = docLoc;

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

        // Open New Document
        oNewWrdDoc = oNewWord.Documents.Open(docSave);
        Object oMissing = System.Reflection.Missing.Value;

        // 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
            oWrdDoc.MailMerge.Execute();

            // Set Mail Merge Document as Active Doc
            //oWrdDoc.Activate();

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            MessageBox.Show(oWord.ActiveDocument.Sections.Count.ToString());
            // 3 Records selected gives 4 Sections Counted??
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // Subtract 1 to account for the extra section being counted?

            int docCnt = oWord.ActiveDocument.Sections.Count - 1;

            int cnt = 0;
            while (cnt != docCnt)
            {
                cnt++;
                // 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();
                // Save New Word Doc
                oNewWord.ActiveDocument.SaveAs2(@"C:\Users\NAME\Desktop\SuccesfullySavedDoc-" + cnt + ".doc");

                // Clear New Word Doc 
                oNewWord.ActiveDocument.Content.Select();
                oNewWord.Selection.TypeBackspace();

                // Set Mail Merge as Active Document
                oWord.Activate();
            }

        // .............

        // Save new docuemnt...?
        oNewWrdDoc.SaveAs2("SuccesfullySavedTest.doc");

    }
    catch (Exception ex)
    {
        MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
    }
    finally
    {
        //
    }
}

...

EDIT3 :我已经清除了每个新循环迭代的文档。现在试图找出为什么每个文档都使用额外的空白页2进行保存。

粗略大纲:

Doc 1:记录1 +一个额外的空白页面(不确定为什么?)

文件2:记录2 +一个额外的空白页面(不确定为什么?)

Doc 3:REcord 3 +一个额外的空白页面(不确定为什么?)

1 个答案:

答案 0 :(得分:0)

几点:

一个或两个常用的免费第三方Addin用于保存多个命名文档,确实有可见的VBA代码,您可以考虑在C#中重新设计/重写。

我以前使用的是一段代码,它为数据源中的每条记录执行一次合并。有人发布了我的旧代码at the end of their message here的一个版本。

所有这些方法都可能由于多种原因而失败。第三方方法有时会生成单个输出,然后在每个分节符时分割输出。这仅适用于某些合并类型,并且在邮件合并主文档中没有其他分节符的情况下。 “my”代码仅在合并一次消耗一条记录时才有效(显然,它可以适用于每个合并等2条记录,但如果邮件合并主文档包含NEXT,NEXTIF或SKIPIF字段,那么每个合并消耗的记录可能会有所不同,问题是AFAIK无法检测消耗了多少记录(除非您可以依赖于在邮件合并主文档中放置一个计数器。)

至于其他方面,我认为你需要改变这一部分:

    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();

因为(除非C#或其他东西正在做我不知道的事情),不能保证新的Word.Document对象将通过您刚刚创建的任何Word.Application实例创建。我认为你需要更像

的东西
Word.Document oWrdDoc = oWord.Documents.Add(); // you may need to provide some parameters here in C#

同样适用于oNewWrdDoc

一旦你创建了这些,我认为rng.FormattedText将会消失或者更容易解决。