如何使用 Open XML SDK 将文本插入内容控件
How to insert text into a content control with the Open XML SDK
我正在尝试开发一种解决方案,该解决方案从 ASP.Net 网页获取输入并将输入值嵌入到 MS Word 文档中的相应内容控件中。 MS Word 文档也有静态数据和一些要嵌入到页眉和页脚字段中的动态数据。
这里的想法是解决方案应该基于 Web。我可以为此目的使用 OpenXML 或您可以建议的任何其他方法吗?
非常感谢您的宝贵意见。我真的很感激他们。
我的项目中有一些代码示例,用于在您在 Word 文档中创建的内容控件中插入一些单词:
public static WordprocessingDocument InsertText(this WordprocessingDocument doc, string contentControlTag, string text)
{
SdtElement element = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>()
.FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>()?.Val == contentControlTag);
if (element == null)
throw new ArgumentException($"ContentControlTag \"{contentControlTag}\" doesn't exist.");
element.Descendants<Text>().First().Text = text;
element.Descendants<Text>().Skip(1).ToList().ForEach(t => t.Remove());
return doc;
}
它只是在文档中查找具有特定 Tag
的第一个内容控件(您可以通过在 word 中启用设计器模式并右键单击内容控件来进行设置),并将当前文本替换为传递给方法的文本。在此之后,文档仍将包含当然可能不需要的内容控件。因此,当我完成文档编辑后,我 运行 使用以下方法来删除内容控件:
internal static WordprocessingDocument RemoveSdtBlocks(this WordprocessingDocument doc, IEnumerable<string> contentBlocks)
{
List<SdtElement> SdtBlocks = doc.MainDocumentPart.Document.Descendants<SdtElement>().ToList();
if (contentBlocks == null)
return doc;
foreach(var s in contentBlocks)
{
SdtElement currentElement = SdtBlocks.FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>()?.Val == s);
if (currentElement == null)
continue;
IEnumerable<OpenXmlElement> elements = null;
if (currentElement is SdtBlock)
elements = (currentElement as SdtBlock).SdtContentBlock.Elements();
else if (currentElement is SdtCell)
elements = (currentElement as SdtCell).SdtContentCell.Elements();
else if (currentElement is SdtRun)
elements = (currentElement as SdtRun).SdtContentRun.Elements();
foreach (var el in elements)
currentElement.InsertBeforeSelf(el.CloneNode(true));
currentElement.Remove();
}
return doc;
}
要从模板打开 WordProcessingDocument
并进行编辑,网上有很多信息。
编辑:
open/save 文档的小示例代码,同时在内存流中使用它们,当然你应该使用额外的存储库来处理这个问题 class,它负责管理真实的文档代码:
byte[] byteArray = File.ReadAllBytes(@"C:\...\Template.dotx");
using (var stream = new MemoryStream())
{
stream.Write(byteArray, 0, byteArray.Length);
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{
//Needed because I'm working with template dotx file,
//remove this if the template is a normal docx.
doc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
doc.InsertText("contentControlName","testtesttesttest");
}
using (FileStream fs = new FileStream(@"C:\...\newFile.docx", FileMode.Create))
{
stream.WriteTo(fs);
}
}
我正在尝试开发一种解决方案,该解决方案从 ASP.Net 网页获取输入并将输入值嵌入到 MS Word 文档中的相应内容控件中。 MS Word 文档也有静态数据和一些要嵌入到页眉和页脚字段中的动态数据。
这里的想法是解决方案应该基于 Web。我可以为此目的使用 OpenXML 或您可以建议的任何其他方法吗?
非常感谢您的宝贵意见。我真的很感激他们。
我的项目中有一些代码示例,用于在您在 Word 文档中创建的内容控件中插入一些单词:
public static WordprocessingDocument InsertText(this WordprocessingDocument doc, string contentControlTag, string text)
{
SdtElement element = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>()
.FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>()?.Val == contentControlTag);
if (element == null)
throw new ArgumentException($"ContentControlTag \"{contentControlTag}\" doesn't exist.");
element.Descendants<Text>().First().Text = text;
element.Descendants<Text>().Skip(1).ToList().ForEach(t => t.Remove());
return doc;
}
它只是在文档中查找具有特定 Tag
的第一个内容控件(您可以通过在 word 中启用设计器模式并右键单击内容控件来进行设置),并将当前文本替换为传递给方法的文本。在此之后,文档仍将包含当然可能不需要的内容控件。因此,当我完成文档编辑后,我 运行 使用以下方法来删除内容控件:
internal static WordprocessingDocument RemoveSdtBlocks(this WordprocessingDocument doc, IEnumerable<string> contentBlocks)
{
List<SdtElement> SdtBlocks = doc.MainDocumentPart.Document.Descendants<SdtElement>().ToList();
if (contentBlocks == null)
return doc;
foreach(var s in contentBlocks)
{
SdtElement currentElement = SdtBlocks.FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>()?.Val == s);
if (currentElement == null)
continue;
IEnumerable<OpenXmlElement> elements = null;
if (currentElement is SdtBlock)
elements = (currentElement as SdtBlock).SdtContentBlock.Elements();
else if (currentElement is SdtCell)
elements = (currentElement as SdtCell).SdtContentCell.Elements();
else if (currentElement is SdtRun)
elements = (currentElement as SdtRun).SdtContentRun.Elements();
foreach (var el in elements)
currentElement.InsertBeforeSelf(el.CloneNode(true));
currentElement.Remove();
}
return doc;
}
要从模板打开 WordProcessingDocument
并进行编辑,网上有很多信息。
编辑:
open/save 文档的小示例代码,同时在内存流中使用它们,当然你应该使用额外的存储库来处理这个问题 class,它负责管理真实的文档代码:
byte[] byteArray = File.ReadAllBytes(@"C:\...\Template.dotx");
using (var stream = new MemoryStream())
{
stream.Write(byteArray, 0, byteArray.Length);
using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{
//Needed because I'm working with template dotx file,
//remove this if the template is a normal docx.
doc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
doc.InsertText("contentControlName","testtesttesttest");
}
using (FileStream fs = new FileStream(@"C:\...\newFile.docx", FileMode.Create))
{
stream.WriteTo(fs);
}
}