Reputation: 2827
I'm trying to get the internal structure of a word document template using the openxml sdk 2.5.
The point is that when I call the innertext property of a docpart where I added a docproperty it always adds an aditional "Error! Unknown document property name." string...
/// <summary>
/// Examines a word document to create the data structure of autotexts
/// </summary>
/// <param name="document">Word document to be processed</param>
/// <returns>OpenXMLAutoTextContainer</returns>
public static OpenXMLAutotextContainer GetAutotextContainer(WordprocessingDocument document)
{
OpenXMLAutotextContainer result = null;
try
{
result = new OpenXMLAutotextContainer()
{
Name = document.ExtendedFilePropertiesPart.Properties.Template.InnerText
};
result.OpenXMLAutoTextList = new Dictionary<string, OpenXMLAutotext>();
List<CIProField> CIProFields = null;
foreach (DocPart _docPart in document.MainDocumentPart.GlossaryDocumentPart.GlossaryDocument.DocParts)
{
if (_docPart.DocPartProperties.Category.Gallery.Val == "autoTxt")
{
CIProFields = new List<CIProField>();
result.OpenXMLAutoTextList.Add(
_docPart.DocPartProperties.DocPartName.Val,
new OpenXMLAutotext()
{
Name = _docPart.DocPartProperties.DocPartName.Val,
Content = _docPart.DocPartBody.InnerText,
CIProFields = CIProFields
});
}
}
}
catch (Exception ex)
{
OpenXMLCustomException e = new OpenXMLCustomException(ex, "GetAutotextContainer");
throw e;
}
return result;
}
}
The OpenXML SDK Output:
<w:docPart xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:docPartPr>
<w:name w:val="W_DocProp01" />
<w:style w:val="Normal" />
<w:category>
<w:name w:val="General" />
<w:gallery w:val="autoTxt" />
</w:category>
<w:behaviors>
<w:behavior w:val="content" />
</w:behaviors>
<w:guid w:val="{12809B83-5021-4211-A70D-EA3447274A83}" />
</w:docPartPr>
<w:docPartBody>
<w:p w:rsidRPr="001E1D2D" w:rsidR="00F6185D" w:rsidP="001E1D2D" w:rsidRDefault="00F6185D">
<w:pPr>
<w:rPr>
<w:lang w:val="es-ES" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:lang w:val="es-ES" />
</w:rPr>
<w:fldChar w:fldCharType="begin" />
</w:r>
<w:r>
<w:rPr>
<w:lang w:val="es-ES" />
</w:rPr>
<w:instrText>DOCPROPERTY "Test_W_DocProp01"</w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:lang w:val="es-ES" />
</w:rPr>
<w:fldChar w:fldCharType="separate" />
</w:r>
<w:r>
<w:rPr>
<w:b />
<w:bCs />
<w:lang w:val="en-US" />
</w:rPr>
<w:t>Error! Unknown document property name.</w:t>
</w:r>
<w:r>
<w:rPr>
<w:lang w:val="es-ES" />
</w:rPr>
<w:fldChar w:fldCharType="end" />
</w:r>
</w:p>
<w:p w:rsidR="00000000" w:rsidRDefault="00F6185D" />
</w:docPartBody>
</w:docPart>
Upvotes: 0
Views: 1336
Reputation: 2865
It seems like you are referencing a document property that is not present in the document. You can set the properties manually via Word (for 2007 see http://office.microsoft.com/en-001/word-help/view-or-change-the-properties-for-an-office-document-HA010047524.aspx#BM15) or via openXML (http://msdn.microsoft.com/en-us/library/ff936167(v=office.14).aspx)
UPDATE
OpenXML does not refresh properties. If you inserted a property and didn't ask Word to refresh it, you'll get the message you're seeing - even if the property is already there. Take a look at this for a more "official" answer - http://social.msdn.microsoft.com/Forums/office/en-US/f72c9489-dc50-457b-8629-567f83882770/update-word-document-properties.
I think that if you plan to work with OpenXML, your best option would be to read the properties like you do. Once you have the name, don't look at the value which is stored there, but get the corresponding document property value. This way you'll always get the most up-to-date version. The value you'll get the way you work now is the last value which was updated in word.
You get use the following method to get a dictionary of custom document property names and values -
private static Dictionary<string, string> GetCustomDocumentProperties(WordprocessingDocument p_document)
{
if (p_document.CustomFilePropertiesPart == null)
{
return new Dictionary<string, string>();
}
else
{
return p_document.CustomFilePropertiesPart.Properties.ToDictionary(p => ((CustomDocumentProperty) p).Name.InnerText,
p => ((CustomDocumentProperty) p).InnerText);
}
}
Upvotes: 2