我正在开发一个需要根据用户输入,数据库值和模板生成Word文档的应用程序。我在网上看了一些例子,并找到了许多不同的方法来生成word文档,但我已经下定决心并决定坚持使用官方Office Open XML SDK 2.5
。现在我刚刚写了一个简单的程序,将一个表(存储在.xml文件中)插入到word文档中:
编辑: 如果对代码不感兴趣,请在底部提问
static void Main(string[] args)
{
XNamespace ns = XNamespace
.Get(@"http://schemas.openxmlformats.org/wordprocessingml/2006/main");
byte[] byteArray = File.ReadAllBytes(@"C:/Users/Alexander/Downloads/WordTest.docx");
using (var stream = new MemoryStream())
{
XDocument xdoc;
stream.Write(byteArray, 0, byteArray.Length);
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{
然后我可以做两件不同的事情,它们会产生相同的输出。
1)使用 OfficeOpenXml.Wordprocessing 命名空间方法:
#region Openxml.WordProcessing
var paragraphs = doc.MainDocumentPart.Document.Body.ToList();
Table tbl = new Table(File.ReadAllText(@"C:/users/alexander/downloads/tablecontent.xml"));
var bookmark = paragraphs.SelectMany(p => p.Descendants<BookmarkStart>()
.Where(bm => bm.Id == "0")).FirstOrDefault();
doc.MainDocumentPart.Document.Body.ReplaceChild(tbl, bookmark.Parent);
#endregion Openxml.WordProcessing
2)使用 Linq-To-XML :
#region LINQ TO XML
XElement xtbl = XElement.Load(
new FileStream(@"C:/users/alexander/downloads/tablecontent.xml", FileMode.Open));
using (StreamReader sr = new StreamReader(doc.MainDocumentPart.GetStream()))
using (XmlReader xr = XmlReader.Create(sr))
xdoc = XDocument.Load(xr);
//Document - Body - Paragraphs - Runs/Bookmarks/etc.
//any way to write this more clearly in linq-to-xml?
var test = xdoc.Elements().First().Elements().First().Elements()
.SelectMany(e => e.Elements()).ToList();
var startBookmark = test.Where(p => p.Name == XName.Get("bookmarkStart", ns.NamespaceName)
&& p.Attribute(XName.Get("id", ns.NamespaceName)).Value == "0").First();
startBookmark.Parent.ReplaceWith(xtbl);
using (XmlWriter xw = XmlWriter.Create(doc.MainDocumentPart.GetStream()))
xdoc.Save(xw);
#endregion LINQ TO XML
最后我将文档写入新文件:
using (FileStream fs =
new FileStream(@"C:/users/alexander/downloads/WordTestModified.docx", FileMode.Create))
{
stream.WriteTo(fs);
}
据我所知,第一个选项更简单,代码更清晰易读(不使用XName
而无需额外StreamReader
/ XmlReader/Writer
)但Linq-to-xml对这种方法有什么明显的优势吗?这将是一个很大的应用程序,我不想在以后受到限制。