Easy creation of form letters written in LaTeX

Author: Tobias Leupold <tobias . leupold at web . de>
Date: 2014-08-15
Manual section:1


serienbrief [options] <LaTeX source file> <database file>


serienbrief creates form letters using a LaTeX source file and a database file. For each record in the database file, serienbrief will create one output file.

A temporary source file where all text pieces tagged as form letter fields are replaced by the respective data will be composed and compiled using the given LaTeX command. Be sure to call serienbrief from the source file's directory, so that non-absolute external references will be found.

The database file

The database file must contain the respective column's name in the first line and all records to be processed in the following lines, always one line per record. All columns have to be separated by one or more tabs. Empty lines will be ignored.

All LaTeX commands can be used in the database as they would be used in the original document.

If it is necessary to have empty fields for some records, I recommend to use LaTeX's \relax command (without curly braces) there. Text like

"Text text **replaceme** text text"

will then become

"Text text \relax text text"

so that the form letter field will be simply ignored by LaTeX (using \relax{} would add additional whitespace).


--delimiter, -d string

The delimiter used before and after form letter fields to tag them in the TeX file. Defaults to **. E. g., **name** would be interpreted by serienbrief by default.

Don't use strings that are handled by LaTeX itself here, such as "_" or "\", as they would be interpreted by LaTeX and probably break your document. LaTeX has to be able to compile the source file as-is, displaying all form letter fields as-is.

--outpattern, -a string

This defines the file names of the generated form letters. All column names from the database file can be referenced and will be replaced by the respective data. Additionally, there are two special "column names": _filename (which will be replaced by the LaTeX document's file name without extension) and _number (which will be replaced by a consecutive number with leading zeros). A wildcard has to be enclosed in square brackets. All characters that are not found and replaced will appear as-is in the generated file name.

The default value is [_filename]-[_number] which will e. g. result in Document-01.pdf, Document-02.pdf and so on. Looking at the example form letter, one could e. g. use --outpattern="[firstname]", which would then result in John.pdf and James.pdf.

If a generated file name is already there (due to identical data), an underscore followed by a consecutive number will be appended automatically. Slashes will be replaced by underscores.

--outdir, -o directory
The directory the created form letters will be stored in. Defaults to serienbrief. This directory will be created if it's not there yet.
--latex, -l command
The command to execute when compiling the source files. Defaults to pdflatex -interaction=nonstopmode.
--repeat, -r x
Repeat the LaTeX run x times. Needed to e. g. get cross-references right. Defaults to 0, meaning the LaTeX call will be done once.
--outext, -e extension
The extension of the output files. As by default pdflatex is used to compile the sources, this defaults to pdf.
--pretend, -p
Don't actually create output. Useful to find errors in the database file.
--force, -f
Ignore all errors and warnings and don't ask anything. Using this option will probably not result in what you want and will definitely not solve any problems occuring without it. This is intended to be used just for automation like the use in scripts.
Don't use colored output.
--help, -?
Show a short help message.


Probably, one wants to create one file containing all form letters for easier printing. To do so, I suggest to use the pdfjam program (from ). Just go to the serienbrief directory created by serienbrief and do pdfjam *.pdf -o all_letters.pdf. This will create one file named "all_letters.pdf" containing all pdf files found in the current directory.


Re-write the whole thing in a reasonable language like Python ;-) Abstract a database backend so that all kinds of sources can be used, not only a tab-separated text file.