2013-11-26 27 views
0

我写了下面的代码,允许用户查询基于要打印的word文档和数据源(不同系统)的数据,他们可以选择SOURCE1,SOURCE2或BOTH。查询数据,放入ODBC DataReader中,然后循环以填充ListView控件。从选定的Word文档部分复制一个额外的空白页面?

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

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

CODE

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

大致的轮廓:

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

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

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

+0

顺便说一句,如果你完全控制了文档的内容/格式,你可以考虑使用Eric White的材料来生成这种输出 - 它根本不使用MailMerge,更符合“ .NET的做事方式“ - http://ericwhite.com/blog/category/open-xml/document-generation-series/ – 2013-11-28 07:49:18

+0

就我个人而言,我会考虑在保存后创建oNewWord文档,创建一个新文档,在你的循环里面。我怀疑这是否会成为主要的表现。 – 2013-12-02 16:33:33

+0

这是一种选择,但我更愿意走这条路线(如果可能的话),只是为了节省一点编码,并保持对任何可能受到维护/更新路上遇到的猎物困扰的人的理解。 –

回答

0

的几点:

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

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

由于多种原因,所有这些方法都可能失败。第三方方法有时会生成单个输出,然后在每个分节符处分割输出。这只适用于某些合并类型,并且在邮件合并主文档中没有附加分节符的情况下。 “我的”代码仅适用于合并每次消耗一条记录的情况(显然,它可以适用于每次合并的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.Document oWrdDoc = oWord.Documents.Add(); // you may need to provide some parameters here in C# 

同样,对于oNewWrdDoc

一旦你创建了这些,我想rng.FormattedText要么消失,或者稍微容易解决。

+0

感谢您的回复!问题不在于让邮件合并本身工作;我有这个。我试图做的是处理我的邮件合并,加载它在屏幕上用户审查(1文档中的所有字母)(工作!),然后审查和用户打印后(如果需要),继续代码处理,我会将邮件合并词文档的每个页面保存为自己的文档在特定位置。此外,Word.App()实例按预期工作。 'oNewWrdDoc = oNewWord.Documents.Open(docSave)'这一行使用oNewWrdDoc实例并在其中加载该文档。 –

+0

如果您查看我的编辑,我已经取得了一些小进展:) –

+0

好的,我已经看到了您的更改,也可以看到我的每条记录合并建议不相关。 如果您使用的是现在获得的问题 oNewWrdDoc.Range.FormattedText = oWord.ActiveDocument.Sections [1] .Range.FormattedText; (在VBA中,它在这里可以正常工作,但我认为你只能得到第1部分的页眉/页脚 - 如果你有它们,也可以从不止一个故事范围复制范围) – 2013-12-02 15:35:56