Search code examples
c#ms-wordopenxml

How to set Publish Date in Word Document using OpenXML


I have a situation where a user can upload a word document which contains placeholders for certain properties (i.e. in MS Word the user has gone to Insert > Quick Parts > Document Properties and chosen a property). The specific properties I want to support are Title, Author, Company and Publish Date.

Title and Author are set as Package Properties, and Company is set as an Extended File Property. These are set with the below code, which works correctly:

private static void SetDocumentProperties(ReportTemplateModel model, WordprocessingDocument wordDocument)
{
    //these properties always exist
    wordDocument.PackageProperties.Title = model.Title;
    wordDocument.PackageProperties.Creator = model.Author;
    wordDocument.PackageProperties.Created = DateTime.Now;
    wordDocument.PackageProperties.Modified = DateTime.Now;

    //these properties can be null
    if (wordDocument.ExtendedFilePropertiesPart == null)
    {
        wordDocument.AddNewPart<ExtendedFilePropertiesPart>();
    }
    if (wordDocument.ExtendedFilePropertiesPart.Properties == null)
    {
        wordDocument.ExtendedFilePropertiesPart.Properties = new Properties(new Company(model.SiteName));
    }
    else
    {
        wordDocument.ExtendedFilePropertiesPart.Properties.Company = new Company(model.SiteName);
    }
}

My problem is that I can't work out how the set the Publish Date property. I have tried adding it as a Custom File Property using the below code (which is adapted from https://www.snip2code.com/Snippet/292005/WDSetCustomProperty), but this does not work. I've read a few things about setting custom properties, but I'm confused how they're meant to work. I'm also unsure if the Publish Date should actually be set as a custom property, or some other type of property.

var customProps = wordDocument.CustomFilePropertiesPart;
if (customProps == null)
{
    customProps = wordDocument.AddCustomFilePropertiesPart();
    customProps.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties();
}
var properties1 = new DocumentFormat.OpenXml.CustomProperties.Properties();

//I have tried both of these lines, neither worked.
//properties1.AddNamespaceDeclaration("op", "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties");
properties1.AddNamespaceDeclaration("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");

var customDocumentProperty1 = new DocumentFormat.OpenXml.CustomProperties.CustomDocumentProperty()
{
    FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
    PropertyId = 2,
    Name = "Publish Date"
};

customDocumentProperty1.Append(new DocumentFormat.OpenXml.VariantTypes.VTLPWSTR { Text = DateTime.Today.ToShortDateString() });

properties1.Append(customDocumentProperty1);

part.Properties = properties1;

What type of property should the Publish Date be set as, and what is the right syntax for setting this?

Update: I have found that Publish Date is a CoverPageProperty which can be created using the below snippet, but I still haven't found how to set it correctly within the document.

var coverPageProps = new DocumentFormat.OpenXml.Office.CoverPageProps.CoverPageProperties
{
    PublishDate = new PublishDate(DateTime.Today.ToShortDateString())
};

Solution

  • Adding the below code to my SetDocumentProperties method seems to work. I must admit I don't fully understand the below code, so any explanation would still be welcome. Additionally, if anyone has a solution which doesn't include writing XML as a string inside C# I would much prefer to avoid that.

    const string publishDatePartId = "publishDatePart";
    
    var publishDateXmlPart = wordDocument.MainDocumentPart.AddNewPart<CustomXmlPart>("application/xml", publishDatePartId);
    
    var writer = new XmlTextWriter(publishDateXmlPart.GetStream(FileMode.Create), System.Text.Encoding.UTF8);
    
    writer.WriteRaw($"<CoverPageProperties xmlns=\"http://schemas.microsoft.com/office/2006/coverPageProps\">" +
                    $"<PublishDate>{DateTime.Today.ToShortDateString()}</PublishDate>" +
                    $"</CoverPageProperties>");
    
    writer.Flush();
    
    writer.Close();
    
    var customXmlPropertiesPart = publishDateXmlPart.AddNewPart<CustomXmlPropertiesPart>(publishDatePartId);
    
    customXmlPropertiesPart.DataStoreItem = new DocumentFormat.OpenXml.CustomXmlDataProperties.DataStoreItem()
    {
        //I don't know what this ID is, but it seems to somehow relate to the Publish Date
        ItemId = "{55AF091B-3C7A-41E3-B477-F2FDAA23CFDA}"
    };