summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/csvmerge/csvmerge.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/csvmerge/csvmerge.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/csvmerge/csvmerge.dtx')
-rw-r--r--macros/latex/contrib/csvmerge/csvmerge.dtx1198
1 files changed, 1198 insertions, 0 deletions
diff --git a/macros/latex/contrib/csvmerge/csvmerge.dtx b/macros/latex/contrib/csvmerge/csvmerge.dtx
new file mode 100644
index 0000000000..995565378e
--- /dev/null
+++ b/macros/latex/contrib/csvmerge/csvmerge.dtx
@@ -0,0 +1,1198 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2019 by Laurence R Taylor
+% -----------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% \fi
+%
+% \iffalse
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{csvmerge}
+\usepackage{hyperref}
+\hypersetup{
+ colorlinks=true,
+ linkcolor=blue,
+ filecolor=magenta,
+ urlcolor=cyan,
+}
+\DisableCrossrefs
+\CodelineNumbered
+\RecordChanges
+\CheckSum{525}
+\begin{document}
+\DocInput{csvmerge.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+%
+% \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 \~}
+%
+%
+%
+% \changes{v1.0}{?2019?/?07?/?17?}{Initial version}
+% \title{csvmerge}
+% \author{Laurence R Taylor}
+% \date{August 8, 2019}
+% \maketitle
+%
+% \begin{abstract}
+% The package |csvmerge.sty| is designed to take a bit of \TeX\ code such as a letter or a line
+% in a table and produce
+% multiple copies of it with parts of each copy filled in from a data file.
+% It is invoked in the usual manner from a master-file, that is a standard
+% \LaTeX\ file with
+%
+% \null\noindent\hskip 1in|\documentclass{whatever}|\\
+% \null\hskip 1in|\usepackage{csvmerge}|\\
+% \null\hskip 1.5in$\vdots$
+%
+% The data source is a standard csv file.
+% The bit of \TeX\ code resides in a blueprint file.
+% The |\usepackage{csvmerge}| can go anywhere in the preamble.
+% \end{abstract}
+% \tableofcontents
+% \def\Hyperlink#1{\hyperlink{#1Description}{\tt \mm #1}}
+% \def\Hypertarget#1#2{\hypertarget{#1Description}{#2}}
+% \xdef\mm{$\backslash\hskip-5pt\backslash$}
+% \section{Introduction}
+%
+% The |csvmerge.sty| merges \TeX\ code with a data file.
+% \begin{itemize}
+% \item
+% The \TeX\ code comes from a blueprint file, which looks like
+% a standard \TeX\ file except it contains no code which should
+% go into the preamble of a normal \TeX\ file.
+% The blueprint file should also not contain a |\begin{document}|
+% nor an |\end{document}|. This stuff goes in the master-file.
+% \item The data file is a standard csv file.
+% \end{itemize}
+% One difference between |csvmerge.sty| and other packages which
+% merge |csv| data into a \TeX\ file is that the user does not need to do
+% much with the |csv|-file. As long as the first row contains reasonable
+% entries describing the contents of its column you are good to go.
+% Extra columns are no problem; subsequent rows can be too short
+% or too long; characters which are special to \TeX\ such as |$| and |&|
+% can appear in the data; \dots\
+% \noindent More details concerning the |csv|-file can be found in subsection 2.1.
+%
+% The |tex|-file consists of standard \TeX\ code. Each row of the |csv|-file is processed
+% and you have access to the values of all the entries on that row as well as the row
+% number. You also can tell if the entry in a particular column is empty.
+% \noindent More details concerning the |tex|-file can be found in subsection 2.2.
+%
+% The main macro, |\mergeFields|, supports two modes.
+% In one mode, \emph{stream mode}, the \TeX\ code from the |tex|-file
+% is added to the input stream at the location from which |\mergeFields| is invoked.
+% In the second mode, \emph{storage mode}, the code is written to a
+% temporary file. You can then use the standard \LaTeX\ |\input| to read the
+% temporary file back into the master-file.
+%
+% Good models for the two modes are the following. Most mail-merges can be
+% done in streaming mode. Because \TeX\ is doing rather complicated things behind
+% the scenes when it is setting a table or a matrix, you are usually better off using
+% storage mode with your blueprint file containing the code for one line of your table/matrix.
+% After the data is generated you can read it back into your table.
+% See \hyperlink{subsubsection.B.3.1}{here} for a typical example.
+%
+% \newpage
+% \section{Usage}
+%
+% \DescribeMacro{\mergeFields}
+% The main macro is |\mergeFields| which takes one argument.
+% The format is
+%\begin{verbatim}
+% \mergeFields{
+% tex={<tex-file>}
+% csv = {<csv-file>}
+% tmp = {<tmp-file>}
+% }
+%\end{verbatim}
+% The |tmp| entry is not required. If there is none, |mergeFields| operates in
+% \emph{streaming} mode, otherwise it acts in \emph{storage} mode.
+% The |<prefix-file>| entry should be a path to the corresponding sort of file.
+% If the file name has spaces you will need to quote it: life is easier if there are no
+% spaces in file names.
+% The format |prefix = {<prefix-file>}| is quite forgiving: all leading and trailing spaces
+% are stripped out so |prefix = { <prefix-file> }| works.
+% The three lines can be in any order and do not even need to be on separate lines.
+% The extensions of the three files are irrelevant: the |tex|-file contains \TeX\ code
+% but it can have an extension of |.txt| (or anything else or none at all) if you prefer.
+% All that matters is that
+% when \TeX\ reads the file the contents have the proper content.
+% If you have a simple project you may be able to complete it just by looking at
+% the examples in \hyperlink{appendix.B}{appendix B}.
+%
+% \subsection{The data file}
+% The data file is a |csv| spreadsheet file.
+% By default the field delimiter is the comma and the
+% text delimiter is the double-quotes character.
+% This is default behavior for most spreadsheets when
+% asked to produce a |cvs| file.
+% If there are no {\tt "}'s in your |csv|-file there should be no problems.
+% In some cases you may need a different set of delimiters
+% and this is supported.
+% See \Hyperlink{setDelimitersTabQuote}\ below for more details.
+%
+% The entries in the first row should consist solely of \emph{alphanumeric characters,
+% punctuation and spaces}.
+% Each entry is a \emph{label} for that column.
+% Labels need not be unique although they usually are except sometimes there are
+% several columns with blank labels.
+%
+% A \emph{field-name} is extracted from a label by deleting all spaces and making all
+% characters lowercase: e.g. a column labeled |First Name| has a field-name
+% |firstname|. Commas are also deleted so a column label of |Last, First Name|
+% becomes a field-name of |lastfirstname|.
+% Distinct labels can have the same field-name although again
+% this seems unlikely except for blank labels.
+%
+% Associated to each field-name is a \emph{field-name-macro}.
+% This macro is private: its name is found by prepending |@LRT@@| to the field-name.
+% When |\mergeFields| is invoked, the data file is read one row at a time.
+% All rows after the first are data.
+% When a row is read, each entry is peeled off and placed in the field-name-macro
+% whose field-name is the one associated to the label for that column
+% with |@LRT@| prepended.
+% For example, if row one of some column contains |First Name|, the field-name is |firstname| and
+% the field-name-macro is |\@LRT@@firstname|. When a row after the first is read,
+% |\@LRT@@firstname| will expand to the entry in the |First Name| column on that row.
+%
+% When |\mergeFields| has read a row and set the field-name-macros the |tex|-file is
+% read and the \TeX\ code evaluated.
+% In streaming mode the result is added to the input stream at
+% the current location whereas in storage mode the result is written to the |tmp|-file.
+%
+% \DescribeMacro{End of csv-file}\Hypertarget{End of csv-file}
+% This process continues until the last line in the |csv|-file is processed OR until an entirely
+% blank line is encountered.
+% \vskip10pt
+% The request for only alphanumeric, punctuation and blanks for entries in row one is
+% not actually enforced but the macro |caselower| from |stringstrings| is used to
+% produce lowercase letters and may do weird things to characters not on the requested list.
+% Without studying the |stringstrings| manual carefully %
+% you may not be able to identify the field-names if you insist on weird characters.
+%
+% It is quite possible that several columns can have the same field-name, and hence
+% the same field-name-macro. In that case the macro will expand to the contents of the
+% column with that field-name which is furthest to the right.
+%
+% Because of the prepended |@LRT@@| you can not use these field-name-macros directly
+% in your |tex|-file.
+% The solution is to use \Hyperlink{Field}{}|{field-name}| which will expand correctly.
+% See the examples in appendix B.
+% \subsubsection{Entry issues}
+% Except for issues discussed here, you should be able to use any
+% standard |csv|-file.
+%
+% The data file is read with the usual \TeX\ issues turned off:
+% |#|, |$|, |&|, |@|, |%|
+% , |^|, |~|, and \verb!|!
+% can all be in your data file.
+% \begin{itemize}
+% \item
+% In streaming mode, only |#|, |$|, |&|, |@|, |%|, |^|, |~| print correctly.
+% The characters \$, \#, \%, @ and \& often occur in data and they print correctly.
+% \TeX\ code will not be rendered correctly so for example, |\$| in the data file produces
+% {$``$\tt\$} when \TeX ed.
+% As long as you are not too creative in your entries you should get the results you want.
+% \item
+% In storage mode the characters above end up printing correctly in the |tmp|-file
+% BUT when you |\input| the |tmp|-file back into your master-file these characters
+% will resume their usual \TeX\ meaning and wreak havoc with your code.
+% If you absolutely must have them, writing |\&|, |\$|, |\#|,
+% etc. in the |csv|-file may save you.
+% \end{itemize}
+%
+% \DescribeMacro{Delimiters}\null\hskip-\parindent
+% There is one more issue. For most csv files, the field separator is the comma.
+% When a field has a comma in it, the entire field is delimited by double quotes ({\tt"}).
+% When the field has a double quote it is converted to a pair of double quotes ({\tt""}) and so on.
+% If you have both commas and quotes in a field the best case scenario is that
+% you will get |""|'s where you were hoping for |"|'s. This probably is not what you want.
+% Even worse, a |",| in a data entry will end the entry prematurely at this point
+% and things deteriorate from there.
+%
+% There is a mechanism to deal with this. Most spreadsheets can save csv files with other
+% field (and text) delimiters. The second most common version of csv has a tab as the
+% field delimiter and quotes for fields which have a tab in a field.
+%
+% These two cases are supported out of the box. By default you get the comma-quotes version.
+% If you add |\setDelimitersTabQuote| before calling |\mergeFields| you will get
+% the tab-quotes version.
+% If you have a second call to |\mergeFields| and the data file is comma-quotes,
+% adding |\setDelimitersCommaQuote| before |\mergeFields| will restore comma-quotes.
+% See \hyperlink{setDelimitersCommaQuoteDescription}{setDelimters\dots}
+% for a more thorough discussion.
+%
+%
+% \subsection{The blueprint file}
+%
+% The blueprint file is a normal \TeX\ file with macros defined as above from the |csv|-file.
+% It should not contain a \verb!\begin{document}! or an \verb!\end{document}!
+% nor anything that needs to be expanded in the preamble.
+% Such things belong in the master file.
+%
+% For mail-merges, the |tex|-file should end with a \verb!\newpage!
+% to guarantee that each copy of the message appears on a
+% different page.
+% If you need custom sizes or headers or you have page numbers that you want to
+% reset for each copy, you should do this in the |tex|-file.
+%
+% To use the data from the |csv|-file you need to write |\Field{some-field-name}| wherever
+% you want the data in your |tex|-file.
+% Some field-names may be rather long so if you are going to use them a lot in your
+% |tex|-file, feel free to write something like |\def\sfn{\Field{some-field-name}}| at the
+% top of your |tex|-file and then use |\sfn| thereafter.
+%
+% One additional issue occurs in storage mode. You may very well want \TeX\ code in your
+% |tex|-file. When |mergeFields| reads a line of data, you want the field-name-macros to
+% expand to their current values but you often do not want your \TeX\ code to expand.
+% It is good practice stick a |\noexpand| in front of each \TeX\ macro.
+% Each line is expanded once when the line is written to the |tmp| file, so the |\noexpand|
+% disappears and you are left with just your \TeX\ macros.
+%
+% If you do define macros like |\sfn| as above, you will need
+% to write\\ |\noexpand\def\noexpand\sfn{\Field{some-field-name}}|.
+% \StopEventually{\PrintIndex}
+%
+% \section{List of public macros}
+% There are the 6 public macros: links are to descriptions of the |@LRT@|-versions which
+% actually do the work.
+%
+% \null\hskip-10pt \begin{tabular}{lll}
+% \Hyperlink{mergeFields}%
+% &\Hyperlink{Field}%
+% &\hbox to 0pt{\Hyperlink{ifFieldEmpty}\hss}%
+% \\
+% \Hyperlink{setDelimitersCommaQuote}&\Hyperlink{setDelimitersTabQuote}%
+% &\Hyperlink{makeMePublic}\\
+% \end{tabular}
+% \begin{itemize}
+% \item |\mergeFields{tex={tex-file}csv={csv-file}}| or
+% \\|\mergeFields{tex={tex-file}csv={csv-file}{tmp={tmp-file}}|\\
+% sets up to do the merge.
+% \hyperlink{section.2}{Section 2} is devoted to a detailed discussion.
+% \item |\Field{field-name}| expands to the current value of the field-name-macro.
+% \item |\ifFieldEmpty{field-name to test}{do if empty}{do if not}|
+% \item The two |\setDelimiters| set the delimiters to match those used in the |csv| file:
+% comma-quotes is the default.
+% \item |\makeMePublic| must be immediately followed by |\@LRT@| or you will get a
+% |Use of \makeMePublic doesn't match its definition.| error. Then you can write
+% |\makeMePublic \@LRT@foo\becomes\Foo| to make the public macro |\Foo| that
+% you just define equal to the private macro |\@LRT@foo|. You may not write
+% |\makeMePublic{\@LRT@foo}\becomes\Foo| or other variants: the first non-white-space
+% character \TeX\ sees after |\makeMePublic| needs to be the start of |\@LRT@|.
+%
+% As a useful example,
+% |\makeMePublic\@LRT@Row\becomes\Row| means you can get your hands on
+% the row number using |\Row|.
+% \end{itemize}
+%
+% \section{Implementation}
+%
+% \begin{macro}{Header}
+% First we have the standard package header stuff.
+% The line numbers in the typeset \jobname.dtx file match the line numbers
+% in the \jobname.sty file
+% generated by \TeX ing the \jobname.ins file.
+% \setcounter{CodelineNo}{15}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[2005/12/01]
+\ProvidesPackage{csvmerge}
+ [2019/07/17 v1.0 merges TeX code with csv data]
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Required Packages}
+% These required packages are part of the standard \href{https://www.tug.org/texlive/}{{\tt TeX Live}}
+%and \href{https://miktex.org}{{\tt MiKTEX}} distributions.
+% \begin{macrocode}
+\RequirePackage{stringstrings}
+\RequirePackage{trimspaces}
+\RequirePackage{etoolbox}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Options}
+% |csvmerge| supports an option which is rarely needed. All the private macros
+% (except \hyperlink{exceptionDescription}{one}) in
+% this package have |@LRT@| or |@lrt@| somewhere in their name so are very
+% unlikely to produce name conflicts. In the very unlikely chance that one or more of
+% the six public macros has a name conflict,
+% this can be alleviated by putting |\usepackage[foo]{csvmerge}|
+% in your master file. Here |foo| can be any string of alphabetical characters.
+% Then the names of all six public macros are invoked with a leading |foo|:
+% |\mergeFields| no longer exists but becomes |\foomergeFields|. The evident change happens
+% with the other five macros.
+%
+% The next two lines of code merely save the option for use
+% \hyperlink{optionsDescription}{later} at the end.
+% \begin{macrocode}
+\DeclareOption*{\xdef\@LRT@CO{\CurrentOption}}
+\ProcessOptions\relax
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+\makeatletter
+
+% \end{macrocode}
+% \begin{macro}{\mergeFields}
+% \Hypertarget{mergeFields}
+% |\@LRT@mergeFields| actually initiates the work.
+% It initializes some macros for later use.
+% Then it collects the |prefix={<prefix-file>}| arguments using |\@LRT@getFilePaths|
+% and checks to be sure it has a |csv|-file
+% and a |tex|-file. If not it bails.
+% Then it checks if it has a |tmp| file and sets the file reading subroutine,
+% |\@LRT@Input| to |\@LRT@streaming| is there is no |tmp| file and to
+% |\@LRT@storage| if there is. If there is a |tmp| file, it is opened.
+% Then |\@LRT@mergeData| is called which actually does the merging.
+% Finally, if there is a |tmp| file, it is closed.
+% \begin{macrocode}
+\newcommand{\@LRT@mergeFields}[1]{%
+\gdef\@LRT@csv{}%
+\gdef\@LRT@tex{}%
+\gdef\@LRT@tmp{}%
+\setcounter{\@LRT@macroPrefix Row}{2}\relax%
+\gdef\@LRT@csvBlankLine{}%
+\@LRT@getFilePaths#1=@%
+\if@LRT@empty{\@LRT@csv}{\@LRT@missingArgumentMessage{csv}}{}%
+\if@LRT@empty{\@LRT@tex}{\@LRT@missingArgumentMessage{tex}}{}%
+\if@LRT@empty{\@LRT@tmp}%
+{\global\let\@LRT@Input\@LRT@streaming}%
+{\global\let\@LRT@Input\@LRT@storage}%
+\if@LRT@empty{\@LRT@tmp}{}{%
+\immediate\openout\@lrt@tmpFile=\@LRT@tmp\relax}%
+\@LRT@mergeData%
+\if@LRT@empty{\@LRT@tmp}{}{\immediate\closeout\@lrt@tmpFile\relax}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \Hypertarget{macroPrefix}{}
+% \begin{macro}{\@LRT@macroPrefix}
+% \begin{macrocode}
+\gdef\@LRT@macroPrefix{@LRT@@}
+
+% \end{macrocode}
+% \end{macro}
+% \Hypertarget{Field}{}
+% \begin{macro}{\Field}
+% |\@LRT@Field| is just a wrapper for a |\csname ... \endcsname|.
+% Notice it adds the |\@LRT@macroPrefix| prefix to the argument so
+% the input is always the field-name and the output is always the value of
+% the corresponding field-name-macro.
+% Because of the third |@| there is no danger that these macros defined from
+% entries in the |csv|-file will conflict with other macros defined in this package
+% since none of them have a |@@| in their names.
+% \begin{macrocode}
+\def\@LRT@Field#1{%
+\csname\@LRT@macroPrefix#1\endcsname%
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ifFieldEmpty}
+% \Hypertarget{ifFieldEmpty}{}
+% |\ifFieldEmpty| takes three arguments.
+% The first argument is a field-name and if the content of the corresponding
+% macro is empty then the second argument is executed: otherwise the
+% third argument is executed.
+%
+% \begin{macrocode}
+\long\gdef\@LRT@ifFieldEmpty#1#2#3{\ifbool{\@LRT@macroPrefix#1}{#2}{#3}}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\setDelimitersCommaQuote}
+%\end{macro}
+% \begin{macro}{\setDelimitersTabQuote}
+% \Hypertarget{setDelimitersCommaQuote}{}
+% \Hypertarget{setDelimitersTabQuote}{}
+% These two |setDelimiters| are similar.
+% Recall how delimiters work. A row in a |csv|-file with comma delimiters
+% looks like |foo1,foo2,foo3,...| so the delimiter is the comma and if
+% |\@LRT@getFieldDelimited| is put in front of this string it will peal off
+% |foo1|. Since |^^I| is \TeX\ for the tab,
+% a row in a csv file with tab delimiters
+% looks like |foo1^^Ifoo2^^Ifoo3^^I...| and so the first two lines of
+% |\@LRT@setDelimitersCommaQuote| and |\@LRT@setDelimitersTabQuote|
+% look the same after switching |,| and |^^I|.
+%
+% There is a wrinkle in the tab case. The tab normally looks to \TeX\ like white space and
+% so by the time the line reaches |\@LRT@getFieldDelimited| the line looks like
+% |foo1foo2foo3...| and there is no way to break off |foo1|. The |\catcode`\^^I12\relax|
+% insures |\@LRT@getFieldDelimited| sees the line as |foo1^^Ifoo2^^Ifoo3^^I...|..
+% This means that the catcode of |^^I| must also be 12 when each line is read and the line
+% and the macro |\gdef\@LRT@catcodes{|\\|\catcode`\^^I12\relax}| insures this.
+% In the comma delimited version no catcode heroics are needed so |\@LRT@catcodes|
+% is empty.
+%
+% If some field contains one or more |\@LRT@fieldDelimiterBack|'s then the |csv|-file will use
+% the text-delimiter at the front and back. When quote is the text delimiter and |foo2| contains
+% a comma but |foo1| and |foo3| do not, the comma delimited string looks like
+% |foo1,"foo2",foo3,...| and the tab delimited string looks like
+% |foo1^^I"foo2"^^Ifoo3^^I...|.
+%
+% The text delimiters have a front one, the double-quotes in both versions, and the back one which is
+% the front text delimiter followed by the back field delimiter.
+%
+% The macro |\@LRT@blankFieldItem| is used to construct what a blank line looks like.
+% In the comma delimited case, you need a string of commas of the same length as
+% the number of entries on line one of the |csv|-file. In the tab delimited case, the blank line
+% turns out to be a blank macro.
+%
+% The |\@LRT@catcodes| macro is a collection of catcodes that need to be changed:
+% nothing for the comma delimited case and |^^I| for the tab delimited case.
+%
+% See \hyperlink{newDelimiterAppendix}{Appendix A} for more discussion on writing your own delimiters.
+% \begin{macrocode}
+{{%
+\gdef\@LRT@setDelimitersCommaQuote{
+\gdef\@LRT@fieldDelimiterBack{,}
+\gdef\@LRT@getFieldDelimited##1,{\@LRT@getFirstArg{##1}}
+\gdef\@LRT@textDelimiterFront{"}
+\gdef\@LRT@getTextDelimited"##1",{\@LRT@getFirstArg{##1}}
+\gdef\@LRT@blankFieldItem{,}
+\gdef\@LRT@catcodes{}
+}%
+}}
+
+{{\catcode`\^^I12\relax%
+\gdef\@LRT@setDelimitersTabQuote{
+\gdef\@LRT@fieldDelimiterBack{^^I}
+\gdef\@LRT@getFieldDelimited##1^^I{\@LRT@getFirstArg{##1}}
+\gdef\@LRT@textDelimiterFront{"}
+\gdef\@LRT@getTextDelimited"##1"^^I{\@LRT@getFirstArg{##1}}
+\gdef\@LRT@blankFieldItem{}
+\gdef\@LRT@catcodes{\catcode`\^^I12\relax}
+}%
+}}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@LRT@makeMePublic}
+% \hypertarget{exceptionDescription}{}
+% \hypertarget{makeMePublicDescription}{}
+% The next line of code defines the only macro which does not have |@LRT@|
+% in its name. It seems sufficiently weird that there should be no name conflicts.
+% Notice that |\makeatletter| is still in effect so |@| has catcode 11.
+%
+% Then we switch to |\makeatother| so |@| has catcode 12.
+% The next line expands to |\@LRT@makeMePublic| with the initial
+% |\@LRT@| having its |@|'s of catcode 11 so it is a private macro.
+% In the |\@LRT@| that you see, the |@|'s have catcode 12 so it is really
+% the macro |\@| with extra stuff. Since it should never be expanded
+% it doesn't really matter. Then we drop back into |\makeatletter| to define
+% more private macros.
+%
+% The net result is that you can write \\
+% \null\hskip1in |\makeMePublic \@LRT@foo\becomes\newMacro| \\in your master-file and
+% the private macro |\@LRT@foo| becomes the same as |\newMacro| and you can
+% use |\newMacro| in your |tex|-file.
+% \begin{macrocode}
+\expandafter\gdef\csname1238LRTLRTsvbneLRT\endcsname{@LRT@}
+\makeatother
+\expandafter\gdef\csname\csname1238LRTLRTsvbneLRT\endcsname
+makeMePublic\endcsname\@LRT@#1\becomes#2{\global\letcs{#2}{@LRT@#1}}%
+\makeatletter
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{private macros}
+% \end{macro}
+% \begin{macro}{\@LRT@Row}
+% \Hypertarget{Row}{}
+% The macro |\@LRT@Row| expands to the number of the row of the |csv|-file currently
+% being read. To get the |\xdef| to expand correctly we needed to define (and did)
+% |\@LRT@macroPrefix| first. Recall that the first line of actual data is row 2.
+% \begin{macrocode}
+\xdef\@LRT@Row{\noexpand\number\noexpand\value{\@LRT@macroPrefix Row}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\if@LRT@empty}\Hypertarget{if@LRT@empty}{}
+% Takes three arguments: if |#1| expands to empty do the code in |#2|;
+% otherwise do the code in |#3|.
+% \begin{macrocode}
+\newcommand{\if@LRT@empty}[3]{\ifthenelse{\equal{#1}{}}{#2}{#3}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@fieldName}
+% Takes an alphanumeric string, uses |\caselower| from the |stringstrings| package
+% to convert the string to all lower case; then it strips the spaces from the answer
+% using |\convertchar|, also from the |stringstrings| package. Next it strips commas from
+% the answer.
+% The final |\@LRT@TheString| makes the answer global.
+% \begin{macrocode}
+\gdef\@LRT@fieldName#1{%
+\caselower[q]{#1}%
+\convertchar[q]{\thestring}{ }{}%
+\convertchar[q]{\thestring}{,}{}%
+\xdef\@LRT@TheString{\thestring}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getFilePaths}
+% |\@LRT@getFilePaths#1=#2@| is a recursive macro which works through the
+% |prefix={<prefix-file>}| argument list.
+% The first argument, |#1|, picks up one |prefix={<prefix-file>}| and |#2| contains the rest of the arguments.
+% If |#1| is not empty it is passed to |\@LRT@extractKeyValue| which collects the
+% prefix and file path.
+% \begin{macrocode}
+\gdef\@LRT@getFilePaths#1=#2@{%
+\xdef\@LRT@hashKey{\trim@spaces{#1}}%
+\if@LRT@empty{\@LRT@hashKey}{}{
+\def\@LRT@test{tex}\ifthenelse{\equal{\@LRT@hashKey}{\@LRT@test}}{}%
+{\def\@LRT@test{csv}\ifthenelse{\equal{\@LRT@hashKey}{\@LRT@test}}{}%
+{\def\@LRT@test{tmp}\ifthenelse{\equal{\@LRT@hashKey}{\@LRT@test}}{}%
+{\@LRT@unknownArgumentMessage{#1}}}}%
+\@LRT@extractKeyValue#2@%
+\expandafter\@LRT@getFilePaths\@LRT@doWeStillHaveStuffToDo @}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@extractKeyValue}
+% |\@LRT@hashKey| contains the prefix and |\@LRT@hashValue| contains the file path.
+% If the prefix is not one of |tex|, |csv| or |tmp| you will be warned.
+% \begin{macrocode}
+\def\@LRT@extractKeyValue#1#2@{%
+\edef\@LRT@hashValue{\trim@spaces{#1}}%
+\xdef\@LRT@doWeStillHaveStuffToDo{\trim@spaces{#2}}%
+\expandafter\xdef\csname @LRT@\@LRT@hashKey\endcsname{\@LRT@hashValue}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@SecondifFieldEmpty}
+% |\@LRT@SecondifFieldEmpty| checks for an empty macro directly.
+% The previously defined \Hyperlink{ifFieldEmpty} uses a different method so both are needed at
+% various points in the code.
+% \begin{macrocode}
+\newcommand{\@LRT@SecondifFieldEmpty}[3]{%
+\edef\@LRT@fieldValue{#1}%
+\ifx\@LRT@fieldValue\@empty\relax{#2}\else{#3}\fi\relax}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getCommaFieldDelimited}
+% The macros |\@LRT@getCommaFieldDelimited|and
+% |\@LRT@getFieldDelimited| are the same when the field delimiter is the comma.
+% The list of field-names is always comma delimited and so
+% we need a |\@LRT@getCommaFieldDelimited| to iterate through it.
+% \begin{macrocode}
+\gdef\@LRT@getCommaFieldDelimited#1,{\@LRT@getFirstArg{#1}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{New counter} The counter containing the row number.
+% \begin{macrocode}
+\newcounter{\@LRT@macroPrefix Row}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{New read/write's}
+% \begin{macrocode}
+\newread\@lrt@csvFile%
+\newread\@lrt@texFile%
+\newwrite\@lrt@tmpFile%
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Messages}
+% \begin{macrocode}
+\gdef\@LRT@justProcessedMessage{%
+\immediate\typeout{}%
+\immediate\typeout{Just processed row %
+\@LRT@Row\space of the data file.}%
+\immediate\typeout{}%
+\stepcounter{\@LRT@macroPrefix Row}\relax%
+}
+
+\gdef\@LRT@failedToOpenMessage#1{%
+\immediate\typeout{}%
+\immediate\typeout{File #1 failed to open.}%
+\immediate\typeout{}\fi%
+\end{document}%
+}
+
+\gdef\@LRT@NoMoreDataMessage{%
+\immediate\typeout{No more data.}%
+\immediate\typeout{}%
+}
+
+\gdef\@LRT@missingArgumentMessage#1{
+\immediate\typeout{}%
+\immediate\typeout{I was never given a path to the #1 file.}%
+\immediate\typeout{}%
+\end{document}%
+}
+
+\gdef\@LRT@unknownArgumentMessage#1{
+\immediate\typeout{}%
+\immediate\typeout{I do not recognize an argument of type #1.}%
+\immediate\typeout{}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Inputs}
+% When |mergeFields| starts up, it knows immediately whether it is in streaming or in storage
+% mode. It sets |\@LRT@Input| to |\@LRT@streaming| or |\@LRT@storage|.
+% Each time a new line of data in the |csv|-file is read the
+% the macros are updated to reflect that data on the current line.
+% |\@LRT@streaming| uses the \LaTeX\ command |\input| to add the |tex|-file to the
+% stream.
+% |\@LRT@storage| works through the data in the |tex|-file.
+% First it opens the |tex| file; then it
+% reads the |tex|-file one line at a time; expands that line; and
+% writes the answer to a the |tmp|-file. When the |eof| for the |tex|-file is reached,
+% the |tex|-file is closed.
+%
+% |\@LRT@catcodeMagic| is used in two places to set the catcodes of certain characters
+% to values that won't cause trouble.
+%
+% |\@LRT@texNotAtEOF{#1}| is used to tighten up the code looping over the lines in
+% the |tex|-file in |\@LRT@storage|.
+% \begin{macrocode}
+\gdef\@LRT@streaming{\input{\@LRT@tex}}
+
+\gdef\@LRT@catcodeMagic{%
+\catcode`\^^M9\relax%
+\catcode`\#12\relax
+\catcode`\$12\relax
+\catcode`\&12\relax
+\catcode`\^12\relax
+\catcode`\_12\relax
+\catcode`\%12\relax
+}
+
+\gdef\@LRT@texNotAtEOF#1{%
+\ifeof\@lrt@texFile{\global\booltrue{@LRT@texEOF}}\else{#1}\fi%
+}
+
+\gdef\@LRT@storage{{%
+\@LRT@catcodeMagic%
+\openin\@lrt@texFile=\@LRT@tex\relax%
+\@LRT@texNotAtEOF{\global\boolfalse{@LRT@texEOF}}%
+\unlessboolexpr{bool{@LRT@texEOF}}{%
+\read\@lrt@texFile to \@LRT@preItem%
+\@LRT@texNotAtEOF{%
+\immediate\write\@lrt@tmpFile{\@LRT@preItem}\relax}%
+}{}%
+\immediate\closein\@lrt@texFile%
+}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@dataLineIterator}
+% This macro looks to see if the next character is |\@LRT@textDelimiterFront|.
+% If it is the entry is collected using |\@LRT@getTextDelimited| and if not we collect it
+% using |\@LRT@getFieldDelimited|.
+% \begin{macrocode}
+\gdef\@LRT@dataLineIterator{%
+\expandafter\@ifnextchar\@LRT@textDelimiterFront%
+{\@LRT@getTextDelimited}{\@LRT@getFieldDelimited}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getFirstArg}
+% This is the |\@LRT@getFirstArg| from the |\@LRT@getFieldDelimited| and \\
+% |\@LRT@getTextDelimited| macros. It collects the first field and then
+% uses |\@LRT@getSecondArg| to collect the rest of the line from the |csv|-file.
+% \begin{macrocode}
+\gdef\@LRT@getFirstArg#1{\gdef\@LRT@firstArg{#1}\@LRT@getSecondArg}
+\gdef\@LRT@getSecondArg#1@{\gdef\@LRT@restArg{#1}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getLOFirstArg}
+% These next two macros do the same thing with the first line of the |csv|-file.
+% The difference is that these two macros put their answers in a different pair of
+% macros than the previous two so we can iterate along both the first line (field-names)
+% and the current line of the |csv|-file.
+% \begin{macrocode}
+\gdef\@LRT@getLOFirstArg#1{\gdef\@LRT@ffirstArg{#1}\@LRT@getLOSecondArg}
+\gdef\@LRT@getLOSecondArg#1@{\gdef\@LRT@frestArg{#1}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getLineOne}
+% This is the version of |\@LRT@getFirstArg| which is used on the first line of the |csv|-file.
+% \begin{macrocode}
+\gdef\@LRT@fieldNameIterator#1,{\@LRT@getLOFirstArg{#1}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@setFirstLineAndBlankLine}
+% This macro collects the first line of the |csv|-file and packages it for later use:
+% |\@lrt@firstline| is the first line when we are done.
+% We also construct |\@LRT@csvBlankLine| which is used to check if
+% a line of the |csv|-file is blank.
+% \begin{macrocode}
+\providebool{@LRT@iterator}
+\gdef\@LRT@setFirstLineAndBlankLine#1{%
+\gdef\@lrt@firstline{}%
+\gdef\@LRT@csvBlankLine{}
+\edef\@LRT@restArg{#1\@LRT@fieldDelimiterBack}
+\booltrue{@LRT@iterator}%
+\whileboolexpr{bool{@LRT@iterator}}{%
+\expandafter\@LRT@dataLineIterator\@LRT@restArg @%
+\@LRT@fieldName{\@LRT@firstArg}%
+\xdef\@lrt@firstline{\@lrt@firstline\@LRT@TheString,}%
+\if@LRT@empty{\@LRT@restArg}%
+{\boolfalse{@LRT@iterator}}{\booltrue{@LRT@iterator}}%
+\ifboolexpr{bool{@LRT@iterator}}%
+{\xdef\@LRT@csvBlankLine{\@LRT@csvBlankLine\@LRT@blankFieldItem}}{}%
+}{}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@getAndProcessNextLine}
+% This is the recursive macro which processes each line of the |csv|-file
+% until there are no more.
+% The code in the first |{{| \dots |}}| pair
+% reads a line from the |csv|-file: the last line here converts
+% the answer from local to global.
+% The code in the second |{{| \dots |}}| pair checks
+% if the line is \hyperlink{End of csv-fileDescription}{blank} or not.
+% |\@LRT@exitGetAndProcessNextLine| exits the recursion and
+% |\@LRT@repeatGetAndProcessNextLine| reloops.
+% \begin{macrocode}
+\gdef\@LRT@getAndProcessNextLine{%
+\unlessboolexpr{bool{@LRT@csvEOF}}{%
+{{%
+\@LRT@catcodeMagic%
+\@LRT@catcodes
+\read\@lrt@csvFile to\@LRT@x@nextLine%
+\ifeof\@lrt@csvFile\relax{\global\booltrue{@LRT@csvEOF}}\else%
+{\global\boolfalse{@LRT@csvEOF}}\fi%
+\xdef\@LRT@nextLine{\@LRT@x@nextLine}%
+}}%
+{{%
+\if@LRT@empty{\@LRT@nextLine}%
+{\global\let\@LRT@next\@LRT@exitGetAndProcessNextLine\relax}%
+{\ifx\@LRT@csvBlankLine\@LRT@nextLine\relax%
+{\global\let\@LRT@next\@LRT@exitGetAndProcessNextLine\relax}\else%
+{\global\let\@LRT@next\@LRT@repeatGetAndProcessNextLine\relax}\fi}%
+\@LRT@next%
+}}%
+}{}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@exitGetAndProcessNextLine}
+% This just exits.
+% \begin{macrocode}
+\gdef\@LRT@exitGetAndProcessNextLine{%
+\closein\@lrt@csvFile\relax\global\booltrue{@LRT@csvEOF}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@repeatGetAndProcessNextLine}
+% This sets up to process the line we just read.
+% \begin{macrocode}
+\gdef\@LRT@repeatGetAndProcessNextLine{%
+\@LRT@processNextLine{\@LRT@nextLine\@LRT@fieldDelimiterBack}}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@setMacrosForOneEntry}
+% This bit of code sets the macro and the if-empty boolean for a single item:
+% \#1 is the field-name and \#2 is the entry in that (row,column).
+% \begin{macrocode}
+\gdef\@LRT@setMacrosForOneEntry#1#2{%
+\expandafter\xdef\csname\@LRT@macroPrefix#1\endcsname{#2}%
+\@LRT@SecondifFieldEmpty{#2}%
+{\global\booltrue{\@LRT@macroPrefix#1}}%
+{\global\boolfalse{\@LRT@macroPrefix#1}}%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@processNextLine}
+% This code actually processes the line from the |csv|-file.
+% The first three lines are setup.
+% The two |\edef|'s do the following: |\@LRT@restArg{#1}| has the entire current row; and
+% |\@LRT@frestArg| has a comma separated list of field-names.
+% Setting |\booltrue{@LRT@iterator}| means the iteration will start.
+% The two |\expandafter| lines do the iteration: the current values are in |\ffirstArg| for
+% the field-name and |\firstArg| for the entry in the current row.
+% The line |\@LRT@setMacrosForOneEntry| sets the contents of the field-name-macro.
+% Finally the
+% |\if@LRT@empty| line checks if we are done.
+%
+% The |\edef| between the two |\expandafter|'s adds a blank entry to the back of
+% |\@LRT@restArg| so if the row is too short in the |csv|-file it will still scan correctly.
+%
+% The |\@LRT@Input| outputs the result either to the stream or to the |tmp|-file
+% and |\@LRT@justProcessedMessage| writes to the terminal which row was just processed.
+% If something suddenly goes wrong you know which row you were working on
+% when things messed up.
+% \begin{macrocode}
+\gdef\@LRT@processNextLine#1{%
+\edef\@LRT@restArg{#1}%
+\edef\@LRT@frestArg{\@lrt@firstline}%
+\booltrue{@LRT@iterator}%
+\whileboolexpr{bool{@LRT@iterator}}{%
+\expandafter\@LRT@fieldNameIterator\@LRT@frestArg @%
+\edef\@LRT@restArgA{\@LRT@restArg\@LRT@fieldDelimiterBack}
+\expandafter\@LRT@dataLineIterator\@LRT@restArgA @%
+\@LRT@setMacrosForOneEntry{\@LRT@ffirstArg}{\@LRT@firstArg}%
+\if@LRT@empty{\@LRT@frestArg}%
+{\boolfalse{@LRT@iterator}}{\booltrue{@LRT@iterator}}%
+}{}%
+\@LRT@Input\relax%
+\@LRT@justProcessedMessage%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@LRT@mergeData}
+% This macro opens the |csv|-file, reads the first row.
+% The code between the |{{ ... }}| makes a comma separated list of field-names
+% in the order in which they occur in the |csv|-file. It also creates a macro which
+% expands to what a blank line in the |csv|-file will look like. It also defines one
+% boolean for each field-name.
+% This requires an iteration over |\@lrtfirstline|.
+%
+% Because \TeX\ |\newif|'s are not global, we need to define the ones we need as soon
+% as possible, which is right here.
+%
+% Then |\@LRT@mergeData| calls |\@LRT@getAndProcessNextLine| which
+% reads and processes the subsequent lines of the |csv| file.
+%
+% Finally it puts out a no-more-data message to let you know |\mergeFields| is finished.
+% \begin{macrocode}
+\gdef\@LRT@mergeData{%
+\providebool{@LRT@texEOF}%
+\immediate\openin\@lrt@csvFile=\@LRT@csv\relax%
+\providebool{@LRT@csvEOF}%
+\boolfalse{@LRT@csvEOF}%
+\ifeof\@lrt@csvFile\@LRT@failedToOpenMessage{\@LRT@csv}\fi%
+{{\@LRT@catcodes
+\read\@lrt@csvFile to\@lrt@firstlineX%
+\@LRT@setFirstLineAndBlankLine{\@lrt@firstlineX}
+}}%
+\booltrue{@LRT@iterator}
+\edef\@LRT@restArg{\@lrt@firstline}%
+\whileboolexpr{bool{@LRT@iterator}}{%
+\expandafter\@LRT@getCommaFieldDelimited\@LRT@restArg @%
+\providebool{\@LRT@macroPrefix\@LRT@firstArg}%
+\if@LRT@empty{\@LRT@restArg}%
+{\boolfalse{@LRT@iterator}}{\booltrue{@LRT@iterator}}%
+}{}%
+\@LRT@getAndProcessNextLine%
+\@LRT@NoMoreDataMessage%
+}
+
+% \end{macrocode}
+% \end{macro}
+% \Hypertarget{options}{}
+% \begin{macro}{Options code}
+% Here is the code which
+% examines the option string and maps the public macro names to the
+% private codes which actually do the work.
+% \begin{macrocode}
+\gdef\@LRT@weirdOption#1{\@ifundefined{@LRT@CO}%
+{\global\csletcs{#1}{@LRT@#1}}{{\global\csletcs{\@LRT@CO #1}{@LRT@#1}}}%
+}
+
+\@LRT@weirdOption{mergeFields}%
+\@LRT@weirdOption{Field}%
+\@LRT@weirdOption{ifFieldEmpty}%
+\@LRT@weirdOption{setDelimitersCommaQuote}%
+\@LRT@weirdOption{setDelimitersTabQuote}%
+\@LRT@weirdOption{makeMePublic}%
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Set the default delimiters}
+% Here \Hypertarget{defaults}{is}
+% where the default delimiters are set.
+% \begin{macrocode}
+\@LRT@setDelimitersCommaQuote
+
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{Finish up}
+% \begin{macrocode}
+\makeatother
+\endinput
+% \end{macrocode}
+% \end{macro}
+% \Finale
+% \newpage
+% \appendix
+% \section{Writing new delimiter macros}\hypertarget{newDelimiterAppendix}{}
+% If the field delimiter is not something \TeX\ sees as white space, life is fairly easy.
+% In your master-file, copy and paste one of the code examples below.
+% Change to suit your needs.
+%
+% \noindent***********************************************************************
+%
+% \begin{verbatim}
+% {{%
+% \makeatletter
+% \gdef\setMyDelimiters{%
+% \gdef\@LRT@fieldDelimiterBack{,}
+% \gdef\@LRT@getFieldDelimited##1,{\@LRT@getFirstArg{##1}}
+% \gdef\@LRT@textDelimiterFront{"}
+% \gdef\@LRT@textDelimiterBack{",}
+% \gdef\@LRT@getTextDelimited"##1",{\@LRT@getFirstArg{##1}}
+% \gdef\@LRT@blankFieldItem{,}
+% \gdef\@LRT@catcodes{}
+% }%
+% \makeatother
+% }}
+% \end{verbatim}
+%
+% \noindent***********************************************************************
+%
+% Replace all occurrences of {\tt ,} by your field delimiter. Replace all occurrences of {\tt "}
+% with your text deliminator
+% and you should be ready to go.
+% Just add |\setMyDelimiters| in your master-file before using |\mergeFields|.
+%
+% If the field delimiter is a white space character such as a tab, then copy and paste
+% the next example
+%
+% \noindent***********************************************************************
+%
+% \begin{verbatim}
+% \makeatletter
+% {{\makeatletter
+% \catcode`\^^I12\relax%
+% \gdef\@LRT@setDelimitersTabQuote{
+% \gdef\@LRT@fieldDelimiterBack{^^I}
+% \gdef\@LRT@getFieldDelimited##1^^I{\@LRT@getFirstArg{##1}}
+% \gdef\@LRT@textDelimiterFront{"}
+% \gdef\@LRT@textDelimiterBack{"^^I}
+% \gdef\@LRT@getTextDelimited"##1"^^I{\@LRT@getFirstArg{##1}}
+% \gdef\@LRT@blankFieldItem{}
+% \gdef\@LRT@catcodes{\catcode`\^^I12\relax}
+% }%
+% }}
+% \makeatother
+% }}
+% \end{verbatim}
+%
+% \noindent***********************************************************************
+%
+% Use Chapter 8 of the \TeX\ book to find how to write your delimiter and replace
+% all occurrences of |\^^I| with the code for your delimiter.
+% Then replace all occurrences of {\tt "} with your text deliminator
+% and hope for the best.
+% Try leaving |\@LRT@blankFieldItem| blank and hope for the best.
+% Again add |\setMyDelimiters| in your master-file before using |\mergeFields|.
+%
+% \section{Some examples}
+% \subsection{\TeX\ code in a table}
+% A typical line in a tabular environment looks like |item1 & item2& item3\\|.
+% Suppose you have 4 columns in your |csv|-file with entries |Last Name|,
+% |First name|, |Numerator| and |Denominator| and you want |item1| to be
+% |Last Name|, |item2| to be |First name| and |item3| to be |\frac{Numerator}{Denominator}|.
+% Here is the needed code in your |tex|-file:
+%
+% \begin{verbatim}
+% \Field{lastname}&\Field{firstname}&%
+% $\noexpand\frac{\Field{numerator}}{\Field{denominator}}$\noexpand\\
+% \end{verbatim}
+% You might have expected to see a |\noexpand| in front of the \$'s but remember \$ is one of
+% those characters which goes through unscathed to the |tmp|-file.
+% It certainly doesn't hurt to write |\noexpand$|. When you read the |tmp|-file back in
+% you do want |$| to resume its meaning of making math mode and it does.
+%
+% The |\noexpand| in front of the |\frac| and the |\\| are needed.
+% You don't want to try to expand either one
+% until the |tmp|-file is read back in.
+%
+% Assuming that the file |merge.tex| contains the code above and that the file |data.csv| contains your data,
+% the following code typesets the table.
+% \begin{verbatim}
+% \documentclass[12pt]{article}
+% \RequirePackage{csvmerge}
+% \begin{document}
+% \mergeFields{
+% tmp={example.tmp}
+% tex ={merge.tex}
+% csv = {data.csv}
+% }
+% \begin{tabular}{lll}
+% \input{example.tmp}
+% \end{tabular}
+% \end{document}
+% \end{verbatim}
+% The |csv|-file needs to contain the four field-names that appear in the |tex|-file,
+% but it is fine if it contains additional columns.
+%
+% \subsection{\TeX\ code in a mail-merge}
+% Here is a snippet of code to do a header in a mail-merge business letter.
+% The field-names from the |csv|-file should be obvious. The interesting point
+% is the usage of |\ifFieldEmpty|.
+% \begin{verbatim}
+% \Field{firstname} \ifFieldEmpty{middleinitial}{}
+% {\Field{middleinitial}.~}\Field{lastname}\par
+% \ifFieldEmpty{streetline1}{}{\Field{streetline1}\par}
+% \ifFieldEmpty{streetline2}{}{\Field{streetline2}\par}
+% \ifFieldEmpty{streetline3}{}{\Field{streetline3}\par}
+% \Field{city}, \Field{stateprovince} \Field{postalcode}
+% \end{verbatim}
+%
+% The |middleinitial| column is a middle initial with no period. Some recipients will have no middle initial
+% but you don't want just a floating period. Also you don't want an additional space.
+% Knuth also suggests that names should be \TeX ed with |First M.~Last| [The \TeX\ book, Ch. 6].
+% The |\ifFieldEmpty| with |streetline1| is probably redundant but often |streetline2| will be empty.
+% If it is not, we want a new line after it, but if it is empty we don't want a blank new line.
+%
+% In storage mode you need a |\noexpand| before the |~|, as well as before the |\par|'s.
+% \subsection{Some master-files}
+% \subsubsection{A table}
+% We are doing a table so we want storage mode.
+% We also want a horizontal line after each row of the table.
+% The master-file:
+% \begin{verbatim}
+% \documentclass[12pt]{amsart}
+% \RequirePackage{csvmerge}
+% \begin{document}
+% \mergeFields{
+% tmp= { ./table.tmp}
+% csv = {./data.csv}
+% tex ={./table.tex }
+% }
+% \begin{tabular}{|l|l|l|l|l|}
+% \hline%
+% \input{./table.tmp}
+% \end{tabular}
+% \end{document}
+% \end{verbatim}
+%
+% The |tex|-file |table.tmp|:
+% \begin{verbatim}
+% % one table line
+% \Field{firstname} &\Field{id} & \Field{city} &\Field{lastname}&
+% \Field{postalcode} \noexpand\\
+% \noexpand\hline
+% \end{verbatim}
+%
+% \subsubsection{A mail-merge}
+% We are doing a mail-merge so we can use streaming mode.
+% Since the |tex|-file name has spaces, we have quoted it.
+% The master-file:
+% \begin{verbatim}
+% \documentclass[12pt]{letter}
+% \RequirePackage{./csvmerge}
+% \begin{document}
+% \mergeFields{ tex = {"./Second letter.template" }
+% csv ={ ./Invites.csv}}
+% \end{document}
+% \end{verbatim}
+%
+% The |tex|-file |Second letter.template|:
+%
+% \begin{verbatim}
+% %First page of letter
+% \setcounter{page}{1}
+%
+% \Field{firstname} \ifFieldEmpty{middleinitial}{}%
+% {\Field{middleinitial}.~}\Field{lastname}\par
+% \ifFieldEmpty{streetline1}{}{\Field{streetline1} \par}
+% \ifFieldEmpty{streetline2}{}{\Field{streetline2}\par}
+% \ifFieldEmpty{streetline3}{}{\Field{streetline3}\par}
+% \Field{city}, \Field{stateprovince} \Field{postalcode}
+%
+% \vskip.25in
+% Dear \Field{preferredfirstname},\par
+% \vskip10pt
+% How come no RSVP?
+% \vskip10pt
+% Bilbo Baggins
+% \newpage
+% \end{verbatim}
+%
+% Here is an equivalent version using storage mode.
+% The master-file:
+% \begin{verbatim}
+% \documentclass[12pt]{letter}
+% \RequirePackage{./csvmerge}
+% \begin{document}
+% \mergeFields{ tex = {"./Second letter.template" }
+% csv ={ ./Invites.csv}tmp={letters}}
+% \input{letters}
+% \end{document}
+% \end{verbatim}
+%
+% We must adjust the |tex|-file |Second letter.template|:
+%
+% \begin{verbatim}
+% %First page of letter
+% \noexpand\setcounter{page}{1}
+%
+% \Field{firstname} \ifFieldEmpty{middleinitial}{}%
+% {\Field{middleinitial}.\noexpand~}\Field{lastname}\noexpand\par
+% \ifFieldEmpty{streetline1}{}{\Field{streetline1} \noexpand\par}
+% \ifFieldEmpty{streetline2}{}{\Field{streetline2}\noexpand\par}
+% \ifFieldEmpty{streetline3}{}{\Field{streetline3}\noexpand\par}
+% \Field{city}, \Field{stateprovince} \Field{postalcode}
+%
+% \noexpand\vskip.25in
+% Dear \Field{preferredfirstname},\par
+% \noexpand\vskip10pt
+% How come no RSVP?
+% \noexpand\vskip10pt
+% Bilbo Baggins
+% \noexpand\newpage
+% \end{verbatim}
+%
+% Usually using storage mode when you don't need it is wasteful since you have to create and
+% save a |tmp|-file. It can come in handy if your letter code has lots of field macros and
+% you can't get one |tex|-file to not have overfull/underfull boxes and the like after the
+% various expansions. The |tmp|-file contains all the letters and you can fine tune each one and
+% then just do
+% \begin{verbatim}
+% \documentclass[12pt]{letter}
+% \begin{document}
+% \input{letters}
+% \end{document}
+% \end{verbatim}
+
+
+
+
+
+