使用OpenXml和C#复制Word文档
我使用Word和OpenXml在C#ASP.NET Web应用程序中提供邮件合并function:
1)上传文档,其中包含许多预定义的字符串以进行替换。
2)使用OpenXML SDK 2.0我打开Word文档,将mainDocumentPart作为字符串并使用Regex执行替换。
3)然后我使用OpenXML创建一个新文档,添加一个新的mainDocumentPart并将替换产生的字符串插入到这个mainDocumentPart中。
但是,新文档中的所有格式/样式等都将丢失。
我猜我可以单独复制和添加样式,定义,注释部分等来模仿原始文档。
但是有没有一种方法使用Open XML复制文档,允许我在新副本上执行替换?
谢谢。
这段代码应该将现有文档中的所有部分复制到新文档中。
using (var mainDoc = WordprocessingDocument.Open(@"c:\sourcedoc.docx", false)) using (var resultDoc = WordprocessingDocument.Create(@"c:\newdoc.docx", WordprocessingDocumentType.Document)) { // copy parts from source document to new document foreach (var part in mainDoc.Parts) resultDoc.AddPart(part.OpenXmlPart, part.RelationshipId); // perform replacements in resultDoc.MainDocumentPart // ... }
我第二次使用内容控制建议。 使用它们标记文档中要执行替换的区域是迄今为止最简单的方法。
至于复制文档(并保留整个文档内容,样式和所有内容),它相对容易:
string documentURL = "full URL to your document"; byte[] docAsArray = File.ReadAllBytes(documentURL); using (MemoryStream stream = new MemoryStream) { stream.Write(docAsArray, 0, docAsArray.Length); // THIS performs doc copy using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) { // perform content control substitution here, making sure to call .Save() // on any documents Part's changed. } File.WriteAllBytes("full URL of your new doc to save, including .docx", stream.ToArray()); }
实际上使用LINQ找到内容控件是小菜一碟。 以下示例查找所有简单文本内容控件(键入为SdtRun):
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) { var mainDocument = doc.MainDocumentPart.Document; var contentControls = from sdt in mainDocument.Descendants() select sdt; foreach (var cc in contentControls) { // drill down through the containment hierarchy to get to // the contained object cc.SdtContentRun.GetFirstChild().GetFirstChild().Text = "my replacement string"; } }
和
元素可能尚不存在,但创建它们很简单:
cc.SdtContentRun.Append(new Run(new Text("my replacement string")));
希望能帮助别人。 :d
我做了一些非常相似的事情,但我没有使用文本替换字符串,而是使用Word Content Controls。 我在以下博客文章SharePoint和Open Xml中记录了一些细节。 该技术并非特定于SharePoint。 您可以在纯ASP.NET或其他应用程序中重用该模式。
此外,我强烈建议您查看Eric White的博客 ,了解有关Open Xml的提示,技巧和技巧。 具体来说,查看Open Xmlpost的内存中操作 ,以及Word内容控制post。 从长远来看,我认为你会发现这些更有帮助。
希望这可以帮助。
作为上述的补遗; 可能更有用的是找到已标记的内容控件(使用GUI一词)。 我最近编写了一些软件,其中填充了包含附加标签的内容控件的文档模板。 要找到它们只是上述LINQ查询的扩展:
var mainDocument = doc.MainDocumentPart.Document; var taggedContentControls = from sdt in mainDocument.Descendants() let sdtPr = sdt.GetFirstChild() let tag = (sdtPr == null ? null : sdtPr.GetFirstChild()) where (tag != null) select new { SdtElem = sdt, TagName = tag.GetAttribute("val", W).Value };
我从其他地方得到了这个代码但是不记得现在在哪里; 完全的功劳归于他们。
该查询只是创建一个匿名类型的IEnumerable,其中包含内容控件及其关联的标记作为属性。 便利!
当您通过将扩展名更改为zip并打开它来查看openxml文档时,您会看到该单词子文件夹包含_rels文件夹,其中列出了所有关系。 这些关系指向你提到的部分(风格……)。 实际上你需要这些部分,因为它们包含格式的定义。 因此,不复制它们将导致新文档使用normal.dot文件中定义的格式,而不是原始文档中定义的格式。 所以我认为你必须复制它们。