%% \CheckSum{108} % \iffalse meta-comment % % File: mailmerge.dtx % % Copyright (C) 2009 Miguel V. S. Frasson (mvsfrasson@gmail.com) % % The LaTeX package mailmerge provides an interface to produce text from % a template where fields are replaced by actual data, like in a % database. It is useful to produce several letters from a template, % certificates or other such documents. It allows to access the entry % number, number of entries and so on. % %<*driver> \documentclass{ltxdoc} \usepackage{doc} \usepackage{amstext,makeidx,ae,mailmerge} \makeindex \newcommand{\ttabrechaves}{\char123} \newcommand{\ttfechachaves}{\char125} \let\ac\ttabrechaves \let\fc\ttfechachaves \begin{document} \DocInput{mailmerge.dtx} \end{document} % % \fi % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \StopEventually % % \changes{1.0}{2009/09/23}{initial version} % % \MakeShortVerb+ % % \title{\textsf{mailmerge}: repeat amount of text merging fields} % \author{Miguel Vin\'\i cius Santini Frasson} % \date{2009--09--23 version 1.0} % % \maketitle % % % \tableofcontents % % \section{Introduction} % % The \LaTeX\ package \textsf{mailmerge} provides an interface to % produce text from a template where fields are replaced by actual % data, like in a database. It is useful to produce several letters % from a template, certificates or other such documents. It allows to % access the entry number, number of entries and so on. % % \section{Usage} % % In short, one needs to: % \begin{enumerate} % \item declare field names, % \item define the repetition and % \item provide entries, each one being a set of values for the fields. % \end{enumerate} % It is important to define the repetition with % \texttt{\string\mailrepeat} \emph{before} provide any entry. We % present the usage in more detail now. % % \begin{enumerate} % \item \DescribeMacro{\mailfields} Declare the names of the fields, % with the command \\\mbox{\qquad} % \texttt{\string\mailfields\ac\textit{name1},\textit{name2},...\fc}\\ % The order declared here is the order in which the values must be % provided in the parameter of +\mailentry+ (see below.) % % \item % \DescribeMacro{\mailrepeat} % \DescribeMacro{\field} % The block of text to be repeated is given as the parameter of % macro +\mailrepeat+ as in\\\mbox{\qquad} % \texttt{\string\mailrepeat\ac\textit{...\ text to be % repeated...\fc}}\\ % Inside the text to be repeated, which can be several paragraphs % long, each instance of \texttt{\string\field\ac\textit{name}\fc} % is replaced by the respective value, this for each entry. % % \DescribeMacro{\numberoffields} \DescribeMacro{\numberofentries} % \DescribeMacro{\entrynumber} The command +\numberoffields+ is % replaced by the number of fields and +\numberofentries+ is % replaced by the number of entries, but it is necessary two runs to % update the value. The command +\entrynumber+ is replaced by the % current entry number. This can be used, for example, in % determining if current entry has an odd or even number. % % For conditional text, depending on field value, one can compare % value's contents, for example, with the +\ifthenelse+ command % provided by % the \textsf{ifthen} package. % % \item \DescribeMacro{\mailentry} For each entry, provide a % command\\\mbox{\qquad} % \texttt{\string\mailentry\ac\textit{value1},\textit{value2},...\fc}\\ % where \texttt{\textit{value1}} is the value of field named % \texttt{\textit{name1}}, \texttt{\textit{value2}} is the value of % field named \texttt{\textit{name2}}, and so on. The values can be % several paragraphs long. If the value has a comma with it, better % enclose the value between curly brackets, like in % \begin{verbatim} % \mailfields{name,friends,drives} % \mailentry{John,{Bart,Robert},yes} % \mailentry{Michael,{Jean,Phillip,Maria},no} % \end{verbatim} % % % \item \DescribeMacro{\mailnewdata} In case of intention of use of % several databases in the same file, use the command +\mailnewdata+, % which resets entries. New uses of +\mailfields+ overhide previous % field names. % \end{enumerate} % % \section{Example} % % \begin{verbatim} % \usepackage{ifthen,mailmerge} % % % \ifequal{A}{B}{what if A=B}{what if A<>B} % \newcommand{\ifequal}[2]{\ifthenelse{\equal{#1}{#2}}} % % \mailfields{name,friends,drives} % % \mailrepeat{\section*{\field{name}'s profile} % % \field{name} has % \ifequal{\field{friends}}{} % {no friends} % {\field{friends} as friends}. % \ifequal{\field{drives}}{yes}{Drives.}{Doesn't drive.} % % (entry \entrynumber\ of \numberofentries) % % % \newpage optional % } % % \mailentry{John,{Bart and Robert},yes} % \mailentry{Sara,{Jean, Phillip and Maria},no} % \mailentry{Edward,,yes} % \end{verbatim} % % \noindent what produces the following output: % % \newcommand{\ifequal}[2]{\ifthenelse{\equal{#1}{#2}}} % % \mailfields{name,friends,drives} % % \mailrepeat{\section*{\field{name}'s profile} % % \field{name} has % \ifequal{\field{friends}}{} % {no friends} % {\field{friends} as friends}. % \ifequal{\field{drives}}{yes}{Drives.}{Doesn't drive.} % % (entry \entrynumber\ of \numberofentries) % % ^^A \newpage optional % } % % \mailentry{John,{Bart and Robert},yes} % \mailentry{Sara,{Jean, Phillip and Maria},no} % \mailentry{Edward,,yes} % % \section{Idea of implementation} % % \begin{itemize} % \item Each new data initialization (call od +\mailnewdata+) defines % a tag command with values `a', `aa', `aaa', and so on, saved in % command +\MAILMcurrtag+. % \item A +\mailfields+ saves field names to commands +\MAILMfieldI+, % +\MAILMfieldII+, +\MAILMfieldIII+, etc (ending with upcase roman % numbers), and at the end, saves in the \texttt{.aux} file the % number of fields in a command determined by the data tag. % \item The +\mailrepeat+ command just saves its parameter to a command. % \item Each \texttt{\string\field\ac\textit{name}\fc} is expanded to % a command \texttt{\string\MAILMthefield\textit{name}}. % \item +\numberoffields+ expands to a command whose name is composed % by \texttt{MAILMnumberfields} plus ``tag''. The same for +\numberofentries+. % \item Each +\mailentry+ defines the comands % \texttt{\string\MAILMthefield\textit{nameN}} to expand to % \texttt{\textit{valueN}}, using % \texttt{\string\MAILMfield\textit{N-in-roman}} to compose the name % of the command and expand an entry of the repetition command. % Now, when the +\field+, +\numberoffields+ and +\numberofentries+ % are expanded, they have ppropriated values. % \end{itemize} % % % \section{Code} % % % Identidication of the package and use of the package \textsf{ifthen}. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{mailmerge}[2009/09/23 v1.0 repeat amount of text merging fields] \RequirePackage{ifthen} % \end{macrocode} % % \subsection{(Re)initialization} % % Reset counters and update tag command +\MAILMcurrtag+. Inicialize once. % \begin{macrocode} \def\MAILMcurrtag{} \newtoks\MAILMtok \newcounter{MAILMcount}% aux counter \newcounter{MAILMentry}% \newcommand{\mailnewdata}{% \setcounter{MAILMentry}{0}% \xdef\MAILMcurrtag{a\MAILMcurrtag}} \mailnewdata % \end{macrocode} % % \subsection{Saving the repetition in a command} % % \DescribeMacro{\mailrepeat} % \begin{macrocode} \newcommand{\mailrepeat}[1]{\gdef\MAILMrepetition{#1}} % \end{macrocode} % % \subsection{Restoring data from aux file} % % \DescribeMacro{\MAILMsetnumfields} % \DescribeMacro{\MAILMsetnumentries} % \DescribeMacro{\numberoffields} % \DescribeMacro{\numberofentries} % Commands that extract info from aux file (saved by +\mailfields+ and % +\mailentry+) and commands that use this information when repeting. % \begin{macrocode} \newcommand{\MAILMsetnumfields}[2] {\expandafter\xdef\csname MAILMnumberoffields#1\endcsname{#2}} \newcommand{\MAILMsetnumentries}[2] {\expandafter\xdef\csname MAILMnumberofentries#1\endcsname{#2}} \newcommand{\numberoffields} {\csname MAILMnumberoffields\MAILMcurrtag\endcsname} \newcommand{\numberofentries} {\csname MAILMnumberofentries\MAILMcurrtag\endcsname} % \end{macrocode} % % \subsection{Saving field names} % % \begin{macrocode} \newcommand{\mailfields}[1]{% \setcounter{MAILMcount}{0}% % \end{macrocode} % \noindent Initiate a loop, where for each entry, the command % +\MAILMaux+ is set to entry name. % \begin{macrocode} \@for\MAILMaux:=#1\do{% % \end{macrocode} % \noindent The next line is to extract white space after comma. % \begin{macrocode} \edef\MAILMaux{\expandafter\@firstofone\MAILMaux\@empty}% % \end{macrocode} % \noindent Define command % \texttt{\string\MAILMfield\textit{Roman-number}}. % \begin{macrocode} \stepcounter{MAILMcount}% \expandafter\edef\csname MAILMfield\Roman{MAILMcount}\endcsname {\MAILMaux}% \edef\numberoffields{\arabic{MAILMcount}}% }% % \end{macrocode} % \noindent Write to \texttt{aux} +\MAILMsetnumfields{tag}{num}+ % \begin{macrocode} \immediate\write\@mainaux{\string\MAILMsetnumfields {\MAILMcurrtag}{\theMAILMcount}}% } % \end{macrocode} % % \subsection{Repeating within an entry} % % \DescribeMacro{\field} % Defining +\field+, that expands to % \texttt{\string\MAILMthefield\textit{name}}. % \begin{macrocode} \newcommand{\field}[1]{\csname MAILMthefield#1\endcsname} % \end{macrocode} % % \DescribeMacro{\mailentry} % \noindent Each entry increments counter (reset in initialization), % saves entry number to aux, saves each value to the command expanded % by +\field+ and expand the repetition, stored in +\MAILMrepetition+. % The implementation is similar to +\mailfields+. % \begin{macrocode} \newcommand{\mailentry}[1]{% \stepcounter{MAILMentry}% \edef\entrynumber{\theMAILMentry}% \immediate\write\@mainaux{\string\MAILMsetnumentries {\MAILMcurrtag}{\theMAILMentry}}% \setcounter{MAILMcount}{0}% \@for\MAILMentryfield:=#1\do{% \MAILMtok=\expandafter{\MAILMentryfield}% \stepcounter{MAILMcount}% \expandafter\long\expandafter\edef \csname MAILMthefield% \csname MAILMfield\Roman{MAILMcount}\endcsname \endcsname {\the\MAILMtok}% }% \MAILMrepetition } % \end{macrocode} % % \Finale \PrintIndex %\PrintChanges % %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % \endinput