3.5 ⁑Mail Merging
The scrlttr2 and newlfm classes both provide ways of creating a template letter for mail merging. However, in case you don't want to be fixed to a specific class, or you want to use the letter or isodoc class (or some other class not described in this book), this section looks at a more generic method of mail-merging using the datatool package.
Recall from §2.7.1 Iterating Through a Database that you can iterate through
a datatool database using \DTLforeach*
. This technique can be used to
create a letter for each person in the database, or you can apply
filtering to only send to a subset of the database.
In fact, this is just a small modification of the “For the More
Adventurous” sections of Exercise 7, Exercise 8 and
Exercise 9. Any settings, such as the sender's details,
that stay constant for all the letters can be set before
\DTLforeach*
. The letter
or newlfm
environment can go inside the body of \DTLforeach*
.
To send a letter to everyone listed in sample people.csv file:
\documentclass{letter} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage[a4paper]{geometry} \usepackage[british]{babel} \usepackage{datatool} \DTLloaddb{people}{people.csv} \DTLloaddb{countries}{country-codes.csv} \name{Mr Big Head} \signature{Big Head} \location{Secret Lab of Experimental Stuff} \address{University of Somewhere\\Some City\\AB3 4YZ} \telephone{0123456789} \begin{document} \DTLforeach*{people}% data {% assignments \Id=id,% \Surname=surname,% \Forenames=forenames,% \Title=title,% \AddressI=address1,% \AddressII=address2,% \Town=town,% \County=county,% \Postcode=postcode,% \CountryCode=country% } {% % fetch country name \xDTLassignfirstmatch{countries}{code}{\CountryCode}{\CountryName=name} \begin{letter}{% recipient's address \DTLifnullorempty{\Title}{}{\Title\␣}\Forenames\␣\Surname\\% \AddressI\\ \DTLifnullorempty{\AddressII}{}{\AddressII\\}% optional line \Town\\ \DTLifnullorempty{\County}{}{\County\\}% optional line \Postcode\\\CountryName} \opening{Dear \DTLifnullorempty{\Title}{\Forenames}{\Title} \Surname} \thispagestyle{firstpage} This is an imaginary letter. This is the second paragraph of the letter. \closing{Yours sincerely} \ps PS: this is a postscript. \encl{Photocopy of something interesting\\ Photocopy of something rather dull} \cc{Prof Important Person\\Dr Bor Ing} \end{letter} } \end{document}
This produces a six page document, where each page contains a letter to one of the six people in the database. You can download or view this document.
To send a letter to everyone listed in sample people.csv file:
\documentclass[stdletter]{newlfm} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage[british]{babel} \usepackage{datatool} \DTLloaddb{people}{people.csv} \DTLloaddb{countries}{country-codes.csv} \newlfmP{orderfromtodate,sigcenter,addrfromphone,addrfromemail} \namefrom{Mr Big Head} \addrfrom{University of Somewhere\\Some City\\AB3 4YZ} \emailfrom{big.head@somewhere.ac.uk} \phonefrom{0123456789} \regarding{A sample letter} \begin{document} \closeline{Yours sincerely} \cclist{Prof Important Person\\Dr Bor Ing} \encllist{Photocopy of something interesting\\ Photocopy of something rather dull} \psitem{this is a postscript} \DTLforeach*{people}% data {% assignments \Id=id,% \Surname=surname,% \Forenames=forenames,% \Title=title,% \AddressI=address1,% \AddressII=address2,% \Town=town,% \County=county,% \Postcode=postcode,% \CountryCode=country% } {% \xDTLassignfirstmatch{countries}{code}{\CountryCode}{\CountryName=name} \nameto{\DTLifnullorempty{\Title}{}{\Title\␣}\Forenames\␣\Surname} \addrto{% \AddressI\\ \DTLifnullorempty{\AddressII}{}{\AddressII\\}% optional line \Town\\ \DTLifnullorempty{\County}{}{\County\\}% optional line \Postcode\\\CountryName } \greetto{Dear \DTLifnullorempty{\Title}{\Forenames}{\Title} \Surname} \begin{newlfm} This is an imaginary letter. This is the second paragraph of the letter. \end{newlfm} } \end{document}
As with the previous example, this produces a six page document, where each page contains a letter to one of the six people in the database. You can download or view this document.
Note
The newlfm
environment tries to determine the total number
of pages per letter. This is done using
at the end of the letter. Since there are six letters, this causes five instances of
LaTeX Warning: Label `totpage' multiply defined.However, since each letter is of the same length, these warnings can be ignored.
Adapt the more adventurous section of Exercise 8 so
that a letter is generated for each person in the
sample people.csv file who has the subscribed field set.
If you prefer, you can use the people SQL table.
(Recall the \ifcsbool
command defined earlier. Alternatively
you can use the optional argument of \DTLforeach*
with
ifthen's \equal
command.)
The recipient's country only needs to be included if it's different from the sender's country. For example, suppose the sender's address is in the United Kingdom, then the country name isn't required for the entries where the recipient's country code is “gb”. Modify your code so that it doesn't include the country name in the recipient's address if it's the same as the sender's country. You can download or view a solution.
If you prefer, you can use one of the other letter classes, such as isodoc, described in §3.4 Writing a Letter Using the isodoc Class. You can download or view a solution using the isodoc class.
This book is also available as A4 PDF or 12.8cm x 9.6cm PDF or paperback (ISBN 978-1-909440-07-4).