3

I am trying to adapt this question/answer on how to do mail merge to work with the letter document class.

The linked answer works great for me, but when I try to change the document class to letter I keep getting an error| Argument on \@tempc has an extra }, but it seems that my braces are balanced. Are letter and datatool incompatible? Here is my example. How can I better understand this error? Thanks.

\documentclass{letter}
\usepackage{datatool}
\usepackage{parskip}

\signature{Richard Herron}
\address{New York, NY}

\makeatletter
% Blank/missing fields commands
% \skipblank adds \\ to filled field
% * version adds \space instead of newline
\newcommand\skipblank{\@ifstar\@spskip\@nlskip}
\newcommand\@nlskip[1]{\ifthenelse{\DTLiseq{#1}{}}{\relax}{#1\\}}
\newcommand\@spskip[1]{\ifthenelse{\DTLiseq{#1}{}}{\relax}{#1\space}}
% \checkblank replaces blank fields with ***
\newcommand\checkblank[1]{\ifthenelse{\DTLiseq{#1}{}}{***}{#1}}
\makeatother

\begin{document}

\DTLloaddb{addresses}{mail-merge-addresses.csv} 
\DTLforeach*{addresses}{%
    \addtitle=Title,
    \firstname=FirstName,
    \lastname=LastName,
    \position=Position,
    \addressi=Address1,
    \addressii=Address2,
    \addressiii=Address3,
    \city=City,
    \state=State,
    \zip=Zip,
\country=Country}
{%
    \begin{letter}{\checkblank{\addtitle}\ \firstname\ \lastname\\
        \skipblank{\position}
        \skipblank{\addressi}
        \skipblank{\addressii}
        \skipblank{\addressiii}
        \city, \state\ \zip\\
        \skipblank*{\country}
    }

    \opening{Dear \checkblank{\addtitle}\ \lastname,}

    This is the text of the letter.

    \closing{Sincerely,}

\end{letter}
}

\end{document}

Edit: I should add that I'm using the same .csv file database that the linked answer uses, but I get the same results if I remove the blank entries.

Title,  LastName,   FirstName,  Position,   Address1,   Address2,   Address3,   City,   State,  Zip,    Country
Dr.,    Smith,  James,  Chair,  Dept. of Physics,   University of Somewhere,    434 East Hall,  Cambridge,  MA, 02139,  
Mr.,    Jones,  Bill,   Director of Human Resources,    ,   University of Nowhere,  A203 King St.,  Stanford,   CA, 94305,  
,   Brown,  Sally,  ,   Firstline,  ,   3rdline,    East Lansing,   MI, ,   USA

1 Answer 1

5

The argument to \begin{letter} is massaged in order to extract the addressee. This massage is incompatible with \ifthenelse.

Here's a way out: we fed the argument in “explicit” form.

\documentclass{letter}
\usepackage{datatool}
\usepackage[businessenvelope]{envlab}
\makelabels

\signature{Richard Herron}
\address{New York, NY}

\makeatletter
% Blank/missing fields commands
% \skipblank adds \\ to filled field
% * version adds \space instead of newline
\newcommand\skipblank{\@ifstar\@spskip\@nlskip}
\newcommand\@nlskip[1]{\ifthenelse{\DTLiseq{#1}{}}{\relax}{#1\\}}
\newcommand\@spskip[1]{\ifthenelse{\DTLiseq{#1}{}}{\relax}{#1\space}}
% \checkblank replaces blank fields with ***
\newcommand\checkblank[1]{\ifthenelse{\DTLiseq{#1}{}}{***}{#1}}

\newtoks\address@toks
\newcommand\addto@address[1]{%
  \address@toks=\expandafter{\the\expandafter\address@toks#1}%
}
\newcommand\makeaddress{%
  \address@toks={}%
  \ifthenelse{\DTLiseq{\addtitle}{}}{\addto@address{***\ }}{\addto@address{\addtitle\ }}%
  \addto@address{\firstname\ }%
  \addto@address{\lastname}%
  \addto@address{\noexpand\\}
  \ifthenelse{\DTLiseq{\position}{}}{}{\addto@address{\position\\}}
  \ifthenelse{\DTLiseq{\addressi}{}}{}{\addto@address{\addressi\\}}
  \ifthenelse{\DTLiseq{\addressii}{}}{}{\addto@address{\addressii\\}}
  \ifthenelse{\DTLiseq{\addressiii}{}}{}{\addto@address{\addressiii\\}}
  \addto@address{\city, }\addto@address{\state\ }\addto@address{\zip}
  \ifthenelse{\DTLiseq{\country}{}}{}{\addto@address{\noexpand\\}}
  \ifthenelse{\DTLiseq{\country}{}}{}{\addto@address{\country}}
  \begingroup
  \edef\x{\endgroup\noexpand\begin{letter}{\the\address@toks}}\x
}
\makeatother

\begin{document}

\DTLloaddb{addresses}{mail-merge-addresses.csv} 
\DTLforeach*{addresses}{%
    \addtitle=Title,
    \firstname=FirstName,
    \lastname=LastName,
    \position=Position,
    \addressi=Address1,
    \addressii=Address2,
    \addressiii=Address3,
    \city=City,
    \state=State,
    \zip=Zip,
\country=Country}
{%
 \makeaddress
    \opening{Dear \checkblank{\addtitle}\ \lastname,}

    This is the text of the letter.

    \closing{Sincerely,}

\end{letter}
}

\end{document}
4
  • That does it. Thanks! But now I have another question. My MWE was too M. When I add back \usepackage{hyperref}, \usepackage[businessenvelope]{envlab}, and \makelabels I get illegal number in definition. Can I not add back envelopes? Would I be better served doing this operation in Python? Or even R? Thanks! Jul 22, 2014 at 13:23
  • @RichardHerron I've changed the implementation, making all the address field without using the \skipblank and similar commands. I don't think that hyperref makes much sense with letters.
    – egreg
    Jul 22, 2014 at 13:39
  • Thanks! Any idea why I get two numbered pages that are blank except for $ \Delta = \Delta $ ? Jul 22, 2014 at 16:50
  • @RichardHerron There was an error, it should be fixed now, see the edit history.
    – egreg
    Jul 22, 2014 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.