添加现有CustomProperty不会更新文档

时间:2011-11-09 08:03:56

标签: c# .net docx

我实际上是使用库“ DocX ”从.Net生成Word文档(2007+)。好处是它可以使用“docx”模板来重新创建或更新文档。

问题:当我“ AddCustomProperty(...)”时,它不会更新word文档。我实际上需要打开它,然后选择所有并按F9。我想知道是否有办法使用DocX库自动更新“自定义属性”。

要重现我的问题,您可以执行以下步骤:

  1. 打开DocX项目中提供的“示例”。
  2. 运行一次(它将在debug \ docs中创建文件)
  3. 打开发票模板,然后添加一行(包含或不包含文本)并保存文件
  4. 重新运行相同的示例项目(它将使用现有模板)
  5. 打开发票结果。执行此操作时,您可以看到表已创建,,所有其他字段尚未更新,直到您选择全部然后按CTRL + F9
  6. 如果有人有解决方案,我很乐意听听。

    (注意:我不希望MS Word互操作)

    项目和样本位于:http://docx.codeplex.com/

1 个答案:

答案 0 :(得分:3)

问题是当我们使用MS Word(我使用2010版本)然后我们修改模板并保存它。它会更改文档包含的内容。

以下是我们首次使用DocX生成模板时所拥有的内容:

<w:fldSimple w:instr="DOCPROPERTY company_name \* MERGEFORMAT" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:r>
    <w:t>
      <w:rPr>
        <w:b />
        <w:sz w:val="24" />
        <w:szCs w:val="24" />
        <w:color w:val="1F497D" />
      </w:rPr>Company Name</w:t>
  </w:r>
</w:fldSimple>

当我们用Word编辑(添加一个断行或一些文本)并保存它时,它会将fldSimple重写为:

<w:p w:rsidR="006D64DE" w:rsidRDefault="006B25B1">
        <w:r>
          <w:fldChar w:fldCharType="begin" />
        </w:r>
        <w:r>
          <w:instrText>DOCPROPERTY company_name \* MERGEFORMAT</w:instrText>
        </w:r>
        <w:r>
          <w:fldChar w:fldCharType="separate" />
        </w:r>
        <w:r>
        <w:rPr>
           <w:b />
          <w:color w:val="1F497D" />
          <w:sz w:val="24" />
      <w:szCs w:val="24" />
    </w:rPr>
  <w:t>Company Name</w:t>
  </w:r>
  ...
  <w:r>
    <w:rPr>
      <w:b />
      <w:color w:val="1F497D" />
      <w:sz w:val="24" />
      <w:szCs w:val="24" />
    </w:rPr>
    <w:fldChar w:fldCharType="end" />
  </w:r>
</w:p>

我没有等待某人解决问题,而是试图做一个初步的实施草案。我实际上修改了方法UpdateCustomPropertyValue(...)。我实际上添加了第一个 foreach 的代码。第二个 foreach 已经存在,它适用于从 DocX 创建的文档。

 internal static void UpdateCustomPropertyValue(DocX document, string customPropertyName, string customPropertyValue)
        {
            foreach (XElement e in document.mainDoc.Descendants(XName.Get("instrText", w.NamespaceName))) 
            {
                string attr_value = e.Value.Replace(" ", string.Empty).Trim();
                string match_value = string.Format(@"DOCPROPERTY  {0}  \* MERGEFORMAT", customPropertyName).Replace(" ", string.Empty);

                if (attr_value.Equals(match_value, StringComparison.CurrentCultureIgnoreCase))
                {
                    XNode node = e.Parent.NextNode;
                    bool found = false;
                    while (true)
                    {
                        if (node.NodeType == XmlNodeType.Element)
                        {
                            var ele = node as XElement;
                            var match = ele.Descendants(XName.Get("t", w.NamespaceName));
                            if (match.Count() > 0)
                            {
                                if (!found)
                                {
                                    match.First().Value = customPropertyValue;
                                    found = true;
                                }
                                else
                                {
                                    ele.RemoveNodes();
                                }
                            }
                            else
                            {
                                match = ele.Descendants(XName.Get("fldChar", w.NamespaceName));
                                if (match.Count() > 0)
                                {
                                    var endMatch = match.First().Attribute(XName.Get("fldCharType", w.NamespaceName));
                                    if (endMatch != null && endMatch.Value == "end")
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        node = node.NextNode;
                    }
                }
            }

            foreach (XElement e in document.mainDoc.Descendants(XName.Get("fldSimple", w.NamespaceName))) 
            {
                string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim();
                string match_value = string.Format(@"DOCPROPERTY  {0}  \* MERGEFORMAT", customPropertyName).Replace(" ", string.Empty);

                if (attr_value.Equals(match_value, StringComparison.CurrentCultureIgnoreCase))
                {
                    XElement firstRun = e.Element(w + "r");
                    XElement firstText = firstRun.Element(w + "t");
                    XElement rPr = firstText.Element(w + "rPr");

                    // Delete everything and insert updated text value
                    e.RemoveNodes();

                    XElement t = new XElement(w + "t", rPr, customPropertyValue);
                    Novacode.Text.PreserveSpace(t);
                    e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
                }
            }
}