class Program { static void Main(string[] args) { const string fileName = "SetCustomProperty.docx"; Console.WriteLine("Manager = " + SetCustomProperty(fileName, "Manager", "Peter", PropertyTypes.Text)); Console.WriteLine("ReviewDate = " + SetCustomProperty(fileName, "ReviewDate", DateTime.Parse("12/21/2010"), PropertyTypes.DateTime)); } public enum PropertyTypes : int { YesNo, Text, DateTime, NumberInteger, NumberDouble } public static string SetCustomProperty( string fileName, string propertyName, object propertyValue, PropertyTypes propertyType) { // Given a document name, a property name/value, and the property type, // add a custom property to a document. The method returns the original // value, if it existed. string returnValue = null; var newProp = new CustomDocumentProperty(); bool propSet = false; // Calculate the correct type. switch (propertyType) { case PropertyTypes.DateTime: // Be sure you were passed a real date, // and if so, format in the correct way. // The date/time value passed in should // represent a UTC date/time. if ((propertyValue) is DateTime) { newProp.VTFileTime = new VTFileTime(string.Format("{0:s}Z", Convert.ToDateTime(propertyValue))); propSet = true; } break; case PropertyTypes.NumberInteger: if ((propertyValue) is int) { newProp.VTInt32 = new VTInt32(propertyValue.ToString()); propSet = true; } break; case PropertyTypes.NumberDouble: if (propertyValue is double) { newProp.VTFloat = new VTFloat(propertyValue.ToString()); propSet = true; } break; case PropertyTypes.Text: newProp.VTLPWSTR = new VTLPWSTR(propertyValue.ToString()); propSet = true; break; case PropertyTypes.YesNo: if (propertyValue is bool) { // Must be lowercase. newProp.VTBool = new VTBool( Convert.ToBoolean(propertyValue).ToString().ToLower()); propSet = true; } break; } if (!propSet) { // If the code was not able to convert the // property to a valid value, throw an exception. throw new InvalidDataException("propertyValue"); } // Now that you have handled the parameters, start // working on the document. newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"; newProp.Name = propertyName; using (var document = WordprocessingDocument.Open(fileName, true)) { var customProps = document.CustomFilePropertiesPart; if (customProps == null) { // No custom properties? Add the part, and the // collection of properties now. customProps = document.AddCustomFilePropertiesPart(); customProps.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties(); } var props = customProps.Properties; if (props != null) { // This will trigger an exception if the property's Name // property is null, but if that happens, the property is damaged, // and probably should raise an exception. var prop = props.Where( p => ((CustomDocumentProperty)p).Name.Value == propertyName).FirstOrDefault(); // Does the property exist? If so, get the return value, // and then delete the property. if (prop != null) { returnValue = prop.InnerText; prop.Remove(); } // Append the new property, and // fix up all the property ID values. // The PropertyId value must start at 2. props.AppendChild(newProp); int pid = 2; foreach (CustomDocumentProperty item in props) { item.PropertyId = pid++; } props.Save(); } } return returnValue; } }