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:
| Situation | What to call |
|---|---|
| Document you just created | AddHeader then SetHeader once. |
| Document opened from disk | GetHeader first, AddHeader only if it returns false. |
| Replacing the content of an existing header | GetHeader, 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.goIf this is your first time using UniOffice, follow the getting started guide to create an API key and set up your development environment.