2011-11-09 11 views
6

De hecho, estoy usando la biblioteca "DocX" para generar documentos de Word (2007+) desde .Net. Lo bueno es que puede usar la plantilla "docx" para recrear o actualizar un documento.Agregar una CustomProperty existente no actualiza el documento

Problema: Cuando "AddCustomProperty (...)" no actualiza el documento de Word. De hecho, necesito abrirlo, seleccionar todo y presionar F9. Me preguntaba si había una forma de actualizar automáticamente las "propiedades personalizadas" usando la biblioteca DocX.

para reproducir mi problema que puede hacer los siguientes pasos:

  1. Abra la "muestra" disponible en el proyecto DOCX.
  2. Ejecutar una vez (se va a crear archivos en los depuración \ docs)
  3. abrir la plantilla de factura y luego añadir una línea (con o sin texto) y guardar el archivo
  4. Vuelva a ejecutar el proyecto misma muestra (usará la plantilla existente)
  5. Abra el resultado de la factura. Al hacerlo, se puede ver que la tabla se han creado, pero , todos los demás campos no han sido actualizados hasta que seleccione todos y luego pulsa Ctrl + F9

Si alguien tiene una solución, con mucho gusto me gustaría saberlo.

(Nota: Yo no quiero que la interoperabilidad MS Word)

proyecto y las muestras están disponibles en: http://docx.codeplex.com/

Respuesta

3

El problema es cuando usamos MS Word (yo uso la versión de 2010) y luego modificamos la plantilla y la guardamos. Cambia lo que contiene el documento.

Esto es lo que tenemos cuando nos generamos la plantilla con 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> 

Y cuando editamos con Word (añadir una línea de ruptura o un texto) y guardarlo, se reescribe la fldSimple a algo así:

<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> 

En lugar de esperar a que alguien solucione el problema, simplemente intenté hacer un primer borrador de implementación. De hecho, modifiqué el método UpdateCustomPropertyValue (...). De hecho, agregué el código del primer foreach. El segundo foreach ya estaba allí y se aplica al documento creado a partir de 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)); 
       } 
      } 
} 
Cuestiones relacionadas