Программно добавить повторяющийся элемент раздела в текстовый документ, используя Open Xml .WordProcessing. NET - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть шаблон документа, который я хочу динамически заполнить, используя C#. Шаблон содержит повторяющийся раздел с несколькими текстовыми полями и текстом stati 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());

Это однако создает поврежденный файл, потому что уникальные идентификаторы также дублируются методом Clone.

Есть идеи о том, как достичь моей цели?

1 Ответ

1 голос
/ 16 февраля 2020

Вот код, который показывает, как вы могли бы сделать это. Обратите внимание, что при этом удаляется существующий уникальный идентификатор (элемент 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);
...