【发布时间】:2016-05-27 15:46:59
【问题描述】:
对于我正在进行的一个项目,我正在研究我们的团队通常不使用这些方法来生成文档。通常,我们使用 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,以及一些其他必要的 Google 搜索,了解如何让 Open XML API 执行此操作……但我没有找到任何可以理解的内容。
问题:我可以通过什么方式获取具有可变数量成员的List<Thing>,并使用 Open XML 获取 MS Word 模板以生成页数相等的文档到成员的数量,都使用完全相同的格式?
【问题讨论】:
-
实际上,您首先应该熟悉如何在 Word UI 中获得最佳结果。我的意思是分析如何使用 Word 的内置功能来实现这一点 - 因为这也是您在 Open XML 中使用的(或自动化 - 没有区别)。例如,这应该是表格格式还是大纲格式?什么应该确定分页方式 - Word 具有格式设置,您可以将其集成到样式中以获得“流畅的流程”。还需要什么其他格式?
-
一旦你有了一个有用的格式,创建一个包含所有元素(包括样式)的最小文档。保存该文档并在 Open XML SDK Productivity Tool 中打开它。这将向您展示构成文档的基础 Word Open XML 以及生成它的 Open XML SDK 代码(如果您想使用该工具)。这应该给你一个起点。一旦你看到底层的 XML,它可能会告诉你如何“转换”你的列表数据......
-
我认为您并没有真正阅读我的问题。虽然我确实下载了该工具并在其中打开了我的模板文档,但我看到了一堆乱码,并且没有任何明确的方法可以获取我的单个页面,根据需要多次复制该页面,并替换这些页面上的占位符文本与我的对象的详细信息。 也许对于我正在尝试做的事情来说,Open XML 不是正确的技术——我对此知之甚少——但我想知道我正在做的要么是可能或不可能。
-
是的,有可能。