Skip to content
Headers in an Existing Document

Headers in an Existing Document

When you open a document rather than create one, it may already have a header, and calling AddHeader regardless leaves the section pointing at two of them. Section.GetHeader returns the header attached to a given type together with a boolean saying whether there was one, which is enough to write code that works either way.

func setOrCreateHeader(doc *document.Document, text string) {
    hdr, ok := doc.BodySection().GetHeader(wml.ST_HdrFtrDefault)
    if !ok {
        hdr = doc.AddHeader()
        doc.BodySection().SetHeader(hdr, wml.ST_HdrFtrDefault)
    }

    para := hdr.AddParagraph()
    run := para.AddRun()
    run.AddBreak()
    run.AddText(text)
}

Call it twice and the first call creates the header, the second finds it and appends a paragraph. The same function works on a document from document.Open that already carries a header from Word.

GetHeader matches by walking the section’s header references, resolving each one’s relationship ID against the document’s header parts. A header created with AddHeader but never passed to SetHeader is not found, because there is no reference to match.

Why the guard matters

SetHeader appends a header reference to the section every time it is called. It does not look for an existing reference of the same type and does not replace one. Two default header references in one section is not a state UniOffice resolves, so what a reader sees depends on the application opening the file.

That makes the check the only safe way to change a header:

SituationWhat to call
Document you just createdAddHeader then SetHeader once.
Document opened from diskGetHeader first, AddHeader only if it returns false.
Replacing the content of an existing headerGetHeader, then Clear() before adding paragraphs.

Header.Clear empties a header’s content while leaving the header part and its reference in place, which is what you want when the goal is to rewrite a header rather than append to it.

Limitations

GetHeader looks at one section. doc.BodySection() is the last section in the document, so on a multi-section file it will not find headers attached to earlier sections. Reach those through paragraph.Properties().Section(), which returns the section on a paragraph if it has one.

There is no call that detaches a header from a section. Setting the same type again adds a second reference rather than swapping, so removing a header means editing section.X().EG_HdrFtrReferences directly.

The example creates its document with document.New() and does not call doc.Close(). Close removes the temporary files created when a document is opened, so it costs nothing here, but any code that reaches this pattern by way of document.Open should defer it.

Run the example

The example calls its setOrCreateHeader helper twice against a new document, so the saved file has one header with two lines of text rather than two headers.

git clone https://github.com/unidoc/unioffice-examples.git
cd unioffice-examples/document/doc-existing-header
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
Last updated on