Skip to content

Document Properties

The built-in properties are the fixed set that every OOXML document has, stored in docProps/core.xml and shown by Word in its document information panel. UniOffice exposes them as Document.CoreProperties, a field inherited from common.DocBase and therefore identical on a spreadsheet and a presentation.

They are not the same thing as Custom Properties, which are arbitrary name and value pairs in a different part with a different API. If the property you want has a fixed name in Word’s dialog it is here; if you invented the name yourself it is there.

Getter and setterStored as
Title / SetTitledc:title
Author / SetAuthordc:creator
Description / SetDescriptiondc:description
Category / SetCategorycp:category
ContentStatus / SetContentStatuscp:contentStatus
LastModifiedBy / SetLastModifiedBycp:lastModifiedBy
Created / SetCreateddcterms:created
Modified / SetModifieddcterms:modified
SetLanguage onlydc:language

Author reading dc:creator is the mapping people trip over when they go looking in the XML for an author element.

Reading and writing

doc, err := document.Open("document.docx")
if err != nil {
    log.Fatalf("error opening document: %s", err)
}
defer doc.Close()

cp := doc.CoreProperties
fmt.Println("Title:", cp.Title())
fmt.Println("Author:", cp.Author())

cp.SetTitle("CP Invoices")
cp.SetAuthor("John Doe")
cp.SetModified(time.Now().UTC())

doc.SaveToFile("document_modified.docx")

CoreProperties is a value type wrapping a pointer, so assigning it to a local and calling setters on the local still edits the document. The setters create their XML element on demand, which means you can set a property on a document that never had one.

Nothing here needs document.New(); the properties round-trip through document.Open unchanged unless you touch them. Note that SaveToFile returns an error the example discards.

Limitations

The getters return the empty string when the element is absent, so a property that was never set and one set to an empty string are indistinguishable.

Several properties in the underlying type have no wrapper method: Subject, Keywords, Revision, LastPrinted, Identifier and Version are all fields on the schema type but have no getter or setter on CoreProperties. Language has a setter and no getter. Reach them through doc.CoreProperties.X(), which returns the *core_properties.CoreProperties and lets you read or assign the fields directly.

Timestamp parsing accepts exactly one layout, 2006-01-02T15:04:05Z. A document whose dcterms:created carries a UTC offset instead of a Z fails to parse, and Created() returns the zero time.Time with the failure logged only at debug level. If a date comes back as year 1 rather than an error, this is why.

The write side does not normalize either. SetCreated and SetModified format the time.Time you hand them without converting to UTC first, then append the Z suffix regardless. Passing time.Now() from a machine in a non-UTC zone therefore writes the local wall clock labeled as UTC, and the document ends up claiming it was modified hours from when it was. Pass time.Now().UTC().

Run the example

The example opens document.docx, prints eight properties as it finds them, then overwrites most of them and saves to document_modified.docx. The values printed are what the input file already contained, not what the code sets afterwards.

git clone https://github.com/unidoc/unioffice-examples.git
cd unioffice-examples/document/doc-properties
go run main.go

If this is your first time using UniOffice, follow the getting started guide to create an API key and set up your development environment.

View the full source

Sample output

Title: CP Invoices
Author: John Doe
Description:
Last Modified By: [a Cyrillic name, reproduced verbatim]
Category: Invoices
Content Status:
Created: 2020-06-09 09:25:00 +0000 UTC
Modified: 2020-06-09 09:28:00 +0000 UTC

Description and Content Status are blank because the input document has no dc:description or cp:contentStatus. The last modified by value is a name in Cyrillic; it comes through intact, and is stood in for above because this page is ASCII. Open document_modified.docx afterwards to see the values the code wrote.

Last updated on