3

使用以下语法查找合并字段时遇到问题

foreach (var field in docx.MainDocumentPart.Document.Descendants<SimpleField>())
{
}

有时上面的代码可以工作并找出合并字段,有时它只显示 null

4

3 回答 3

2

问题是 word 可以将合并字段实现为 SimpleField 或 FieldChar。SimpleField 元素包含合并字段的所有详细信息,对于 FieldChar,它有一个 begin 元素,后跟字段代码、带有运行的段落和用于存储字段显示值的文本,最后是合并字段 end 元素。开始和结束之间的所有元素都属于合并字段。

合并字段实现为 FieldChar

<w:r>
  <w:fldChar w:fldCharType="begin" />
</w:r>
<w:r>
  <w:instrText xml:space="preserve"> MERGEFIELD  AnotherBodyField  \* MERGEFORMAT </w:instrText>
</w:r>
<w:r>
  <w:fldChar w:fldCharType="separate" />
</w:r>
<w:r w:rsidR="003A6EEC">
  <w:rPr>
    <w:noProof />
  </w:rPr>
  <w:t>«AnotherBodyField»</w:t>
</w:r>
<w:r>
  <w:rPr>
    <w:noProof />
  </w:rPr>
  <w:fldChar w:fldCharType="end" />
</w:r>

合并字段实现为 SimpleField

<w:fldSimple w:instr=" MERGEFIELD  TestMergField  \* MERGEFORMAT ">
    <w:r w:rsidR="00C44AC1">
      <w:rPr>
        <w:noProof />
      </w:rPr>
      <w:t>«TestMergField»</w:t>
    </w:r>
</w:fldSimple>

SimpleField 对象包含所有合并字段内容,所以这段代码就可以了。var simpleMergeField = documentProcessor.MainDocumentPart.Document.Body.Descendants();

对于 FieldChar,您需要注意 FieldCharValues.Begin、FieldCharValues.Separate 和 FieldCharValues.End。两者之间的每个元素都包含在合并字段内容中。

于 2015-04-23T01:14:54.763 回答
0

请验证您的合并字段是否存在文档的哪个部分。它可能存在于页眉或页脚部分。您可以通过制作 xml 包来找出这一点。检查每个页眉、页脚 xml。

您可以使用以下语句遍历页眉部分和页脚部分

foreach (var header in docx.MainDocumentPart.Headerparts)
    {

        foreach (var field in header.RootElement.Descendants<SimpleField>())
        {
        }
    }
     foreach (var footerin docx.MainDocumentPart.FooterParts)
    {

        foreach (var field in footer.RootElement.Descendants<SimpleField>())
        {
        }
    }
于 2013-11-12T10:32:25.850 回答
0

多年后,总结上面的 2 个答案,创建按名称查找所有合并字段的代码解决方案:

var splitter = new[] { ' ', '"' };
const string mergefield = "MERGEFIELD";
var mergeFields = mainPart.HeaderParts.Cast<OpenXmlPart>()
    .Concat(mainPart.FooterParts.Cast<OpenXmlPart>())
    .Concat(new OpenXmlPart[] { mainPart })
    .SelectMany(x => x.RootElement.Descendants<SimpleField>().Select(sf => new { text = sf.Instruction.Value, el = (OpenXmlElement)sf })
                    .Concat(x.RootElement.Descendants<FieldCode>().Select(fc=> new { text = fc.Text, el = (OpenXmlElement)fc})))
    .Select(a => new { words = a.text.Split(splitter, StringSplitOptions.RemoveEmptyEntries), el = a.el })
    .Where(a => mergefield.Equals(a.words.FirstOrDefault(), StringComparison.OrdinalIgnoreCase))
    .ToLookup(k => string.Join(" ",k.words.Skip(1).TakeWhile(i=>i!= "\\*")), v => v.el);
于 2016-09-19T09:38:36.047 回答