The LaTeX mailmerge
package is super useful, especially for creating multiple versions of tests.
Before I discovered mailmerge
, my workflow for writing a test was basically:
- Write one version of the test.
- Make a duplicate of the file.
- Edit the file to change all the constants.
At least, that was my intended workflow. But typically I would also:
- Realize that there was some change I wanted to make to the test.
- Painstakingly make the same change to both versions of the test, double-checking that the wording remained consistent between versions.
Sometimes I would repeat the last two steps multiple times. This was obnoxiously inefficient.
Then I discovered the mailmerge
package.
Here is a basic (silly) example illustrating how the package works:
\documentclass[letterpaper, 12pt]{amsart}
%% packages
\usepackage{mailmerge}
\usepackage{fouriernc}
\usepackage{url}
\usepackage{tikz}
\title{Some U.S.~state capital facts}
\begin{document}
\maketitle
\mailrepeat{
The capital of \field{state} is \field{capital}.
The U.S. Census Bureau estimates that in mid-2017,
there were \field{population} people living in
\field{capital}\footnote{\field{cite}}.
}
\mailfields{state,capital,population,cite}
\mailentry{Illinois,Springfield,%
{167,376},\url{https://goo.gl/YGDdE6}}
%% Draw a square:
\vskip 1 em
\begin{tikzpicture}
\draw (0, 0) -- (1, 0)
-- (1, 1) -- (0, 1) -- cycle;
\end{tikzpicture}
\vskip 1 em
\mailentry{Minnesota,St.~Paul,%
{306,621},\url{https://goo.gl/F6rXZ7}}
\mailentry{Oregon,Salem,%
{169,798},\url{https://goo.gl/Zc4tDC}}
\mailentry{Pennsylvania,Harrisburg,%
{49,192},\url{https://goo.gl/NQypQG}}
\end{document}
This produces:
SOME U.S. STATE CAPITAL FACTSThe capital of Illinois is Springfield. The U.S. Census Bureau estimates that in mid-2017, there were 167,376 people living in Springfield1.
The capital of Minnesota is St. Paul. The U.S. Census Bureau estimates that in mid-2017, there were 306,621 people living in St. Paul2.
The capital of Oregon is Salem. The U.S. Census Bureau estimates that in mid-2017, there were 169,798 people living in Salem3.
The capital of Pennsylvania is Harrisburg. The U.S. Census Bureau estimates that in mid-2017, there were 49,192 people living in Harrisburg4.
This is followed by the appropriate footnotes.
Notice:
- The text you want repeated is specified as the argument of the
\mailrepeat
macro. - Within the
\mailrepeat
, we specify the mail-merged info with\field{
[field name]}
- The names of the mail merge fields are given as a comma-delimited list with the
\mailfields
macro. - The actual mail-merge is accomplished with the
\mailentry
macro. The argument to this macro is a comma-delimited list of the material to place into the fields.
I put the silly TikZ square in this example to illustrate that the mail-merged text is placed where the \mailentry
occurs in the code.
Spacing is significant in the \mailentry
macro. If there is a space next to \field{
[field name]}
in the \mailrepeat
and after the comma the corresponding field in the \mailentry
, this will produce an awkward amount of space in the output. For example,
\mailentry{Minnesota, St.~Paul,
{306,621},\url{https://goo.gl/F6rXZ7}}
will produce:
Notice the extra space before the two instances of “St. Paul” and before the population. Compare to what is produced when there is no space before the comma and there is a %
before the line break (which prevents the line break from being treated as a space):
\mailentry{Minnesota,St.~Paul,%
{306,621},\url{https://goo.gl/F6rXZ7}}
It’s very subtle, but I am a perfectionist.
If you have many fields, the comma-delimited list argument to the \mailentry
can get unwieldy. One trick I use is to end each entry with a comment containing
the field name:
\mailentry{Minnesota%state
,St.~Paul%capital
,{306,621}%population
,\url{https://goo.gl/F6rXZ7}%cite
}
Especially when the fields are difficult to tell apart based on content (e.g., when they are different constants for math problems), this makes it easier to know which field you are changing. Also, the comments prevent any space or line break before the comma from affecting the output.
For a test, each version would correspond to a single \mailentry
. Consider
this made-up quiz, which has two versions (Form A and B):
\documentclass[letterpaper, 11pt]{article}
%% packages
\usepackage{amsmath}
\usepackage{mailmerge}
\usepackage{fouriernc}
\usepackage{enumitem}
\usepackage{fullpage}
\begin{document}
\mailrepeat{
\setcounter{page}{1}
\centerline{\textbf{Quiz \#1}, Form \field{form}}
\vskip 1 em
\begin{enumerate}
\item (2 points) Expand
\(\left(x^{\field{exponent1}} + 2x\right)^2\).
\vfill
\item (3 points) Suppose
\(f(x) =
\field{coeff1}x^2 + \field{coeff2}x + 1\).
Find \(f(5)\).
\vfill
\end{enumerate}
\newpage
\begin{enumerate}[resume]
\item (5 points) Solve for \(x\):
\[\field{coeff3}x^4 - \field{coeff4}x^3
= 0\]
\vfill
\end{enumerate}
\newpage
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Mail merge info:
\mailfields{form, coeff1, coeff2,
coeff3, coeff4, exponent1}
\mailentry{A%form
,6%coeff1
,8%coeff2
,2%coeff3
,7%coeff4
,3%exponent1
}
\mailentry{B%form
,5%coeff1
,9%coeff2
,3%coeff3
,5%coeff4
,5%exponent1
}
\end{document}
At the start of the \mailrepeat
ed code is the macro \setcounter{page}{1}
,
which resets the page number to 1; otherwise, Form B would start on Page 3.
Also, I ended the \mailrepeat
ed code with a \newpage
, ensuring that each
version is on a separate page.
If you print \(\lceil N/2\rceil\) copies of the resulting PDF (where \(N\) is the number of students in your course), two-sided, then the pile of quizzes will be alternated by version as they come out of the printer, ready to hand out to your class.