2013-11-26 56 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