Я понимаю, что вы пытаетесь сделать, это вставить грязный элемент w:fldSimple
(класс SimpleField
) в ваш документ, чтобы Word обновил все поля, включая оглавление, как только пользователь откроет этот документ с помощью Microsoft Word,Однако, если вы посмотрите на разметку Open XML, созданную Microsoft Word после обновления полей, вы увидите, что ваш w:fldSimple
является виновником.
Я создал следующий код для получения простогоДокумент Word с (в значительной степени) просто полем:
[Fact]
public void CheckBookmarkNotDefined()
{
using WordprocessingDocument wordDocument = WordprocessingDocument.Create(
"SimpleField.docx", WordprocessingDocumentType.Document);
MainDocumentPart part = wordDocument.AddMainDocumentPart();
part.Document =
new Document(
new Body(
new Paragraph(
new SimpleField
{
Instruction = "sdtContent",
Dirty = true
})));
}
Приведенный выше код создает следующую разметку Open XML в основной части документа:
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:fldSimple w:instr="sdtContent" w:dirty="true" />
</w:p>
</w:body>
</w:document>
Обратите внимание, что w:fldSimple
элемент содержится в элементе w:p
(класс Paragraph
), так как добавление его к элементу w:body
(класс Body
) приводит к недопустимой разметке Open XML.
Открытие этого документа в Microsoft Word, обновлениеПоля и сохранение документа заставляют Word создавать следующую разметку Open XML (которую я немного упростил):
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:fldChar w:fldCharType="begin"/>
</w:r>
<w:r>
<w:instrText>sdtContent</w:instrText>
</w:r>
<w:r>
<w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r>
<w:rPr>
<w:b/>
<w:bCs/>
</w:rPr>
<w:t>Error! Bookmark not defined.</w:t>
</w:r>
<w:r>
<w:fldChar w:fldCharType="end"/>
</w:r>
</w:p>
<w:sectPr>
[Child elements removed for clarity]
</w:sectPr>
</w:body>
</w:document>
Вы можете видеть, что Word превратил простое поле (элемент w:fldSimple
)) в сложное поле, используя несколько элементов w:fldChar
и один элемент w:instrText
, имеющий в качестве содержимого sdtContent. Далее вы можете увидеть текст «Ошибка! Закладка не определена». как результат поля.
Word создает это сообщение об ошибке, потому что текст вашей инструкции ("sdtContent"
) неверен. Если вы замените "sdtContent"
допустимым именем поля, например "AUTONUM"
, вы не увидите этого сообщения об ошибке. Однако в случае AUTONUM
вы, очевидно, получите результат видимого поля. Чтобы избежать этого, вы можете использовать поле REF
, для которого вам нужна действительная закладка. Это создается в следующем примере:
[Fact]
public void CreateSimpleFieldForAutomaticUpdate()
{
using WordprocessingDocument wordDocument = WordprocessingDocument.Create(
"SimpleFieldRef.docx", WordprocessingDocumentType.Document);
MainDocumentPart part = wordDocument.AddMainDocumentPart();
part.Document =
new Document(
new Body(
new Paragraph(
new Run(
new Text("Hello World!"))),
new BookmarkStart { Id = "32767", Name = "_RefUpdate" },
new BookmarkEnd { Id = "32767" },
new Paragraph(
new SimpleField
{
Instruction = "REF _RefUpdate",
Dirty = true
}),
new SectionProperties()));
}
Вам необходимо написать код для вставки элемента w:bookmarkStart
(класс BookmarkStart
), элемента w:bookmarkEnd
(класс BookmarkEnd
),и элемент w:p
с вашим дочерним элементом w:fldSimple
непосредственно перед элементом w:sectPr
(класс SectionProperties
). В моем примере я использовал большое целочисленное значение в качестве идентификатора закладки и _RefUpdate
в качестве имени закладки, которое также используется в свойстве Instruction
.