I am actually using the library "DocX" to generate Word document (2007+) from .Net. What is good is that it can use "docx" template to recreate or update a document.
Problem: When I "AddCustomProperty(...)" it does not update the word document. I actually need to open it and then select all and push F9. I was wondering if there was a way to auto-update the "custom properties" using the DocX library.
To reproduce my problem you can do the following steps:
If anyone has a solution, I would gladly like to ear about it.
(Note: I don't want the MS Word interop)
Project and samples are available at : http://docx.codeplex.com/
The problem is when we use MS Word (I use the 2010 version) and then we modify the template and save it. It changes what the document contains.
Here's what we have when we first generate the 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 with Word (add a break line or some text) and we save it, it rewrite the fldSimple to something like that:
<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>
Instead of waiting someone to fix the issue, I simply tried to do a first draft of implementation. I actually modified the method UpdateCustomPropertyValue(...). I actually added the code of the first foreach. The second foreach was already there and it apply to 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));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With