Attaching documents to questions

The attachments statement

The attachments block (which can also be written attachment) creates documents that users can download and/or e-mail.

It can be used within a question or outside of a question.

mandatory: True
question: Your document is ready.
attachment:
  - name: A hello world document
    filename: Hello_World
    description: |
      A document with a classic message
    content: |
      Hello, world!
attachment-simple

The name, filename, and description items can contain Mako templates. The name and description filenames can also contain Markdown. (The filename cannot contain Markdown, since it’s a filename, after all.)

Overview of document creation methods

There are several ways to make downloadable documents using the attachments block. Each has its own features and limitations.

Method 1: generating documents from scratch using Markdown

First, you can generate attachments from Markdown. In the same way that you format the text of questions, you can format the text of attachments. This document source:

Hello, ${ user }.  This text is in **bold face**.

would become this document content:

Hello, John Doe. This text is in bold face.

In this way, you can produce documents in PDF, RTF, and DOCX format.

In addition to using Markdown, you can use docassemble-specific markup codes to do things like center text, insert a page break, or insert a case caption.

Method 2: filling in fields

The second way to make attachments is to generate PDF or DOCX using templates that you prepare in Adobe Acrobat Pro or Microsoft Word. You put the template file in the data/templates folder of a package. The attachments block will take the template and “fill in the blanks” using values from interview variables, providing the user with a filled-in version of the template.

Here is an example that generates a PDF file:

question: |
  Here is your PDF form
attachment:
  name: A filled-in form
  filename: filled-form
  pdf template file: sample-form.pdf
  fields:
    Your Name: |
      ${ user }
    Your Organization: |
      ${ user.organization }
    Apple Checkbox: |
      ${ likes_apples }
    Orange Checkbox: |
      ${ likes_oranges }
    Pear Checkbox: |
      ${ likes_pears }
    Toast Checkbox: |
      ${ likes_toast }
mandatory: True
pdf-fill

Here is an example that generates a .docx file:

mandatory: True
question: |
  Here is your document.
attachment:
  name: Your letter
  filename: letter
  docx template file: letter_template.docx
docx-template

Comparison of the methods

Each method has benefits.

The advantage of the fill-in-fields method is that you have more direct, WYSIWYG control over document formatting.

The advantage of the Markdown method is that you can concentrate on the content and let docassemble handle the formatting. For example, there are automatic methods for generating case captions in legal documents created from Markdown, whereas if you create your legal document in .docx format, you will need to construct your caption in the .docx template file and make sure that it gets filled in correctly. The Markdown method allows for more readable embedded if/then/else statements. In the .docx template method, you have to write:

I {% if employed %}have a job.{% else %}am unemployed.{% endif %}

By contrast, Markdown treats single line breaks as spaces, so you can write:

I
% if employed:
have a job.
% else
am unemployed.
% endif

You may find it easier to read your if/then/else statements when you can arrange them vertically in this fashion.

If you use the PDF fill-in field method to populate fields in a PDF file, you will have total control over pagination, but you will need to worry about whether the user’s content will fit into the provided fields. Also, the PDF fill-in field method requires that you write an itemized list of fields in your document and the values you want those fields to have. Markdown documents and DOCX fill-in forms are more flexible because they do not require this itemization of fields. Also, note that the DOCX fill-in forms method provides not only a .docx file, but a PDF version of that .docx file.

Creating files from Markdown

Creating PDF and RTF files from Markdown

The following attachment block offers the user a PDF file and an RTF file containing the phrase “Hello, world!”

mandatory: True
question: Your document is ready.
attachment:
  - name: A hello world document
    filename: Hello_World
    description: |
      A document with a classic message
    content: |
      Hello, world!
attachment-simple

The content item can contain Mako and Markdown. Pandoc converts the content into PDF, RTF, and HTML (the HTML is just for previewing the document in the browser).

The PDF file will be called Hello_World.pdf and will look like this in a PDF viewer (depending on the user’s software):

document screenshot

The RTF file will be called Hello_World.rtf and will look like this in a word processor (depending on the user’s software):

document screenshot

If the user clicks the “Preview” tab, an HTML version of the document will be visible:

document screenshot

Creating DOCX files from Markdown

docassemble can use Pandoc to convert Markdown into a Microsoft Word .docx file. These .docx files are not created by default because they do not support all of the features that are supported by RTF and PDF formats. To generate .docx files, specify docx as one of the valid formats:

question: Here is your document.
attachments:
  - name: Summary of Benefits
    filename: benefits_summary
    valid formats:
      - docx
      - pdf    
    content: |
      [BOLDCENTER] Summary of Benefits

      ${ client } is entitled to
      benefits plan ${ benefits }.
mandatory: True
document-docx

Note that you can also create .docx files using the docx template file feature, which is described below.

To customize document styles, headers, and footers in your .docx file, see the docx reference file setting, discussed below.

Reading Markdown content from separate files

If the content of your document is lengthy and you would rather not type it into the interview YAML file as a content directive within an attachments block, you can import the content from a separate file using content file:

question: Your document is ready.
attachment:
  - name: A *hello world* document
    filename: Hello_World_Document
    content file: hello.md
mandatory: True
document-file

The content of the Markdown file, hello.md, is:

Hello, world!

Files referenced with content file are assumed to reside in the data/templates directory within the package in which the interview YAML file is located. You can specify filenames in other locations by specifying a package name and path. For example:

content file: docassemble.demo:data/templates/complaint.md

The content file can also refer to a list of file names:

content file:
  - introduction.md
  - jurisdiction.md
  - discussion.md

In this case, the content of multiple content file files will be concatenated.

Formatting documents with special markup tags

In addition to using Markdown syntax, you can use docassemble-specific markup tags to control the appearance of documents.

  • [START_INDENTATION] - From now on, indent the first line of every paragraph.
  • [STOP_INDENTATION] - From now on, do not indent the first line of every paragraph.
  • [BEGIN_TWOCOL] First column text [BREAK] Second column text [END_TWOCOL] - Puts text into two columns.
  • [FLUSHLEFT] - Used at the beginning of a paragraph to indicate that the paragraph should be flushed left and not indented.
  • [FLUSHRIGHT] - Used at the beginning of a paragraph to indicate that the paragraph should be flushed right and not indented.
  • [CENTER] - Used at the beginning of a paragraph to indicate that the paragraph should be centered.
  • [BOLDCENTER] - Like [CENTER] except that text is bolded.
  • [NOINDENT] - Used at the beginning of a paragraph to indicate that the first line of the paragraph should not be indented.
  • [INDENTBY 1in] - Used at the beginning of a paragraph to indicate that all the lines of the paragraph should be indented on the left. In this example, the amount of indentation is one inch. You can express lengths using units of in for inches, pt for points, or cm for centimeters.
  • [INDENTBY 1in 0.5in] - This is like the previous tag, except it indents both on the left and on the right. In this example, the amount of left indentation is one inch and the amount of right indentation is half an inch.
  • [BORDER] - Used at the beginning of a paragraph to indicate that the paragraph should have a box drawn around it. (The border will only go around one paragraph; that is, the effect of [BORDER] lasts until the next empty line. You can use [NEWPAR] in place of an empty line to extend the effect of the [BORDER] tag to another paragraph.)
  • [SINGLESPACING] - From now on, paragraphs should be single-spaced without indentation the first lines.
  • [ONEANDAHALFSPACING] - From now on, paragraphs should be one-and-a-half-spaced, with indentation of first lines.
  • [DOUBLESPACING] - From now on, paragraphs should be double-spaced, with indentation of first lines.
  • [TRIPLESPACING] - From now on, paragraphs should be triple-spaced, with indentation of first lines.
  • [TIGHTSPACING] - This is like [SINGLESPACING] except there is no spacing between paragraphs.
  • [NBSP] - Insert a non-breaking space.
  • [ENDASH] - Normally, -- produces an en-dash, but if you want to be explicit, [ENDASH] will do the same thing.
  • [EMDASH] - Normally, --- produces an em-dash, but if you want to be explicit, [EMDASH] will do the same thing.
  • [HYPHEN] - Insert a hyphen. Normally, --- produces an em-dash, but if you want to be explicit, [HYPHEN] will do the same thing.
  • [PAGEBREAK] - Insert a manual page break.
  • [PAGENUM] - Insert the current page number.
  • [SECTIONNUM] - Insert the current section number.
  • [NEWPAR] - Insert a paragraph break. (Cannot be used within [FLUSHLEFT], [FLUSHRIGHT], [CENTER], or [BOLDCENTER] environments.)
  • [SKIPLINE] - Skip a line (insert vertical space). This is different from [NEWPAR] because [NEWPAR] breaks a paragraph but multiple calls to [NEWPAR] will not insert additional vertical space. (Cannot be used within [FLUSHLEFT], [FLUSHRIGHT], [CENTER], or [BOLDCENTER] environments.)
  • [BR] - Insert a line break. [BR] is useful to use with environments like [FLUSHLEFT], [FLUSHRIGHT], [CENTER], and [BOLDCENTER] that only apply to a single paragraph. Within the [BEGIN_TWOCOL] environment, a standard Markdown paragraph break (pressing enter twice, i.e., leaving one blank line) has the same effect.
  • [TAB] - Insert a tab (horizontal space), e.g., to indent the first line of a paragraph when it otherwise would not be indented.

This interview demonstrates these features:

mandatory: True
question: Here is your document.
attachment:
  name: A demonstration
  filename: demo_document
  description: |
    This document demonstrates the
    markup codes you can insert into
    document text.
  metadata:
    FirstFooterLeft: |
      First of [TOTALPAGES] pages
    HeaderLeft: |
      Page [PAGENUM] of [TOTALPAGES]
  content: |
    [BOLDCENTER] Lorem Ipsum Dolor Sit
    Amet

    [BEGIN_CAPTION]
    Consectetur adipiscing elit.
    
    Integer nec ${ client_name } odio.

    Praesent libero.

    [VERTICAL_LINE]

    Sed cursus ante dapibus diam.

    Sed nisi.
    [END_CAPTION]

    [CENTER] Nulla quis sem at
    nibh elementum imperdiet.

    Duis sagittis ipsum. Praesent
    mauris. Fusce nec tellus sed
    augue semper porta. Mauris massa.
    Proin ut ligula vel nunc egestas
    porttitor.
    
    Vestibulum lacinia arcu eget nulla. 
    Class aptent taciti sociosqu ad
    litora torquent per conubia nostra,
    per inceptos himenaeos.
    
    Curabitur sodales
    ligula in libero. Praesent
    mauris. Fusce nec tellus sed
    augue semper porta. Mauris massa.
    Proin ut ligula vel nunc egestas
    porttitor.

    [FLUSHLEFT] Sed dignissim. [NEWLINE]
    Lacinia nunc. [NEWLINE]
    Curabitur tortor. [NEWLINE]
    These lines are [NEWLINE]
    flushed left.

    Pellentesque nibh.

    [NOINDENT] Primis tacimates eos
    in. Vel affert vituperata te, eos
    te melius legimus temporibus. At
    quaeque aliquando contentiones
    his. First-line indentation is
    suppressed in this paragraph.
    
    [FILE stareps.eps]
    
    Unless a width is specified, images
    will be displayed four inches wide.
    Maecenas mattis. Sed convallis
    tristique sem.

    [FLUSHRIGHT] Proin ut ligula
    vel nunc egestas porttitor.
    [NEWLINE]
    Quisque volutpat condimentum
    velit. [NEWLINE]
    We are flushed right.
    
    Morbi lectus risus, iaculis vel,
    suscipit quis, luctus non, massa.
    Time for a page break.

    [PAGEBREAK]

    Nulla facilisi. Ut fringilla.
    Suspendisse potenti.
    
    [INDENTBY 3in] Curabitur tortor.
    Pellentesque nibh. Aenean quam.
    In scelerisque sem at dolor.
    Maecenas mattis. Sed convallis
    tristique sem. Proin ut ligula
    vel nunc egestas porttitor. I
    am indented by three inches.

    [INDENTBY 1in 1in] Morbi lectus
    risus, iaculis vel, suscipit quis,
    luctus non, massa.  Fusce ac
    turpis quis ligula lacinia
    aliquet. Sed convallis tristique
    sem. I am indented by one inch
    on each side.

    Now, let's put text in two columns
    side by side.
    
    [BEGIN_TWOCOL]

    This is the first column.
    
    Nulla facilisi.

    Let's insert some vertical space.

    [SKIPLINE]
    Cras metus.

    [BREAK]

    This is the second column.
    
    Cras metus. Let's have some
    vertical space again.

    [SKIPLINE]

    Integer id quam.

    Morbi mi.

    [END_TWOCOL]

    
    Quisque nisl felis, venenatis
    tristique, dignissim in,
    ultrices sit amet, augue.

    [FLUSHLEFT] [FILE bluediamond.png, 0.5in]

    Maecenas mattis. Sed convallis
    tristique sem.
    
    [BORDER] Vestibulum ante ipsum
    primis in faucibus orci luctus et
    ultrices posuere cubilia
    Curae; [FILE bluediamond.png, 10pt]
    Morbi lacinia molestie dui. 

    Here we see various types of dashes.
    Praesent[HYPHEN]mauris.  Nulla 
    quis [ENDASH] sem at nibh
    elementum imperdiet.  Duis
    sagittis[EMDASH]ipsum.

    [BORDER] Class aptent
    taciti sociosqu ad litora torquent
    per conubia nostra, per inceptos 
    himenaeos.
    [NEWPAR]
    Curabitur sodales ligula in libero.
    Sed dignissim lacinia nunc.
    [NEWPAR]
    You can include paragraph breaks 
    inside of a border.

    Aenean quam. In scelerisque sem at 
    dolor. Maecenas mattis. Sed 
    convallis tristique sem.  Let us 
    now stop indenting the first line 
    of each paragraph.

    [STOP_INDENTATION]

    Duis sagittis ipsum. Praesent
    mauris. Fusce nec tellus sed
    augue semper porta. Mauris massa.
    Proin ut ligula vel nunc egestas
    porttitor.

    Praesent mauris. Fusce nec tellus sed
    augue semper porta. 

    [TAB] Even though we are no longer
    indenting the first line of each 
    paragraph automatically, we can 
    still indent manually.
    
    Vestibulum lacinia arcu eget nulla. 
    Class aptent taciti sociosqu ad
    litora torquent per conubia nostra,
    per inceptos himenaeos.  Let us go
    back to indenting the first line
    of each paragraph.  

    [START_INDENTATION]

    Duis sagittis ipsum. Praesent mauris. 
    Fusce nec tellus sed augue semper 
    porta. Mauris massa.  Proin ut 
    ligula vel nunc egestas porttitor.
    
    Vestibulum lacinia arcu eget nulla. 
    Class aptent taciti sociosqu ad
    litora torquent per conubia nostra,
    per inceptos himenaeos.  Let's try
    single spacing now.

    [SINGLESPACING]

    Ullum primis scripserit ne vis, ad eam
    quem dictas dissentias. Alia
    scripserit vel cu, choro delicata
    dissentiunt mel no, reque persequeris
    mei an. Paulo graeci ex eos, no usu
    dicit inimicus. In putant ornatus
    forensibus cum, percipit mediocrem
    in vel.

    Alii timeam eos ut, habeo oblique
    ocurreret ei sea. Quis utroque
    definiebas et per, ad sumo
    repudiandae eam, pro no sale
    adolescens. Habeo splendide
    evertitur has eu, in has vocent
    signiferumque. Ex qui homero graeci
    quaerendum, nulla veniam blandit
    ei mea. Sea at idque referrentur.
    Sit autem liberavisse te.  Let's 
    go back to double spacing now.

    [DOUBLESPACING]

    Sea ad tacimates elaboraret, 
    vel simul urbanitas efficiantur id. 
    Id mel option denique. Ludus essent
    eu ius, natum option appareat cu mea, 
    in saepe deterruisset pri. Mei et vero 
    admodum. At quas pertinax sed, et mel 
    modo probo iriure. Per te sententiae 
    elaboraret. Cum tritani delectus 
    definitionem ne.
document-markup

Formatting documents with Pandoc templates and metadata

You can also control global formatting options by setting metadata for the document. These options are passed through to Pandoc, where they are applied to document templates.

---
question: Your document is ready.
sets: provide_user_with_document
attachment:
  - name: A *hello world* document
    filename: Hello_World_Document
    metadata:
      SingleSpacing: True
      fontsize: 10pt
    description: A document with a **classic** message
    content: |
      Hello, world!  Quisque ut tempus enim. Aliquam tristique
      placerat metus sollicitudin imperdiet. Donec eget dignissim
      libero, eu elementum justo.

      Maecenas iaculis mollis aliquam. Nullam vestibulum erat in
      sapien ultrices dignissim eu et turpis. Vivamus vestibulum felis
      eu sodales ornare. Nunc auctor sapien et porttitor posuere.
---

Metadata values can contain Mako template commands.

Metadata applicable to RTF and PDF files

  • If you wish to use a standard document title, set the following:
    • title
    • author - a list
    • date
  • toc - default is not defined. If defined, a table of contents is included.
  • SingleSpacing - set this to True for single spacing and no indentation of first lines of paragraphs.
  • OneAndAHalfSpacing - set to True for 1.5 spacing, with indentation of first lines.
  • DoubleSpacing - set this to True for double spacing with indentation of first lines. This is the default.
  • TripleSpacing - set this to True for triple spacing with indentation of first lines.
  • fontsize - default is 12pt. Must be one of 10pt, 11pt, and 12pt.
  • Indentation - not defined by default. By default, the first line of each paragraph is indented, unless SingleSpacing is set, in which case there is no indentation.
  • IndentationAmount - not defined by default. When double spacing is used, the default is 0.5 inches of first-line indentation in each paragraph.
  • To set the text of headers and footers (which can contain Mako and Markdown), define one or more of the following:
    • FirstFooterLeft
    • FirstFooterCenter
    • FirstFooterRight
    • FirstHeaderLeft
    • FirstHeaderCenter
    • FirstHeaderRight
    • FooterLeft
    • FooterCenter
    • FooterRight
    • HeaderLeft
    • HeaderCenter
    • HeaderRight

Metadata applicable to generated PDFs only

The following metadata tags only apply to PDF file generation. To change analogous formatting in RTF files, you will need to create your own RTF document template (for more information on how to do that, see the next section).

  • HangingIndent - set this to True if you want text in lists to using hanging indentation.
  • fontfamily - default is mathptmx (Times Roman).
  • lang and mainlang - not defined by default. If defined, polyglossia (for XeTeX) or babel is loaded and the language is set to mainlang if polyglossia is loaded and lang if babel is loaded.
  • papersize - default is letterpaper.
  • documentclass - default is article.
  • numbersections - default is True. If true, sections are numbered; if false, they are not. (In LaTeX, secnumdepth is set to 5, otherwise 0.)
  • geometry - default is left=1in,right=1in,top=1in,bottom=1in,heightrounded. These are options for the the geometry package that set the page margins.
  • TopMargin - default is 1in. If you changed the top margin in geometry, change it here as well.
  • BottomMargin - default is 1in. If you changed the bottom margin in geometry, change it here as well.
  • FooterSkip - default is not defined. If defined, will set the footskip option of the geometry package to control spacing between the footer and the text.
  • author-meta - default is not defined. Sets author item of PDF metadata using the pdfauthor option of hyperref.
  • title-meta - default is not defined. Sets title item of PDF metadata using the pdftitle option of hyperref.
  • citecolor - default is not defined. Sets the citecolor option of hyperref, which will default to blue if this is not defined.
  • urlcolor - default is not defined. Sets the urlcolor option of hyperref, which will default to blue if this is not defined.
  • linkcolor - default is not defined. Sets the linkcolor option of hyperref, which will default to magenta if this is not defined.
  • abstract - default is not defined. If defined, it will include an article abstract in the standard LaTeX format.

Additional customization of document formatting

You can exercise greater control over document formatting by creating your own template files for Pandoc. The default template files are located in the docassemble.base package in the docassemble/base/data/templates directory. The files include:

  • Legal-Template.tex: this is the LaTeX template that Pandoc uses to generate PDF files.
  • Legal-Template.yml: default Pandoc metadata for the Legal-Template.tex template, in YAML format. Options passed through metadata items within an attachment will append or overwrite these default options.
  • Legal-Template.rtf: this is the template that Pandoc uses to generate RTF files.
  • Legal-Template.docx: this is the reference file that Pandoc uses to generate DOCX files. You can edit this file to change default styles, headers, and footers.

To use your own template files, specify them using the following options to attachment:

  • initial yaml: one or more YAML files from which Pandoc metadata options should be gathered. If specified, the default file Legal-Template.yml is not loaded. If specifying more than one file, use YAML list syntax.
  • additional yaml: one or more YAML files from which Pandoc metadata options should be gathered, in addition to whatever options are loaded through initial_yaml. This can be used to load the metadata in Legal-Template.yml but to overwrite particular values. If specifying more than one file, use YAML list syntax.
  • template file: a single .tex file to be used as the Pandoc template for converting Markdown to PDF.
  • rtf template file: a single .rtf file to be used as the Pandoc template for converting Markdown to RTF.
  • docx reference file: a single .docx file to be used as the Pandoc docx reference file for converting Markdown to DOCX.

Filenames are assumed to reside in the data/templates directory within the package in which the interview YAML file is located. You can specify filenames in other packages by referring to the package name. For example:

template file: docassemble.demo:data/templates/MyTemplate.tex

Here is an example:

---
question: Your document is ready.
sets: provide_user_with_document
attachment:
  - name: Response to Motion for Summary Judgment
    filename: Summary_Judgment_Response
    additional yaml:
      - docassemble.pennsylvania:data/templates/legal_format.yml
      - docassemble.pennsylvania:data/templates/pleading_format.yml
    template file: summary_judgment_template.tex
    rtf template file: summary_judgment_template.rtf
    content: |
      The court should decide in my favor.
---

If this question appears within a YAML file located in the package docassemble.pa_family_law, the assumption is that the files summary_judgment_template.tex and summary_judgment_template.rtf will exist in the directory docassemble/pa_family_law/data/templates within that package.

If you want to use a custom template for all the attachments in a given interview, you do not have to specify the same values for every attachment. Instead, you can set attachment template options that will be applied to all attachments in the interview:

---
attachment options:
  additional yaml:
    - docassemble.pennsylvania:data/templates/legal_format.yml
    - docassemble.pennsylvania:data/templates/pleading_format.yml
  template file: summary_judgment_template.tex
  rtf template file: summary_judgment_template.rtf
---

If you use an interview-wide attachment options block to set defaults, you can override those defaults for a particular attachment by providing specific options within the question block.

Creating files by filling in a template

Filling PDF templates

If you have a PDF file that contains fillable fields (e.g. fields added using Adobe Acrobat Pro or a similar application), docassemble can fill in the fields of the PDF file using information from an interview and provide the user with a copy of that PDF file with the fields filled in. To do this, use the attachments statement as above, but instead of providing content or content file, provide a pdf template file and a dictionary of fields.

For example, here is an interview that populates fields in a file called sample-form.pdf:

question: |
  Here is your PDF form
attachment:
  name: A filled-in form
  filename: filled-form
  pdf template file: sample-form.pdf
  fields:
    Your Name: |
      ${ user }
    Your Organization: |
      ${ user.organization }
    Apple Checkbox: |
      ${ likes_apples }
    Orange Checkbox: |
      ${ likes_oranges }
    Pear Checkbox: |
      ${ likes_pears }
    Toast Checkbox: |
      ${ likes_toast }
mandatory: True
pdf-fill

The pdf template file is assumed to reside in the data/templates directory of your package, unless a specific package name is specified. For example, you could refer to a file in another package by writing:

pdf template file: docassemble.missouri-family-law:data/templates/form.pdf

In Adobe Acrobat Pro’s “Add or Edit Fields” mode, the PDF file looks like this:

sample form

The fields must be in the form of a YAML dictionary. The names of the fields listed in fields must correspond exactly with the names of the fields in the PDF file. Luckiliy, there is a tool that will help you extract the literal field names from a PDF file.

When writing the values of the fields, you can use Mako, but not Markdown. If you use Markdown, it will be interpreted literally. Checkbox fields will be checked if and only if the value evaluates to “True” or “Yes.”

The section below on passing values using code explains alternative ways that you can populate the values of fields in a PDF file.

By default, the PDF files created by filling in forms in a pdf template file can be edited by the user; the fill-in form boxes will still exist in the resulting document.

If you want to prevent users from editing the forms created through pdf template file, set the editable directive to False. For example:

question: |
  Here is your PDF form
attachment:
  name: A filled-in form
  filename: filled-form
  pdf template file: sample-form.pdf
  editable: False
  fields:
    Your Name: |
      ${ user }
    Your Organization: |
      ${ user.organization }
    Apple Checkbox: |
      ${ likes_apples }
    Orange Checkbox: |
      ${ likes_oranges }
    Pear Checkbox: |
      ${ likes_pears }
    Toast Checkbox: |
      ${ likes_toast }
mandatory: True
pdf-fill-not-editable

How to insert signatures or other images into fillable PDF files

To add a signature or other image to a fillable PDF file, use Adobe Acrobat Pro to insert a “Digital Signature” into the document where you want the signature to appear. Give it the height and width you want the image to have. Give the field a unique name.

Then, the image will be a field, just like a checkbox or a text box is a fill-in field. In your pdf template file, set the field to ${ user.signature } or another reference to an image. docassemble will trim whitespace from the edges of the image and fit the image into the “Digital Signature” box.

For example, here is an interview that populates text fields and inserts a signature into the template Transfer-of-Ownership.pdf:

question: |
  Please sign your name below.
signature: user.signature
under: |
  ${ user }
---
sets: final_screen
question: Congratulations!
subquestion: |
  You have now transferred everything
  you own to ${ friend }.
attachment:
  - name: Transfer of Ownership
    filename: Transfer-of-Ownership
    pdf template file: |
      Transfer-of-Ownership.pdf
    fields:
      "grantor": ${ user }
      "grantee": ${ friend }
      "collection": ${ prized_collection }
      "signature": ${ user.signature }
pdf-fill-signature

It is important that each “Digital Signature” field have a unique name. If there is more than one field in the PDF template with the same name, docassemble will not be able to locate it. If you want to insert the same signature in more than one spot in a document, you can do so as long as each “Digital Signature” field has a different name. For example:

    fields:
      first signature: ${ user.signature }
      second signature: ${ user.signature }
      third signature: ${ user.signature }

Filling DOCX templates

You can fill in fields in .docx template files by referring to a docx template file.

mandatory: True
question: |
  Here is your document.
attachment:
  name: Your letter
  filename: letter
  docx template file: letter_template.docx
docx-template

This allows you to use Microsoft Word to design your document and apply formatting. docassemble will simply “fill in the blanks.” (This is in contrast to the method of using docx as one of the valid formats, described above. When you use that method, you assemble a document from scratch by writing Markdown text that is then converted to .docx format.)

The file referenced with docx template file is assumed to reside in the data/templates directory of your package, unless a specific package name is specified. For example, you could refer to a .docx file in another package by writing:

docx template file: docassemble.missouri-family-law:data/templates/form.docx

In the example above, the letter_template.docx file contains the following text:

letter template source

The docx template file feature relies heavily on the Python package known as python-docx-template. This package uses the Jinja2 templating system to indicate fields in the .docx file. Jinja2 is different from the Mako templating system, which docassemble uses primarily.

When you work on .docx templates, be careful not to confuse the rules of these two templating formats. The biggest difference between the formats is that Mako uses the syntax ${ variable_name }, while Jinja2 uses the syntax {{ variable_name }}.

Also, the python-docx-template package uses a slightly modified version of the Jinja2 syntax to account for the fact that it is being used inside of a .docx file. The standard Jinja2 way of writing a “for loop” is:

{% for item in fruit_list %}
{{ item }} is a type of fruit.
{% endfor %}

In a .docx template, however, this will result in extraneous line breaks. You can avoid this by writing:

{%p for item in fruit_list %}
{{ item }} is a type of fruit.
{%p endfor %}

The p indicates that the paragraph containing the {%p ... %} statement should be removed from the document. When you edit the spacing of paragraphs in your .docx file, you need to edit the paragraph spacing of paragraphs that do not contain {%p ... %} statements. You may need to change both the spacing after a paragraph and the spacing before a paragraph in order to get the results you want. Other modifiers besides p include tr for table rows and tc for table columns.

If your interview uses dictionary data structures, you may need to change the “auto-format” settings of your word processor so that “straight quotes” are used instead of “curly quotes” within Jinja2 syntax. This will fail:

curly quotes

But this will correct the problem:

straight quotes

Images can be inserted into .docx files. This is illustrated in the example above: the variable user.signature is a graphics image (an image of the user’s signature created with the signature block). You can also use the [FILE ...] markup syntax to insert an image. However, do not mix image references with other text inside of a single field.

When you use docx template file, the user is provided with both a PDF file and a .docx file. The PDF file is generated by converting the .docx file to PDF format using LibreOffice. To suppress the creation of the PDF version, you can add a valid formats directive.

Note that you cannot use Markdown formatting syntax in text that you insert into a .docx file. If you do, it will pass through literally. Apply all of your formatting in the .docx template file.

Here is an example that demonstrates how to use DAList and DADict in a .docx template and using Jinja2 templating code.

event: document_shown
question: |
  Here is the document.
attachment:
  docx template file: docx-jinja2-demo.docx
docx-jinja2-demo

The docx-jinja2-demo.docx file looks like this:

docx jinja2 source

For more information on using Jinja2 in .docx templates, see the documentation of python-docx-template.

Inserting tables into .docx templates

You can assemble tables in a .docx template using a Jinja2 “for loop.”

Here is an example. The .docx template looks like this:

table template source

Note that the row that should be repeated is sandwiched between two rows containing for and endfor Jinja2 statements. Both of these statements use the tr prefix. These two rows, which span the width of the table, will not appear in the final output. The final output will look something like this:

table template result

In this example, each row corresponds to an item in a Python dict called seeds_of_fruit. Here is an example of an interview that gathers items into a DADict called seeds_of_fruit and provides the .docx file.

objects:
  seeds_of_fruit: DADict
---
mandatory: true
code: |
  seeds_of_fruit.there_are_any = True
  introduction_shown
---
question: |
  Tell me about a fruit.
fields:
  - Name: seeds_of_fruit.new_item_name
  - Seeds: seeds_of_fruit.new_item_value
    datatype: integer
    min: 0
---
question: |
  Are there any other fruits you would
  like to describe?
yesno: seeds_of_fruit.there_is_another
---
mandatory: True
question: |
  Here is your document.
attachment:
  docx template file: table_template.docx
docx-template-table

For more information about gathering items into a DADict object, see the Dictionary subsection of the Groups section of the documentation.

Passing values only for particular fields

By default, all of the variables in your interview will be available in the .docx template. If you do not want this, perhaps because your .docx template uses a different variable naming convention, you can use the fields directive to indicate a mapping between the fields in the .docx template and the values that you want to be filled in. This operates much like the PDF fill-in fields feature.

The content of fields is converted into a data structure, which is passed to the render() method of python-docx-template. The data structure needs to be a Python dict, but it can contain other data types. For example, in this interview, fields contains a list of ingredients.:

mandatory: True
question: |
  Here is your recipe.  Enjoy!
attachment:
  name: Your recipe
  filename: recipe
  docx template file: recipe_template.docx
  fields:
    title: Mandelbrot cookies
    oven_temperature: ${ oven_degrees } degrees
    ingredients:
      - apple sauce
      - ${ special_ingredient }
      - flour
      - sugar
    preparation_time: 48 hours
docx-recipe

In your .docx file, you will need to use appropriate Jinja2 syntax in order to process the list of ingredients. Here is an example of a .docx file that uses the above data structure:

recipe template source

For more information on using Jinja2 in .docx templates, see the documentation of python-docx-template.

Passing values using code

When you use the fields directive with pdf template file, you have to use Mako in order to pass the values of interview variables to the template. For example, suppose you have a PDF file with these fields:

fruit template

You can use an interview like this to populate the fields:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: fruit_template.pdf
  fields:
    favorite_fruit: ${ favorite_fruit }
    favorite_veggie: ${ favorite_veggie }
    favorite_legume: ${ favorite_legume }
    favorite_fungus: ${ favorite_fungus }
fruit-template-alt-1

However, this is a bit punctuation-heavy and repetitive. As an alternative, you can use the field variables directive to list the variables you want to pass:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: fruit_template.pdf
  field variables:
    - favorite_fruit
    - favorite_veggie
    - favorite_legume
    - favorite_fungus
fruit-template-alt-2

This will have the same effect.

The field variables directive only works when your variable in the template has the same name as the variable in your interview, and when you do not need to perform any transformations on the variable before passing it to the template.

The field variables directive, and other directives described in this subsection, work both with pdf template file and docx template file. But note that since the .docx assembly process by default accesses all of your interview variables, you will normally only need to use field variables with PDF templates.

Suppose you want to pass the results of functions or methods to a template that looks like this:

letter template

One way to pass the results of functions or methods it is to use fields, where every value is a Mako variable reference containing code:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: letter.pdf
  fields:
    letter_date: ${ today() }
    subject_line: ${ subject_of_letter }
    recipient_address: ${ recipient.address_block() }
pdf-template-alt-1

You can achieve the same result with less punctuation by using the field code directive:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: letter.pdf
  field code:
    letter_date: today()
    subject_line: subject_of_letter
    recipient_address: recipient.address_block()
pdf-template-alt-2

There is still another way of passing values to a template: you can include a code directive that contains Python code that evaluates to a Python dict in which the keys are the names of variables in the template, and the values are the values you want those variables to have. For example:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: letter.pdf
  code:
    dict(letter_date=today(), 
         subject_line=subject_of_letter, 
         recipient_address=recipient.address_block())
pdf-template-alt-3

Note that the code must be a single Python expression, not a list of statements. It can be difficult to cram a lot of logic into a Python expression, so you may want to create a variable to hold the values. For example:

mandatory: True
question: Here is your document.
attachment:
  pdf template file: letter.pdf
  code: letter_variables
---
code: |
  letter_variables = dict()
  letter_variables['letter_date'] = today()
  if letter_type == 'threat':
    letter_variables['subject_line'] = "Litigation hold"
  else:
    letter_variables['subject_line'] = "Matter we discussed"
  letter_variables['recipient_address'] = recipient.address_block()
reconsider: True
pdf-template-alt-4

Note that the use of the reconsider modifier is important here. Remember that docassemble will only ask a question or run code when it encounters an undefined variable. If the recipient’s address is undefined when docassemble tries to run the code above, docassemble will ask a question to gather it, but once that question is answered, docassemble will have no reason to run the above code again because letter_variables will already be defined – albeit in an incomplete state, with a letter_date item and a subject_line item but without a recipient_address item. Setting reconsider to True ensures that whenever a screen in the interview needs to know the value of letter_variables, that value will be “reconsidered”—treated as undefined—and the code above will be re-run in order to obtain a fresh definition of letter_variables.

The fields, field variables, and field code directives are not mutually exclusive. When they are used together, they supplement each other. (In .docx templates, however, the fields do not supplement the values of variables in the interview dictionary; if you use fields, field variables, and field code, docassemble will not use the interview dictionary as a whole.)

Here is a variation on the original PDF fill-in example above that uses code to supplement the values of fields:

question: |
  Here is your PDF form
attachments:
  - name: A filled-in form
    filename: filled-form
    pdf template file: sample-form.pdf
    fields:
      Your Name: |
        ${ user }
      Your Organization: |
        ${ user.organization }
      Apple Checkbox: |
        ${ likes_apples }
      Pear Checkbox: |
        ${ likes_pears }
    code: |
      {"Orange Checkbox": likes_oranges,
       "Toast Checkbox": likes_toast}
mandatory: True
pdf-fill-code

Like the Mako tag ${ ... }, the fields, field variables, and field code directives will convert the values of your variables to a format suitable for printing. If you are using the .docx template format and you only use the {{ ... }} syntax in your template, this will always be appropriate. But if you want to use “for loops” and other features of Jinja2 when passing variables using fields, field variables, or field code, you should read the next section, which explains how to pass variables in “raw” format to the template.

Turning off automatic conversion of .docx variables

Normally, all values that you transfer to a .docx template using fields, field variables, and field code are converted so that they display appropriately in your .docx file. For example, if the value is a DAFile graphics image, it will be converted so that it displays in the .docx file as an image. Or, if the value contains document markup codes that indicate line breaks, these will display as actual line breaks in the .docx file, rather than as codes like [BR].

However, if your .docx file uses Jinja2 templating to do complicated things like for loops, this conversion might cause problems.

For example, suppose you have a variable vegetable_list that is defined as a DAList with items ['potatoes', 'beets'], and you pass it to a .docx template as follows.

event: document_shown
question: |
  Here are your instructions.
attachment:
  docx template file: instruction_template.docx
  field variables:
    - vegetable_list

This will work as intended if your template uses vegetable_list in a context like:

make sure to bring {{ vegetable_list }} to the party

This will result in:

make sure to bring potatoes and beets to the party

When the DAList is converted, the .comma_and_list() method is automatically applied to make the data structure “presentable.”

However, suppose you wanted to write:

{%p for vegetable in vegetable_list: %}
Don't forget to bring {{ vegetable }}!
{%p endfor %}

In this case, since the variable vegetable_list has been converted into a literal piece of text, potatoes and beets, the for loop will loop over each character, not over each vegetable. You will get:

Don’t forget to bring p!

Don’t forget to bring o!

Don’t forget to bring t!

Don’t forget to bring a!

Don’t forget to bring t!

and so on.

You can prevent the conversion of vegetable_list into text by using raw field variables instead of field variables. For example:

event: document_shown
question: |
  Here are your instructions.
attachment:
  docx template file: instruction_template.docx
  raw field variables:
    - vegetable_list

Now, the vegetable_list variable in the .docx template will be a real list that Jinja2 can process. The output will be what you expected:

Don’t forget to bring potatoes! Don’t forget to bring beets!

The conversion to text is also done if you use field code or code to pass variables to a .docx template. In order to pass variables in “raw” form using field code or code, you can wrap the code in the raw() function. For more information, see the documentation for the raw() function.

How to get a list of field names in a PDF or DOCX file

When logged in to docassemble as a developer, you can go to “Utilities” from the menu and, under “Get list of fields from PDF/DOCX template,” you can upload a PDF or DOCX file that has fillable fields in it. docassemble will scan the file, identify its fields, and present you with the YAML text of a question that uses that file as a pdf template file or a docx template file with a list of fields.

Saving documents as variables

Including an attachments section in a question block will offer the user a chance to download an assembled document and e-mail it to themselves.

Sometimes, you might want to do other things with the document, like e-mail it, or post it to a web site.

You can save an assembled document to a variable by adding a variable name key to an attachment. For example:

mandatory: True
question: Ok, all done.
subquestion: |
  % if submit_to_authority:
    % if sent_ok:
  Your document was sent.
    % else:
  For some reason, I was not able to
  send your document.
    % endif
  % else:
  Ok, I will not send your document to
  The Man.
  % endif
---
question: Your document is ready.
subquestion: |
  Would you like to submit the document
  below to the authorities?
yesno: submit_to_authority
attachment:
  - name: A *hello world* document
    filename: Hello_World_Document
    variable name: hello_file
    content: |
      Hello, world!
---
code: |
  sent_ok = send_email(to=[authority],
                       template=my_email,
                       attachments=[hello_file])
document-variable-name

You can also assemble a document and save it to a variable without presenting it to the user in this manner. You do not need to use attachments with a question; it can stand on its own, and it will be evaluated when docassemble needs the definition of the variable indicated by variable name.

The following example creates a PDF file and an RTF file containing the message “Hello, world!” and offers the files as hyperlinks.

attachment:
  filename: Hello_World
  variable name: my_file
  content: |
    Hello, world!
---
mandatory: True
question: |
  All done.
subquestion: |
  You can download your document in
  [PDF](${ my_file.pdf.url_for() })
  or
  [RTF](${ my_file.rtf.url_for() })
  format.
document-variable-name-link

The varible indicated by variable name will be defined as an object of class DAFileCollection. An object of this type will have attributes for each file type generated, where each atttribute is an object of type DAFile. In the above example, the variable my_file.pdf will be the PDF DAFile, and the variable my_file.rtf will be the RTF DAFile. A DAFile has the following attributes:

  • filename: the path to the file on the filesystem;
  • mimetype: the MIME type of the file;
  • extension: the file extension (e.g., pdf or rtf); and
  • number: the internal integer number used by docassemble to keep track of documents stored in the system

See objects for an explanation of the DAFile and DAFileCollection classes.

Using code to generate the list of attachments

The list of attachments shown in a question can be generated by Python code that returns a list of DAFileCollection objects. If attachment code is included in the question, the value will be evaluated as Python code.

In the following example, the Python code returns an array of three DAFileCollection objects, each of which was generated with a separate attachment block.

mandatory: True
question: |
  Here are your documents!
attachment code: |
  [doc_one, doc_two, doc_three]
---
attachment:
  name: The first document
  filename: document_one
  description: |
    This is the first document
    of a series.
  variable name: doc_one
  content: |
    Hello, world number one!
---
attachment:
  name: The second document
  filename: document_two
  description: |
    This is the second document
    of a series.
  variable name: doc_two
  content: |
    Hello, world number two!
---
attachment:
  name: The third document
  filename: document_three
  description: |
    This is the third document
    of a series.
  variable name: doc_three
  content: |
    Hello, world number three!
attachment-code

Limiting availability of file formats

You limit the file formats that are generated by attachments.

question: Your document is ready.
attachment:
  - name: A hello world document
    filename: Hello_World_Document
    valid formats:
      - pdf
    description: |
      A document with a classic message
    content: |
      Hello, world!
mandatory: True
valid-formats

In this example, the user will not have the option of seeing an HTML preview and will only be able to download the PDF file.

Note that when you use docx template file, the user is normally provided with both a PDF file and a DOCX file. The PDF file is generated by converting the DOCX file to PDF format. To hide the PDF file, set valid formats to docx only.

Assembling documents in a different language than the current language

If you need to produce a document in a different language than the user’s language, then the linguistic functions may operate in a way you do not want them to operate.

For example, if your user is Spanish-speaking, but you need to produce an English language document, you may find that a word or two in the English language document has been translated into Spanish. (E.g., this can happen if your document template uses linguistic functions from docassemble.base.util). You can remedy this by defining a language for the document.

initial: True
code: |
  set_language('es')
---
mandatory: True
language: es
question: El documento está listo.
attachment:
  - name: Alimentos
    language: en
    filename: food_order
    content: |
      This customer would like to order
      ${ comma_and_list('fries', 'a Coke') }.
document-language

Without language: en, the output would be:

This customer would like to order fries y a Coke.

With language: en, the output is:

This customer would like to order fries and a Coke.

Preventing the user from e-mailing documents

When attachments are included in a question, the user will be given an option to e-mail the documents to an e-mail address. If you would like to disable this feature, set allow emailing to False.

By default, the user can e-mail documents:

question: Your document is ready.
sets: provide_user_with_document
attachment:
  - name: A hello world document
    filename: Hello_World
    description: |
      A document with a classic message
    content: |
      Hello, world!
allow-emailing-true

Including allow emailing: False will disable this:

mandatory: True
question: Your document is ready.
attachment:
  - name: A hello world document
    filename: Hello_World
    description: |
      A document with a classic message
    content: |
      Hello, world!
allow emailing: False
allow-emailing-false