2016-05-27 55 views
0

對於我正在開發的項目,我正在調查我們團隊通常不用於生成文檔的方法。通常情況下,我們使用ActiveReports來生成我們提供給客戶端的PDF,但這不是一個選項,因爲我們的紙張尺寸 - 我們一直在嚴重問題獲得任何不是8.5「x 11」,以良好地玩瀏覽器端PDF插件或我們支持的打印機。從數據列表中生成Open XML中的多頁文檔

我想要做的具體事情是創建一個文件1 ... n 4「x6」索引卡片。如前所述,我可以有不同數量的數據條目,我需要生成。

我使用的Open XML在過去的唯一途徑是採取一個模板,替換數據的關鍵詞,我想注入,則服務生成的文檔到客戶端,如下圖所示:

報告類:

public class ThingReport : IDisposable 
{ 
    #region Variables/Properties 

    private readonly string _templatePath = string.Empty; 
    private MemoryStream _reportStream; 

    #endregion Variables/Properties 

    #region Constructor 

    public ThingReport(string templatePath) 
    { 
     _templatePath = templatePath; 
    } 

    #endregion Constructor 

    #region Methods 

    public void Dispose() 
    { 
     _reportStream.Dispose(); 
    } 

    public void RunReport(IList<Thing> things) 
    { 
     _reportStream = new MemoryStream(); 

     using (FileStream fs = File.OpenRead(_templatePath)) 
     { 
      fs.CopyTo(_reportStream); 
      _reportStream.Seek(0x00000000, SeekOrigin.Begin); 
      fs.Close(); 
     } 

     using (WordprocessingDocument pkgDoc = WordprocessingDocument.Open(_reportStream, true)) 
     { 
      // Set basic properties of the document... 
      pkgDoc.PackageProperties.Creator = "My App"; 
      pkgDoc.PackageProperties.Created = DateTime.Now; 
      pkgDoc.PackageProperties.Title = "Some document"; 
      pkgDoc.PackageProperties.ContentType = "application/msword"; 

      // Read the full document text, in prep for editing... 
      string docText; 
      using (StreamReader sr = new StreamReader(pkgDoc.MainDocumentPart.GetStream())) 
      { 
       docText = sr.ReadToEnd(); 
       sr.Close(); 
      } 

      // Replace the recipient. 
      // Source: https://msdn.microsoft.com/en-us/library/office/bb508261.aspx 
      Regex recipientRegex = new Regex("«Recipient»"); 
      docText = recipientRegex.Replace(docText, things[0].PersonName); 

      // Template has 3 fields in it; replace those fields with details of child data. 
      for (int i = 0; i < 3; i++) 
      { 
       string presentedDate = string.Empty; 
       string presentedNotes = string.Empty; 
       if (i <= things.Count - 1) 
       { 
        var thing = things[i]; 
        presentedDate = thing.thingDate.ToString("MM/dd/yyyy"); 
        presentedNotes = thing.Notes; 
       } 

       string dateReplaceText = string.Format("«ThingDate{0}»", i + 1); 
       Regex dateRegex = new Regex(dateReplaceText); 
       docText = dateRegex.Replace(docText, presentedDate); 

       string noteReplaceText = string.Format("«ThingNote{0}»", i + 1); 
       Regex noteRegex = new Regex(noteReplaceText); 
       docText = noteRegex.Replace(docText, presentedNotes); 
      } 

      // Write the modified document to the stream. 
      using (StreamWriter sw = new StreamWriter(pkgDoc.MainDocumentPart.GetStream(FileMode.Create))) 
      { 
       sw.Write(docText); 
       sw.Close(); 
      } 

      // Close the unmanaged resource! 
      pkgDoc.Close(); 
     } 
    } 

    public byte[] Export() 
    { 
     return _reportStream.ToArray(); 
    } 

    #endregion Methods 
}  

我從沒碰過一次使用Word模板跨多個數據項。由於這是我們團隊的其他人員都具有相同經驗的技術,因此我不能要求他們如何操作,因爲他們和我一樣知道。

我查了Open XML API for word documents,以及其他一些必要的谷歌搜索如何獲得Open XML API來做到這一點...但我沒有發現任何我可以理解的東西。

問:以什麼方式我可以採取List<Thing>,成員數量可變的,並且使用Open XML採取MS Word模板來生成具有等於成員人數若干頁的文件,所有使用完全相同的格式?

+0

其實,你應該先做的是熟悉如何在Word界面中獲得最佳效果。我的意思是分析如何使用Word的內置功能來完成此操作 - 因爲這也是您在Open XML中使用的內容(或自動化 - 沒有任何區別)。例如,這應該是表格格式,大綱格式?什麼應該確定一個頁面如何分解 - Word具有格式設置,您可以在樣式中集成以獲得「平滑流動」。還需要其他什麼格式? –

+0

獲得有用的格式後,創建一個包含所有元素(包括樣式)的最小文檔。保存該文檔並在Open XML SDK生產力工具中打開它。這將向您展示組成該文檔的基礎Word Open XML以及用於生成它的Open XML SDK代碼(如果您想使用該工具)。這應該給你一個出發點。一旦你看到底層的XML可能會告訴你如何「變換」你的列表數據... –

+0

我不認爲你真的看我的問題。雖然我下載了該工具並在其中打開了我的模板文檔,但我看到了一堆亂碼,並沒有任何明確的方法取得我的單個頁面,根據需要多次複製該頁面,並在這些頁面上替換佔位符文本與我的對象的細節。 **也許**開放XML並不是我正在嘗試做的事情的正確技術 - 我對此不是很瞭解 - 但我想要知道我正在做的事情是可能的或不可能的。 –

回答

2

我建議你創建一個合併字段數量與您的Thing/object成員映射的單詞模板,然後執行與列表的郵件合併。

使用DocIO庫Syncfusion的,可以實現非常容易。 DocIO是一個讀取和寫入Word 2003/2007/2010/2013/2016文件的.NET庫。如果您符合條件,整套控件可通過community license program免費獲得(商業應用程序)。社區許可證是完整的產品,沒有任何限制或水印。

例如,讓我們創建一個Word文檔模板與合併域如下圖所示,考慮你的客戶(列表)的詳細信息列表。

Input Word template

步驟1:創建控制檯應用程序
步驟2:添加參考Syncfusion.DocIO.Base,Syncfusion.Compression.Base和Syncfusion.OfficeChart.Base
您可以添加這些也參考了使用NuGet的項目。
第3步:複製&粘貼以下代碼片段。確保正確引用輸入單詞模板。

此代碼將根據您的要求生成文檔,對於每件事情/客戶,它將在生成的Word文檔中生成單獨的頁面。

Download Demo

using System.Collections.Generic; 
using Syncfusion.DocIO.DLS; 
using Syncfusion.DocIO; 

namespace DocIO_MailMerge 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     List<Customer> customers = new List<Customer>(); 
     customers.Add(new Customer("Maria", "Anders", "[email protected]", "USA")); 
     customers.Add(new Customer("Ana", "Trujillo", "[email protected]", "USA")); 
     customers.Add(new Customer("Antonio", "Moreno", "[email protected]", "UK")); 
     customers.Add(new Customer("Thomas", "Hardy", "[email protected]", "Mexico")); 

     using (WordDocument wordDocument = new WordDocument(@"Template.docx")) 
     { 
      wordDocument.MailMerge.Execute(customers); 
      wordDocument.Save("Result.docx", FormatType.Docx); 
     } 

     System.Diagnostics.Process.Start("Result.docx"); 
    } 
} 
class Customer 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string MailID { get; set; } 
    public string Country { get; set; } 
    public Customer(string firstName, string lastName, string emailID, string country) 
    { 
     FirstName = firstName; 
     LastName = lastName; 
     MailID = emailID; 
     Country = country; 
    } 
} 
} 

注:我爲Syncfusion工作。