Добавление существующего CustomProperty не обновляет документ - PullRequest
6 голосов
/ 09 ноября 2011

Я на самом деле использую библиотеку " DocX " для создания документа Word (2007+) из .Net. Что хорошо, так это то, что он может использовать шаблон «docx» для воссоздания или обновления документа.

Проблема : Когда я " AddCustomProperty (...) ", он не обновляет документ word. Мне действительно нужно открыть его, а затем выбрать все и нажать F9. Мне было интересно, есть ли способ автоматического обновления «пользовательских свойств» с помощью библиотеки DocX.

Чтобы воспроизвести мою проблему, вы можете сделать следующие шаги:

  1. Откройте «образец», доступный в проекте DocX.
  2. Запустите его один раз (он создаст файлы в debug \ docs)
  3. Откройте шаблон счета, затем добавьте строку (с текстом или без текста) и сохраните файл
  4. Перезапустить тот же пример проекта (он будет использовать существующий шаблон)
  5. Открыть результат счета. Когда вы это сделаете, вы увидите, что таблица была создана, НО , все остальные поля не были обновлены, пока вы не выберете все, а затем нажмите CTRL + F9

Если у кого-то есть решение, я бы с радостью об этом подумал.

(Примечание: я не хочу взаимодействия с MS Word)

Проект и образцы доступны по адресу: http://docx.codeplex.com/

1 Ответ

3 голосов
/ 09 ноября 2011

Проблема в том, что мы используем 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));
                }
            }
}
...