Template with a Header
A letterhead template is the common case for document.OpenTemplate: the header
carries the logo and address block, the footer carries the small print, and your
program supplies the letter. The catch is that clearing the body also clears the
section properties that point at the header, so the header part survives the
open but stops being referenced. You have to attach it again before saving.
Reattaching the header
doc, err := document.OpenTemplate("letter_template.docx")
if err != nil {
return err
}
defer doc.Close()
if len(doc.Headers()) > 0 {
doc.BodySection().SetHeader(doc.Headers()[0], wml.ST_HdrFtrDefault)
}
if len(doc.Footers()) > 0 {
doc.BodySection().SetFooter(doc.Footers()[0], wml.ST_HdrFtrDefault)
}Headers() returns the header parts in the order they were stored in the file,
which is not a meaningful order. A template with one header is unambiguous; a
template with a first-page header and a different default one is not, and there
is nothing on Header that tells you which is which. Attaching the wrong one is
silent.
The type argument decides where the header appears: wml.ST_HdrFtrDefault for
ordinary pages, wml.ST_HdrFtrFirst for the first page of the section, and
wml.ST_HdrFtrEven for even pages. ST_HdrFtrEven also needs even and odd
headers enabled in the document settings before Word will honor it, which
Odd and Even Headers covers.
Generating one document per record
The example loads a JSON file of letters and calls generateDoc for each. Each
call reopens the template, so every letter starts from a clean copy. That matters:
a Document is mutable and there is no reset, so reusing one across records
would append the second letter under the first. Reopening a small template per
record is cheap next to the cost of writing the file.
Body text is styled by looking for the “Normal” style in doc.Styles.Styles()
and passing it to para.SetStyle, which keeps the generated paragraphs in the
template’s font rather than the library default. SetStyle wants the style ID
rather than the display name; “Normal” is one of the cases where the two are
identical, so passing the name works here and would not for a style like
“Heading 1”. doc.Styles.SearchStyleByName is the reliable way to go from a
display name to the ID.
Limitations
SetHeader appends a reference to the section rather than replacing one, so
calling it twice with the same type leaves two references in the section
properties. Attach each type once.
If the header cannot be resolved to a relationship ID, SetHeader logs a debug
message and writes an empty reference instead of returning an error. Enable the
library logger while developing against an unfamiliar template, or the header
simply will not be there.
OpenTemplate also drops page size, orientation and margins along with the rest
of the section properties. A letterhead built on non-default margins needs those
set again through doc.BodySection().
The example writes into ./output/. SaveToFile does not create directories,
so a missing output folder surfaces as a failure to generate the document.
Run the example
loadLetters reads data/letters.json into a slice of letter values, and
generateDoc renders one .docx per recipient into output/, named after the
receiver.
git clone https://github.com/unidoc/unioffice-examples.git
cd unioffice-examples/document/template-with-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.