Skip to content

Preformatted text

Word collapses runs of spaces and ignores newlines, so a multi-line string placed in a document arrives as one long line with its indentation gone. That is fine for prose and wrong for a log excerpt, an address, or a code sample.

from docxtpl import Preformatted, Template

tpl = Template("report.docx")
tpl.render({"excerpt": Preformatted(log_output)})
tpl.save("report.docx")

In the template:

{{ excerpt }}

Newlines become line breaks, leading whitespace survives, and the text is escaped — which matters, because this is the object people reach for when the text came from outside the application.

Preformatted("""
    def render(self):
        if self.tags & {"<", "&"}:
            return escaped(self.text)
""")

Listing is the same object under docxtpl's name.

Preformatted or a plain string?

A plain string expands the same escapes — \n to a line break, \t to a tab, \a to a new paragraph, \f to a page break. What Preformatted adds is whitespace preservation: with a plain string, Word may collapse the leading spaces of an indented line.

plain string Preformatted
\n → line break yes yes
\t → tab yes yes
leading spaces kept not reliably yes
escaped yes, unless autoescape=False always

It is still one paragraph

The text is one run inside the paragraph the tag was in, so the paragraph's style, spacing and indentation apply to all of it. To give the excerpt its own look, apply a style to that paragraph in Word — Word's built-in No Spacing or a monospaced style of your own — and everything rendered into it inherits it.

For content that needs to be several paragraphs, with styles of its own, use a fragment.