使用 OpenXml.WordProcessing .NET 以编程方式将重复节项目添加到 word 文档

Programmatically add repeating section item to a word document using OpenXml.WordProcessing .NET

我有一个文档模板,我想使用 C# 动态填充它。该模板包含一个重复部分,其中有几个文本框和一些静态文本。我希望能够填充文本框并在需要时添加新的部分项目。

几乎工作的代码如下:

WordprocessingDocument doc = WordprocessingDocument.Open(@"C:\in\test.docx", true);
var mainDoc = doc.MainDocumentPart.Document.Body
    .GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.SdtBlock>()                    
    .GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.SdtContentBlock>();

var person = mainDoc.ChildElements[mainDoc.ChildElements.Count-1];
person.InsertAfterSelf<DocumentFormat.OpenXml.Wordprocessing.SdtBlock>(
    (DocumentFormat.OpenXml.Wordprocessing.SdtBlock) person.Clone());

然而,这会生成损坏的文件,因为唯一 ID 也会被克隆方法复制。

知道如何实现我的目标吗?

下面是一些代码,展示了如何执行此操作。请注意,这会删除现有的唯一 ID(w:id 元素)以确保不会重复。

using WordprocessingDocument doc = WordprocessingDocument.Open(@"C:\in\test.docx", true);

// Get the w:sdtContent element of the first block-level w:sdt element,
// noting that "sdtContent" is called "mainDoc" in the question.
SdtContentBlock sdtContent = doc.MainDocumentPart.Document.Body
    .Elements<SdtBlock>()
    .Select(sdt => sdt.SdtContentBlock)
    .First();

// Get last element within SdtContentBlock. This seems to represent a "person".
SdtBlock person = sdtContent.Elements<SdtBlock>().Last();

// Create a clone and remove an existing w:id element from the clone's w:sdtPr
// element, to ensure we don't repeat it. Note that the w:id element is optional
// and Word will add one when it saves the document.
var clone = (SdtBlock) person.CloneNode(true);
SdtId id = clone.SdtProperties?.Elements<SdtId>().FirstOrDefault();
id?.Remove();

// Add the clone as the new last element.
person.InsertAfterSelf(clone);