从数据列表中以Open XML格式生成多页文档

时间:2016-05-27 15:46:59

标签: c# ms-word export openxml

对于我正在进行的项目,我正在调查我们团队通常不会用于生成文档的方法。通常情况下,我们使用ActiveReports生成我们为客户提供的PDF,但由于我们的纸张尺寸,这不是一个选项 - 我们一直有严重问题得到的东西不是8.5“x 11 “可以很好地使用浏览器端的PDF插件或我们支持的打印机。

我正在尝试做的具体事情是使用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模板以生成具有多个成员的文档页面数等于成员数,都使用完全相同的格式?

1 个答案:

答案 0 :(得分:2)

我建议您创建一个包含多个合并字段的单词模板,以便与Thing /对象的成员进行映射,然后使用List执行Mail merge。

使用Syncfusion的DocIO库,您可以更轻松地实现它。 DocIO是一个.NET库,可以读取和写入Word 2003/2007/2010/2013/2016文件。如果您符合条件,则可以通过community license program免费获得整套控件(商业应用程序)。社区许可是完整的产品,没有任何限制或水印。

例如,让我们使用合并字段创建如下所示的Word文档模板,并考虑您有一个客户(列表)详细信息列表。

Input Word template

第1步:创建控制台应用程序
第2步:添加对Syncfusion.DocIO.Base,Syncfusion.Compression.Base和Syncfusion.OfficeChart.Base的引用         您也可以使用NuGet将这些引用添加到您的项目中 第3步:复制&amp;粘贴以下代码段。确保正确引用输入字模板。

此代码将根据您的要求生成文档,对于每个/客户,它将在生成的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", "maria.Anders@example.com", "USA"));
        customers.Add(new Customer("Ana", "Trujillo", "ana.trujillp@example.com", "USA"));
        customers.Add(new Customer("Antonio", "Moreno", "antonio.moreno@example.com", "UK"));
        customers.Add(new Customer("Thomas", "Hardy", "thomas.hardy@example.com", "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工作。