Add existing CustomProperty does not update the document

I really use the DocX library to create a Word document (2007+) from .Net. It's good that it can use the docx template to recreate or update the document.

Problem . When I AddCustomProperty (...) , it does not update the word document. I really need to open it and then select everything and press F9. I was wondering if there is a way to automatically update "user properties" using the DocX library.

To reproduce my problem, you can take the following steps:

  • Open the "sample" available in the DocX project.
  • Run it once (it will create files in debug \ docs)
  • Open the invoice template and add a line (with or without text) and save the file
  • Re-run the same sample project (it will use the existing template)
  • Open an invoice. When you do this, you will see that the table has been created, BUT> , all other fields have not been updated until you select everything, and then press CTRL + F9

If anyone has a solution, I would love to take care of it.

(Note: I do not want to use MS Word)

Design and samples are available at: http://docx.codeplex.com/

+6
source share
1 answer

The problem is that we use MS Word (I use the 2010 version), and then we modify the template and save it. It changes the contents of the document.

Here is what we have when we first create a template using 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> 

And when we edit Word (add an interrupt line or some text), and we save it, it rewrites fldSimple like this:

 <w:pw: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> 

Instead of waiting for someone to fix this problem, I just tried to make the first implementation project. I actually modified the UpdateCustomPropertyValue (...) method. I really added the code of the first foreach . The second foreach already exists and applies to the document created from 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)); } } } 
+3
source

Source: https://habr.com/ru/post/901093/


All Articles