summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/datatool/datatool-user.tex
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/datatool/datatool-user.tex
Initial commit
Diffstat (limited to 'macros/latex/contrib/datatool/datatool-user.tex')
-rw-r--r--macros/latex/contrib/datatool/datatool-user.tex11443
1 files changed, 11443 insertions, 0 deletions
diff --git a/macros/latex/contrib/datatool/datatool-user.tex b/macros/latex/contrib/datatool/datatool-user.tex
new file mode 100644
index 0000000000..08f01e258f
--- /dev/null
+++ b/macros/latex/contrib/datatool/datatool-user.tex
@@ -0,0 +1,11443 @@
+\documentclass[report,widecs]{nlctdoc}
+
+\DeleteShortVerb{\|}
+
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{ifthen}
+\usepackage[verbose=false]{datatool}
+\usepackage{mfirstuc}[2017/11/10]
+\usepackage{datapie,databar,databib,person,datagidx}
+\usepackage{textcomp}
+\usepackage{graphicx}
+\usepackage{colortbl}
+\usepackage{booktabs}
+\usepackage{metalogo}
+\usepackage{cmap}
+\usepackage{alltt}
+\ifpdf
+\usepackage{mathpazo}
+\usepackage[scaled=.88]{helvet}
+\usepackage{courier}
+\fi
+\usepackage{caption}
+\usepackage[colorlinks,
+ bookmarks,
+ hyperindex=false,
+ pdfauthor={Nicola L.C. Talbot},
+ pdftitle={datatool: Databases and data manipulation},
+ pdfkeywords={LaTeX,package,database,data,chart,plot}]{hyperref}
+\usepackage{xr-hyper}
+\usetikzlibrary{snakes}
+
+\PageIndex
+\IndexPrologue{\chapter*{Index}}
+\setcounter{IndexColumns}{2}
+
+\ifpdf
+ \externaldocument{datatool-code}
+\fi
+
+\doxitem{Counter}{counter}{counters}
+\doxitem{Option}{option}{package options}
+
+\newcommand*{\desctr}[1]{\DescribeCounter{#1}\ctrfmt{#1}}
+
+\newrobustcmd{\dbs}{\texttt{\string\\}}
+
+\newcommand{\idbs}{%
+ \dbs\index{\string\\\actualchar\dbs\encapchar usage}%
+}
+
+\setlength\marginparwidth{70pt}
+
+
+ %bibliography database
+\DTLnewdb{docbib}
+\DTLnewrow{docbib}
+\DTLnewdbentry{docbib}{CiteKey}{Goossens}
+\DTLnewdbentry{docbib}{EntryType}{book}
+\DTLnewdbentry{docbib}{Author}{{}{Goossens}{}{Michel},{}{Mittelbach}{}{Frank},{}{Samarin}{}{Alexander}}
+\DTLnewdbentry{docbib}{Title}{The \LaTeX\ Companion}
+\DTLnewdbentry{docbib}{Publisher}{Addison-Wesley}
+\DTLnewdbentry{docbib}{Year}{1994}
+
+ % datagidx index example database
+
+\newgidx{gidx-index}{Index}% define a database for the index
+
+\DTLgidxSetDefaultDB{gidx-index}% set this as the default
+
+\newterm{mac\'edoine}
+\newterm{macram\'e}
+\newterm[label=elite]{{\'e}lite}
+\newterm{reptile}
+\newterm[seealso={reptile}]{crocodylian}
+
+\newterm
+ [%
+ parent=crocodylian
+ ]
+ {crocodile}
+
+\newterm
+ [%
+ parent=crocodylian
+ ]
+ {alligator}
+
+\newterm
+ [%
+ parent=crocodylian,
+ description={(also cayman)}
+ ]
+ {caiman}
+
+\newterm[see={caiman}]{cayman}
+
+\begin{document}
+% Some of the commands are too long to produce nicely formatted
+% paragraphs so use ragged-right:
+\raggedright
+\setlength{\parindent}{1em}%
+
+\MakeShortVerb{"}
+
+ \title{User Manual for datatool bundle version~2.31}
+ \author{Nicola L.C. Talbot\\
+\url{http://www.dickimaw-books.com/}}
+
+ \date{2018-12-07}
+ \maketitle
+
+\pagenumbering{roman}
+
+\noindent
+The \styfmt{datatool} bundle comes with the following documentation:
+\begin{description}
+ \item[datatool-user.pdf]
+ This document is the main user guide for the \styfmt{datatool}
+ bundle.
+
+ \item[\url{datatool-code.pdf}]
+ Advanced users wishing to know more about the inner workings of
+ all the packages provided in the \styfmt{datatool} bundle should
+ read \qt{Documented Code for datatool v2.31}
+
+ \item[INSTALL] Installation instructions.
+
+ \item[CHANGES] Change log.
+
+ \item[README] Package summary.
+\end{description}
+
+\begin{important}
+There's an old adage, ``use the right tool for the right job.''
+A carpenter's fine chisel is the right tool for delicate carving,
+but if you try to use it to hack off a tree branch it will take a
+long time. That doesn't mean there's something wrong with the
+chisel. It just means you're using the wrong tool for the job.
+
+The \styfmt{datatool} bundle is provided to help perform repetitive
+commands, such as mail merging, but since \TeX\ is designed as a
+typesetting language, don't expect this bundle to perform as
+efficiently as custom database systems or a dedicated mathematical
+or scripting language. \textbf{If the provided packages take a frustratingly
+long time to compile your document, use another language to perform
+your calculations or data manipulation and save the results in a
+file that can be input into your document.} For large amounts of
+data that need to be sorted or filtered or joined, consider storing your data
+in an~SQL database and use
+\app{datatooltk}\footnote{\url{http://www.dickimaw-books.com/software/datatooltk/}} to import the data,
+using SQL syntax to filter, sort and otherwise
+manipulate the values.
+\end{important}
+
+This bundle consists of the following packages:
+\begin{description}
+\item[\sty{datatool}] Main package providing database support.
+Automatically loads \sty{datatool-base}.
+
+\item[\sty{datatool-base}] Provides the main library code for
+numerical and string functions. Automatically
+loads \sty{datatool-fp} or \sty{datatool-pgfmath} depending on
+package options.
+
+\item[\sty{datagidx}] Package for generating indexes and glossaries.
+Automatically loads \sty{datatool}.
+
+\item[\sty{databar}] Package for drawing bar charts.
+Automatically loads \sty{datatool}.
+
+\item[\sty{datapie}] Package for drawing pie charts.
+Automatically loads \sty{datatool}.
+
+\item[\sty{dataplot}] Package for drawing simple line graphs.
+Automatically loads \sty{datatool}.
+
+\item[\sty{databib}] Package for loading a bibliography into a
+database. Automatically loads \sty{datatool}.
+
+\item[\sty{person}] Package for referencing people by the
+appropriate gender pronouns. Automatically loads \sty{datatool}.
+
+\end{description}
+
+In addition, there are two mutually exclusive packages
+\sty{datatool-fp} and \sty{datatool-pgfmath} that provide
+mathematical related commands that are just wrapper functions for
+\sty{fp} or \sty{pgfmath} commands. These can be loaded individually
+without loading \sty{datatool}. For example, the following documents
+produce the same results, but the first uses the \sty{fp} package
+and the second uses the \sty{pgfmath} package:
+
+\begin{enumerate}
+\item Using \sty{fp} macros:
+\begin{verbatim}
+\documentclass{article}
+\usepackage{datatool-fp}
+\begin{document}
+1=2: \dtlifnumeq{1}{2}{true}{false}.
+\end{document}
+\end{verbatim}
+
+\item Using \sty{pgfmath} macros:
+\begin{verbatim}
+\documentclass{article}
+\usepackage{datatool-pgfmath}
+\begin{document}
+1=2: \dtlifnumeq{1}{2}{true}{false}.
+\end{document}
+\end{verbatim}
+
+\end{enumerate}
+
+\begin{important}
+Both \sty{fp} and \sty{pgfmath} have some limitations. These limitations
+will therefore also be present in the various packages provided
+with \sty{datatool}, according to the underlying package used.
+\end{important}
+
+\cleardoublepage
+\pdfbookmark[0]{Contents}{contents}
+\tableofcontents
+\cleardoublepage
+\pdfbookmark[0]{List of Examples}{examples}
+\listofexamples
+\cleardoublepage
+\pdfbookmark[0]{List of Figures}{figures}
+\listoffigures
+\cleardoublepage
+\pdfbookmark[0]{List of Tables}{tables}
+\listoftables
+
+\pagenumbering{arabic}
+\chapter{Introduction}
+
+ \changes{1.0}{2007 July 22}{Initial version}
+The \sty{datatool} bundle consists of the following
+packages: \sty{datatool} (which loads \sty{datatool-base} and either
+\sty{datatool-fp} or \sty{datatool-pgfmath}), \sty{datagidx}, \sty{datapie}, \sty{dataplot},
+\sty{databar}, \sty{databib} and \sty{person}.
+
+\begin{itemize}
+\item The \sty{datatool} package can be used to:
+\begin{itemize}
+\item Create or load databases.
+\item Sort rows of a database (either numerically or alphabetically,
+ascending or descending).
+\item Perform repetitive operations on each row of a database
+(e.g.\ mail merging). Conditions may be imposed to exclude rows.
+\end{itemize}
+Package Options:
+ \begin{description}
+ \item[\pkgopt{utf8}] Boolean key. May be used to switch off the UTF-8
+ support described on \pageref{utf8support} in \sectionref{sec:sort}.
+ If you both load \sty{inputenc} with UTF-8
+ support and you use accent commands like \cs{'} or \cs{c} then make
+ sure you have at least version 2.05 of \sty{mfirstuc}
+ if you want to use commands like \ics{makefirstuc}.
+ \item[\pkgopt{verbose}] Boolean key. If
+ \pkgoptval{true}{verbose}, prints informational messages in
+ transcript.
+ \item[\pkgopt{math}] May take one of two values:
+ \pkgoptval{fp}{math} (load \sty{datatool-fp}) or
+ \pkgoptval{pgfmath}{math} (load \sty{datatool-pgfmath}). Default is:
+ \pkgoptval{fp}{math}.
+ \item[\pkgopt{delimiter}] Delimiter used in CSV files.
+ Default is a double quote (\texttt{\string"}).
+ \item[\pkgopt{separator}] Delimiter used in CSV files.
+ Default is a comma (\texttt{,}).
+ \end{description}
+
+\item The \sty{datatool-base} package can be used to:
+\begin{itemize}
+\item Determine whether an argument is an integer, a real number,
+currency or a string. (Scientific notation is currently not
+supported.) Locale dependent number settings are supported (such
+as a comma as a decimal character and a full stop as a number
+group character).
+\item Convert locale dependent numbers/currency to the decimal
+format required by the \sty{fp} or \sty{pgfmath} packages, enabling fixed point
+arithmetic to be performed on elements of the database.
+\item Names can be converted to initials.
+\item Determine if strings are all upper or lower case.
+\item Perform string comparisons (both case sensitive and case insensitive).
+\end{itemize}
+Package Options:
+ \begin{description}
+ \item[\pkgopt{verbose}] Boolean key. If
+ \pkgoptval{true}{verbose}, prints informational messages in
+ transcript.
+ \item[\pkgopt{math}] May take one of two values:
+ \pkgoptval{fp}{math} (load \sty{datatool-fp}) or
+ \pkgoptval{pgfmath}{math} (load \sty{datatool-pgfmath}). Default is:
+ \pkgoptval{fp}{math}.
+ \end{description}
+
+\item The \sty{datagidx} package (see \autoref{sec:datagidx}) can be used
+to generate indexes or glossaries as an alternative to packages
+such as \sty{glossaries}.
+
+\item The \sty{datapie} package (see \autoref{sec:datapie}) can be used to convert a database into
+a pie chart:
+\begin{itemize}
+\item Segments can be separated from the rest of the chart to make
+them stand out.
+\item Colour/grey scale options.
+\item Predefined segment colours can be changed.
+\item Hooks provided to add extra information to the chart
+\end{itemize}
+
+\item The \sty{databar} package (see \autoref{sec:databar}) can be used to convert a database into
+a bar chart:
+\begin{itemize}
+\item Colour/grey scale options.
+\item Predefined bar colours can be changed.
+\item Hooks provided to add extra information to the chart
+\end{itemize}
+
+(The \sty{datapie} and \sty{databar} packages do not support the
+creation of 3D charts, and I have no plans to implement them at any
+later date. The use of 3D charts should be discouraged. They may look
+pretty, but the purpose of a chart is to be informative. Three
+dimensional graphics cause distortion, which can result in misleading
+impressions. The \sty{pgf} manual provides a more in-depth
+discussion on the matter.)
+
+\item The \sty{dataplot} package (see \autoref{sec:dataplot}) can be used to convert a database into
+a two dimensional plot using markers and/or lines. Three dimensional
+plots are currently not supported.
+
+\item The \sty{databib} package (see \autoref{sec:databib}) can be used to convert a \BibTeX\ database
+into a \sty{datatool} database.
+
+\item The \sty{person} package (see \autoref{sec:person}) can be
+used for gender-specific mail-merging and similar uses to avoid the
+cumbersome use of the impersonal \qt{he\slash she}.
+
+\end{itemize}
+
+\chapter{Data Types}
+\label{sec:datatypes}
+
+The \sty{datatool-base} package recognises four data types: integers,
+real numbers, currency and strings.
+
+\begin{description}
+\item[Integers] An integer is a sequence of digits, optionally
+groups of three digits may be separated by the number group character.
+The default number group character is a comma (,) but may be
+changed using \cs{DTLsetnumberchars} (see below).
+
+\item[Real Numbers] A real number is an integer followed by the
+decimal character followed by one or more digits. The decimal
+character is a full stop (.) by default. The number group
+and decimal characters may be changed using
+\begin{definition}[\DescribeMacro{\DTLsetnumberchars}]%
+\cs{DTLsetnumberchars}\marg{number group character}\marg{decimal character}
+\end{definition}
+\begin{important}
+Note that scientific notation is not supported, and the number group
+character may not be used after the decimal character.
+\end{important}
+
+\item[Currency] A currency symbol followed by an integer or
+real number is considered to be the currency data type.
+There are two predefined currency symbols, "\$" and \cs{pounds}.
+In addition, if any of the following commands are defined at the
+start of the document, they are also considered to be a currency
+symbol: \cs{texteuro}, \cs{textdollar}, \cs{textstirling},
+\cs{textyen}, \cs{textwon}, \cs{textcurrency}, \cs{euro}
+and \cs{yen}. Additional currency symbols can be defined using
+\begin{definition}[\DescribeMacro{\DTLnewcurrencysymbol}]%
+\cs{DTLnewcurrencysymbol}\marg{symbol}
+\end{definition}
+
+\item[Strings] Anything that doesn't belong to the above three
+types is considered to be a string.
+
+\end{description}
+
+\section{Conditionals}
+\label{sec:ifconditions}
+
+The following conditionals are provided by the \sty{datatool-base}
+package:
+\begin{definition}[\DescribeMacro{\DTLifint}]%
+\cs{DTLifint}\marg{text}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{text} is an integer then do \meta{true part}, otherwise
+do \meta{false part}. For example
+\begin{verbatim}
+\DTLifint{2536}{integer}{not an integer}
+\end{verbatim}
+produces:
+\DTLifint{2536}{integer}{not an integer}.
+
+The number group character may appear in the number, for example:
+\begin{verbatim}
+\DTLifint{2,536}{integer}{not an integer}
+\end{verbatim}
+produces:
+\DTLifint{2,536}{integer}{not an integer}.
+However, the number group character may only be followed by a group
+of three digits. For example:
+\begin{verbatim}
+\DTLifint{2,5,3,6}{integer}{not an integer}
+\end{verbatim}
+produces:
+\DTLifint{2,5,3,6}{integer}{not an integer}.
+The number group character may be changed. For example:
+\begin{verbatim}
+\DTLsetnumberchars{.}{,}%
+\DTLifint{2,536}{integer}{not an integer}
+\end{verbatim}
+this now produces:
+\DTLsetnumberchars{.}{,}\relax
+\DTLifint{2,536}{integer}{not an integer}, since 2,536 is now
+a real number.
+
+Note that nothing else can be appended or prepended to the
+number. For example:
+\begin{verbatim}
+\DTLsetnumberchars{,}{.}%
+\DTLifint{2,536m}{integer}{not an integer}
+\end{verbatim}
+produces:
+\DTLsetnumberchars{,}{.}\relax
+\DTLifint{2,536m}{integer}{not an integer}.
+
+\begin{definition}[\DescribeMacro{\DTLifreal}]%
+\cs{DTLifreal}\marg{text}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{text} is a real number then do \meta{true part}, otherwise
+do \meta{false part}. For example
+\begin{verbatim}
+\DTLifreal{1000.0}{real}{not real}
+\end{verbatim}
+produces:
+\DTLifreal{1000.0}{real}{not real}.
+
+Note that an integer is not considered a real number:
+\begin{verbatim}
+\DTLifreal{1,000}{real}{not real}
+\end{verbatim}
+produces:
+\DTLifreal{1,000}{real}{not real}.
+
+Whereas
+\begin{verbatim}
+\DTLifreal{1,000.0}{real}{not real}
+\end{verbatim}
+produces:
+\DTLifreal{1,000.0}{real}{not real}.
+
+However
+\begin{verbatim}
+\DTLsetnumberchars{.}{,}%
+\DTLifreal{1,000}{real}{not real}
+\end{verbatim}
+produces:
+\DTLsetnumberchars{.}{,}\relax
+\DTLifreal{1,000}{real}{not real} since the comma is now
+the decimal character.
+
+Currency is not considered to be real:
+\begin{verbatim}
+\DTLsetnumberchars{,}{.}%
+\DTLifreal{\$1.00}{real}{not real}
+\end{verbatim}
+produces:
+\DTLsetnumberchars{,}{.}\relax
+\DTLifreal{\$1.00}{real}{not real}.
+
+\begin{definition}[\DescribeMacro{\DTLifcurrency}]%
+\cs{DTLifcurrency}\marg{text}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{text} is currency, then do \meta{true part}, otherwise
+do false part. For example:
+\begin{verbatim}
+\DTLifcurrency{\$5.99}{currency}{not currency}
+\end{verbatim}
+produces:
+\DTLifcurrency{\$5.99}{currency}{not currency}. Similarly:
+\begin{verbatim}
+\DTLifcurrency{\pounds5.99}{currency}{not currency}
+\end{verbatim}
+produces:
+\DTLifcurrency{\pounds5.99}{currency}{not currency}.
+Note, however, that
+\begin{verbatim}
+\DTLifcurrency{US\$5.99}{currency}{not currency}
+\end{verbatim}
+produces:
+\DTLifcurrency{US\$5.99}{currency}{not currency}. If you want
+this to be considered currency, you will have to add the
+sequence "US\$" to the set of currency symbols:
+\begin{verbatim}
+\DTLnewcurrencysymbol{US\$}%
+\DTLifcurrency{US\$5.99}{currency}{not currency}
+\end{verbatim}
+this now produces:
+\DTLnewcurrencysymbol{US\$}\relax
+\DTLifcurrency{US\$5.99}{currency}{not currency}.
+
+This document has used the \sty{textcomp} package which defines
+\cs{texteuro}, so this is also considered to be currency. For
+example:
+\begin{verbatim}
+\DTLifcurrency{\texteuro5.99}{currency}{not currency}
+\end{verbatim}
+produces:
+\DTLifcurrency{\texteuro5.99}{currency}{not currency}.
+
+The preferred method is to display the euro symbol in a sans-serif
+font, but
+\begin{verbatim}
+\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}
+\end{verbatim}
+will produce:
+\DTLifcurrency{\textsf{\texteuro}5.99}{currency}{not currency}.
+
+It is better to define a new command, for example:
+\begin{verbatim}
+\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}
+\end{verbatim}
+and add that command to the list of currency symbols. In fact,
+in this case, if you define the command \cs{euro} in the
+preamble, it will automatically be added to the list of known
+currency symbols. If however you define \cs{euro} in the document,
+you will have to add it using \ics{DTLnewcurrencysymbol}. For
+example:
+\begin{verbatim}
+\newcommand*{\euro}{\textsf{\texteuro}}%
+\DTLnewcurrencysymbol{\euro}%
+\DTLifcurrency{\euro5.99}{currency}{not currency}
+\end{verbatim}
+produces:
+\DeclareRobustCommand*{\euro}{\textsf{\texteuro}}\relax
+\DTLnewcurrencysymbol{\euro}\relax
+\DTLifcurrency{\euro5.99}{currency}{not currency}.
+
+\begin{definition}[\DescribeMacro{\DTLifcurrencyunit}]%
+\cs{DTLifcurrencyunit}\marg{text}\marg{symbol}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{text} is currency, and uses \meta{symbol} as the unit of
+currency, then do \meta{true part} otherwise do \meta{false part}.
+For example:
+\begin{verbatim}
+\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}
+\end{verbatim}
+produces:
+\DTLifcurrencyunit{\$6.99}{\$}{dollars}{not dollars}.
+Another example:
+\begin{verbatim}
+\def\cost{\euro10.50}%
+\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}
+\end{verbatim}
+produces:
+\def\cost{\euro10.50}\relax
+\DTLifcurrencyunit{\cost}{\euro}{euros}{not euros}.
+
+\begin{definition}[\DescribeMacro{\DTLifnumerical}]%
+\cs{DTLifnumerical}\marg{text}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{text} is numerical (either an integer, real number or
+currency) then do \meta{true part} otherwise do
+\meta{false part}.
+For example:
+\begin{verbatim}
+\DTLifnumerical{1,000.0}{number}{string}.
+\end{verbatim}
+produces: \DTLifnumerical{1,000.0}{number}{string}.
+Whereas
+\begin{verbatim}
+\DTLsetnumberchars{.}{,}%
+\DTLifnumerical{1,000.0}{number}{string}.
+\end{verbatim}
+produces:
+\DTLsetnumberchars{.}{,}\relax
+\DTLifnumerical{1,000.0}{number}{string}.
+Since the number group character is now a full stop, and the
+decimal character is now a comma. (The number group character
+may only appear before the decimal character, not after it.)
+
+Currency is also considered to be numerical:
+\begin{verbatim}
+\DTLsetnumberchars{,}{.}%
+\DTLifnumerical{\$1,000.0}{number}{string}.
+\end{verbatim}
+produces:
+\DTLsetnumberchars{,}{.}\relax
+\DTLifnumerical{\$1,000.0}{number}{string}.
+
+\begin{definition}[\DescribeMacro{\DTLifstring}]%
+\cs{DTLifstring}\marg{text}\marg{true part}\marg{false part}
+\end{definition}
+This is the opposite of \cs{DTLifnumerical}. If \meta{text} is
+not numerical, do \meta{true part}, otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLifcasedatatype}]%
+\cs{DTLifcasedatatype}\marg{text}\marg{string case}\marg{int case}\marg{real case}\marg{currency case}
+\end{definition}
+If \meta{text} is a string do \meta{string case}, if \meta{text}
+is an integer do \meta{int case}, if \meta{text} is a real number
+do \meta{real case}, if \meta{text} is currency do
+\meta{currency case}. For example:
+\begin{verbatim}
+\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}
+\end{verbatim}
+produces:
+\DTLifcasedatatype{1,000}{string}{integer}{real}{currency}.
+
+\begin{definition}[\DescribeMacro{\dtlifnumeq}]%
+\cs{dtlifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false
+paty}
+\end{definition}
+If \meta{num1} is equal to \meta{num2}, then do \meta{true part},
+otherwise to \meta{false part} where \meta{num1} and \meta{num2}
+are plain numbers using a full stop as the decimal point and no
+number group separator. For currency or locale dependent numbers use
+\cs{DTLifnumeq}.
+
+\begin{definition}[\DescribeMacro{\DTLifnumeq}]%
+\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{num1} is equal to \meta{num2}, then do \meta{true part},
+otherwise do \meta{false part}. Note that both \meta{num1} and
+\meta{num2} must be numerical (either integers, real numbers or
+currency). The currency symbol is ignored when determining
+equality. For example
+\begin{verbatim}
+\DTLifnumeq{\pounds10.50}{10.5}{true}{false}
+\end{verbatim}
+produces:
+\DTLifnumeq{\pounds10.50}{10.5}{true}{false}, since they are
+considered to be numerically equivalent. Likewise:
+\begin{verbatim}
+\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}
+\end{verbatim}
+produces:
+\DTLifnumeq{\pounds10.50}{\$10.50}{true}{false}.
+
+\pagebreak
+\begin{definition}[\DescribeMacro{\DTLifstringeq}]%
+\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifstringeq*}]%
+\cs{DTLifstringeq*}\marg{string1}\marg{string2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{string1} and \meta{string2} are the same, then do
+\meta{true part}, otherwise do \meta{false part}. The starred
+version ignores the case, the unstarred version is case
+sensitive. Both
+\meta{string1} and \meta{string2} are considered to be strings,
+so for example:
+\begin{verbatim}
+\DTLifstringeq{10.50}{10.5}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq{10.50}{10.5}{true}{false}.
+
+Note that
+\begin{verbatim}
+\DTLifstringeq{Text}{text}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq{Text}{text}{true}{false}, whereas
+\begin{verbatim}
+\DTLifstringeq*{Text}{text}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq*{Text}{text}{true}{false}, however it should also be
+noted that many commands will be ignored, so:
+\begin{verbatim}
+\DTLifstringeq{\uppercase{t}ext}{text}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq{\uppercase{t}ext}{text}{true}{false}.
+
+Spaces are considered to be equivalent to \cs{space} and "~". For
+example:
+\begin{verbatim}
+\DTLifstringeq{an apple}{an~apple}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq{an apple}{an~apple}{true}{false}. Consecutive spaces
+are treated as the same, for example:
+\begin{verbatim}
+\DTLifstringeq{an apple}{an apple}{true}{false}
+\end{verbatim}
+produces:
+\DTLifstringeq{an apple}{an apple}{true}{false}.
+
+\begin{definition}[\DescribeMacro{\DTLifeq}]%
+\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifeq*}]%
+\cs{DTLifeq*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+If both \meta{arg1} and \meta{arg2} are numerical, then this is
+equivalent to \cs{DTLifnumeq}, otherwise it is equivalent to
+\cs{DTLifstringeq} (when using \cs{DTLifeq}) or \cs{DTLifstringeq*}
+(when using \cs{DTLifeq*}).
+
+\begin{definition}[\DescribeMacro{\dtlifnumlt}]%
+\cs{dtlifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false
+paty}
+\end{definition}
+If \meta{num1} is less than \meta{num2}, then do \meta{true part},
+otherwise to \meta{false part} where \meta{num1} and \meta{num2}
+are plain numbers using a full stop as the decimal point and no
+number group separator. For currency or locale dependent numbers use
+\cs{DTLifnumlt}.
+
+\begin{definition}[\DescribeMacro{\DTLifnumlt}]%
+\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{num1} is less than \meta{num2}, then do \meta{true part},
+otherwise do \meta{false part}. Note that both \meta{num1} and
+\meta{num2} must be numerical (either integers, real numbers or
+currency).
+
+\begin{definition}[\DescribeMacro{\DTLifstringlt}]%
+\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true
+part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifstringlt*}]%
+\cs{DTLifstringlt*}\marg{string1}\marg{string2}\marg{true
+part}\marg{false part}
+\end{definition}
+If \meta{string1} is alphabetically less than \meta{string2}, then do
+\meta{true part}, otherwise do \meta{false part}. The starred
+version ignores the case, the unstarred version is case
+sensitive.
+For example:
+\begin{verbatim}
+\DTLifstringlt{aardvark}{zebra}{less}{not less}
+\end{verbatim}
+produces:
+\DTLifstringlt{aardvark}{zebra}{less}{not less}.
+
+Note that both \meta{string1} and \meta{string2} are considered to be
+strings, so for example:
+\begin{verbatim}
+\DTLifstringlt{2}{10}{less}{not less}
+\end{verbatim}
+produces:
+\DTLifstringlt{2}{10}{less}{not less}, since the string "2"
+comes after the string "10" when arranged alphabetically.
+
+The case sensitive (unstarred) version considers uppercase characters
+to be less than lowercase characters, so
+\begin{verbatim}
+\DTLifstringlt{B}{a}{less}{not less}
+\end{verbatim}
+produces:
+\DTLifstringlt{B}{a}{less}{not less}, whereas
+\begin{verbatim}
+\DTLifstringlt*{B}{a}{less}{not less}
+\end{verbatim}
+produces:
+\DTLifstringlt*{B}{a}{less}{not less}.
+
+\begin{definition}[\DescribeMacro{\DTLiflt}]%
+\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLiflt*}]%
+\cs{DTLiflt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{arg1} and \meta{arg2} are both numerical, then this
+is equivalent to \cs{DTLifnumlt}, otherwise it is equivalent
+to \cs{DTLstringlt} (when using \cs{DTLiflt}) or
+\cs{DTLstringlt*} (when using \cs{DTLiflt*}).
+
+\begin{definition}[\DescribeMacro{\DTLifnumgt}]%
+\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{num1} is greater than \meta{num2}, then do \meta{true part},
+otherwise do \meta{false part}. Note that both \meta{num1} and
+\meta{num2} must be numerical (either integers, real numbers or
+currency).
+
+\begin{definition}[\DescribeMacro{\DTLifstringgt}]%
+\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true
+part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifstringgt*}]%
+\cs{DTLifstringgt*}\marg{string1}\marg{string2}\marg{true
+part}\marg{false part}
+\end{definition}
+If \meta{string1} is alphabetically greater than \meta{string2}, then
+do \meta{true part}, otherwise do \meta{false part}. The
+starred version ignores the case, the unstarred version is
+case sensitive. For example:
+\begin{verbatim}
+\DTLifstringgt{aardvark}{zebra}{greater}{not greater}
+\end{verbatim}
+produces:
+\DTLifstringgt{aardvark}{zebra}{greater}{not greater}.
+
+Note that both \meta{string1} and \meta{string2} are considered to be
+strings, so for example:
+\begin{verbatim}
+\DTLifstringgt{2}{10}{greater}{not greater}
+\end{verbatim}
+produces:
+\DTLifstringgt{2}{10}{greater}{not greater}, since the string "2"
+comes after the string "10" when arranged alphabetically.
+
+As with \cs{DTLifstringlt}, uppercase characters are considered
+to be less than lower case characters when performing a
+case sensitive comparison so:
+\begin{verbatim}
+\DTLifstringgt{B}{a}{greater}{not greater}
+\end{verbatim}
+produces:
+\DTLifstringgt{B}{a}{greater}{not greater}, whereas
+\begin{verbatim}
+\DTLifstringgt*{B}{a}{greater}{not greater}
+\end{verbatim}
+produces:
+\DTLifstringgt*{B}{a}{greater}{not greater}.
+
+\begin{definition}[\DescribeMacro{\DTLifgt}]%
+\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifgt*}]%
+\cs{DTLifgt*}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{arg1} and \meta{arg2} are both numerical, then this
+is equivalent to \cs{DTLifnumgt}, otherwise it is equivalent
+to \cs{DTLstringgt} (when using \cs{DTLifgt}) or
+\cs{DTLstringgt*} (when using \cs{DTLifgt*}).
+
+\begin{definition}[\DescribeMacro{\DTLifnumclosedbetween}]%
+\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+\meta{max} must be numerical (either integers, real numbers or
+currency). The currency symbol is ignored when determining
+equality. For example:
+\begin{verbatim}
+\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}
+\end{verbatim}
+produces:
+\DTLifnumclosedbetween{5.4}{5}{7}{inside}{outside}.
+Note that the closed range includes end points:
+\begin{verbatim}
+\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}
+\end{verbatim}
+produces:
+\DTLifnumclosedbetween{5}{5}{7}{inside}{outside}.
+
+\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween}]%
+\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifstringclosedbetween*}]%
+\cs{DTLifstringclosedbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+This determines if \meta{string} is between \meta{min} and
+\meta{max} in the alphabetical sense, or is equal to either
+\meta{min} or \meta{max}. The starred version ignores the case,
+the unstarred version is case sensitive.
+
+\begin{definition}[\DescribeMacro{\DTLifclosedbetween}]%
+\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifclosedbetween*}]%
+\cs{DTLifclosedbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+equivalent to\newline
+\cs{DTLifnumclosedbetween}\newline
+otherwise it is equivalent to\newline
+\cs{DTLifstringclosedbetween}\newline
+(when using \cs{DTLifclosedbetween}) or\newline
+\cs{DTLifstringclosedbetween*}\newline
+(when using \cs{DTLifclosedbetween*}).
+
+\begin{definition}[\DescribeMacro{\DTLifnumopenbetween}]%
+\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+otherwise do \meta{false part}. Note that \meta{num}, \meta{min} and
+\meta{max} must be numerical (either integers, real numbers or
+currency). Again, the currency symbol is ignored when determining
+equality. For example:
+\begin{verbatim}
+\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}
+\end{verbatim}
+produces:
+\DTLifnumopenbetween{5.4}{5}{7}{inside}{outside}.
+Note that end points are not included. For example:
+\begin{verbatim}
+\DTLifnumopenbetween{5}{5}{7}{inside}{outside}
+\end{verbatim}
+produces:
+\DTLifnumopenbetween{5}{5}{7}{inside}{outside}.
+
+\begin{definition}[\DescribeMacro{\DTLifstringopenbetween}]%
+\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifstringopenbetween*}]%
+\cs{DTLifstringopenbetween*}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+This determines if \meta{string} is between \meta{min} and
+\meta{max} in the alphabetical sense.
+The starred version ignores the case,
+the unstarred version is case sensitive.
+
+\begin{definition}[\DescribeMacro{\DTLifopenbetween}]%
+\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLifopenbetween*}]%
+\cs{DTLifopenbetween*}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{arg}, \meta{min} and \meta{max} are numerical, then this is
+equivalent to
+\cs{DTLifnumopenbetween}
+otherwise it is equivalent to
+\cs{DTLifstringopenbetween}
+(when using \cs{DTLifopenbetween}) or
+\cs{DTLifstringopenbetween*}
+(when using \cs{DTLifopenbetween*}).
+
+\begin{definition}[\DescribeMacro{\DTLifFPclosedbetween}]%
+\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{min} $\leq$ \meta{num} $\leq$ \meta{max} then do \meta{true part},
+otherwise do \meta{false part} where \meta{num}, \meta{min}
+and \meta{max} are all in standard fixed point notation (i.e.\
+no number group separator, no currency symbols and a full stop as
+a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLifFPopenbetween}]%
+\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{min} $<$ \meta{num} $<$ \meta{max} then do \meta{true part},
+otherwise do \meta{false part} where \meta{num}, \meta{min}
+and \meta{max} are all in standard fixed point notation (i.e.\
+no number group separator, no currency symbols and a full stop as
+a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLifAllUpperCase}]%
+\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part}
+\end{definition}
+Tests if \meta{string} is all upper case. For example:
+\begin{verbatim}
+\DTLifAllUpperCase{WORD}{all upper}{not all upper}
+\end{verbatim}
+produces:
+\DTLifAllUpperCase{WORD}{all upper}{not all upper},
+whereas
+\begin{verbatim}
+\DTLifAllUpperCase{Word}{all upper}{not all upper}
+\end{verbatim}
+produces:
+\DTLifAllUpperCase{Word}{all upper}{not all upper}.
+Note also that:
+\begin{verbatim}
+\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}
+\end{verbatim}
+also produces:
+\DTLifAllUpperCase{\MakeUppercase{word}}{all upper}{not all upper}.
+\cs{MakeTextUppercase} (defined in David Carlisle's \sty{textcase}
+package) and \cs{uppercase} are also detected, otherwise, if
+a command is encountered, the case of the command is considered.
+For example:
+\begin{verbatim}
+\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}
+\end{verbatim}
+produces:
+\DTLifAllUpperCase{MAN{\OE}UVRE}{all upper}{not all upper}.
+
+\begin{definition}[\DescribeMacro{\DTLifAllLowerCase}]%
+\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part}
+\end{definition}
+Tests if \meta{string} is all lower case. For example:
+\begin{verbatim}
+\DTLifAllLowerCase{word}{all lower}{not all lower}
+\end{verbatim}
+produces:
+\DTLifAllLowerCase{word}{all lower}{not all lower},
+whereas
+\begin{verbatim}
+\DTLifAllLowerCase{Word}{all lower}{not all lower}
+\end{verbatim}
+produces:
+\DTLifAllLowerCase{Word}{all lower}{not all lower}.
+Note also that:
+\begin{verbatim}
+\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}
+\end{verbatim}
+also produces:
+\DTLifAllLowerCase{\MakeLowercase{WORD}}{all lower}{not all lower}.
+\cs{MakeTextLowercase} (defined in David Carlisle's \sty{textcase}
+package) and \cs{lowercase} are also detected, otherwise, if
+a command is encountered, the case of the command is considered.
+For example:
+\begin{verbatim}
+\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}
+\end{verbatim}
+produces:
+\DTLifAllLowerCase{man{\oe}uvre}{all lower}{not all lower}.
+
+\begin{definition}[\DescribeMacro{\DTLifSubString}]%
+\cs{DTLifSubString}\marg{string}\marg{substring}\marg{true
+part}\marg{false part}
+\end{definition}
+This tests if \meta{substring} is a sub-string of \meta{string}.
+This command performs a case sensitive match. For example:
+\begin{verbatim}
+\DTLifSubString{An apple}{app}{is substring}{isn't substring}
+\end{verbatim}
+produces:
+\DTLifSubString{An apple}{app}{is substring}{isn't substring}.
+Note that spaces are considered to be equivalent to \cs{space}
+or "~", so
+\begin{verbatim}
+\DTLifSubString{An apple}{n~a}{is substring}{isn't substring}
+\end{verbatim}
+produces:
+\DTLifSubString{An apple}{n~a}{is substring}{isn't substring},
+but other commands are skipped, so
+\begin{verbatim}
+\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't
+substring}
+\end{verbatim}
+produces:
+\DTLifSubString{An \uppercase{a}pple}{app}{is substring}{isn't
+substring}, since the \cs{uppercase} command is ignored. Note also
+that grouping is ignored, so:
+\begin{verbatim}
+\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring}
+\end{verbatim}
+produces:
+\DTLifSubString{An {ap}ple}{app}{is substring}{isn't substring}.
+
+\cs{DTLifSubString} is case sensitive, so:
+\begin{verbatim}
+\DTLifSubString{An Apple}{app}{is substring}{isn't substring}
+\end{verbatim}
+produces:
+\DTLifSubString{An Apple}{app}{is substring}{isn't substring}.
+
+\begin{definition}[\DescribeMacro{\DTLifStartsWith}]%
+\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true
+part}\marg{false part}
+\end{definition}
+This is like \cs{DTLifSubString}, except that \meta{substring} must
+occur at the start of \meta{string}. This command performs a case
+sensitive match. For example,
+\begin{verbatim}
+\DTLifStartsWith{An apple}{app}{prefix}{not a prefix}
+\end{verbatim}
+produces:
+\DTLifStartsWith{An apple}{app}{prefix}{not a prefix}. All the
+above remarks for \cs{DTLifSubString} also applies to
+\cs{DTLifStartsWith}. For example:
+\begin{verbatim}
+\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix}
+\end{verbatim}
+produces:
+\DTLifStartsWith{\uppercase{a}n apple}{an~}{prefix}{not a prefix},
+since \cs{uppercase} is ignored, and "~" is considered to be the
+same as a space, whereas
+\begin{verbatim}
+\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix}
+\end{verbatim}
+produces:
+\DTLifStartsWith{An apple}{an~}{prefix}{not a prefix}.
+
+\section{\texorpdfstring{\sty{ifthen}}{ifthen} conditionals}
+\label{sec:ifthen}
+
+The commands described in the previous section can not be
+used as the conditional part of the \cs{ifthenelse} or
+\cs{whiledo} commands provided by the \sty{ifthen} package.
+This section describes analogous commands which may only be
+used in the conditional argument of \cs{ifthenelse} and
+\cs{whiledo}. These may be used with the boolean operations
+\cs{not}, \cs{and} and \cs{or} provided by the \sty{ifthen} package.
+See the \sty{ifthen} documentation for further details.
+
+\begin{definition}[\DescribeMacro{\DTLisstring}]%
+\cs{DTLisstring}\marg{text}
+\end{definition}
+Tests if \meta{text} is a string. For example:
+\begin{verbatim}
+\ifthenelse{\DTLisstring{some text}}{string}{not a string}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisstring{some text}}{string}{not a string}.
+
+\begin{definition}[\DescribeMacro{\DTLisnumerical}]%
+\cs{DTLisnumerical}\marg{text}
+\end{definition}
+Tests if \meta{text} is numerical (i.e.\ not a string). For example:
+\begin{verbatim}
+\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisnumerical{\$10.95}}{numerical}{not numerical}.
+
+Note however that \cs{DTLisnumerical} requires more care than
+\cs{DTLifnumerical} when used with some of the other currency
+symbols. Consider:
+\begin{verbatim}
+\DTLifnumerical{\pounds10.95}{numerical}{not numerical}
+\end{verbatim}
+This produces:
+\DTLifnumerical{\pounds10.95}{numerical}{not numerical}.
+However
+\begin{verbatim}
+\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisnumerical{\pounds10.95}}{numerical}{not numerical}.
+This is due to the expansion that occurs within \cs{ifthenelse}.
+This can be prevented using \cs{noexpand}, for example:
+\begin{verbatim}
+\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisnumerical{\noexpand\pounds10.95}}{numerical}{not numerical}.
+
+Likewise:
+\begin{verbatim}
+\def\cost{\pounds10.95}%
+\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}
+\end{verbatim}
+produces:
+\def\cost{\pounds10.95}\relax
+\ifthenelse{\DTLisnumerical{\noexpand\cost}}{numerical}{not numerical}.
+
+\begin{definition}[\DescribeMacro{\DTLiscurrency}]%
+\cs{DTLiscurrency}\marg{text}
+\end{definition}
+Tests if \meta{text} is currency. For example:
+\begin{verbatim}
+\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLiscurrency{\$10.95}}{currency}{not currency}.
+
+The same warning given above for \cs{DTLisnumerical} also applies
+here.
+
+\begin{definition}[\DescribeMacro{\DTLiscurrencyunit}]%
+\cs{DTLiscurrencyunit}\marg{text}\marg{symbol}
+\end{definition}
+Tests if \meta{text} is currency and that currency uses \meta{symbol} as the unit
+of currency.
+For example:
+\begin{verbatim}
+\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLiscurrencyunit{\$6.99}{\$}}{dollars}{not dollars}.
+Another example:
+\begin{verbatim}
+\def\cost{\euro10.50}%
+\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+{euros}{not euros}
+\end{verbatim}
+produces:
+\def\cost{\euro10.50}\relax
+\ifthenelse{\DTLiscurrencyunit{\noexpand\cost}{\noexpand\euro}}%
+{euros}{not euros}. Again note the use of \cs{noexpand}.
+
+\begin{definition}[\DescribeMacro{\DTLisreal}]%
+\cs{DTLisreal}\marg{text}
+\end{definition}
+Tests if \meta{text} is a fixed point number (again, an integer is
+not considered to be a fixed point number). For example:
+\begin{verbatim}
+\ifthenelse{\DTLisreal{1.5}}{real}{not real}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisreal{1.5}}{real}{not real}.
+
+\begin{definition}[\DescribeMacro{\DTLisint}]%
+\cs{DTLisint}\marg{text}
+\end{definition}
+Tests if \meta{text} is an integer. For example:
+\begin{verbatim}
+\ifthenelse{\DTLisint{153}}{integer}{not an integer}
+\end{verbatim}
+produces:
+\ifthenelse{\DTLisint{153}}{integer}{not an integer}.
+
+\begin{definition}[\DescribeMacro{\DTLislt}]%
+\cs{DTLislt}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is less than \meta{arg2}. As with
+\cs{DTLiflt}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case sensitive
+alphabetical comparison is used. (Note that there is no starred
+version of this command, but you can instead use \cs{DTLisilt}
+to ignore the case.)
+
+\begin{definition}[\DescribeMacro{\DTLisilt}]%
+\cs{DTLisilt}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is less than \meta{arg2}. As with
+\cs{DTLiflt*}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case insensitive
+alphabetical comparison is used.
+
+\begin{definition}[\DescribeMacro{\DTLisgt}]%
+\cs{DTLisgt}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is greater than \meta{arg2}. As with
+\cs{DTLifgt}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case sensitive
+alphabetical comparison is used. (Note that there is no starred
+version of this command, instead use \cs{DTLisigt} to
+ignore the case.)
+
+\begin{definition}[\DescribeMacro{\DTLisigt}]%
+\cs{DTLisigt}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is greater than \meta{arg2}. As with
+\cs{DTLifgt*}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case insensitive
+alphabetical comparison is used.
+
+\begin{definition}[\DescribeMacro{\DTLiseq}]%
+\cs{DTLiseq}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is equal to \meta{arg2}. As with
+\cs{DTLifeq}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case sensitive
+alphabetical comparison is used. (Note that there is no starred
+version of this command, instead use \cs{DTLisieq}.)
+
+\begin{definition}[\DescribeMacro{\DTLisieq}]%
+\cs{DTLisieq}\marg{arg1}\marg{arg2}
+\end{definition}
+This checks if \meta{arg1} is equal to \meta{arg2}. As with
+\cs{DTLifeq*}, if \meta{arg1} and \meta{arg2} are numerical,
+a numerical comparison is used, otherwise a case insensitive
+alphabetical comparison is used.
+
+\begin{definition}[\DescribeMacro{\DTLisclosedbetween}]%
+\cs{DTLisclosedbetween}\marg{arg}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{arg} lies between \meta{min} and
+\meta{max} (end points included). As with
+\cs{DTLifclosedbetween}, if the arguments are numerical,
+a numerical comparison is used, otherwise a case sensitive
+alphabetical comparison is used. (Note that there is no starred
+version of this command, instead use \cs{DTLisiclosedbetween}.)
+
+\begin{definition}[\DescribeMacro{\DTLisiclosedbetween}]%
+\cs{DTLisiclosedbetween}\marg{arg}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{arg} lies between \meta{min} and
+\meta{max} (end points included). As with
+\cs{DTLifclosedbetween*}, if the arguments are numerical,
+a numerical comparison is used, otherwise a case insensitive
+alphabetical comparison is used.
+
+\begin{definition}[\DescribeMacro{\DTLisopenbetween}]%
+\cs{DTLisopenbetween}\marg{arg}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{arg} lies between \meta{min} and
+\meta{max} (end points excluded). As with
+\cs{DTLifopenbetween}, if the arguments are numerical,
+a numerical comparison is used, otherwise a case sensitive
+alphabetical comparison is used. (Note that there is no starred
+version of this command, instead use \cs{DTLisiopenbetween}.)
+
+\begin{definition}[\DescribeMacro{\DTLisiopenbetween}]%
+\cs{DTLisiopenbetween}\marg{arg}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{arg} lies between \meta{min} and
+\meta{max} (end points excluded). As with
+\cs{DTLifopenbetween*}, if the arguments are numerical,
+a numerical comparison is used, otherwise a case insensitive
+alphabetical comparison is used.
+
+\begin{definition}[\DescribeMacro{\DTLisFPlt}]%
+\cs{DTLisFPlt}\marg{num1}\marg{num2}
+\end{definition}
+This checks if \meta{num1} is less than \meta{num2}, where both
+numbers are in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPlteq}]%
+\cs{DTLisFPlteq}\marg{num1}\marg{num2}
+\end{definition}
+This checks if \meta{num1} is less than or equal to \meta{num2}, where both
+numbers are in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPgt}]%
+\cs{DTLisFPgt}\marg{num1}\marg{num2}
+\end{definition}
+This checks if \meta{num1} is greater than \meta{num2}, where both
+numbers are in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPgteq}]%
+\cs{DTLisFPgteq}\marg{num1}\marg{num2}
+\end{definition}
+This checks if \meta{num1} is greater than or equal to \meta{num2}, where both
+numbers are in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPeq}]%
+\cs{DTLisFPeq}\marg{num1}\marg{num2}
+\end{definition}
+This checks if \meta{num1} is equal to \meta{num2}, where both
+numbers are in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPclosedbetween}]%
+\cs{DTLisFPclosedbetween}\marg{num}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{num} lies between \meta{min} and
+\meta{max} (end points included). All arguments must be
+numbers in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisFPopenbetween}]%
+\cs{DTLisFPopenbetween}\marg{num}\marg{min}\marg{max}
+\end{definition}
+This checks if \meta{num} lies between \meta{min} and
+\meta{max} (end points excluded). All arguments must be
+numbers in standard fixed point format (i.e.\ no number group
+separators, no currency and a full stop as a decimal point).
+
+\begin{definition}[\DescribeMacro{\DTLisSubString}]%
+\cs{DTLisSubString}\marg{string}\marg{substring}
+\end{definition}
+This checks if \meta{substring} is contained in \meta{string}.
+The remarks about \cs{DTLifSubString} also apply to
+\cs{DTLisSubString}. This command performs a case sensitive
+match.
+
+\begin{definition}[\DescribeMacro{\DTLisPrefix}]%
+\cs{DTLisPrefix}\marg{string}\marg{prefix}
+\end{definition}
+This checks if \meta{string} starts with \meta{prefix}.
+The remarks about \cs{DTLifStartsWith} also apply to
+\cs{DTLisPrefix}. This command performs a case sensitive
+match.
+
+\begin{definition}[\DescribeMacro{\DTLisinlist}]%
+\cs{DTLisinlist}\marg{element}\marg{list}
+\end{definition}
+This checks if \meta{element} is in \meta{list}. (Internally uses
+\cs{DTLifinlist}.)
+
+\chapter{Fixed Point Arithmetic}
+\label{sec:fp}
+
+\begin{important}
+The \sty{datatool} bundle doesn't support scientific
+notation.
+\end{important}
+
+The \sty{datatool-base} package uses either the \sty{fp} or the \sty{pgfmath} package to perform
+fixed point arithmetic, however all numbers must be converted
+from the locale dependent format into the format required by the
+\sty{fp} or \sty{pgfmath} packages. A numerical value (i.e.\ an integer, a real
+or currency) can be converted into a plain decimal number using
+\begin{definition}[\DescribeMacro{\DTLconverttodecimal}]%
+\cs{DTLconverttodecimal}\marg{num}\marg{cmd}
+\end{definition}
+The decimal number will be stored in \meta{cmd} which must be
+a control sequence. For example:
+\begin{verbatim}
+\DTLconverttodecimal{1,563.54}{\mynum}
+\end{verbatim}
+\DTLconverttodecimal{1,563.54}{\mynum}\relax
+will define \cs{mynum} to be \texttt{\mynum}. The command \cs{mynum}
+can then be used in any of the arithmetic macros provided by the
+\sty{fp} or \sty{pgfmath} packages.
+
+\begin{important}
+The arguments to \cs{DTLconverttodecimal} don't get fully expanded
+so, for example,
+\begin{verbatim}
+\def\myval{1.23}
+\DTLconverttodecimal{\myval}{\mynum}
+\end{verbatim}
+will work, but the following \emph{\bfseries won't} work:
+\begin{verbatim}
+\def\myval{1.23}
+\def\myotherval{\myval}
+\DTLconverttodecimal{\myotherval}{\mynum}
+\end{verbatim}
+Nor will the following work:
+\begin{verbatim}
+\def\myval{9}
+\DTLconverttodecimal{\myval 9}{\mynum}
+\end{verbatim}
+\end{important}
+There are two commands provided to perform
+the reverse:
+\begin{definition}[\DescribeMacro{\DTLdecimaltolocale}]%
+\cs{DTLdecimaltolocale}\marg{number}\marg{cmd}
+\end{definition}
+This converts a plain decimal number \meta{number} (that uses a full
+stop as the decimal character and has no number group characters)
+into a locale dependent format. The resulting number is stored
+in \meta{cmd}, which must be a control sequence. For example:
+\begin{verbatim}
+\DTLdecimaltolocale{6795.3}{\mynum}
+\end{verbatim}
+\DTLdecimaltolocale{6795.3}{\mynum}
+will define \cs{mynum} to be \texttt{\mynum}.
+
+\begin{definition}[\DescribeMacro{\DTLdecimaltocurrency}]%
+\cs{DTLdecimaltocurrency}\marg{number}\marg{cmd}
+\end{definition}
+This will convert a plain decimal number \meta{number} into a
+locale dependent currency format. For example:
+\begin{verbatim}
+\DTLdecimaltocurrency{267.5}{\price}\price
+\end{verbatim}
+will produce:
+\DTLdecimaltocurrency{267.5}{\price}\price.
+
+The currency symbol used by \cs{DTLdecimaltocurrency} is
+initially "\$", but it will use the currency last encountered.
+So, for example
+\begin{verbatim}
+\DTLifcurrency{\texteuro45.00}{}{}%
+\DTLdecimaltocurrency{267.5}{\price}\price
+\end{verbatim}
+will produce:
+\DTLifcurrency{\texteuro45.00}{}{}\relax
+\DTLdecimaltocurrency{267.5}{\price}\price. This is because
+the last currency symbol to be encountered was \cs{texteuro}.
+You can reset the currency symbol using the command:
+\begin{definition}[\DescribeMacro{\DTLsetdefaultcurrency}]%
+\cs{DTLsetdefaultcurrency}\marg{symbol}
+\end{definition}
+For example:
+\begin{verbatim}
+\DTLsetdefaultcurrency{\textyen}%
+\DTLdecimaltocurrency{267.5}{\price}\price
+\end{verbatim}
+will produce:
+\DTLsetdefaultcurrency{\textyen}\relax
+\DTLdecimaltocurrency{267.5}{\price}\price
+
+The \sty{datatool-base} package provides convenience commands which
+use \cs{DTLconverttodecimal}, and then use the basic macros provided
+by the \sty{fp}\slash\sty{pgfmath} package. The resulting value is then converted
+back into the locale format using
+\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}.
+Note that since these commands use \cs{DTLconverttodecimal} the
+caveat above regarding expansion also applies to all the commands.
+
+\begin{important}
+If you don't require currency or locale conversion, you can reduce
+the package overheads by using the commands defined in the
+\sty{datatool-fp} or \sty{datatool-pgfmath} packages which provide
+interface commands to \sty{fp} or \sty{pgfmath}, respectively.
+(See sections~\ref*{sec:code:datatool-fp}
+and~\ref*{sec:code:datatool-pgfmath} of the documented code,
+\texttt{datatool-code.pdf}.)
+Alternatively, you can just use the \sty{fp} or \sty{pgfmath}
+commands explicitly. (See the \sty{fp} or \sty{pgf} manuals for
+further details.)
+\end{important}
+
+
+\begin{definition}[\DescribeMacro{\DTLadd}]%
+\cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgadd}]%
+\cs{DTLgadd}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to \meta{num1}+\meta{num2}.
+\cs{DLTadd} sets \meta{cmd} locally, while \cs{DTLgadd} sets
+\meta{cmd} globally.
+
+For example:
+\begin{verbatim}
+\DTLadd{\result}{3,562.65}{412.2}\result
+\end{verbatim}
+will produce:
+\DTLadd{\result}{3,562.65}{412.2}\result. Since
+\cs{DTLconverttodecimal} can convert currency to a real
+number, you can also add prices. For example:
+\begin{verbatim}
+\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result
+\end{verbatim}
+produces:
+\DTLadd{\result}{\pounds3,562.65}{\pounds452.2}\result.
+
+Note that \sty{datatool} isn't aware of exchange rates! If you
+use different currency symbols, the last symbol will be used.
+For example
+\begin{verbatim}
+\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result
+\end{verbatim}
+produces:
+\DTLadd{\result}{\pounds3,562.65}{\euro452.2}\result.
+
+Likewise, if one value is a number and the other is a currency,
+the type of the last value, \meta{num2}, will be used for the
+result. For example:
+\begin{verbatim}
+\DTLadd{\result}{3,562.65}{\$452.2}\result
+\end{verbatim}
+produces:
+\DTLadd{\result}{3,562.65}{\$452.2}\result.
+
+\begin{definition}[\DescribeMacro{\DTLaddall}]%
+\cs{DTLaddall}\marg{cmd}\marg{number list}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgaddall}]%
+\cs{DTLgaddall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the sum of all
+the numbers in \meta{number list}.
+\cs{DLTaddall} sets \meta{cmd} locally, while \cs{DTLgaddall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLaddall{\total}{25.1,45.2,35.6}\total
+\end{verbatim}
+produces:
+\DTLaddall{\total}{25.1,45.2,35.6}\total.
+Note that if any of the numbers in \meta{number list} contain
+a comma, you must group the number. Example:
+\begin{verbatim}
+\DTLaddall{\total}{{1,525},{2,340},500}\total
+\end{verbatim}
+produces:
+\DTLaddall{\total}{{1,525},{2,340},500}\total.
+
+\begin{definition}[\DescribeMacro{\DTLsub}]%
+\cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgsub}]%
+\cs{DTLgsub}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to
+\meta{num1}$-$\meta{num2}.
+\cs{DLTsub} sets \meta{cmd} locally, while \cs{DTLgsub} sets
+\meta{cmd} globally.
+
+For example:
+\begin{verbatim}
+\DTLsub{\result}{3,562.65}{412.2}\result
+\end{verbatim}
+will produce:
+\DTLsub{\result}{3,562.65}{412.2}\result. As with \cs{DTLadd},
+\meta{num1} and \meta{num2} may be currency.
+
+\begin{definition}[\DescribeMacro{\DTLmul}]%
+\cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgmul}]%
+\cs{DTLgmul}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to
+\meta{num1}$\times$\meta{num2}.
+\cs{DLTmul} sets \meta{cmd} locally, while \cs{DTLgmul} sets
+\meta{cmd} globally.
+
+For example:
+\begin{verbatim}
+\DTLmul{\result}{568.95}{2}\result
+\end{verbatim}
+will produce:
+\DTLmul{\result}{568.95}{2}\result. Again, \meta{num1} or
+\meta{num2} may be currency, but unlike \cs{DTLadd} and \cs{DTLsub},
+currency overrides integer/real. For example:
+\begin{verbatim}
+\DTLmul{\result}{\pounds568.95}{2}\result
+\end{verbatim}
+will produce:
+\DTLmul{\result}{\pounds568.95}{2}\result. Likewise,
+\begin{verbatim}
+\DTLmul{\result}{2}{\pounds568.95}\result
+\end{verbatim}
+will produce:
+\DTLmul{\result}{2}{\pounds568.95}\result. Although it doesn't make
+sense to multiply two currencies, \sty{datatool} will allow
+\begin{verbatim}
+\DTLmul{\result}{\$2}{\pounds568.95}\result
+\end{verbatim}
+which will produce:
+\DTLmul{\result}{\$2}{\pounds568.95}\result.
+
+\begin{definition}[\DescribeMacro{\DTLdiv}]%
+\cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgdiv}]%
+\cs{DTLgdiv}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to
+\meta{num1}$\div$\meta{num2}.
+\cs{DLTdiv} sets \meta{cmd} locally, while \cs{DTLgdiv} sets
+\meta{cmd} globally.
+
+For example:
+\begin{verbatim}
+\DTLdiv{\result}{501}{2}\result
+\end{verbatim}
+will produce:
+\DTLdiv{\result}{501}{2}\result. Again, \meta{num1} or \meta{num2}
+may be currency, but the resulting type will be not be a currency
+if both \meta{num1} and \meta{num2} use the same currency symbol.
+For example:
+\begin{verbatim}
+\DTLdiv{\result}{\$501}{\$2}\result
+\end{verbatim}
+will produce:
+\DTLdiv{\result}{\$501}{\$2}\result. Whereas
+\begin{verbatim}
+\DTLdiv{\result}{\$501}{2}\result
+\end{verbatim}
+will produce:
+\DTLdiv{\result}{\$501}{2}\result.
+
+\begin{definition}[\DescribeMacro{\DTLabs}]%
+\cs{DTLabs}\marg{cmd}\marg{num}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgabs}]%
+\cs{DTLgabs}\marg{cmd}\marg{num}
+\end{definition}
+This sets \meta{cmd} to the absolute value of \meta{num}.
+\cs{DLTabs} sets \meta{cmd} locally, while \cs{DTLgabs} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLabs{\result}{-\pounds2.50}\result
+\end{verbatim}
+produces:
+\DTLabs{\result}{-\pounds2.50}\result.
+
+\begin{definition}[\DescribeMacro{\DTLneg}]%
+\cs{DTLneg}\marg{cmd}\marg{num}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgneg}]%
+\cs{DTLgneg}\marg{cmd}\marg{num}
+\end{definition}
+This sets \meta{cmd} to the negative of \meta{num}.
+\cs{DLTneg} sets \meta{cmd} locally, while \cs{DTLgneg} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLneg{\result}{\pounds2.50}\result
+\end{verbatim}
+produces:
+\DTLneg{\result}{\pounds2.50}\result.
+
+\begin{definition}[\DescribeMacro{\DTLsqrt}]%
+\cs{DTLsqrt}\marg{cmd}\marg{num}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgsqrt}]%
+\cs{DTLgsqrt}\marg{cmd}\marg{num}
+\end{definition}
+This sets \meta{cmd} to the sqrt root of \meta{num}.
+\cs{DLTsqrt} sets \meta{cmd} locally, while \cs{DTLgsqrt} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLsqrt{\result}{2}\result
+\end{verbatim}
+produces:
+\DTLsqrt{\result}{2}\result.
+
+\begin{definition}[\DescribeMacro{\DTLmin}]%
+\cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgmin}]%
+\cs{DTLgmin}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to the minimum of
+\meta{num1} and \meta{num2}.
+\cs{DLTmin} sets \meta{cmd} locally, while \cs{DTLgmin} sets
+\meta{cmd} globally. For example:
+\begin{verbatim}
+\DTLmin{\result}{256}{32}\result
+\end{verbatim}
+produces:
+\DTLmin{\result}{256}{32}\result.
+Again, \meta{num1} and \meta{num2} may
+be currency. For example:
+\begin{verbatim}
+\DTLmin{\result}{256}{\pounds32}\result
+\end{verbatim}
+produces:
+\DTLmin{\result}{256}{\pounds32}\result, whereas
+\begin{verbatim}
+\DTLmin{\result}{\pounds256}{32}\result
+\end{verbatim}
+produces:
+\DTLmin{\result}{\pounds256}{32}\result. As mentioned above,
+\sty{datatool} doesn't know about exchange rates, so be careful
+about mixing currencies. For example:
+\begin{verbatim}
+\DTLmin{\result}{\pounds5}{\$6}\result
+\end{verbatim}
+produces:
+\DTLmin{\result}{\pounds5}{\$6}\result, which may not necessarily
+be true!
+
+\begin{definition}[\DescribeMacro{\DTLminall}]%
+\cs{DTLminall}\marg{cmd}\marg{number list}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgminall}]%
+\cs{DTLgminall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the minimum of all
+the numbers in \meta{number list}.
+\cs{DLTminall} sets \meta{cmd} locally, while \cs{DTLgminall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLminall{\theMin}{25.1,45.2,35.6}\theMin
+\end{verbatim}
+produces:
+\DTLminall{\theMin}{25.1,45.2,35.6}\theMin.
+Note that if any of the numbers in \meta{number list} contain
+a comma, you must group the number. Example:
+\begin{verbatim}
+\DTLminall{\theMin}{{1,525},{2,340},500}\theMin
+\end{verbatim}
+produces:
+\DTLminall{\theMin}{{1,525},{2,340},500}\theMin.
+
+\begin{definition}[\DescribeMacro{\DTLmax}]%
+\cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgmax}]%
+\cs{DTLgmax}\marg{cmd}\marg{num1}\marg{num2}
+\end{definition}
+This sets the control sequence \meta{cmd} to the maximum of
+\meta{num1} and \meta{num2}.
+\cs{DLTmax} sets \meta{cmd} locally, while \cs{DTLgmax} sets
+\meta{cmd} globally. For example:
+\begin{verbatim}
+\DTLmax{\result}{256}{32}\result
+\end{verbatim}
+produces:
+\DTLmax{\result}{256}{32}\result.
+Again, \meta{num1} and \meta{num2} may
+be currency, but the same warnings for \cs{DTLmin} apply.
+
+\begin{definition}[\DescribeMacro{\DTLmaxall}]%
+\cs{DTLmaxall}\marg{cmd}\marg{number list}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgmaxall}]%
+\cs{DTLgmaxall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the maximum of all
+the numbers in \meta{number list}.
+\cs{DLTmaxall} sets \meta{cmd} locally, while \cs{DTLgmaxall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax
+\end{verbatim}
+produces:
+\DTLmaxall{\theMax}{25.1,45.2,35.6}\theMax.
+Note that if any of the numbers in \meta{number list} contain
+a comma, you must group the number. Example:
+\begin{verbatim}
+\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax
+\end{verbatim}
+produces:
+\DTLmaxall{\theMax}{{1,525},{2,340},500}\theMax.
+
+\begin{definition}[\DescribeMacro{\DTLmeanforall}]%
+\cs{DTLmeanforall}\marg{cmd}\marg{number list}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgmeanall}]%
+\cs{DTLgmeanforall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the arithmetic mean of all
+the numbers in \meta{number list}.
+\cs{DLTmeanforall} sets \meta{cmd} locally, while \cs{DTLgmeanforall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean
+\end{verbatim}
+produces:
+\DTLmeanforall{\theMean}{25.1,45.2,35.6}\theMean.
+Note that if any of the numbers in \meta{number list} contain
+a comma, you must group the number. Example:
+\begin{verbatim}
+\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean
+\end{verbatim}
+produces:
+\DTLmeanforall{\theMean}{{1,525},{2,340},500}\theMean.
+
+\begin{definition}[\DescribeMacro{\DTLvarianceforall}]%
+\cs{DTLvarianceforall}\marg{cmd}\marg{number list}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgvarianceforall}]%
+\cs{DTLgvarianceforall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the variance of all
+the numbers in \meta{number list}.
+\cs{DLTvarianceforall} sets \meta{cmd} locally, while \cs{DTLgvarianceforall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar
+\end{verbatim}
+produces:
+\DTLvarianceforall{\theVar}{25.1,45.2,35.6}\theVar.
+Again note that if any of the numbers in \meta{number list}
+contain a comma, you must group the number.
+
+\begin{definition}[\DescribeMacro{\DTLsdforall}]%
+\cs{DTLsdforall}\marg{cmd}\marg{number list}
+\end{definition}
+\pagebreak
+\begin{definition}[\DescribeMacro{\DTLgsdforall}]%
+\cs{DTLgsdforall}\marg{cmd}\marg{number list}
+\end{definition}
+This sets the control sequence \meta{cmd} to the standard deviation of all
+the numbers in \meta{number list}.
+\cs{DLTsdforall} sets \meta{cmd} locally, while \cs{DTLgsdforall} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD
+\end{verbatim}
+produces:
+\DTLsdforall{\theSD}{25.1,45.2,35.6}\theSD.
+Note that if any of the numbers in \meta{number list} contain
+a comma, you must group the number. Example:
+\begin{verbatim}
+\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD
+\end{verbatim}
+produces:
+\DTLsdforall{\theSD}{{1,525},{2,340},500}\theSD.
+
+\begin{definition}[\DescribeMacro{\DTLround}]%
+\cs{DTLround}\marg{cmd}\marg{num}\marg{num digits}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLground}]%
+\cs{DTLground}\marg{cmd}\marg{num}\marg{num digits}
+\end{definition}
+This sets \meta{cmd} to \meta{num} rounded to \meta{num digits}
+after the decimal character.
+\cs{DLTround} sets \meta{cmd} locally, while \cs{DTLground} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLround{\result}{3.135276}{2}\result
+\end{verbatim}
+produces: \DTLround{\result}{3.135276}{2}\result.
+
+\begin{definition}[\DescribeMacro{\DTLtrunc}]%
+\cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgtrunc}]%
+\cs{DTLgtrunc}\marg{cmd}\marg{num}\marg{num digits}
+\end{definition}
+This sets \meta{cmd} to \meta{num} truncated to \meta{num digits}
+after the decimal character.
+\cs{DLTtrunc} sets \meta{cmd} locally, while \cs{DTLgtrunc} sets
+\meta{cmd} globally. Example:
+\begin{verbatim}
+\DTLtrunc{\result}{3.135276}{2}\result
+\end{verbatim}
+produces: \DTLtrunc{\result}{3.135276}{2}\result.
+
+\pagebreak
+\begin{definition}[\DescribeMacro{\DTLclip}]%
+\cs{DTLclip}\marg{cmd}\marg{num}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgclip}]%
+\cs{DTLgclip}\marg{cmd}\marg{num}
+\end{definition}
+This sets \meta{cmd} to \meta{num} with all unnecessary 0's
+removed.
+\cs{DLTclip} sets \meta{cmd} locally, while \cs{DTLgclip} sets
+\meta{cmd} globally.
+
+\chapter{Strings}
+\label{sec:strings}
+
+Strings are considered to be anything non-numerical. The
+\sty{datatool} package loads the \sty{substr} package, so
+you can use the commands defined in that package to determine
+if one string is contained in another string. In addition,
+the \sty{datatool} provides the following macros:
+
+\begin{definition}[\DescribeMacro{\DTLsubstitute}]%
+\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement}
+\end{definition}
+This replaces the first occurrence of \meta{original} in
+\meta{cmd} with \meta{replacement}. Note that \meta{cmd} must
+be the name of a command. For example:
+\begin{verbatim}
+\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr
+\end{verbatim}
+produces:
+\def\mystr{abcdce}\DTLsubstitute{\mystr}{c}{z}\mystr.
+
+\begin{definition}[\DescribeMacro{\DTLsubstituteall}]%
+\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement}
+\end{definition}
+This replaces all occurrences of \meta{original} in
+\meta{cmd} with \meta{replacement}, where again, \meta{cmd} must
+be the name of a command. For example:
+\begin{verbatim}
+\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr
+\end{verbatim}
+produces:
+\def\mystr{abcdce}\DTLsubstituteall{\mystr}{c}{z}\mystr.
+
+\begin{definition}[\DescribeMacro{\DTLsplitstring}]%
+\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before
+cmd}\marg{after cmd}
+\end{definition}
+This splits \meta{string} at the first occurrence of \meta{split text}
+and stores the before part in the command \meta{before cmd} and
+the after part in the command \meta{after cmd}. For example:
+\begin{verbatim}
+\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}%
+Before part: ``\beforepart''. After part: ``\afterpart''
+\end{verbatim}
+produces:
+\DTLsplitstring{abcdce}{c}{\beforepart}{\afterpart}\relax
+Before part: ``\beforepart''. After part: ``\afterpart''.
+Note that for \cs{DTLsplitstring}, \meta{string} is not
+expanded, so
+\begin{verbatim}
+\def\mystr{abcdce}%
+\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}%
+Before part: ``\beforepart''. After part: ``\afterpart''
+\end{verbatim}
+produces:
+\def\mystr{abcdce}\relax
+\DTLsplitstring{\mystr}{c}{\beforepart}{\afterpart}%
+Before part: ``\beforepart''. After part: ``\afterpart''. If you
+want the string expanded, you will need to use \cs{expandafter}:
+\begin{verbatim}
+\def\mystr{abcdce}%
+\expandafter\DTLsplitstring\expandafter
+{\mystr}{c}{\beforepart}{\afterpart}%
+Before part: ``\beforepart''. After part: ``\afterpart''
+\end{verbatim}
+which produces:
+\def\mystr{abcdce}\relax
+\expandafter\DTLsplitstring\expandafter
+{\mystr}{c}{\beforepart}{\afterpart}\relax
+Before part: ``\beforepart''. After part: ``\afterpart''.
+
+\begin{definition}[\DescribeMacro{\DTLinitials}]%
+\cs{DTLinitials}\marg{string}
+\end{definition}
+This converts \meta{string} (typically a name) into initials.
+For example:
+\begin{verbatim}
+\DTLinitials{Mary Ann}
+\end{verbatim}
+produces:
+\DTLinitials{Mary Ann} (including the final full stop). Note that
+\begin{verbatim}
+\DTLinitials{Mary-Ann}
+\end{verbatim}
+produces:
+\DTLinitials{Mary-Ann} (including the final full stop).
+Be careful if the initial letter has an
+accent. The accented letter needs to be placed in a group, if
+you want the initial to also have an accent, otherwise the
+accent command will be ignored. For example:
+\begin{verbatim}
+\DTLinitials{{\'E}lise Adams}
+\end{verbatim}
+produces:
+\DTLinitials{{\'E}lise Adams}, whereas
+\begin{verbatim}
+\DTLinitials{\'Elise Adams}
+\end{verbatim}
+produces:
+\DTLinitials{\'Elise Adams} In fact, any command which appears
+at the start of the name that is not enclosed in a group will
+be ignored. For example:
+\begin{verbatim}
+\DTLinitials{\MakeUppercase{m}ary ann}
+\end{verbatim}
+produces:
+\DTLinitials{\MakeUppercase{m}ary ann}, whereas
+\begin{verbatim}
+\DTLinitials{{\MakeUppercase{m}}ary ann}
+\end{verbatim}
+produces:
+\DTLinitials{{\MakeUppercase{m}}ary ann}, but note that
+\begin{verbatim}
+\DTLinitials{\MakeUppercase{mary ann}}
+\end{verbatim}
+produces:
+\DTLinitials{\MakeUppercase{mary ann}}
+
+\begin{definition}[\DescribeMacro{\DTLstoreinitials}]%
+\cs{DTLstoreinitials}\marg{string}\marg{cmd}
+\end{definition}
+This converts \meta{string} into initials and stores the
+result in \meta{cmd} which must be a command name. The remarks
+about \cs{DTLinitials} also relate to \cs{DTLstoreinitials}.
+For example
+\begin{verbatim}
+\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials
+\end{verbatim}
+produces:
+\DTLstoreinitials{Marie-{\'E}lise del~Rosario}{\theInitials}\theInitials
+
+Both the above commands rely on the following to format the
+initials:
+\begin{definition}[\DescribeMacro{\DTLafterinitials}]%
+\cs{DTLafterinitials}
+\end{definition}
+This indicates what to do at the end of the initials. This
+simply does a full stop by default.
+
+\begin{definition}[\DescribeMacro{\DTLbetweeninitials}]%
+\cs{DTLbetweeninitials}
+\end{definition}
+This indicates what to do between initials. This does a
+full stop by default.
+
+\begin{definition}[\DescribeMacro{\DTLinitialhyphen}]%
+\cs{DTLinitialhyphen}
+\end{definition}
+This indicates what to do at a hyphen. This simply does a hyphen
+by default, but can be redefined to do nothing to prevent the
+hyphen appearing in the initials.
+
+\begin{definition}[\DescribeMacro{\DTLafterinitialbeforehyphen}]%
+\cs{DTLafterinitialbeforehyphen}
+\end{definition}
+This indicates what to do between an initial and a hyphen.
+This simply does a full stop by default.
+
+For example
+\begin{verbatim}
+\renewcommand*{\DTLafterinitialbeforehyphen}{}%
+\DTLinitials{Marie-{\'E}lise del~Rosario}
+\end{verbatim}
+produces:
+{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax
+\DTLinitials{Marie-{\'E}lise del~Rosario}}
+whereas
+\begin{verbatim}
+\renewcommand*{\DTLafterinitialbeforehyphen}{}%
+\renewcommand*{\DTLafterinitials}{}%
+\renewcommand*{\DTLbetweeninitials}{}%
+\renewcommand*{\DTLinitialhyphen}{}%
+\DTLinitials{Marie-{\'E}lise del~Rosario}
+\end{verbatim}
+produces:
+{\renewcommand*{\DTLafterinitialbeforehyphen}{}\relax
+\renewcommand*{\DTLafterinitials}{}\relax
+\renewcommand*{\DTLbetweeninitials}{}\relax
+\renewcommand*{\DTLinitialhyphen}{}\relax
+\DTLinitials{Marie-{\'E}lise del~Rosario}}
+
+\chapter{Comma-Separated Lists}
+\label{sec:csvlists}
+
+The \styfmt{datatool-base} package automatically loads the
+\sty{etoolbox} package, so you can use any of the list
+commands provided by that package, or you can use
+the internal command \cs{@for} provided by the \LaTeX\ kernel
+(and modified by the \sty{xfor} package, which is also loaded
+by \styfmt{datatool-base}).
+
+In addition to those commands, \styfmt{datatool-base}
+provides some commands that deal with comma-separated lists.
+Note that this just refers to a control sequence that stores
+a list of elements separated by commas, for example:
+\begin{verbatim}
+\newcommand{\mylist}{elephant,ant,zebra,duck}
+\end{verbatim}
+This isn't the same as comma-separated files, which is dealt
+with in \sectionref{sec:databases}.
+
+\begin{definition}[\DescribeMacro{\DTLformatlist}]
+\cs{DTLformatlist}\marg{list}
+\end{definition}
+Formats the comma-separated list. The unstarred version scopes
+the internal operation. The starred form doesn't.
+The \meta{list} may either be an explicit comma-separated list or
+a control sequence whose replacement
+text is a comma-separated list. If the list contains empty
+elements then \cs{DTLformatlist} will either include or
+skip the empty element according to the conditional:
+\begin{definition}[\DescribeMacro{\ifDTLlistskipempty}]
+\cs{ifDTLlistskipempty}
+\end{definition}
+For example:
+\begin{verbatim}
+\newcommand{\mylist}{elephant,,ant,zebra,duck}%
+\DTLlistskipemptytrue
+\DTLformatlist{\mylist}\par
+\DTLlistskipemptyfalse
+\DTLformatlist{\mylist}
+\end{verbatim}
+which produces:
+\begin{display}
+\newcommand{\mylist}{elephant,,ant,zebra,duck}%
+\DTLlistskipemptytrue
+\DTLformatlist{\mylist}\par
+\DTLlistskipemptyfalse
+\DTLformatlist{\mylist}
+\end{display}
+The default setting is
+\begin{verbatim}
+\DTLlistskipemptytrue
+\end{verbatim}
+Note that this may cause a difference when upgrading to v2.31
+as in previous versions \cs{DTLformatlist} didn't skip empty
+elements. To restore the original behaviour use:
+\begin{verbatim}
+\DTLlistskipemptyfalse
+\end{verbatim}
+before \cs{DTLformatlist}.
+
+The list formatting command inserts
+\begin{definition}[\DescribeMacro\DTLlistformatsep]
+\cs{DTLlistformatsep}
+\end{definition}
+between each item, except for the last pair which uses:
+\begin{definition}[\DescribeMacro\DTLlistformatlastsep]
+\cs{DTLlistformatlastsep}
+\end{definition}
+if there are only two items in the list or
+\begin{definition}[\DescribeMacro\DTLlistformatoxford]
+\cs{DTLlistformatoxford}\cs{DTLlistformatlastsep}
+\end{definition}
+if there are three or more items in the list.
+\cs{DTLlistformatlastsep} uses
+\begin{definition}[\DescribeMacro\DTLandname]
+\cs{DTLandname}
+\end{definition}
+Each item in the list is formatted according to
+\begin{definition}[\DescribeMacro\DTLlistformatitem]
+\cs{DTLlistformatitem}\marg{item}
+\end{definition}
+
+The default definitions are:
+\begin{itemize}
+\item \cs{DTLlistformatitem}\marg{item}: just does \meta{item};
+\item \cs{DTLlistformatsep}: \verb*|, | (comma followed by a space);
+\item \cs{DTLandname}: if \ics{andname} is
+defined this is defined as \cs{andname}
+otherwise it's defined as \verb|\&|;
+\item \cs{DTLlistformatlastsep}: does \verb*| \DTLandname\space|;
+\item \cs{DTLlistformatoxford}: does nothing (so if you want an
+Oxford comma you need to redefine this).
+\end{itemize}
+For example
+\begin{verbatim}
+\renewcommand{\DTLlistformatitem}[1]{\emph{#1}}%
+\renewcommand{\DTLlistformatoxford}{,}%
+\renewcommand{\DTLandname}{and}%
+One: \DTLformatlist{elephant}.
+
+Two: \DTLformatlist{elephant,ant}.
+
+Three: \DTLformatlist{elephant,ant,zebra}.
+
+Four: \DTLformatlist{elephant,ant,zebra,duck}.
+\end{verbatim}
+produces:
+\begin{display}
+\renewcommand{\DTLlistformatitem}[1]{\emph{#1}}%
+\renewcommand{\DTLlistformatoxford}{,}%
+\renewcommand{\DTLandname}{and}%
+One: \DTLformatlist{elephant}.
+
+Two: \DTLformatlist{elephant,ant}.
+
+Three: \DTLformatlist{elephant,ant,zebra}.
+
+Four: \DTLformatlist{elephant,ant,zebra,duck}.
+\end{display}
+
+You can test if an element is contained in a comma-separated list
+using:
+\begin{definition}[\DescribeMacro{\DTLifinlist}]
+\cs{DTLifinlist}\marg{element}\marg{list}\marg{true part}\marg{false part}
+\end{definition}
+If \meta{element} is contained in the comma-separated list given
+by \meta{list}, then this does \meta{true part} otherwise it does false
+part. (Does a one level expansion on \meta{list}, but no
+expansion on \meta{element}.)
+
+\begin{definition}[\DescribeMacro{\DTLnumitemsinlist}]
+\cs{DTLnumitemsinlist}\marg{list}\marg{cmd}
+\end{definition}
+Counts the number of elements in \meta{list} and stores the
+result in \meta{cmd}, which must be a control sequence.
+As from v2.31, this obeys the conditional \cs{ifDTLlistskipempty}
+to determine if empty elements should be skipped. For example:
+\begin{verbatim}
+\newcommand{\mylist}{foo,,bar,baz,wibble}
+Number of non-empty elements:
+\DTLnumitemsinlist{\mylist}{\listnum}\listnum.\par
+\DTLlistskipemptyfalse
+Number of elements (including empty):
+\DTLnumitemsinlist{\mylist}{\listnum}\listnum.
+\end{verbatim}
+This produces:
+\begin{display}
+\newcommand{\mylist}{foo,,bar,baz,wibble}
+Number of non-empty elements: \DTLnumitemsinlist{\mylist}{\listnum}\listnum.\par
+\DTLlistskipemptyfalse
+Number of elements (including empty): \DTLnumitemsinlist{\mylist}{\listnum}\listnum.
+\end{display}
+
+\begin{definition}[\DescribeMacro{\DTLlistelement}]
+\cs{DTLlistelement}\marg{list}\marg{index}
+\end{definition}
+Does the \meta{index}th element of the list (starting at 1 for
+the first element) or generates a warning if the index is out
+of range. This obeys the conditional \cs{ifDTLlistskipempty}
+to determine if empty elements should be skipped.
+For example:
+\begin{verbatim}
+\newcommand{\mylist}{foo,,bar,baz,wibble}
+3rd item in list (skip empty): \DTLlistelement{\mylist}{3}.\par
+\ifDTLlistskipempty
+3rd item in list (include empty): \DTLlistelement{\mylist}{3}.
+\end{verbatim}
+This produces:
+\begin{display}
+\newcommand{\mylist}{foo,,bar,baz,wibble}
+3rd item in list (skip empty): \DTLlistelement{\mylist}{3}.\par
+\ifDTLlistskipempty
+3rd item in list (include empty): \DTLlistelement{\mylist}{3}.
+\end{display}
+
+\begin{definition}[\DescribeMacro{\DTLfetchlistelement}]
+\cs{DTLfetchlistelement}\marg{list}\marg{index}\marg{cs}
+\end{definition}
+Like \cs{DTLlistelement} but it stores the \meta{index}th
+element in the command given by \meta{cs}.
+
+\begin{definition}[\DescribeMacro\dtlsortlist]
+\cs{dtlsortlist}\marg{list cs}\marg{criteria cs}
+\end{definition}
+This sorts the comma-separated list stored in the command
+\meta{list cs} according to the criteria command
+\meta{criteria cs}. The criteria command must take three arguments:
+a count register in which to store the result, element \meta{A} and
+element \meta{B}. If \meta{A} is considered less that \meta{B}, the
+count register should be set to $-1$, if \meta{A} and \meta{B} are
+considered the same then the count register should be set to 0,
+and if \meta{A} is considered greater than \meta{B}, then the count
+register should be set to 1.
+\begin{important}
+It's inefficient to use \TeX\ to sort and comparisons are only
+made according to the character codes and so are inappropriate
+for extended Latin or non-Latin alphabets. It's better to use
+an external tool where possible.
+\end{important}
+
+The \styfmt{datatool-base} package provides some predefined
+criteria commands:
+\begin{definition}[\DescribeMacro\dtlcompare]
+\cs{dtlcompare}\marg{register}\marg{A}\marg{B}
+\end{definition}
+A case-sensitive comparison.
+\begin{definition}[\DescribeMacro\dtlicompare]
+\cs{dtlicompare}\marg{register}\marg{A}\marg{B}
+\end{definition}
+A case-insensitive comparison.
+\begin{definition}[\DescribeMacro\dtlwordindexcompare]
+\cs{dtlwordindexcompare}\marg{register}\marg{A}\marg{B}
+\end{definition}
+English word-ordering comparison for indexes, as described by
+the Oxford Style Manual.
+\begin{definition}[\DescribeMacro\dtlletterindexcompare]
+\cs{dtlletterindexcompare}\marg{register}\marg{A}\marg{B}
+\end{definition}
+English letter-ordering comparison for indexes.
+Those last two commands are described in more detail in
+\sectionref{sec:sort}.
+
+For example:
+\begin{verbatim}
+\newcommand{\mylist}{elephant,ant,zebra,duck}
+\dtlsortlist{\mylist}{\dtlcompare}
+
+\mylist.
+\end{verbatim}
+produces:
+\begin{display}
+\newcommand{\mylist}{elephant,ant,zebra,duck}
+\dtlsortlist{\mylist}{\dtlcompare}
+
+\mylist.
+\end{display}
+
+If you are building up a list, you may prefer to use:
+\begin{definition}[\DescribeMacro\dtlinsertinto]
+\cs{dtlinsertinto}\marg{element}\marg{list cs}\marg{criteria cs}
+\end{definition}
+which inserts \meta{element} into the list stored in the
+command \meta{list cs} according to the criteria command
+\meta{criteria cs}. This is more efficient than first building the
+list and then sorting it.
+
+For example:
+\begin{verbatim}
+\newcommand{\mylist}{}
+\dtlinsertinto{elephant}{\mylist}{\dtlcompare}
+\dtlinsertinto{ant}{\mylist}{\dtlcompare}
+\dtlinsertinto{zebra}{\mylist}{\dtlcompare}
+\dtlinsertinto{duck}{\mylist}{\dtlcompare}
+
+\mylist.
+\end{verbatim}
+produces:
+\begin{display}
+\newcommand{\mylist}{}
+\dtlinsertinto{elephant}{\mylist}{\dtlcompare}
+\dtlinsertinto{ant}{\mylist}{\dtlcompare}
+\dtlinsertinto{zebra}{\mylist}{\dtlcompare}
+\dtlinsertinto{duck}{\mylist}{\dtlcompare}
+
+\mylist.
+\end{display}
+
+Note that \cs{dtlinsertinto} doesn't expand \meta{element}.
+If the element is stored in a command, you need to
+expand it first. For example:
+\begin{verbatim}
+\newcommand*{\element}{ant}
+\expandafter\dtlinsertinto\expandafter{\element}{\mylist}{\dtlcompare}
+\end{verbatim}
+
+To ensure that the element is first fully expanded, you can
+use:
+\begin{definition}[\DescribeMacro\edtlinsertinto]
+\cs{edtlinsertinto}\marg{element}\marg{list cs}\marg{criteria cs}
+\end{definition}
+This will fully expand \meta{element} using \cs{protected@edef}
+and then use \cs{dtlinsertinto}.
+
+\chapter{Databases}
+\label{sec:databases}
+
+The \sty{datatool} package provides a means of creating and
+loading databases. Once a database has been created (or loaded),
+it is possible to iterate through each row of data, to make it
+easier to perform repetitive actions, such as mail merging.
+
+\begin{important}
+Whilst \TeX\ is an excellent typesetting language,
+it is not designed as a database management system, and
+attempting to use it as such is like trying to fasten a screw
+with a knife instead of a screwdriver: it can be done, but requires
+great care and is more time consuming. Version 2.0 of the
+\sty{datatool} package uses a completely different method of storing
+the data to previous versions.\footnote{Many thanks to Morten H\o gholm
+for providing the new code.} As a result, the code is much more efficient,
+however, large databases and complex operations will still slow the
+time taken to process your document. Therefore, if you can, it is
+better to do the complex operations using whatever system created
+the data in the first place.
+\end{important}
+
+Some advanced commands for accessing database information are
+described in \autoref{sec:advanced}, but using \TeX\ is nowhere near
+as efficient as, say, using a SQL database, so don't expect too much
+from this package.
+
+\label{datatooltk}%
+I've written a Java helper application to accompany \sty{datatool}
+called \app{datatooltk}. The installer is available
+on CTAN at
+\url{http://mirrors.ctan.org/support/datatooltk/datatooltk-installer.jar}. The application will allow you to edit
+files saved using \ics{DTLsaverawdb} or \ics{DTLprotectedsaverawdb} in a~graphical interface or
+import data from a~SQL database, a~CSV file or a~\sty{probsoln}
+dataset.
+
+Each database has the data stored internally in a token register and
+the header information is stored in an internal control sequence.
+In general you don't need to worry about the way it's stored, except
+that row indexes start from 1 (the first row of data) and column
+indexes also start from 1. Columns may be referenced by a label
+but rows can only be referenced by the row index. Once the internal
+commands and registers have been set, \styfmt{datatool} doesn't keep
+a record of how or where the information came from (such as a CSV
+file or through a file created by \app{datatooltk}). Changes to the
+data only modify the internal commands and are lost at the end of
+the \LaTeX\ run unless you save the data.
+
+\section{Creating a New Database}
+\label{sec:newdb}
+
+\begin{definition}[\DescribeMacro{\DTLnewdb}]%
+\cs{DTLnewdb}\marg{db name}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgnewdb}]%
+\cs{DTLgnewdb}\marg{db name}
+\end{definition}
+This command creates a new empty database called \meta{db name}. The
+second form is for global definitions. You
+can test if a database is empty using:
+\begin{definition}[\DescribeMacro{\DTLifdbempty}]%
+\cs{DTLifdbempty}\marg{db name}\marg{true part}\marg{false part}
+\end{definition}
+If the database called \meta{db name} is empty, do \meta{true part},
+otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLrowcount}]%
+\cs{DTLrowcount}\marg{db name}
+\end{definition}
+This command displays the number of rows in the database called
+\meta{db name}.
+
+\begin{definition}[\DescribeMacro{\DTLcolumncount}]%
+\cs{DTLcolumncount}\marg{db name}
+\end{definition}
+This command displays the number of columns (or keys) in the
+database called \meta{db name}.
+
+\begin{definition}[\DescribeMacro{\DTLnewrow}]%
+\cs{DTLnewrow}\marg{db name}
+\end{definition}
+This command starts a new row in the database called \meta{db name}.
+This new row becomes the current row when adding new entries.
+
+For example, the following creates an empty database called
+\texttt{mydata}:
+\begin{verbatim}
+\DTLnewdb{mydata}
+\end{verbatim}
+\DTLnewdb{mydata}\relax
+The following tests if the database is empty:
+\begin{verbatim}
+\DTLifdbempty{mydata}{empty}{not empty}!
+\end{verbatim}
+This produces:
+\DTLifdbempty{mydata}{empty}{not empty}!
+
+The following adds an empty row to the database, this is the
+first row of the database:
+\begin{verbatim}
+\DTLnewrow{mydata}
+\end{verbatim}
+\DTLnewrow{mydata}\relax
+Note that even though the only row in the database is currently
+empty, the database is no longer considered to be empty:
+\begin{verbatim}
+\DTLifdbempty{mydata}{empty}{not empty}!
+\end{verbatim}
+This now produces:
+\DTLifdbempty{mydata}{empty}{not empty}! The row count is
+given by
+\begin{verbatim}
+\DTLrowcount{mydata}
+\end{verbatim}
+which produces:
+\DTLrowcount{mydata}. The column count is given by
+\begin{verbatim}
+\DTLcolumncount{mydata}
+\end{verbatim}
+which produces: \DTLcolumncount{mydata}.
+
+\begin{definition}[\DescribeMacro{\DTLnewdbentry}]%
+\cs{DTLnewdbentry}\marg{db name}\marg{key}\marg{value}
+\end{definition}
+This creates a new entry with the identifier \meta{key} whose value
+is \meta{value} and adds it to the last row of the database
+called \meta{db name}. For example:
+\begin{verbatim}
+\DTLnewdbentry{mydata}{Surname}{Smith}
+\DTLnewdbentry{mydata}{FirstName}{John}
+\end{verbatim}
+Adds an entry with identifier \texttt{Surname} and value
+\texttt{Smith} to the last row of the database named
+\texttt{mydata}, and then adds an entry with identifier
+\texttt{FirstName} and value \texttt{John}. Note that the
+key should not contain any fragile commands. It is generally
+best to only use non-active characters in the key.
+
+The value isn't expanded by default, but you can change this
+using the declaration:
+\begin{definition}[\DescribeMacro{\dtlexpandnewvalue}]
+\cs{dtlexpandnewvalue}
+\end{definition}
+This can be localised by placing it in a group, or you can
+switch back using:
+\begin{definition}[\DescribeMacro{\dtlnoexpandnewvalue}]
+\cs{dtlnoexpandnewvalue}
+\end{definition}
+
+\importantpar
+Note that database entries can't contain paragraph
+breaks as many of the macros used by \sty{datatool} are short
+commands. If you do need a paragraph break in an entry, you can
+instead use the command:
+\begin{definition}[\DescribeMacro{\DTLpar}]%
+\cs{DTLpar}
+\end{definition}
+For example:
+\begin{verbatim}
+\DTLnewdbentry{mydata}{Description}{First paragraph.\DTLpar
+Second paragraph.}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLaddentryforrow}]%
+\cs{DTLaddentryforrow}\marg{db}\marg{assign list}%
+\marg{condition}\marg{key}\allowbreak\marg{value}
+\end{definition}
+This adds the entry with the key given by \meta{key} and value
+given by \meta{value} to the first row in the database
+\meta{db} which satisfies the condition given by
+\meta{condition}. The \meta{assign list} argument is the same
+as for \cs{DTLforeach} (described in \autoref{sec:dbforeach})
+and may be used to set the values which are to be tested in
+\meta{condition} (where, again, \meta{condition} is the same
+as for \cs{DTLforeach}). For example:
+\begin{verbatim}
+\DTLaddentryforrow{mydata}{\firstname=FirstName,\surname=Surname}%
+{\DTLiseq{\firstname}{John}\and\DTLiseq{\surname}{Smith}}%
+{Score}{75}
+\end{verbatim}
+Note that unlike \cs{DTLnewdbentry}, the value is always expanded
+when adding an entry using \cs{DTLaddentryforrow}.
+
+\begin{definition}[\DescribeMacro{\DTLsetheader}]%
+\cs{DTLsetheader}\marg{db}\marg{key}\marg{header}
+\end{definition}
+This assigns a header for a given key in the database named
+\meta{db}. This is used by \cs{DTLdisplaydb} and
+\cs{DTLdisplaylongdb} in the header row (see
+\autoref{sec:displaydb}). If you don't assign
+a header, the header will be given by the key.
+For example:
+\begin{verbatim}
+\DTLsetheader{mydata}{Price}{Price (\$)}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLaddcolumn}]
+\cs{DTLaddcolumn}\marg{db}\marg{key}
+\end{definition}
+Adds a new column with the given key to the database \meta{db}. This
+doesn't add any data to the column, just identifies it as an
+available column. The starred version doesn't check if the database
+exists.
+
+\section{Loading a Database from an External ASCII File}
+\label{sec:loaddb}
+
+\begin{important}
+\cs{DTLloaddb} and \cs{DTLloadrawdb}, described in this section, can't
+parse files that have newline characters within entries. The
+\app{datatooltk} application (see page~\pageref{datatooltk}) can
+parse them, so if you have multilined entries in a CSV file, you
+can convert it to \sty{datatool}'s internal database format using
+\app{datatooltk} and the input it using \ics{input} or \ics{DTLloaddbtex}. See the
+\app{datatooltk} documentation for further details.
+\end{important}
+Remember that row numbers in \sty{datatool} refer to the row index
+of the internal data not to line numbers in the CSV file.
+
+Instead of using the commands described in \autoref{sec:newdb}
+to create a new database, you can load a database from an
+external ASCII file using:
+\begin{definition}[\DescribeMacro{\DTLloaddb}]%
+\cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename}
+\end{definition}
+
+\begin{important}
+Make sure your document uses the same encoding as \meta{filename}.
+For example, if \meta{filename} is UTF-8, then include the following
+in your document:
+\begin{verbatim}
+\usepackage[utf8]{inputenc}
+\end{verbatim}
+\end{important}
+By default, \cs{DTLloaddb} creates a new database called \meta{db
+name} before it loads the data given in the file \meta{filename}.
+If you want to append the data, use
+\begin{definition}[\DTLnewdbonloadfalse]
+\cs{DTLnewdbonloadfalse}
+\end{definition}
+before you use \cs{DTLloaddb}. You can reverse this using
+\begin{definition}[\DTLnewdbonloadtrue]
+\cs{DTLnewdbonloadtrue}
+\end{definition}
+The file (\meta{filename}) may have a header row at the start of the file,
+which provides the \meta{key} when creating a new database entry
+using \ics{DTLnewdbentry}.
+The optional argument \meta{options}
+is a \meta{key}=\meta{value} list of options.
+\begin{important}
+Some of the keys may take a comma-separated list as a value.
+Note that spaces count in the default \TeX\ way within these lists.
+Remember that \TeX\ considers an end-of-line character as a space.
+If you have a long list, consider using the comment character (\%)
+to suppress unwanted space caused by line breaks in the code.
+\end{important}
+Available options are:
+\begin{description}
+\item[\csopt{DTLloaddb}{noheader}] This is a boolean value and
+indicates if the file does not contain a header. If no value is
+supplied, "true" is assumed (i.e.\ the file doesn't contain a header
+row). If this option is omitted, it is assumed that the file
+contains a header row.
+
+\item[\csopt{DTLloaddb}{keys}] This is a comma-separated list of
+keys to use, where the keys are listed in the same order as the
+columns. If the file has a header, these keys will override the
+values given in the header row. If the file has no header row and no
+keys are supplied in \meta{options}, then the keys will be given by
+\cs{dtldefaultkey}\meta{n}, where \meta{n} is the column number and
+\DescribeMacro{\dtldefaultkey}\cs{dtldefaultkey} defaults to
+``\dtldefaultkey''. Note that the list of keys must be delimited by
+braces since they contain commas.
+For example:
+\begin{verbatim}
+\DTLloaddb[noheader,keys={Temperature,Time,T2G}]{data}{data.csv}
+\end{verbatim}
+
+\item[\csopt{DTLloaddb}{autokeys}] This is a boolean option that
+will automatically assign default keys (\cs{dtldefaultkey}\meta{n},
+as above) for all columns, regardless of whether the file has a
+header row. If true, this option overrides the
+\csopt{DTLloaddb}{keys} option. You may want to use this if you have
+a header row with many fields containing active characters but you
+only want to use commands like \cs{DTLdisplaydb}. (In which case,
+you may want to consider using \cs{DTLloadrawdb} to load the data.)
+
+\item[\csopt{DTLloaddb}{headers}] This is a comma-separated list of
+headers. If not supplied, the header will be the same as that given
+in the header row, or the key if there is no header row. Note that
+the list of headers must be delimited by braces since they contain
+commas. For example:
+\begin{verbatim}
+\DTLloaddb[noheader,keys={Temperature,Time,T2G},%
+headers={\shortstack{Incubation\\Temperature},%
+\shortstack{Incubation\\Time},%
+\shortstack{Time to\\Growth}}]{data}{data.csv}
+\end{verbatim}
+
+\item[\csopt{DTLloaddb}{omitlines}]
+This should be a non-negative integer that specifies how many rows
+to skip at the start of the file.
+\end{description}
+
+By default, the entries in the database
+must be separated by a comma, and optionally delimited by the
+double quote character (\verb|"|). The separator can be changed
+to a tab separator using the command:
+\begin{definition}[\DescribeMacro{\DTLsettabseparator}]%
+\cs{DTLsettabseparator}
+\end{definition}
+Note that this command changes the category code of the tab
+character to~12 (other). If, after you have loaded your data, you want to
+reset the tab category code to~10 (space), you can use:
+\begin{definition}[\DescribeMacro{\DTLmaketabspace}]%
+\cs{DTLmaketabspace}
+\end{definition}
+Don't use this command before you load any tab-separated data.
+
+To set the separator to a character other than a tab, you need to use
+\begin{definition}[\DescribeMacro{\DTLsetseparator}]%
+\cs{DTLsetseparator}\marg{character}
+\end{definition}
+The delimiter can be changed using
+\begin{definition}[\DescribeMacro{\DTLsetdelimiter}]%
+\cs{DTLsetdelimiter}\marg{character}
+\end{definition}
+\begin{important}
+Note that spaces count in the usual \TeX\ manner and won't be
+trimmed from either side of the separators.
+\end{important}
+
+For example, suppose you have a file called \texttt{mydata.csv}
+which contains the following:
+\begin{verbatim}
+FirstName,Surname,Score
+John,"Smith, Jr",68
+Jane,Brown,75
+Andy,Brown,42
+Z\"oe,Adams,52
+\end{verbatim}
+then
+\begin{verbatim}
+\DTLloaddb{mydata}{mydata.csv}
+\end{verbatim}
+is equivalent to:
+\begin{verbatim}
+\DTLnewdb{mydata}
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{FirstName}{John}%
+\DTLnewdbentry{mydata}{Surname}{Smith, Jr}%
+\DTLnewdbentry{mydata}{Score}{68}%
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{FirstName}{Jane}%
+\DTLnewdbentry{mydata}{Surname}{Brown}%
+\DTLnewdbentry{mydata}{Score}{75}%
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{FirstName}{Andy}%
+\DTLnewdbentry{mydata}{Surname}{Brown}%
+\DTLnewdbentry{mydata}{Score}{42}%
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{FirstName}{Z\"oe}%
+\DTLnewdbentry{mydata}{Score}{52}%
+\DTLnewdbentry{mydata}{Surname}{Adams}%
+\end{verbatim}
+Note that the entry \texttt{Smith, Jr} had to be delimited in
+\texttt{mydata.csv} using the double quote character since it
+contained a comma which is used as the separator.
+The percent symbol \% can be used as a comment character within the
+file.
+
+The file used in the above example contained a \LaTeX\ command,
+namely \verb|\"|. When using \ics{DTLloaddb} all the special
+characters that appear in the command retain their \LaTeX\ meaning
+when the file is loaded. It is likely however that the data file
+may have been created by another application that is not \TeX-aware,
+such as a spreadsheet application. For example, suppose you
+have a file called, say, \texttt{products.csv} which looks
+like:
+\begin{verbatim}
+Product,Cost
+Fruit & Veg,$1.25
+Stationary,$0.80
+\end{verbatim}
+This file contains two of \TeX's special characters, namely
+"&" and \verb|$|. In this case, if you try to load the file
+using \ics{DTLloaddb}, you will encounter errors. Instead you
+can use:
+\begin{definition}[\DescribeMacro{\DTLloadrawdb}]%
+\cs{DTLloadrawdb}\oarg{options}\marg{db name}\marg{filename}
+\end{definition}
+This is similar to \ics{DTLloaddb} except that it maps nine of
+the ten special characters onto commands which produce that
+symbol. The only character that retains its active state is the
+backslash character, so you will still need to check the file
+for backslash characters. The mappings used are listed in
+\autoref{tab:rawmappings}. So using the file \texttt{products.csv},
+as described above,
+\begin{verbatim}
+\DTLloadrawdb{mydata}{products.csv}
+\end{verbatim}
+is equivalent to:
+\begin{verbatim}
+\DTLnewdb{mydata}
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{Product}{Fruit \& Veg}%
+\DTLnewdbentry{mydata}{Cost}{\$1.25}%
+\DTLnewrow{mydata}%
+\DTLnewdbentry{mydata}{Product}{Stationary}%
+\DTLnewdbentry{mydata}{Cost}{\$0.80}%
+\end{verbatim}
+As with \ics{DTLloaddb}, you can govern whether or not a new
+database should be created with \ics{DTLnewdbonloadtrue} and
+\ics{DTLnewdbonloadfalse}.
+
+Note that \cs{DTLloadrawdb} is not recommended for CSV files that
+contain commands. Any active characters occurring within the
+file must be mapped. The mapping is done through
+expansion. Version 2.28 now uses \cs{xdef} rather than
+\cs{protected@xdef}, but \cs{DTLloadrawdb} isn't intended for files
+containing \LaTeX\ code, but rather for files generated by a
+non-\TeX\ aware method that doesn't guard against \LaTeX\ special
+characters.
+
+If you have UTF-8 data, it's best to use an engine that natively
+supports Unicode. Remember that there's no point using
+\cs{DTLloadrawdb} (instead of \cs{DTLloaddb}) if your file doesn't
+contain any special characters that require mapping. It's less
+efficient to load if each row has to be converted, particularly for
+large files.
+
+\begin{table}[htbp]
+\caption[Special character mappings used by
+\cs{DTLloadrawdb}]{Special character mappings used by
+\cs{DTLloadrawdb} (note that the backslash retains its active state)}
+\label{tab:rawmappings}
+\centering
+\begin{tabular}{cl}
+Character & Mapping\\
+\verb|%| & \verb|\%|\\
+\verb|$| & \verb|\$|\\
+\verb|&| & \verb|\&|\\
+\verb|#| & \verb|\#|\\
+\verb|_| & \verb|\_|\\
+\verb|{| & \verb|\{|\\
+\verb|}| & \verb|\}|\\
+\verb|~| & \cs{textasciitilde}\\
+\verb|^| & \cs{textasciicircum}
+\end{tabular}
+\end{table}
+
+It may be that there are other characters that require mapping.
+For example, the file \texttt{products.csv} may instead look like:\par
+\vskip\baselineskip
+\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+Product,Cost
+Fruit \& Veg,\pounds1.25
+Stationary,\pounds0.80
+\end{ttfamily}
+\vskip\baselineskip
+The pound character is not an internationally standard keyboard
+character, and does not generally achieve the desired effect when used
+in a \LaTeX\ document. It may therefore be necessary to convert
+this symbol to an appropriate control sequence. This can be done
+using the command:
+\begin{definition}[\DescribeMacro{\DTLrawmap}]%
+\cs{DTLrawmap}\marg{string}\marg{replacement}
+\end{definition}
+For example:\par
+\vskip\baselineskip
+\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+\cs{DTLrawmap}\char`\{\pounds\char`\}\char`\{\cs{pounds}\char`\}
+\end{ttfamily}
+\vskip\baselineskip\noindent
+will replace all occurrences\footnote{when it is loaded into the
+\LaTeX\ database, it does not modify the data file!}\ of
+\texttt{\pounds} with \cs{pounds}. Naturally, the mappings must be
+set \emph{prior} to loading the data with \cs{DTLloadrawdb}.
+
+\begin{important}
+Note that the warning in the previous section about no
+paragraph breaks in an entry also applies to entries loaded from a
+database. If you do need a paragraph break, use \ics{DTLpar} instead
+of \cs{par}, but remember that each row of data in an external data
+file must not have a line break.
+\end{important}
+
+\section{Displaying the Contents of a Database}
+\label{sec:displaydb}
+
+Once you have created a database, either loading it from an
+external file, as described in \autoref{sec:loaddb}, or using the
+commands described in \autoref{sec:newdb}, you can display the
+entire database in a \env{tabular} or \env{longtable}
+environment.
+
+\begin{definition}[\DescribeMacro{\DTLdisplaydb}]%
+\cs{DTLdisplaydb}\oarg{omit list}\marg{db}
+\end{definition}
+This displays the database given by \meta{db} in a \env{tabular}
+environment. The first row displays the headers for the database
+in bold, the subsequent rows display the values for each key
+in each row of the database. The optional argument \meta{omit list}
+is a comma-separated list of column keys to omit. (All columns displayed by default.)
+
+\begin{definition}[\DescribeMacro{\DTLdisplaylongdb}]%
+\cs{DTLdisplaylongdb}\oarg{options}\marg{db}
+\end{definition}
+This is like \cs{DTLdisplaydb} except that it uses the
+\env{longtable} environment instead of the \env{tabular}
+environment. Note that if you use this command, you must load the
+\sty{longtable} package, as it is not loaded by \sty{datatool}.
+The optional argument \meta{options} is a comma-separated list
+of key=value pairs. The following keys are available:
+\begin{description}
+\item[caption] The caption for the \env{longtable}.
+
+\item[contcaption] The continuation caption.
+
+\item[shortcaption] The caption to be used in the list of tables.
+
+\item[label] The label for this table.
+
+\item[omit] Comma-separated list of column keys to omit.
+
+\item[foot] The \env{longtable}'s foot.
+
+\item[lastfoot] The foot for the last page of the \env{longtable}.
+\end{description}
+For example, suppose I have a database called "iris", then I can
+display the contents in a \env{longtable} using:
+\begin{verbatim}
+\DTLdisplaylongdb[%
+caption={Iris Data},%
+label={tab:iris},%
+contcaption={Iris Data (continued)},%
+foot={\em Continued overleaf},%
+lastfoot={}%
+]{iris}
+\end{verbatim}
+I can then reference the table using \verb|\ref{tab:iris}|.
+
+See the \sty{longtable} documentation for details on how to
+change the \env{longtable} settings, such as how to change the
+table so that it is left aligned instead of centred on the page.
+
+Note that if you want more control over the way the data is
+displayed, for example, you want to filter rows or columns, you will
+need to use \cs{DTLforeach}, described in \autoref{sec:dbforeach}.
+
+\begin{example}{Displaying the Contents of a Database}{ex:displaydb}
+Suppose I have a file called \texttt{t2g.csv} that contains the
+following:
+\begin{verbatim}
+40,120,40
+40,90,60
+35,180,20
+55,190,40
+\end{verbatim}
+This represents time to growth data, where the first column
+is the incubation temperature, the second column is the incubation
+time and the third column is the time to growth. This file has no
+header row, so when it is loaded, the \csopt{DTLloaddb}{noheaders}
+option is required. Note that \cs{DTLdisplaydb} only puts the data
+in a \env{tabular} environment, so \cs{DTLdisplaydb} needs to be
+put in a \env{table} environment with a caption to make it a float.
+
+First load the data base, setting the keys and headers:
+\begin{verbatim}
+\DTLloaddb[noheader,%
+keys={Temperature,Time,T2G},%
+headers={\shortstack{Incubation\\Temperature},%
+\shortstack{Incubation\\Time},\shortstack{Time to\\Growth}}%
+]{t2g}{t2g.csv}
+\end{verbatim}
+\DTLnewdb{t2g}\relax
+\DTLnewrow*{t2g}\relax
+\DTLnewdbentry*{t2g}{Temperature}{40}\relax
+\DTLnewdbentry*{t2g}{Time}{120}\relax
+\DTLnewdbentry*{t2g}{T2G}{40}\relax
+\DTLnewrow*{t2g}\relax
+\DTLnewdbentry*{t2g}{Temperature}{40}\relax
+\DTLnewdbentry*{t2g}{Time}{90}\relax
+\DTLnewdbentry*{t2g}{T2G}{60}\relax
+\DTLnewrow*{t2g}\relax
+\DTLnewdbentry*{t2g}{Temperature}{35}\relax
+\DTLnewdbentry*{t2g}{Time}{180}\relax
+\DTLnewdbentry*{t2g}{T2G}{20}\relax
+\DTLnewrow*{t2g}\relax
+\DTLnewdbentry*{t2g}{Temperature}{55}\relax
+\DTLnewdbentry*{t2g}{Time}{190}\relax
+\DTLnewdbentry*{t2g}{T2G}{40}\relax
+\DTLsetheader*{t2g}{Temperature}{\shortstack{Incubation\\Temperature}}\relax
+\DTLsetheader*{t2g}{Time}{\shortstack {Incubation\\Time}}\relax
+\DTLsetheader*{t2g}{T2G}{\shortstack {Time to\\Growth}}\relax
+
+Now display the data in a table:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Time to Growth Data}
+\centering
+\DTLdisplaydb{t2g}
+\end{table}
+\end{verbatim}
+The result is shown in \autoref{tab:t2g}.
+\begin{table}[htbp]
+\caption{Time to Growth Data}
+\label{tab:t2g}
+\centering
+\DTLdisplaydb{t2g}
+\end{table}
+\end{example}
+
+Each column in the database has an associated data type which
+indicates what type of data is in that column. This may be one
+of: string, integer, real number or currency. If a column contains
+more than one type, the data type is determined as follows:
+\begin{itemize}
+\item If the column contains at least one string, then the column
+data type is string.
+
+\item If the column doesn't contain a string, but contains at least
+one currency, then the column data type is currency.
+
+\item If the column contains only real numbers and integers, the
+column data type is real number.
+
+\item The column data type is integer if the column only
+contains integers.
+\end{itemize}
+The column data type is updated whenever a new entry is added
+to the database. Note that the column data type is not adjusted
+when an entry is removed from the database.
+
+The column alignments used by \cs{DTLdisplaydb} are given by:
+\begin{definition}[\DescribeMacro{\dtlstringalign}]%
+\cs{dtlstringalign}
+\end{definition}\noindent
+The string alignment defaults to \texttt{l} (left aligned).
+
+\begin{definition}[\DescribeMacro{\dtlintalign}]%
+\cs{dtlintalign}
+\end{definition}\noindent
+The integer alignment defaults to \texttt{r} (right aligned).
+
+\begin{definition}[\DescribeMacro{\dtlrealalign}]%
+\cs{dtlrealalign}
+\end{definition}\noindent
+The alignment for real numbers defaults to \texttt{r} (right
+aligned).
+
+\begin{definition}[\DescribeMacro{\dtlcurrencyalign}]%
+\cs{dtlcurrencyalign}
+\end{definition}\noindent
+The currency alignment defaults to \texttt{r} (right aligned).
+
+You can redefine these to change the column alignments. For
+example, if you want columns containing strings to have the
+alignment "p{2in}", then you can redefine \cs{dtlstringalign} as
+follows:
+\begin{verbatim}
+\renewcommand{\dtlstringalign}{p{2in}}
+\end{verbatim}
+
+\begin{important}
+You can't use \sty{siunitx}'s "S" column alignment
+with either \cs{DTLdisplaydb} or \cs{DTLdisplaylongdb}. Instead, you
+will need to use \cs{DTLforeach}. The \sty{siunitx} documentation
+provides an example.
+\end{important}
+
+In addition to the \cs{dtl}\meta{type}"align" commands above, you
+can also modify the \env{tabular} column styles by redefining the
+following three commands:
+\begin{definition}[\DescribeMacro{\dtlbeforecols}]
+\cs{dtlbeforecols}
+\end{definition}
+(before the first column)
+\begin{definition}[\DescribeMacro{\dtlbetweencols}]
+\cs{dtlbetweencols}
+\end{definition}
+(between each column) and
+\begin{definition}[\DescribeMacro{\dtlaftercols}]
+\cs{dtlaftercols}
+\end{definition}
+(after the last column).
+
+For example, to
+place a vertical line before the start of the first column and
+after the last column, do:
+\begin{verbatim}
+\renewcommand{\dtlbeforecols}{|}
+\renewcommand{\dtlaftercols}{|}
+\end{verbatim}
+If you additionally want vertical lines between columns, do:
+\begin{verbatim}
+\renewcommand{\dtlbetweencols}{|}
+\end{verbatim}
+
+Limited modifications can be made to the way the data is displayed
+with \cs{DTLdisplaydb} and \cs{DTLdisplaylongdb}.
+The commands controlling the formatting are described below.
+If a more complicated layout is required, you will need to use
+\cs{DTLforeach} described in \autoref{sec:dbforeach}.
+
+\begin{definition}[\DescribeMacro{\dtlheaderformat}]%
+\cs{dtlheaderformat}\marg{header}
+\end{definition}
+This indicates how to format a column header, where the header is
+given by \meta{header}. This defaults to
+\cs{null}\cs{hfil}\cs{textbf}\marg{header}\cs{hfil}\cs{null}.
+
+\begin{definition}[\DescribeMacro{\dtlstringformat}]%
+\cs{dtlstringformat}\marg{text}
+\end{definition}
+This specifies how to format each entry in the columns that contain
+strings. This defaults to just displaying \meta{text}.
+
+\begin{definition}[\DescribeMacro{\dtlintformat}]%
+\cs{dtlintformat}\marg{text}
+\end{definition}
+This specifies how to format each entry in the columns that contain
+only integers. This defaults to just displaying \meta{text}.
+
+\begin{definition}[\DescribeMacro{\dtlrealformat}]%
+\cs{dtlrealformat}\marg{text}
+\end{definition}
+This specifies how to format each entry in the columns that contain
+only real numbers or a mixture of real numbers and integers. This
+defaults to just displaying \meta{text}.
+
+\begin{definition}[\DescribeMacro{\dtlcurrencyformat}]%
+\cs{dtlcurrencyformat}\marg{text}
+\end{definition}
+This specifies how to format each entry in the columns that contain
+only currency or currency mixed with real numbers and/or integers.
+This defaults to just displaying \meta{text}.
+
+\begin{definition}[\DescribeMacro{\dtldisplayvalign}]
+\cs{dtldisplayvalign}
+\end{definition}
+Specifies the vertical alignment of the \env{tabular} environment
+used by \cs{DTLdisplaydb}. Defaults to \texttt{c} (centred). May be redefined
+to \texttt{t} (top) or \texttt{b} (bottom).
+
+\begin{definition}[\DescribeMacro{\dtldisplaycr}]
+\cs{dtldisplaycr}
+\end{definition}
+Specifies how to separate rows. Defaults to just
+\ics{tabularnewline}.
+
+\begin{definition}[\DescribeMacro{\dtldisplaystarttab}]%
+\cs{dtldisplaystarttab}
+\end{definition}
+This is a hook to add something at the beginning of the
+\env{tabular} environment. This defaults to nothing.
+In the case of \cs{DTLdisplaylongdb}, this hook is done before the
+header row on each page of the \env{longtable}.
+
+\begin{definition}[\DescribeMacro{\dtldisplayendtab}]%
+\cs{dtldisplayendtab}
+\end{definition}
+This is a hook to add something at the end of the
+\env{tabular} environment. This defaults to nothing.
+In the case of \cs{DTLdisplaylongdb}, this hook is only done on the
+\emph{last} page of the \env{longtable}. You have to use the
+\texttt{foot} option to specify some code to do at the end of each page.
+
+\begin{definition}[\DescribeMacro{\dtldisplayafterhead}]%
+\cs{dtldisplayafterhead}
+\end{definition}
+This is a hook to add something after the header row, before
+the first row of data. This defaults to nothing.
+In the case of \cs{DTLdisplaylongdb}, this hook is done after the
+header row on each page of the \env{longtable}.
+
+\begin{definition}[\DescribeMacro{\dtldisplaystartrow}]%
+\cs{dtldisplaystartrow}
+\end{definition}
+This is a hook to add something at the start of each row, but
+not including the header row or the first row of data. This
+defaults to nothing.
+
+If you want to use the \sty{booktabs} package, you can redefine the
+above three commands to use \ics{toprule}, \ics{midrule} and
+\ics{bottomrule}:
+\begin{verbatim}
+\renewcommand{\dtldisplaystarttab}{\toprule}
+\renewcommand{\dtldisplayafterhead}{\midrule}
+\renewcommand{\dtldisplayendtab}{\\\bottomrule}
+\end{verbatim}
+
+\begin{example}{Balance Sheet}{ex:balance}
+Suppose you have a file called "balance.csv" that contains
+the following:
+\begin{verbatim}
+Description,In,Out,Balance
+Travel expenses,,230,-230
+Conference fees,,400,-630
+Grant,700,,70
+Train fare,,70,0
+\end{verbatim}
+\DTLnewdb{balance}\relax
+\DTLnewrow{balance}\relax
+\DTLnewdbentry{balance}{Description}{Travel expenses}\relax
+\DTLnewdbentry{balance}{In}{}\relax
+\DTLnewdbentry{balance}{Out}{230.00}\relax
+\DTLnewdbentry{balance}{Balance}{-230.00}\relax
+\DTLnewrow{balance}\relax
+\DTLnewdbentry{balance}{Description}{Conference fees}\relax
+\DTLnewdbentry{balance}{In}{}\relax
+\DTLnewdbentry{balance}{Out}{400.00}\relax
+\DTLnewdbentry{balance}{Balance}{-630.00}\relax
+\DTLnewrow{balance}\relax
+\DTLnewdbentry{balance}{Description}{Grant}\relax
+\DTLnewdbentry{balance}{In}{700.00}\relax
+\DTLnewdbentry{balance}{Out}{}\relax
+\DTLnewdbentry{balance}{Balance}{70.00}\relax
+\DTLnewrow{balance}\relax
+\DTLnewdbentry{balance}{Description}{Train Fare}\relax
+\DTLnewdbentry{balance}{In}{}\relax
+\DTLnewdbentry{balance}{Out}{70.00}\relax
+\DTLnewdbentry{balance}{Balance}{0.00}\relax
+\DTLsetheader{balance}{In}{In (\pounds)}\relax
+\DTLsetheader{balance}{Out}{Out (\pounds)}\relax
+\DTLsetheader{balance}{Balance}{Balance (\pounds)}\relax
+The data can be loaded using:
+\begin{verbatim}
+\DTLloaddb[headers={Description,In (\pounds),Out (\pounds),Balance
+(\pounds)}]{balance}{balance.csv}
+\end{verbatim}
+
+Suppose I want negative numbers to be displayed in red. I can do
+this by redefining \cs{dtlrealformat} to check if the entry
+is negative. For example:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Balance Sheet}
+\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
+\centering
+\DTLdisplaydb{balance}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:balance}.
+\begin{table}[htbp]
+\caption{Balance Sheet}
+\label{tab:balance}
+\renewcommand*{\dtlrealformat}[1]{\DTLiflt{#1}{0}{\color{red}}{}#1}
+\centering
+\DTLdisplaydb{balance}
+\end{table}
+\end{example}
+
+\section{Iterating Through a Database}
+\label{sec:dbforeach}
+
+Once you have created a database, either loading it from an
+external file, as described in \autoref{sec:loaddb}, or using the
+commands described in \autoref{sec:newdb}, you can then iterate
+through each row of the database and access elements in that row.
+
+\begin{important}
+The \cs{DTLforeach} command is provided as a convenient way of
+iterating through databases with the option to filter rows,
+cross-reference rows or have nested loops, but for large databases it can be
+\emph{extremely slow}, especially if the unstarred version is used.
+If you have a large database, consider pre-processing the data using
+an external script. See also \sectionref{sec:advancediter}.
+\end{important}
+
+\begin{definition}[\DescribeMacro{\DTLforeach}]%
+\cs{DTLforeach}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLforeach*}]%
+\cs{DTLforeach*}\oarg{condition}\marg{db name}\marg{assign list}\marg{text}
+\end{definition}
+This will iterate through each row of the database called
+\meta{db name}, applying \meta{text} to each row of the database
+where \meta{condition} is met. The argument \meta{assign list} is a
+comma separated list of \meta{cmd}"="\meta{key} pairs. At the
+start of each row, each command \meta{cmd} in \meta{assign list}
+will be set to the value of the entry given by \meta{key}.
+These commands may then be used in \meta{text}.
+
+\begin{important}
+Note that this assignment is done globally to ensure
+that \cs{DLTforeach} works correctly in a \env{tabular} environment.
+Since you may want to use the same set of commands in a later
+\cs{DTLforeach}, the commands are not checked to determine if they
+already exist. It is therefore important that you check you are not
+using an existing command whose value should not be changed.
+\end{important}
+
+The optional argument \meta{condition} is a condition in the
+form allowed by \cs{ifthenelse}. This includes the commands
+provided by the \sty{ifthen} package (such as \cs{not}, \cs{and},
+\cs{or}), as well as the commands
+described in \autoref{sec:ifthen}. The default value of
+\meta{condition} is "\boolean{true}".
+
+The starred version \cs{DTLforeach*} is a read-only version.
+If you want to modify the database using any of the commands
+described in \autoref{sec:editdb}, you must use the unstarred
+version. The starred version is faster.
+
+\begin{important}
+As is generally the case with command arguments, verbatim (for
+example, using \cs{verb} or the \env{verbatim} environment) can't be used in any of
+the arguments of \cs{DTLforeach}, specifically verbatim can't be
+used in \meta{text}.
+\end{important}
+
+There are also environment alternatives:
+\begin{definition}[\DescribeEnv{DTLenvforeach}]%
+\cs{begin}\{DTLenvforeach\}\oarg{condition}\marg{db name}\marg{assign list}
+\end{definition}
+\begin{definition}[\DescribeEnv{DTLenvforeach*}]%
+\cs{begin}\{DTLenvforeach*\}\oarg{condition}\marg{db name}\marg{assign list}
+\end{definition}
+However, note that since these environments gather the contents of
+their body, they also suffer from the above limitation.
+\begin{important}
+Verbatim can't be used in the body of \env{DTLenvforeach} or
+\env{DTLenvforeach*}.
+\end{important}
+
+\begin{example}{Student scores}{ex:scores}
+Suppose you have a data file called \texttt{studentscores.csv} that
+contains the following:
+\begin{verbatim}
+FirstName,Surname,StudentNo,Score
+John,"Smith, Jr",102689,68
+Jane,Brown,102647,75
+Andy,Brown,103569,42
+Z\"oe,Adams,105987,52
+Roger,Brady,106872,58
+Clare,Verdon,104356,45
+\end{verbatim}
+\DTLnewdb{scores}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{John}\relax
+\DTLnewdbentry{scores}{Surname}{Smith, Jr}\relax
+\DTLnewdbentry{scores}{StudentNo}{102689}\relax
+\DTLnewdbentry{scores}{Score}{68}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{Jane}\relax
+\DTLnewdbentry{scores}{Surname}{Brown}\relax
+\DTLnewdbentry{scores}{StudentNo}{102647}\relax
+\DTLnewdbentry{scores}{Score}{75}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{Andy}\relax
+\DTLnewdbentry{scores}{Surname}{Brown}\relax
+\DTLnewdbentry{scores}{StudentNo}{103569}\relax
+\DTLnewdbentry{scores}{Score}{42}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{Z\"oe}\relax
+\DTLnewdbentry{scores}{Score}{52}\relax
+\DTLnewdbentry{scores}{StudentNo}{105987}\relax
+\DTLnewdbentry{scores}{Surname}{Adams}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{Roger}\relax
+\DTLnewdbentry{scores}{Score}{58}\relax
+\DTLnewdbentry{scores}{StudentNo}{106872}\relax
+\DTLnewdbentry{scores}{Surname}{Brady}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{FirstName}{Clare}\relax
+\DTLnewdbentry{scores}{Score}{45}\relax
+\DTLnewdbentry{scores}{StudentNo}{104356}\relax
+\DTLnewdbentry{scores}{Surname}{Verdon}\relax
+and you load the data into a database called "scores" using:
+\begin{verbatim}
+\DTLloaddb{scores}{studentscores.csv}
+\end{verbatim}
+you can then display the database in a table as follows:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\% start new row
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:scores}. (Note that since I didn't
+need the student registration number, I didn't bother to
+assign a command to the key "StudentNo".)
+
+\begin{important}
+Note that the new row command \idbs\ has been placed at the
+start of the final argument in the above example. This is necessary
+as placing it at the end of the argument will cause an unwanted row
+at the end of the table. This is a feature of the loop mechanism.
+\end{important}
+
+\begin{table}[htbp]
+\caption[Student scores (displaying a database in a
+table)]{Student scores}\label{tab:scores}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+\end{example}
+
+The macro \ics{DTLforeach} may be nested up to three times. Each
+level uses the corresponding counters:
+\desctr{DTLrowi},
+\desctr{DTLrowii} and
+\desctr{DTLrowiii} which keep track of
+the current row.
+
+\begin{important}
+Note that these counters are only incremented when
+\meta{condition} is satisfied, therefore they will not have the
+correct value in \meta{condition}. These counters are incremented
+using \cs{refstepcounter} before the start of \meta{text}, so they
+may be referenced using \cs{label}, however remember that \cs{label}
+references the last counter to be incremented using
+\cs{refstepcounter} \emph{in the current scope}. The \cs{label}
+should therefore be the first command in \meta{text} to ensure that
+it references the current row counter.
+\end{important}
+
+\begin{definition}[\DescribeMacro{\DTLcurrentindex}]%
+\cs{DTLcurrentindex}
+\end{definition}
+At the start of each iteration in \cs{DTLforeach},
+\cs{DTLcurrentindex} is set to the arabic value of the current row
+counter. Note that this is only set after the condition is tested,
+so it should only be used in the body of \cs{DTLforeach} not in
+the condition. It is also only set locally, so if you use it in
+a tabular environment, it can only be used before the first instance
+of \verb|\\| or \verb|&| in the current iteration.
+
+Within the body of \ics{DTLforeach} (i.e.\ within \meta{text})
+the following conditionals may be used:
+\begin{definition}[\DescribeMacro{\DTLiffirstrow}]%
+\cs{DTLiffirstrow}\marg{true part}\marg{false part}
+\end{definition}
+If the current row is the first row, then do \meta{true part},
+otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLiflastrow}]%
+\cs{DTLiflastrow}\marg{true part}\marg{false part}
+\end{definition}
+If the current row is the last row, then do \meta{true part},
+otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLifoddrow}]%
+\cs{DTLifoddrow}\marg{true part}\marg{false part}
+\end{definition}
+If the current row number is an odd number, then do \meta{true part},
+otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLsavelastrowcount}]%
+\cs{DTLsavelastrowcount}\marg{cmd}
+\end{definition}
+This command will store the value of the row counter used in
+the last occurrence of \ics{DTLforeach} in the control sequence
+\meta{cmd}.
+
+\begin{definition}[\DescribeMacro{\DTLforeachkeyinrow}]%
+\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text}
+\end{definition}
+This iterates through each key in the current row, (globally) assigns
+\meta{cmd} to the value of that key, and does \meta{text}
+(\meta{cmd} must be a control sequence and may be used in
+\meta{text}). This command may only be used in the body of
+\cs{DTLforeach}. At each iteration, \cs{DTLforeachkeyinrow} sets
+\cs{dtlkey} to the current key, \cs{dtlcol} to the current column
+index, \cs{dtltype} to the data type for the current column,
+and \cs{dtlheader} to the header for the current column. Note that
+\cs{dtltype} corresponds to the column type but if the entries in
+the column have mixed types, it may not correspond to the type
+of the current entry.
+
+\begin{definition}[\DescribeMacro{\dtlbreak}]%
+\cs{dtlbreak}
+\end{definition}
+You can break out of most of the loops provided by \sty{datatool}
+using \cs{dtlbreak}. Note, however, that it doesn't break the loop
+until the end of the current iteration. There is no provision for
+a "next" or "continue" style command.
+
+Additional loop commands provided by \sty{datatool} are
+described in the documented code (datatool-code.pdf).
+
+\begin{example}{Student Scores---Labelling}{ex:label}
+In the previous example, the student scores, stored in the
+database "scores" were placed in a table. In this example the
+table will be modified slightly to number each student according
+to the row. Suppose I also want to identify which row Jane Brown
+is in, and reference it in the text. The easiest way to do this
+is to construct a label on each row which uniquely identifies
+that student. The label can't simply be constructed from the
+surname, as there are two students with the same surname. In order
+to create a unique label, I can either construct a label from
+both the surname and the first name, or I can use the student's
+registration number, or I can use the student's score, since all
+the scores are unique. The former method will cause a problem since
+one of the names (Z\"oe) contains an accent command. Although
+the registration numbers are all unique, they are not particularly
+memorable, so I shall instead use the scores.
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores}
+\centering
+\begin{tabular}{cllc}
+\bfseries Row &
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\label{row:\score}\\\theDTLrowi &
+\firstname & \surname & \score}%
+\end{tabular}
+\end{table}
+
+Jane Brown scored the highest (75\%), her score can be seen on
+row~\ref{row:75}.
+\end{verbatim}
+This produces \autoref{tab:scoreslab} and the following text:
+Jane Brown scored the highest (75\%), her score can be seen on
+row~\ref*{row:75}.
+
+Notes:
+\begin{itemize}
+\item the \cs{label} command is placed before
+"\\" to ensure that it is in the same scope as the command
+"\refstepcounter{DTLrowi}".
+
+\item To avoid unwanted spaces the end of line characters are
+commented out with the percent (\texttt{\%}) symbol.
+\end{itemize}
+
+\begin{table}[htbp]
+\caption[Student scores (labelling rows)]{Student
+scores}\label{tab:scoreslab}
+\centering
+\begin{tabular}{cllc}
+\bfseries Row &
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\label{row:\score}\\\theDTLrowi &
+\firstname & \surname & \score}\relax
+\end{tabular}
+\end{table}
+\end{example}
+
+\begin{example}{Filtering Rows}{ex:filter}
+As mentioned earlier, the optional argument \meta{condition} of
+\ics{DTLforeach} provides a means to exclude certain rows.
+This example uses the database defined in \autoref{ex:scores},
+but only displays the information for students whose marks are
+above 60. At the end of the table, \cs{DTLsavelastrowcount}
+is used to store the number of rows in the table. (Note that
+\cs{DTLsavelastrowcount} is outside of \ics{DTLforeach}.)
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Top student scores}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*[\DTLisgt{\score}{60}]{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\firstname & \surname & \score}
+\end{tabular}
+
+\DTLsavelastrowcount{\n}%
+\n\ students scored above 60\%.
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:topscores}. Note that in this example,
+I could have specified the condition as "\score>60" since all
+the scores are integers, however, as it's possible that an entry
+may feasibly have a decimal score I have used \ics{DTLisgt} instead.
+
+\begin{table}[htbp]
+\caption[Top student scores (filtering rows using
+\cs{DTLisgt})]{Top student scores}\label{tab:topscores}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach*[\DTLisgt{\score}{60}]{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\firstname & \surname & \score}
+\end{tabular}
+
+\DTLsavelastrowcount{\n}\relax
+\n\ students scored above 60\%.
+\end{table}
+
+Suppose now, I only want to display the scores for students whose
+surname begins with `B'. I can do this as follows:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (B)}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*[\DTLisopenbetween{\surname}{B}{C}]{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:Bscores}.
+
+\begin{table}[htbp]
+\caption[Student scores (B) --- filtering rows using \newline
+\cs{DTLisopenbetween}]{Student scores (B)}\label{tab:Bscores}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach*[\DTLisopenbetween{\surname}{B}{C}]{scores}
+{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+
+\end{example}
+
+\begin{example}{Checking for the First Row (booktabs)}{ex:iffirst}
+Suppose I want to use the \sty{booktabs} package and I want to use
+\ics{midrule} after the header row. I can use \ics{DTLiffirstrow} to
+check if the loop is on the first row of the iteration. (Remember
+that you need to load the \sty{booktabs} package in the preamble
+with \cs{usepackage}.) Using the same database as before:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (booktabs)}
+\centering
+\begin{tabular}{llc}
+\toprule
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*{scores}%
+ {\firstname=FirstName,\surname=Surname,\score=Score}%
+ {%
+ \DTLiffirstrow{\\\midrule}{\\}%
+ \firstname & \surname & \score
+ }% end of loop
+ \\\bottomrule
+\end{tabular}%
+\end{table}
+\end{verbatim}
+(The commands \ics{toprule}, \ics{midrule} and \ics{bottomrule} are
+all provided by \sty{booktabs}.) This produces
+\autoref{tab:iffirst}.
+
+\begin{table}[htbp]
+\caption{Student scores (booktabs)}
+\label{tab:iffirst}
+\centering
+\begin{tabular}{llc}
+\toprule
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\DTLiffirstrow{\\\midrule}{\\}%
+\firstname & \surname & \score}%
+\\\bottomrule
+\end{tabular}%
+\end{table}
+
+\end{example}
+
+\begin{example}{Breaking Out of a Loop}{ex:dtlbreak}
+Suppose I only want to display the first three rows of a database.
+I could do:\footnote{Recall that \ctr{DTLrowi} is incremented
+after the condition is tested, so it will be out by 1 when the
+condition is tested which is why \texttt{<3} is used instead of
+\texttt{<4}.}
+\begin{verbatim}
+\DTLforeach*[\value{DTLrowi}<3]{scores}%
+{\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\\firstname & \surname & \score
+}
+\end{verbatim}
+However, this isn't very efficient, as it still has to iterate
+through the entire database, checking if the condition is met. If
+the database has over 100 entries, this will slow the time taken
+to create the table. It would therefore be much more efficient
+to break out of the loop when row count exceeds 3:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{First Three Rows}
+\centering
+\begin{tabular}{llr}
+\bfseries First Name & \bfseries Surname & \bfseries Score (\%)%
+\DTLforeach*{scores}%
+{\firstname=FirstName,\surname=Surname,\score=Score}{%
+\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}%
+\\\firstname & \surname & \score
+}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:dtlbreak}. Note that the loop is not
+broken until the end of the current iteration, so even though
+\cs{dtlbreak} occurs at the start of the third row, the loop isn't
+finished until the third row is completed. (Recall that
+\cs{DTLcurrentindex} must be used before the first instance of
+\verb|\\| or \verb|&|.) Alternatively, you can use
+\ctr{DTLrowi} instead:
+\begin{verbatim}
+\DTLforeach{scores}%
+{\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\\firstname & \surname & \score
+\ifthenelse{\value{DTLrowi}=3}{\dtlbreak}{}%
+}%
+\end{verbatim}
+
+\begin{table}[htbp]
+\caption{First Three Rows}
+\label{tab:dtlbreak}%
+\centering
+\begin{tabular}{llr}
+\bfseries First Name & \bfseries Surname & \bfseries Score (\%)\relax
+\DTLforeach*{scores}%
+{\firstname=FirstName,\surname=Surname,\score=Score}{%
+\ifthenelse{\DTLcurrentindex=3}{\dtlbreak}{}\relax
+\\\firstname & \surname & \score
+}%
+\end{tabular}
+\end{table}
+\end{example}
+
+\begin{example}{Stripy Tables}{ex:stripy}
+This example uses the same database as in the previous examples.
+It requires the \sty{colortbl} package, which provides the
+command \cs{rowcolor}. The command \cs{DTLifoddrow} is used
+to produce a striped table.
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{A stripy table}\label{tab:stripy}
+\centering
+\begin{tabular}{llc}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}%
+\firstname & \surname & \score}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:stripy}.
+
+\begin{table}[htbp]
+\caption[A stripy table (illustrating the use of
+\cs{DTLifoddrow})]{A stripy table}\label{tab:stripy}
+\centering
+\begin{tabular}{llc}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\\DTLifoddrow{\rowcolor{blue}}{\rowcolor{green}}\relax
+\firstname & \surname & \score}\relax
+\end{tabular}
+\end{table}
+\end{example}
+
+\begin{example}{Two Database Rows per Tabular Row}{ex:2rows}
+In order to save space, you may want two database rows per
+tabular row, when displaying a database in a \env{tabular}
+environment. This can be accomplished using \ics{DTLifoddrow}.
+For example
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Two database rows per tabular row}
+\centering
+\begin{tabular}{llcllc}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%) &
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{%
+\DTLifoddrow{\\}{&}%
+\firstname & \surname & \score}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+produces \autoref{tab:2rows}
+
+\begin{table}[htbp]
+\caption[Two database rows per tabular row (illustrating the
+use of\newline \cs{DTLifoddrow})]{Two database rows per tabular
+row}\label{tab:2rows}
+\centering
+\begin{tabular}{llcllc}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%) &
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach*{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\DTLifoddrow{\\}{&}\relax
+\firstname & \surname & \score}\relax
+\end{tabular}
+\end{table}
+
+(To order column-wise, instead of row-wise, see
+\autoref{ex:twoblocks}.)
+\end{example}
+
+\begin{example}{Iterating Through Keys in a Row}{ex:foreachkey}
+Suppose you have lots of columns in your database, and you
+want to display them all without having to set a variable for
+each column. You can leave the assignment list in \cs{DTLforeach}
+blank, and iterate through the keys using \cs{DTLforeachkeyinrow}.
+For example:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student Scores (Iterating Through Keys)}
+\centering
+\begin{tabular}{llll}
+\bfseries First Name & \bfseries Surname &
+\bfseries Registration No. &
+\bfseries Score (\%)%
+\DTLforeach*{scores}{}{%
+\\\gdef\doamp{\gdef\doamp{&}}%
+\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:foreachkey}.
+\begin{table}[htbp]
+\caption{Student Scores (Iterating Through Keys)}
+\label{tab:foreachkey}
+\centering
+\begin{tabular}{llll}
+\bfseries First Name & \bfseries Surname &
+\bfseries Registration No. &
+\bfseries Score (\%)\relax
+\DTLforeach*{scores}{}{%
+\\\gdef\doamp{\gdef\doamp{&}}\relax
+\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax
+\end{tabular}
+\end{table}
+
+Note that the "&" must be between columns, so I have defined
+a command called \cs{doamp} that on first use redefines
+itself to do "&". So, for each row, at the start of
+the key iteration, \cs{doamp} does nothing, and on subsequent
+iterations it does "&". This ensures that the correct number of
+"&"s are used. Since each cell in the \env{tabular} environment
+is scoped, \cs{gdef} is needed instead of \cs{def}.
+
+In the above, I needed to know how many columns are in the
+database, and the order that the headings should appear. If you
+are unsure, you can use \cs{dtlforeachkey} to determine the
+number of columns and to display the header row. For example:
+\begin{verbatim}
+ \begin{table}[htbp]
+ \caption{Student Scores}
+ \centering
+ % Work out the column alignments.
+ \def\colalign{}%
+ \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+ {\edef\colalign{\colalign l}}%
+ % Begin the tabular environment.
+ \edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+ \dobegintabular
+ % Do the header row.
+ \gdef\doamp{\gdef\doamp{&}}%
+ \dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+ {\doamp\bfseries \theHead}%
+ % Iterate through the data.
+ \DTLforeach*{scores}{}{%
+ \\\gdef\doamp{\gdef\doamp{&}}%
+ \DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}%
+ \end{tabular}
+ \end{table}
+\end{verbatim}
+
+\begin{table}[htbp]
+\caption[Student Scores (Using \cs{dtlforeachkey} and \newline
+\cs{DTLforeachkeyinrow})]{Student Scores (Using \cs{dtlforeachkey} and
+\cs{DTLforeachkeyinrow})}
+\label{tab:foreachkey2}
+\centering
+\def\colalign{}%
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\edef\colalign{\colalign l}}%
+\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax
+\dobegintabular
+\gdef\doamp{\gdef\doamp{&}}\relax
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\doamp\bfseries \theHead}\relax
+\DTLforeach*{scores}{}{%
+\\\gdef\doamp{\gdef\doamp{&}}\relax
+\DTLforeachkeyinrow{\thisValue}{\doamp\thisValue}}\relax
+\end{tabular}
+\end{table}
+
+Notes:
+\begin{itemize}
+\item In order to determine the column alignment for the
+\env{tabular} environment, I first define \cs{colalign} to
+nothing, and then I iterate through the keys appending
+\texttt{l} to \cs{colalign}. Since \cs{colalign} only contains
+alphabetical characters, I can just use \cs{edef} for this. I
+could modify this to check the data type and, say, use \texttt{l}
+(left alignment) for columns containing strings and \texttt{c}
+(centred) for the other columns:
+\begin{verbatim}
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\ifnum\theType=0\relax
+ \edef\colalign{\colalign l}% column contains strings
+ \else
+ \edef\colalign{\colalign c}% column contains numerical values
+ \fi
+}%
+\end{verbatim}
+
+\item To ensure \cs{colalign} gets correct expanded when passed
+to the \env{tabular} environment I temporarily define
+\cs{dobegintabular} to the code required to start the
+\env{tabular} environment:
+\begin{verbatim}
+\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+\end{verbatim}
+This sets \cs{dobegintabular} to \verb|\begin{tabular}{llll}|.
+After defining \cs{dobegintabular}, I then need to use it.
+
+\item As before, I use \cs{doamp} to put the ampersands between
+columns.
+
+\item Recall that I can set the headers using \cs{DTLsetheader}
+or using the \csopt{DTLloaddb}{headers} key when loading the data
+from an external file. For example:
+\begin{verbatim}
+\DTLsetheaders{scores}{FirstName}{First Name}
+\DTLsetheaders{scores}{Score}{Score (\%)}
+\end{verbatim}
+\end{itemize}
+
+Recall that \cs{DTLforeachkeyinrow} sets \cs{dtlkey} to the
+current key. This can be used to filter out columns. Alternatively,
+if you know the column index, you can test \cs{dtlcol} instead.
+The following code modifies the above example so that it filters
+out the column whose key is \texttt{StudentNo}:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student Scores (Filtering Out a Column)}
+\centering
+\def\colalign{}%
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}%
+\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}%
+\dobegintabular
+\gdef\doamp{\gdef\doamp{&}}%
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}%
+\DTLforeach*{scores}{}{%
+\\\gdef\doamp{\gdef\doamp{&}}%
+\DTLforeachkeyinrow{\thisValue}{%
+ \DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+The result is shown in \autoref{tab:foreachkey3}.
+
+\begin{table}[htbp]
+\caption{Student Scores (Filtering Out a Column)}
+\label{tab:foreachkey3}
+\centering
+\def\colalign{}%
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\DTLifeq{\theKey}{StudentNo}{}{\edef\colalign{\colalign l}}}%
+\edef\dobegintabular{\noexpand\begin{tabular}{\colalign}}\relax
+\dobegintabular
+\gdef\doamp{\gdef\doamp{&}}\relax
+\dtlforeachkey(\theKey,\theCol,\theType,\theHead)\in{scores}\do
+{\DTLifeq{\theKey}{StudentNo}{}{\doamp\bfseries \theHead}}\relax
+\DTLforeach*{scores}{}{%
+\\\gdef\doamp{\gdef\doamp{&}}\relax
+\DTLforeachkeyinrow{\thisValue}{\relax
+\DTLifeq{\dtlkey}{StudentNo}{}{\doamp\thisValue}}}\relax
+\end{tabular}
+\end{table}
+\end{example}
+
+\begin{example}{Nested \cs{DTLforeach}}{ex:nested}
+In this example I have a CSV file called "index.csv" which
+contains:
+\begin{verbatim}
+File,Temperature,NaCl,pH
+exp25a.csv,25,4.7,0.5
+exp25b.csv,25,4.8,1.5
+exp30a.csv,30,5.12,4.5
+\end{verbatim}
+\DTLnewdb{index}\relax
+\DTLnewrow{index}\relax
+\DTLnewdbentry{index}{File}{exp25a.csv}\relax
+\DTLnewdbentry{index}{Temperature}{25}\relax
+\DTLnewdbentry{index}{NaCl}{4.7}\relax
+\DTLnewdbentry{index}{pH}{0.5}\relax
+\DTLnewrow{index}\relax
+\DTLnewdbentry{index}{File}{exp25b.csv}\relax
+\DTLnewdbentry{index}{Temperature}{25}\relax
+\DTLnewdbentry{index}{NaCl}{4.8}\relax
+\DTLnewdbentry{index}{pH}{1.5}\relax
+\DTLnewrow{index}\relax
+\DTLnewdbentry{index}{File}{exp30a.csv}\relax
+\DTLnewdbentry{index}{Temperature}{30}\relax
+\DTLnewdbentry{index}{NaCl}{5.12}\relax
+\DTLnewdbentry{index}{pH}{4.5}\relax
+The first column of this file contains the name of another
+CSV file which has the results of a time to growth experiment
+performed at the given incubation temperature, salt concentration
+and pH. The file "exp25a.csv" contains the following:
+\begin{verbatim}
+Time,Log Count
+0,3.75
+23,3.9
+45,4.0
+\end{verbatim}
+\DTLnewdb{exp25a.csv}\relax
+\DTLnewrow{exp25a.csv}\relax
+\DTLnewdbentry{exp25a.csv}{Time}{0}\relax
+\DTLnewdbentry{exp25a.csv}{Log Count}{3.75}\relax
+\DTLnewrow{exp25a.csv}\relax
+\DTLnewdbentry{exp25a.csv}{Time}{23}\relax
+\DTLnewdbentry{exp25a.csv}{Log Count}{3.9}\relax
+\DTLnewrow{exp25a.csv}\relax
+\DTLnewdbentry{exp25a.csv}{Time}{45}\relax
+\DTLnewdbentry{exp25a.csv}{Log Count}{4.0}\relax
+The file "exp25b.csv" contains the following:
+\begin{verbatim}
+Time,Log Count
+0,3.6
+60,3.8
+120,4.0
+\end{verbatim}
+\DTLnewdb{exp25b.csv}\relax
+\DTLnewrow{exp25b.csv}\relax
+\DTLnewdbentry{exp25b.csv}{Time}{0}\relax
+\DTLnewdbentry{exp25b.csv}{Log Count}{3.6}\relax
+\DTLnewrow{exp25b.csv}\relax
+\DTLnewdbentry{exp25b.csv}{Time}{60}\relax
+\DTLnewdbentry{exp25b.csv}{Log Count}{3.8}\relax
+\DTLnewrow{exp25b.csv}\relax
+\DTLnewdbentry{exp25b.csv}{Time}{120}\relax
+\DTLnewdbentry{exp25b.csv}{Log Count}{4.0}\relax
+The file "exp30a.csv" contains the following:
+\begin{verbatim}
+Time,Log Count
+0,3.73
+23,3.67
+60,4.9
+\end{verbatim}
+\DTLnewdb{exp30a.csv}\relax
+\DTLnewrow{exp30a.csv}\relax
+\DTLnewdbentry{exp30a.csv}{Time}{0}\relax
+\DTLnewdbentry{exp30a.csv}{Log Count}{3.73}\relax
+\DTLnewrow{exp30a.csv}\relax
+\DTLnewdbentry{exp30a.csv}{Time}{23}\relax
+\DTLnewdbentry{exp30a.csv}{Log Count}{3.67}\relax
+\DTLnewrow{exp30a.csv}\relax
+\DTLnewdbentry{exp30a.csv}{Time}{60}\relax
+\DTLnewdbentry{exp30a.csv}{Log Count}{4.9}\relax
+Suppose I now want to iterate through "index.csv", load the given
+file, and create a table for that data. I can do this using
+nested \ics{DTLforeach} as follows:
+\begin{verbatim}
+ % load index data file
+\DTLloaddb{index}{index.csv}
+
+ % iterate through index database
+\DTLforeach{index}{\theFile=File,\theTemp=Temperature,%
+\theNaCl=NaCl,\thepH=pH}{%
+ % load results file into database of the same name
+\DTLloaddb{\theFile}{\theFile}%
+ % Create a table
+\begin{table}[htbp]
+\caption{Temperature = \theTemp, NaCl = \theNaCl,
+pH = \thepH}\label{tab:\theFile}
+\centering
+\begin{tabular}{rl}
+\bfseries Time & \bfseries Log Count
+\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{%
+\\\theTime & \theLogCount}%
+\end{tabular}
+\end{table}
+}
+\end{verbatim}
+This creates \autoref{tab:exp25a.csv} to \autoref{tab:exp30a.csv}.
+(Note that each table is given a label that is based on the
+database name, to ensure that it is unique.)
+
+\DTLforeach{index}{\theFile=File,\theTemp=Temperature,\theNaCl
+=NaCl,\thepH=pH}{
+\begin{table}[htbp]
+\caption[Temperature = \theTemp, NaCl = \theNaCl,
+pH = \thepH\space (illustrating nested
+\cs{DTLforeach})]{Temperature = \theTemp, NaCl = \theNaCl,
+pH = \thepH}\label{tab:\theFile}
+\centering
+\begin{tabular}{rl}
+\bfseries Time & \bfseries Log Count
+\DTLforeach{\theFile}{\theTime=Time,\theLogCount=Log Count}{
+\\\theTime & \theLogCount}%
+\end{tabular}
+\end{table}
+}
+\end{example}
+
+\begin{example}{Dynamically Allocating Field Name}{ex:dyn}
+(This example was suggested by Bill~Hobbs.) Suppose you have a
+directory containing members of multiple clubs. The CSV file
+(say, \texttt{clubs.csv}) may look something like:
+\begin{verbatim}
+First Name,Surname,Rockin,Single
+John,"Smith, Jr",member,
+Jane,Brown,,friend
+Andy,Brown,friend,member
+Z\"oe,Adams,member,member
+Roger,Brady,friend,friend
+Clare,Verdon,member,
+\end{verbatim}
+\DTLnewdb{clubs}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{John}\relax
+\DTLnewdbentry{clubs}{Surname}{Smith, Jr}\relax
+\DTLnewdbentry{clubs}{Rockin}{member}\relax
+\DTLnewdbentry{clubs}{Single}{}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{Jane}\relax
+\DTLnewdbentry{clubs}{Surname}{Brown}\relax
+\DTLnewdbentry{clubs}{Rockin}{}\relax
+\DTLnewdbentry{clubs}{Single}{friend}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{Andy}\relax
+\DTLnewdbentry{clubs}{Surname}{Brown}\relax
+\DTLnewdbentry{clubs}{Rockin}{friend}\relax
+\DTLnewdbentry{clubs}{Single}{member}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{Z\"oe}\relax
+\DTLnewdbentry{clubs}{Surname}{Adams}\relax
+\DTLnewdbentry{clubs}{Rockin}{member}\relax
+\DTLnewdbentry{clubs}{Single}{member}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{Roger}\relax
+\DTLnewdbentry{clubs}{Surname}{Brady}\relax
+\DTLnewdbentry{clubs}{Rockin}{friend}\relax
+\DTLnewdbentry{clubs}{Single}{friend}\relax
+\DTLnewrow{clubs}\relax
+\DTLnewdbentry{clubs}{First Name}{Clare}\relax
+\DTLnewdbentry{clubs}{Surname}{Verdon}\relax
+\DTLnewdbentry{clubs}{Rockin}{member}\relax
+\DTLnewdbentry{clubs}{Single}{}\relax
+(Blank entries indicate that the person is not a member of that
+club.) The data can be loaded as follows:
+\begin{verbatim}
+\DTLloaddb{clubs}{clubs.csv}
+\end{verbatim}
+Suppose at the beginning of your document you have specified
+which club you are interested in ("Rockin" or "Single") and
+store it in \cs{DIdent}:
+\begin{verbatim}
+\newcommand{\DIdent}{Rockin}
+\end{verbatim}
+\newcommand{\DIdent}{Rockin}\relax
+You can now display the members for this particular club as
+follows:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Club Membership}
+\centering
+\begin{tabular}{lll}
+\bfseries First Name & \bfseries Surname & \bfseries Status
+\DTLforeach*[\not\DTLiseq{\status}{}]{clubs}
+{\firstname=First Name,\surname=Surname,\status=\DIdent}{%
+\\\firstname & \surname & \status
+}%
+\end{tabular}
+\end{table}
+\end{verbatim}
+The result is shown in \autoref{tab:dyn}.
+
+\begin{table}[htbp]
+\caption{Club Membership}
+\label{tab:dyn}
+\centering
+\begin{tabular}{lll}
+\bfseries First Name & \bfseries Surname & \bfseries Status
+\DTLforeach*[\not\DTLiseq{\status}{}]{clubs}
+{\firstname=First Name,\surname=Surname,\status=\DIdent}{\relax
+\\\firstname & \surname & \status
+}\relax
+\end{tabular}
+\end{table}
+\end{example}
+
+\section{Null Values}
+\begin{important}
+Note that a null value is not the same as an empty value. Empty
+values can be tested using \sty{etoolbox}'s \ics{ifdefempty} or
+similar.
+\end{important}
+
+If a database is created using \cs{DTLnewdb}, \cs{DTLnewrow}
+and \cs{DTLnewdbentry} (rather than loading it from an ASCII
+file), it is possible for some of the entries to have null values
+when a value is not assigned to a given key for a given row.
+It's also possible for data fetched from a~SQL database using
+\app{datatooltk} to contain null values, and you can use
+the \app{datatooltk} GUI to assign null values, but data loaded using
+\cs{DTLloaddb} (or \cs{DTLloadrawdb}) will have empty not null
+values for any \emph{blank} cells. However, you will get null values when
+loading a CSV file if cells are missing (rather than empty). For
+example:
+\begin{verbatim}
+Column 1,Column 2,Column 3
+Foo,Bar
+Foo,,Baz
+Foo,Bar,Baz
+\end{verbatim}
+This has an empty cell (the second column in \texttt{Foo,,Baz}) and
+a null cell (the third column in \texttt{Foo,Bar}). If the first
+row of data was instead
+\begin{verbatim}
+Foo,Bar,
+\end{verbatim}
+then the third column is now empty, not null.
+
+When you iterate through the database using \cs{DTLforeach}
+(described in \autoref{sec:dbforeach}),
+if an entry is missing for a given row, the associated command given
+in the \meta{values} argument will be set to a null value. This
+value depends on the data type associated with the given key.
+
+\begin{definition}[\DescribeMacro{\DTLstringnull}]%
+\cs{DTLstringnull}
+\end{definition}
+This is the null value for a string.
+
+\begin{definition}[\DescribeMacro{\DTLnumbernull}]%
+\cs{DTLnumbernull}
+\end{definition}
+This is the null value for a number.
+
+\begin{definition}[\DescribeMacro{\DTLifnull}]%
+\cs{DTLifnull}\marg{cmd}\marg{true part}\marg{false part}
+\end{definition}
+This checks if \meta{cmd} is null where \meta{cmd} is a control
+sequence, if it is, then \meta{true part}
+is done, otherwise \meta{false part} is done. This macro is
+illustrated in \autoref{ex:null} below.
+
+\begin{definition}[\DescribeMacro{\DTLifnullorempty}]
+\cs{DTLifnullorempty}\marg{cmd}\marg{true part}\marg{false part}
+\end{definition}
+This checks if \meta{cmd} is null or empty, where \meta{cmd} is a
+control sequence. If it is it does \meta{true part}, otherwise
+\meta{false part}.
+
+\begin{example}{Null vs Empty Values}{ex:null}
+Consider the following (which creates a database called "emailDB"):
+\begin{verbatim}
+\DTLnewdb{emailDB}
+\DTLnewrow{emailDB}
+\DTLnewdbentry{emailDB}{Surname}{Jones}
+\DTLnewdbentry{emailDB}{FirstName}{Mary}
+\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk}
+\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com}
+\DTLnewrow{emailDB}
+\DTLnewdbentry{emailDB}{Surname}{Smith}
+\DTLnewdbentry{emailDB}{FirstName}{Adam}
+\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk}
+\DTLnewdbentry{emailDB}{RegNum}{12345}
+\end{verbatim}
+\DTLnewdb{emailDB}\relax
+\DTLnewrow{emailDB}\relax
+\DTLnewdbentry{emailDB}{Surname}{Jones}\relax
+\DTLnewdbentry{emailDB}{FirstName}{Mary}\relax
+\DTLnewdbentry{emailDB}{Email1}{mj@my.uni.ac.uk}\relax
+\DTLnewdbentry{emailDB}{Email2}{mj@somewhere.com}\relax
+\DTLnewrow{emailDB}\relax
+\DTLnewdbentry{emailDB}{Surname}{Smith}\relax
+\DTLnewdbentry{emailDB}{FirstName}{Adam}\relax
+\DTLnewdbentry{emailDB}{Email1}{as@my.uni.ac.uk}\relax
+\DTLnewdbentry{emailDB}{RegNum}{12345}\relax
+In the above example, the first row of the database contains
+an entry with the key "Email2", but the second row doesn't.
+Whereas the second row contains an entry with the key "RegNum",
+but the first row doesn't. That is, this database has two null (not
+empty) values.
+
+The following code puts the information in a \env{tabular}
+environment:
+\begin{verbatim}
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Num%
+\DTLforeach*{emailDB}{\firstname=FirstName,\surname=Surname,%
+\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+\\\firstname & \surname & \emailI & \emailII & \regnum}%
+\end{tabular}
+\end{verbatim}
+This produces the following:\par\vskip\baselineskip\noindent
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Num\relax
+\DTLforeach*{emailDB}{\firstname=FirstName,\surname
+=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+\\\firstname & \surname & \emailI & \emailII & \regnum}\relax
+\end{tabular}
+\par\vskip\baselineskip
+Note that on the first row of data, the registration number appears as
+0, while on the next row, the second email address appears as
+NULL. The \sty{datatool} package has identified the key "RegNum"
+for this database as a numerical key, since all elements in the
+database with that key are numerical, whereas it has
+identified the key "Email2" as a string, since there is at least
+one element in this database with that key that is a string. Null
+numerical values are set to \cs{DTLnumbernull} (\DTLnumbernull), and
+null strings are set to \cs{DTLstringnull} (\DTLstringnull).
+
+The following code checks each value to determine whether it
+is null using \cs{DTLifnull}. If it is, the text \emph{Missing}
+is inserted, otherwise the value itself is used:
+\begin{verbatim}
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Num%
+\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,%
+\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}%
+\end{tabular}
+\end{verbatim}
+This produces the following:\par\vskip\baselineskip\noindent
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Num\relax
+\DTLforeach{emailDB}{\firstname=FirstName,\surname
+=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}\relax
+\end{tabular}
+\par\vskip\baselineskip\noindent
+If you want to do this, you may find it easier to define a
+convenience command that will display some appropriate text
+if an entry is missing, for example:
+\begin{verbatim}
+\newcommand*{\checkmissing}[1]{\DTLifnull{#1}{---}{#1}}
+\end{verbatim}
+Then instead of typing, say,
+\begin{verbatim}
+\DTLifnull{\regnum}{---}{\regnum}
+\end{verbatim}
+you can instead type:
+\begin{verbatim}
+\checkmissing{\regnum}
+\end{verbatim}
+
+Now suppose that instead of defining the database using \cs{DTLnewdb},
+\cs{DTLnewrow} and \cs{DTLnewdbentry}, you have a file with the
+contents:
+\begin{ttfamily}\setlength{\parindent}{0pt}\par\vskip\baselineskip
+Surname,FirstName,RegNum,Email1,Email2
+
+\DTLforeach{emailDB}{\surname=Surname,\firstname=FirstName,\regNo
+=RegNum,\emailI=Email1,\emailII
+=Email2}{\relax
+\surname,\firstname,\DTLifnull{\regNo}{}{\regNo},\emailI,\DTLifnull{\emailII}{}{\emailII}\par
+}
+\end{ttfamily}\par\vskip\baselineskip\noindent
+and you load the data from this file using \cs{DTLloaddb}
+(defined in \autoref{sec:loaddb}). Now the
+database has \emph{no null values}, but has an \emph{empty} value for the
+key "RegNum" on the first row of the database, and an empty
+value for the key "Email2" on the second row of the database.
+Now, the following code
+\begin{verbatim}
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Number%
+\DTLforeach{emailDB}{\firstname=FirstName,\surname=Surname,%
+\emailI=Email1,\emailII=Email2,\regnum=RegNum}{%
+\\\DTLifnull{\firstname}{\emph{Missing}}{\firstname} &
+\DTLifnull{\surname}{\emph{Missing}}{\surname} &
+\DTLifnull{\emailI}{\emph{Missing}}{\emailI} &
+\DTLifnull{\emailII}{\emph{Missing}}{\emailII} &
+\DTLifnull{\regnum}{\emph{Missing}}{\regnum}}%
+\end{tabular}
+\end{verbatim}
+produces:\par\vskip\baselineskip\noindent
+\begin{tabular}{lllll}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Email 1 &
+\bfseries Email 2 &
+\bfseries Reg Number\relax
+\DTLforeach{emailDB}{\firstname=FirstName,\surname
+=Surname,\emailI=Email1,\emailII=Email2,\regnum=RegNum}{\relax
+\\\firstname & \surname & \emailI & \DTLifnull{\emailII}{}{\emailII} & \DTLifnull{\regnum}{}{\regnum}}\relax
+\end{tabular}
+
+\medskip
+
+Now the missing entries are simply blank instead of containing
+\emph{Missing}. This is because they're empty not null. In this
+case, you may prefer to use \cs{DTLifnullorempty} instead of
+\cs{DTLifnull}.
+\end{example}
+
+\section{Editing Database Rows}
+\label{sec:editdb}
+
+A row can be removed from a data base using:
+\begin{definition}[\DescribeMacro{\DTLremoverow}]%
+\cs{DTLremoverow}\marg{db name}\marg{row index}
+\end{definition}
+where \meta{row index} is the index of the unwanted row. For
+example:
+\begin{verbatim}
+\DTLremoverow{scores}{2}
+\end{verbatim}
+will delete the second row in the database labelled ``scores''.
+There is also a starred version that doesn't check for the
+existence of the database. Remember that the row index refers to the
+internal data not to a reference in the external source if the data
+has been input.
+
+The following commands may be used in the body of the
+\ics{DTLforeach} loop,\footnote{Only the unstarred version of
+\cs{DTLforeach}; the starred version is read-only.}\ to edit the
+current row of the loop. (See also \autoref{sec:currentrow}.)
+
+\begin{definition}[\DescribeMacro{\DTLappendtorow}]%
+\cs{DTLappendtorow}\marg{key}\marg{value}
+\end{definition}
+This appends a new entry with the given \meta{key} and \meta{value}
+to the current row.
+(\meta{value} is expanded.)
+
+\begin{definition}[\DescribeMacro{\DTLreplaceentryforrow}]%
+\cs{DTLreplaceentryforrow}\marg{key}\marg{value}
+\end{definition}
+This replaces the entry for \meta{key} with \meta{value}.
+(\meta{value} is expanded.)
+
+\begin{definition}[\DescribeMacro{\DTLremoveentryfromrow}]%
+\cs{DTLremoveentryfromrow}\marg{key}
+\end{definition}
+This removes the entry for \meta{key} from the current row.
+
+\begin{definition}[\DescribeMacro{\DTLremovecurrentrow}]%
+\cs{DTLremovecurrentrow}
+\end{definition}
+This removes the current row from the database.
+
+\begin{example}{Editing Database Rows}{ex:editdb}
+In this example I have a CSV file called "marks.csv" that contains
+student marks for three assignments:
+\DTLnewdb{marks}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{John}\relax
+\DTLnewdbentry{marks}{Surname}{Smith, Jr}\relax
+\DTLnewdbentry{marks}{StudentNo}{102689}\relax
+\DTLnewdbentry{marks}{Assignment 1}{68}\relax
+\DTLnewdbentry{marks}{Assignment 2}{57}\relax
+\DTLnewdbentry{marks}{Assignment 3}{72}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{Jane}\relax
+\DTLnewdbentry{marks}{Surname}{Brown}\relax
+\DTLnewdbentry{marks}{StudentNo}{102647}\relax
+\DTLnewdbentry{marks}{Assignment 1}{75}\relax
+\DTLnewdbentry{marks}{Assignment 2}{84}\relax
+\DTLnewdbentry{marks}{Assignment 3}{80}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{Andy}\relax
+\DTLnewdbentry{marks}{Surname}{Brown}\relax
+\DTLnewdbentry{marks}{StudentNo}{103569}\relax
+\DTLnewdbentry{marks}{Assignment 1}{42}\relax
+\DTLnewdbentry{marks}{Assignment 2}{52}\relax
+\DTLnewdbentry{marks}{Assignment 3}{54}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{Z\"oe}\relax
+\DTLnewdbentry{marks}{Surname}{Adams}\relax
+\DTLnewdbentry{marks}{StudentNo}{105987}\relax
+\DTLnewdbentry{marks}{Assignment 1}{52}\relax
+\DTLnewdbentry{marks}{Assignment 2}{48}\relax
+\DTLnewdbentry{marks}{Assignment 3}{57}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{Roger}\relax
+\DTLnewdbentry{marks}{Surname}{Brady}\relax
+\DTLnewdbentry{marks}{StudentNo}{106872}\relax
+\DTLnewdbentry{marks}{Assignment 1}{58}\relax
+\DTLnewdbentry{marks}{Assignment 2}{60}\relax
+\DTLnewdbentry{marks}{Assignment 3}{62}\relax
+\DTLnewrow{marks}\relax
+\DTLnewdbentry{marks}{FirstName}{Clare}\relax
+\DTLnewdbentry{marks}{Surname}{Verdon}\relax
+\DTLnewdbentry{marks}{StudentNo}{104356}\relax
+\DTLnewdbentry{marks}{Assignment 1}{45}\relax
+\DTLnewdbentry{marks}{Assignment 2}{50}\relax
+\DTLnewdbentry{marks}{Assignment 3}{48}\relax
+\begin{ttfamily}\setlength{\parindent}{0pt}\par
+Surname,FirstName,StudentNo,Assignment 1,Assignment 2,Assignment 3
+
+\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\regNo
+=StudentNo,\assignI=Assignment 1,\assignII
+=Assignment 2,\assignIII=Assignment 3}{\relax
+\char`\"\surname\char`\",\DTLifstringeq{\firstname}{Zoe}{Z\string\"oe}{\firstname},\regNo,\assignI,\assignII,\assignIII\par
+}
+\end{ttfamily}\par\noindent
+First load this into a database called "marks":
+\begin{verbatim}
+\DTLloaddb{marks}{marks.csv}
+\end{verbatim}
+Suppose now I want to compute the average mark for each
+student, and append this to the database. I can do this as
+follows:
+\begin{verbatim}
+\DTLforeach{marks}{%
+\assignI=Assignment 1,%
+\assignII=Assignment 2,%
+\assignIII=Assignment 3}{%
+\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+\DTLappendtorow{Average}{\theMean}}
+\end{verbatim}
+\DTLforeach{marks}{\assignI=Assignment 1,\assignII
+=Assignment 2,\assignIII=Assignment 3}{\relax
+\DTLmeanforall{\theMean}{\assignI,\assignII,\assignIII}%
+\DTLappendtorow{Average}{\theMean}}\relax
+For each row in the "marks" database, I now have an extra key
+called "Average" that contains the average mark over all three
+assignments for a given student. I can now put this data into
+a table:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student marks}
+\centering
+\begin{tabular}{llcccc}
+\bfseries Surname & \bfseries First Name &
+\bfseries Assign 1 &
+\bfseries Assign 2 &
+\bfseries Assign 3 &
+\bfseries Average Mark%
+\DTLforeach{marks}%
+{% assign variable
+ \surname=Surname,\firstname=FirstName,%
+ \average=Average,\assignI=Assignment 1,%
+ \assignII=Assignment 2,\assignIII=Assignment 3}%
+{% start new row
+ \\\surname & \firstname & \assignI & \assignII & \assignIII &
+ \DTLround{\average}{\average}{2}% round to 2 dp
+ \DTLclip{\average}{average}%clip unnecessary 0s
+ \average
+}\relax
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:meanmarks}.
+
+Note that if I only wanted the averages for the table and nothing
+else, I could simply have computed the average in each row of the
+table and displayed it without adding the information to the
+database, however I am going to reuse this information in
+\autoref{ex:multibar}, so adding it to the database means that
+I don't need to recompute the mean.
+
+\begin{table}[htbp]
+\caption[Student marks (with averages)]{Student
+marks}\label{tab:meanmarks}
+\centering
+\begin{tabular}{llcccc}
+\bfseries Surname & \bfseries First Name &
+\bfseries Assign 1 &
+\bfseries Assign 2 &
+\bfseries Assign 3 &
+\bfseries Average Mark\relax
+\DTLforeach{marks}{\surname=Surname,\firstname=FirstName,\average
+=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII
+=Assignment 3}{\\\surname
+& \firstname & \assignI & \assignII & \assignIII &
+\DTLround{\average}{\average}{2}\DTLclip{\average}{\average}\average}\relax
+\end{tabular}
+\end{table}
+
+\end{example}
+
+\section{Arithmetical Computations on Database Entries}
+
+The commands used in \autoref{sec:fp} can be used on database
+entries. You can, of course, directly use the commands provided
+by the \sty{fp} package if you know that the values are in the
+correct format (i.e.\ no currency symbols, no number group
+separators and a full stop as the decimal point) but if this is
+not the case, then you should use the commands described in
+\autoref{sec:fp}. If you want to use a command provided by the
+\sty{fp} package, that does not have a wrapper function in
+\sty{datatool}, then you will need to convert the value using
+\ics{DTLconverttodecimal}, and convert it back using either
+\ics{DTLdecimaltolocale} or \ics{DTLdecimaltocurrency}.
+
+\begin{example}{Arithmetical Computations}{ex:mean}
+In this example, I am going to produce a table similar to
+\autoref{tab:scores}, except that I want to add an extra row at the
+end which contains the average score.
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores}\label{tab:mean}
+\centering
+\def\total{0}%
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\firstname & \surname &
+\DTLgadd{\total}{\score}{\total}%
+\score
+}\\
+\multicolumn{2}{l}{\bfseries Average Score} &
+\DTLsavelastrowcount{\n}%
+\DTLdiv{\average}{\total}{\n}%
+\DTLround{\average}{\average}{2}%
+\average
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:mean}.
+\textbf{Notes:}
+\begin{itemize}
+\item I had to use \ics{DTLgadd} rather than \ics{DTLadd} since it
+occurs within a \env{tabular} environment which puts each entry
+in a local scope.
+
+\item I used \ics{DTLsavelastrowcount} to store the number of
+rows produced by \ics{DTLforeach} in the control sequence \cs{n}.
+
+\item I used \ics{DTLround} to round the average score to 2 decimal
+places.
+\end{itemize}
+
+\begin{table}[htbp]
+\caption[Student scores (using arithmetic computations)]{Student
+scores}\label{tab:mean}
+\centering
+\def\total{0}\relax
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\firstname & \surname &
+\DTLgadd{\total}{\score}{\total}\relax
+\score
+}\\
+\multicolumn{2}{l}{\bfseries Average Score} &
+\DTLsavelastrowcount{\n}\relax
+\DTLdiv{\average}{\total}{\n}\relax
+\DTLround{\average}{\average}{2}\relax
+\average
+\end{tabular}
+\end{table}
+\end{example}
+
+\begin{definition}[\DescribeMacro{\DTLsumforkeys}]%
+\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command sums all the entries over all the databases listed in
+the comma separated list of database names \meta{db list} for each
+key in \meta{key list} where the condition given by \meta{condition}
+is true. The second optional argument \meta{assign list} is the same
+as the assignment list used by \ics{DTLforeach}, so that you can use
+the information in \meta{condition}. The result is stored in
+\meta{cmd} which must be a control sequence. For example:
+\begin{verbatim}
+\DTLsumforkeys{scores}{Score}{\total}
+\end{verbatim}
+sets \cs{total} to the sum of all the scores in the database
+called "scores".
+
+\begin{definition}[\DescribeMacro{\DTLsumcolumn}]%
+\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLsumforkeys} that only sums
+the entries in a single column (specified by \meta{key}) for
+a single database (specified by \meta{db}) and doesn't provide any
+filtering. The result is stored in \meta{cmd} which must be
+a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLmeanforkeys}]%
+\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command computes the arithmetic mean of all the entries over
+all the databases listed in \meta{db list} for all keys in \meta{key
+list} where the condition given by \meta{condition} is true. The
+second optional argument \meta{assign list} is the same as the
+assignment list used by \ics{DTLforeach}, so that you can use the
+information in \meta{condition}. The result is stored in \meta{cmd}
+which must be a control sequence. For example:
+\begin{verbatim}
+\DTLmeanforkeys{scores}{Score}{\average}
+\end{verbatim}
+sets \cs{average} to the mean of all the scores in the database
+called "scores".
+
+\begin{definition}[\DescribeMacro{\DTLmeanforcolumn}]%
+\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLmeanforkeys} that only computes
+the mean for a single column (specified by \meta{key}) for
+a single database (specified by \meta{db}) and doesn't provide any
+filtering. The result is stored in \meta{cmd} which must be
+a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLvarianceforkeys}]%
+\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command computes the variance of all the entries over all the
+databases listed in \meta{db list} for all keys in \meta{key list}
+where the condition given by \meta{condition} is true. The second
+optional argument \meta{assign list} is the same as the assignment
+list used by \ics{DTLforeach}, so that you can use the information
+in \meta{condition}. The result is stored in \meta{cmd} which must
+be a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLvarianceforcolumn}]%
+\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLvarianceforkeys} that only
+computes the variance for a single column (specified by \meta{key})
+for a single database (specified by \meta{db}) and doesn't provide
+any filtering. The result is stored in \meta{cmd} which must be a
+control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLsdforkeys}]%
+\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command computes the standard deviation of all the entries over
+all the databases listed in \meta{db list} for all keys in \meta{key
+list} where the condition given by \meta{condition} is true. The
+second optional argument \meta{assign list} is the same as the
+assignment list used by \ics{DTLforeach}, so that you can use the
+information in \meta{condition}. The result is stored in \meta{cmd}
+which must be a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLsdforcolumn}]%
+\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLsdforkeys} that only computes the
+standard deviation for a single column (specified by \meta{key}) for
+a single database (specified by \meta{db}) and doesn't provide any
+filtering. The result is stored in \meta{cmd} which must be a
+control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLminforkeys}]%
+\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command determines the minimum value over all entries for all
+keys in \meta{key list} over all the databases listed in \meta{db
+list} where \meta{condition} is true. The second optional argument
+\meta{assign list} is the same as the assignment list used by
+\ics{DTLforeach}, so that you can use the information in
+\meta{condition}. The result is stored in \meta{cmd}, which must be
+a control sequence. For example
+\begin{verbatim}
+\DTLminforkeys{scores}{Score}{\theMin}
+\end{verbatim}
+sets \cs{theMin} to the minimum score in the database.
+
+\begin{definition}[\DescribeMacro{\DTLminforcolumn}]%
+\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLminforkeys} that only computes
+the minimum for a single column (specified by \meta{key}) for
+a single database (specified by \meta{db}) and doesn't provide any
+filtering. The result is stored in \meta{cmd} which must be
+a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLmaxforkeys}]%
+\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd}
+\end{definition}
+This command determines the maximum value over all entries for all
+keys in \meta{key list} over all the databases listed in \meta{db
+list} where \meta{condition} is true. The second optional argument
+\meta{assign list} is the same as the assignment list used by
+\ics{DTLforeach}, so that you can use the information in
+\meta{condition}. The result is stored in \meta{cmd}, which must be
+a control sequence. For example
+\begin{verbatim}
+\DTLminforkeys{scores}{Score}{\theMax}
+\end{verbatim}
+sets \cs{theMax} to the minimum score in the database.
+
+\begin{definition}[\DescribeMacro{\DTLmaxforcolumn}]%
+\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd}
+\end{definition}
+This is a faster version of \cs{DTLmaxforkeys} that only computes
+the maximum for a single column (specified by \meta{key}) for
+a single database (specified by \meta{db}) and doesn't provide any
+filtering. The result is stored in \meta{cmd} which must be
+a control sequence.
+
+\begin{definition}[\DescribeMacro{\DTLcomputebounds}]%
+\cs{DTLcomputebounds}\marg{db list}\marg{x key}\marg{y key}\marg{minX cmd}\marg{minY cmd}\marg{maxX cmd}\marg{maxY cmd}
+\end{definition}
+Computes the maximum and minimum $x$ and $y$ values over all
+the databases listed in \meta{db list} where the $x$ value
+is given by \meta{x key} and the $y$ value is given by
+\meta{y key}. The results are stored in \meta{minX cmd},
+\meta{minY cmd}, \meta{maxX cmd} and \meta{maxY cmd}.
+
+\begin{example}{Mail Merging}{ex:mailmerging}
+This example uses the database given in \autoref{ex:scores} and
+uses \ics{DTLmeanforkeys} to determine the average score. A letter
+is then created for each student to inform them of their score
+and the class average.
+
+\begin{verbatim}
+\documentclass{letter}
+
+\usepackage{datatool}
+
+\begin{document}
+ % load database
+\DTLloaddb{scores}{studentscores.csv}
+ % compute arithmetic mean for key `Score'
+\DTLmeanforkeys{scores}{Score}{\average}
+ % Round the average to 2 decimal places
+\DTLround{\average}{\average}{2}
+ % Save the highest score in \maxscore
+\DTLmaxforkeys{scores}{Score}{\maxscore}
+
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,%
+\score=Score}{%
+\begin{letter}{}
+\opening{Dear \firstname\ \surname}
+
+\DTLifnumgt{\score}{60}{Congratulations you}{You} achieved a score
+of \score\% which was \DTLifnumgt{\score}{\average}{above}{below}
+the average of \average\%. \DTLifnumeq{\score}{\maxscore}{You
+achieved the highest score}{The top score was \maxscore}.
+
+\closing{Yours Sincerely}
+\end{letter}
+}
+\end{document}
+\end{verbatim}
+
+To determine a person's gender when mail merging, see
+\autoref{sec:person}.
+\end{example}
+
+\section{Sorting a Database}
+\label{sec:sort}
+
+The sort methods described here use \TeX\ to sort, which is very
+inefficient. The comparison handlers use a character code comparison
+rather than locale-sensitive alphabetic ordering. It's more
+efficient to use \app{datatooltk} to import and sort at the same
+time.
+
+\begin{definition}[\DescribeMacro{\dtlsort}]%
+\cs{dtlsort}\oarg{replacement key list}\marg{sort criteria}\marg{db
+name}\marg{handler}
+\end{definition}
+This will sort the database called \meta{db name} according to
+the criteria given by \meta{sort criteria}, which must be a
+comma separated list of keys and optionally "="\meta{order}, where
+\meta{order} is either "ascending" or "descending". If the order
+is omitted, "ascending" is assumed. The database keeps track of
+the data type for a given key, and uses this to determine whether
+an alphabetical or numerical sort is required.
+
+The final argument \meta{handler} is the command used for the
+comparisons and is the same as the \meta{criteria cs} command
+used by \cs{dtlsortlist} and \cs{dtlinsertinto}, described
+in \sectionref{sec:csvlists}. The predefined handlers are:
+\begin{description}
+\item[\ics{dtlcompare}] A case-sensitive comparison.
+\item[\ics{dtlicompare}] A case-insensitive comparison.
+\item[\ics{dtlwordindexcompare}] English word-ordering comparison
+for indexes, as described by the Oxford Style Manual.
+\item[\ics{dtlletterindexcompare}] English letter-ordering
+comparison for indexes.
+\end{description}
+The last two handlers, \cs{dtlwordindexcompare} and
+\cs{dtlletterindexcompare}, assume that inversion commas are
+indicated using one of the following commands:
+\begin{itemize}
+\item To indicate name inversion:
+\begin{definition}[\DescribeMacro\datatoolpersoncomma]
+\cs{datatoolpersoncomma}
+\end{definition}
+Example: \verb|Knuth\datatoolpersoncomma Donald E.|
+
+\item To indicate place inversion:
+\begin{definition}[\DescribeMacro\datatoolplacecomma]
+\cs{datatoolplacecomma}
+\end{definition}
+Example:
+\verb|New York\datatoolplacecomma USA|
+
+\item To indicate subject inversion:
+\begin{definition}[\DescribeMacro\datatoolsubjectcomma]
+\cs{datatoolsubjectcomma}
+\end{definition}
+Example: \verb|New York\datatoolsubjectcomma population|
+\end{itemize}
+In addition, the start of parenthetical material should be indicated
+with
+\begin{definition}[\DescribeMacro\datatoolparenstart]
+\cs{datatoolparenstart}
+\end{definition}
+Example: \verb|High Water\datatoolparenstart play|
+
+Following the guidelines of the Oxford Style Manual, when sorting
+terms that have identical pre-inversion parts, the following
+ordering is applied: people, places, subjects, no inversions and
+parenthetical.
+
+\begin{example}{Sorting a Database---Dealing with
+Inversions}{ex:sortinversion}
+This uses the example given in Chapter~16 of the Oxford Style
+Manual. Suppose I~define my database as follows:
+\begin{verbatim}
+\DTLnewdb{inversiondata}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York, New York}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolsubjectcomma
+population}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolplacecomma
+USA}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolpersoncomma
+Earl of}
+\end{verbatim}
+\DTLnewdb{inversiondata}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York, New York}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolsubjectcomma
+population}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolplacecomma
+USA}
+\DTLnewrow{inversiondata}
+\DTLnewdbentry{inversiondata}{Term}{New York\datatoolpersoncomma
+Earl of}
+
+First of all, display the unsorted data:
+\begin{verbatim}
+\DTLdisplaydb{inversiondata}
+\end{verbatim}
+This produces:
+\begin{display}
+\DTLdisplaydb{inversiondata}
+\end{display}
+
+Now sort the data using the \ics{dtlwordindexcompare} handler:
+\begin{verbatim}
+\dtlsort{Term}{inversiondata}{\dtlwordindexcompare}
+\end{verbatim}
+\dtlsort{Term}{inversiondata}{\dtlwordindexcompare}%
+and display again:
+\begin{verbatim}
+\DTLdisplaydb{inversiondata}
+\end{verbatim}
+which now produces:
+\begin{display}
+\DTLdisplaydb{inversiondata}
+\end{display}
+There are three entries here with pre-inversion text that's simply
+\texttt{New York}. Since each of these three entries has the same
+pre-inversion text, they need to be sorted according to the type of
+inversion: person, place, subject. The fourth entry (New York, New
+York) doesn't have an inversion since the comma is part of the title
+of the named work. It's therefore sorted according to \texttt{New
+York, New York} rather than just \texttt{New York} and so comes
+after all the \texttt{New York} entries.
+\end{example}
+
+If you want to write your own comparison handler, see the documented
+code for details on the syntax of the handler. (You may want to
+consider uploading your handler as a separate package to CTAN if you
+think it will be of general use.)
+
+\label{utf8support}%
+As from version 2.24, the predefined handlers now have limited support for UTF-8
+characters. \emph{This is still experimental.} The support will
+automatically be switched on if the \sty{inputenc} package is loaded
+with the \pkgopt{utf8} option before loading \sty{datatool-base}
+(which is automatically loaded by \sty{datatool}). If \sty{inputenc}
+is loaded after \sty{datatool-base}, you can use the (boolean) \pkgopt{utf8}
+option when you load \sty{datatool-base} to enable it. For example,
+either:
+\begin{verbatim}
+\usepackage[utf8]{inputenc}
+\usepackage{datatool-base}
+\end{verbatim}
+or
+\begin{verbatim}
+\usepackage[utf8]{datatool-base}
+\usepackage[utf8]{inputenc}
+\end{verbatim}
+(As from version 2.28, you can now also pass the \pkgopt{utf8}
+option to \sty{datatool} and \sty{datagidx}.)
+You can also enable this option after \sty{datatool-base} has been loaded
+using
+\begin{definition}[\DescribeMacro\dtlenableUTFviii]
+\cs{dtlenableUTFviii}
+\end{definition}
+or disable it with
+\begin{definition}[\DescribeMacro\dtldisableUTFviii]
+\cs{dtldisableUTFviii}
+\end{definition}
+For example:
+\begin{verbatim}
+\usepackage[utf8]{inputenc}
+\usepackage{datatool}
+\dtldisableUTFviii
+\end{verbatim}
+This option isn't required for \XeLaTeX, which treats each UTF-8
+character as an individual token.
+
+With regular (pdf)\LaTeX\ (as opposed to \XeLaTeX) each UTF-8 character is
+actually treated as two tokens that represent the first and second
+octet of the UTF-8 character. This means that it's not possible for
+\TeX\ to obtain a character code using the usual backtick method, so
+(with this option enabled) if a UTF-8 character is detected, the handlers
+described above will pass both octet tokens to one of the following commands:
+\begin{definition}[\DescribeMacro\dtlsetUTFviiicharcode]
+\cs{dtlsetUTFviiicharcode}\marg{octet tokens}\marg{count}
+\end{definition}
+(for the case-sensitive handler \ics{dltcompare}) and
+\begin{definition}[\DescribeMacro\dtlsetUTFviiilccharcode]
+\cs{dtlsetUTFviiilccharcode}\marg{octet tokens}\marg{count}
+\end{definition}
+(for the case-insensitive handlers).
+
+By default the first simply does:
+\begin{definition}[\DescribeMacro\dtlsetdefaultUTFviiicharcode]
+\cs{dtlsetdefaultUTFviiicharcode}\marg{octet tokens}\marg{count}
+\end{definition}
+and the second does
+\begin{definition}[\DescribeMacro\dtlsetdefaultUTFviiilccharcode]
+\cs{dtlsetdefaultUTFviiilccharcode}\marg{octet tokens}\marg{count}
+\end{definition}
+
+In all the above \meta{octet tokens} are the two octets forming the
+UTF-8 character and \meta{count} is a count register in which to
+store the relevant character code.
+
+The default commands simply set the character code for certain
+common accented Latin characters (such as \'e) to the code for their
+unaccented version (such as e). You can redefine
+\cs{dtlsetUTFviiicharcode} and \cs{dtlsetUTFviiilccharcode} to test
+for additional characters. For example, to add the Norwegian
+characters \ae, \o\ and \aa\ to the end of the Latin alphabet, you
+can do:
+\begin{verbatim}
+\renewcommand*{\dtlsetUTFviiicharcode}[2]{%
+ \ifstrequal{#1}{Æ}%
+ {%
+ #2=91\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ø}%
+ {%
+ #2=92\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ã…}%
+ {%
+ #2=93\relax
+ }%
+ {%
+ \ifstrequal{#1}{æ}%
+ {%
+ #2=123\relax
+ }%
+ {%
+ \ifstrequal{#1}{ø}%
+ {%
+ #2=124\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ã¥}%
+ {%
+ #2=125\relax
+ }%
+ {%
+ \dtlsetdefaultUTFviiicharcode{#1}{#2}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+
+\renewcommand*{\dtlsetUTFviiilccharcode}[2]{%
+ \ifstrequal{#1}{Æ}%
+ {%
+ #2=123\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ø}%
+ {%
+ #2=124\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ã…}%
+ {%
+ #2=125\relax
+ }%
+ {%
+ \ifstrequal{#1}{æ}%
+ {%
+ #2=123\relax
+ }%
+ {%
+ \ifstrequal{#1}{ø}%
+ {%
+ #2=124\relax
+ }%
+ {%
+ \ifstrequal{#1}{Ã¥}%
+ {%
+ #2=125\relax
+ }%
+ {%
+ \dtlsetdefaultUTFviiilccharcode{#1}{#2}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+\end{verbatim}
+
+In the case where a~character is a single token (for example, with
+Latin-1 encoding), the code associated with that character is set
+using
+\begin{definition}[\DescribeMacro\dtlsetcharcode]
+\cs{dtlsetcharcode}\marg{c}\marg{count register}
+\end{definition}
+(for case-sensitive comparison) and
+\begin{definition}[\DescribeMacro\dtlsetlccharcode]
+\cs{dtlsetlccharcode}\marg{c}\marg{count register}
+\end{definition}
+(for case-insensitive comparison), where \meta{c} is the character
+and \meta{count register} is a count register. The default
+definitions are:
+\begin{verbatim}
+\newcommand*{\dtlsetcharcode}[2]{#2=`#1\relax}
+\newcommand*{\dtlsetlccharcode}[2]{#2=\lccode`#1\relax}
+\end{verbatim}
+So, for example, the letter \qt{e} has the code \number`e\ whereas
+(with the Latin-1 encoding) the letter \qt{\'e} has the code 233.
+This means that \qt{\'e} will be sorted after \qt{e}. It may be that
+you want \qt{\'e} to be treated the same as \qt{e} when making the
+comparison. In this case, you need to redefine \cs{dtlsetcharcode}
+and \cs{dtlsetlccharcode}. For example, for the case-sensitive
+comparisons:
+\begin{verbatim}
+\renewcommand*{\dtlsetcharcode}[2]{%
+ \ifstrequal{#1}{É}%
+ {%
+ #2=`E\relax
+ }%
+ {%
+ \ifstrequal{#1}{é}%
+ {%
+ #2=`e\relax
+ }%
+ {%
+ #2=`#1\relax
+ }%
+ }%
+}
+\end{verbatim}
+and for the case-insensitive comparisons:
+\begin{verbatim}
+\renewcommand*{\dtlsetlccharcode}[2]{%
+ \ifboolexpr
+ {%
+ test {\ifstrequal{#1}{é}}
+ or test {\ifstrequal{#1}{É}}
+ }%
+ {%
+ #2=`e\relax
+ }%
+ {%
+ #2=\lccode`#1\relax
+ }%
+}
+\end{verbatim}
+(Extra conditionals will need to be added for other diacritics.
+Alternative conditionals, such as \cs{ifx} or \cs{ifnum}, may be more
+efficient. In the above I've used the \sty{etoolbox} commands for
+clarity.)
+
+There are two shortcut commands for \cs{dtlsort}:
+\begin{definition}[\DescribeMacro{\DTLsort}]%
+\cs{DTLsort}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLsort*}]%
+\cs{DTLsort*}\oarg{replacement key list}\marg{sort criteria}\marg{db name}
+\end{definition}
+these use the \ics{dtlcompare} and \ics{dtlicompare} handlers,
+respectively.
+
+The optional argument \meta{replacement key list} is a list of
+keys to use if the current key given in \meta{sort criteria}
+is null for a given entry. Null keys are unlikely to occur if
+you have loaded the database from an external ASCII file, but
+may occur if the database is created using \cs{DTLnewdb},
+\cs{DTLnewrow} and \cs{DTLnewdbentry}. For example:
+\begin{verbatim}
+\DTLsort[Editor,Organization]{Author}{mydata}
+\end{verbatim}
+will sort according to the "Author" key, but if that key is missing
+for a given row of the database, the "Editor" key will be used,
+and if the "Editor" key is missing, it will use the "Organization"
+key. Note that this is not the same as:
+\begin{verbatim}
+\DTLsort{Author,Editor,Organization}{mydata}
+\end{verbatim}
+which will first compare the "Author" keys, but if the author names
+are the same, it will then compare the "Editor" keys, and if the
+editor names are also the same, it will then compare the
+"Organization" keys.
+
+The unstarred version uses a case sensitive comparison for strings,
+whereas the starred version ignores the case when comparing strings.
+Note that the case sensitive comparison orders uppercase characters
+before lowercase characters, so the letter B is considered to be
+lower than the letter a.
+
+\begin{example}{Sorting a Database}{ex:sort}
+This example uses the database called "scores" defined in
+\autoref{ex:scores}. First, I am going to sort the database
+according to the student scores in descending order (highest to
+lowest) and display the database in a table
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (sorted by score)}
+\centering
+\DTLsort{Score=descending}{scores}%
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:sortscores}.
+
+\begin{table}[htbp]
+\caption{Student scores (sorted by score)}\label{tab:sortscores}
+\centering
+\DTLsort{Score=descending}{scores}\relax
+\begin{tabular}{llr}
+\bfseries First Name &
+\bfseries Surname &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\firstname & \surname & \score}
+\end{tabular}
+\end{table}
+
+Now I am going to sort the database according to
+surname and then first name, and display it in a table. Note that
+since I want to sort in ascending order, I can omit the
+"=ascending" part of the sort criteria. I have also decided to
+reverse the first and second columns, so that the surname is
+in the first column.
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (sorted by name)}
+\centering
+\DTLsort{Surname,FirstName}{scores}%
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:sortname}.
+\begin{table}[htbp]
+\caption{Student scores (sorted by name)}\label{tab:sortname}
+\centering
+\DTLsort{Surname,FirstName}{scores}\relax
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+
+Now suppose I add two new students to the database:
+\begin{verbatim}
+\DTLnewrow{scores}%
+\DTLnewdbentry{scores}{Surname}{van der Mere}%
+\DTLnewdbentry{scores}{FirstName}{Henk}%
+\DTLnewdbentry{scores}{Score}{71}%
+\DTLnewrow{scores}%
+\DTLnewdbentry{scores}{Surname}{de la Mere}%
+\DTLnewdbentry{scores}{FirstName}{Jos}%
+\DTLnewdbentry{scores}{Score}{58}%
+\end{verbatim}
+\DTLnewrow{scores}
+\DTLnewdbentry{scores}{Surname}{van der Mere}\relax
+\DTLnewdbentry{scores}{FirstName}{Henk}\relax
+\DTLnewdbentry{scores}{Score}{71}\relax
+\DTLnewrow{scores}\relax
+\DTLnewdbentry{scores}{Surname}{de la Mere}\relax
+\DTLnewdbentry{scores}{FirstName}{Jos}\relax
+\DTLnewdbentry{scores}{Score}{58}\relax
+and again I try sorting the database, and displaying the contents
+as a table:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (case sensitive sort)}
+\centering
+\DTLsort{Surname,FirstName}{scores}%
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:sortname2}. Notice that the surnames
+aren't correctly ordered. This is because a case-sensitive
+sort was used. Changing \cs{DTLsort} to \cs{DTLsort*} in the
+above code produces \autoref{tab:sortname3}.
+
+\begin{table}[htbp]
+\caption{Student scores (case sensitive sort)}\label{tab:sortname2}
+\centering
+\DTLsort{Surname,FirstName}{scores}\relax
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+
+\begin{table}[htbp]
+\caption{Student scores (case ignored when
+sorting)}\label{tab:sortname3}
+\centering
+\DTLsort*{Surname,FirstName}{scores}\relax
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)\relax
+\DTLforeach{scores}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+
+\end{example}
+
+\begin{example}{Influencing the sort order}{ex:sortswitchargs}
+Consider the data displayed in \autoref{tab:sortname3}, suppose that
+you want the names ``van der Mere'' and ``de la Mere'' sorted
+according to the actual surname ``Mere'' rather than by the ``von
+part''. There are two ways you can do this: firstly, you could store
+the von part in a separate field, and then sort by surname, then von
+part, then first name, or you could define a command called, say,
+\cs{switchargs}, as follows:
+\begin{verbatim}
+\newcommand*{\switchargs}[2]{#2#1}
+\end{verbatim}
+\newcommand*{\switchargs}[2]{#2#1}\relax
+then store the data as:
+\begin{verbatim}
+FirstName,Surname,StudentNo,Score
+John,"Smith, Jr",102689,68
+Jane,Brown,102647,75
+Andy,Brown,103569,42
+Z\"oe,Adams,105987,52
+Roger,Brady,106872,58
+Clare,Verdon,104356,45
+Henk,\switchargs{Mere}{van der },106789,71
+Jos,\switchargs{Mere}{de la },104256,58
+\end{verbatim}
+\DTLnewdb{scores2}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{John}\relax
+\DTLnewdbentry{scores2}{Surname}{Smith, Jr}\relax
+\DTLnewdbentry{scores2}{StudentNo}{102689}\relax
+\DTLnewdbentry{scores2}{Score}{68}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{Jane}\relax
+\DTLnewdbentry{scores2}{Surname}{Brown}\relax
+\DTLnewdbentry{scores2}{StudentNo}{102647}\relax
+\DTLnewdbentry{scores2}{Score}{75}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{Andy}\relax
+\DTLnewdbentry{scores2}{Surname}{Brown}\relax
+\DTLnewdbentry{scores2}{StudentNo}{103569}\relax
+\DTLnewdbentry{scores2}{Score}{42}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{Z\"oe}\relax
+\DTLnewdbentry{scores2}{Score}{52}\relax
+\DTLnewdbentry{scores2}{StudentNo}{105987}\relax
+\DTLnewdbentry{scores2}{Surname}{Adams}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{Roger}\relax
+\DTLnewdbentry{scores2}{Score}{58}\relax
+\DTLnewdbentry{scores2}{StudentNo}{106872}\relax
+\DTLnewdbentry{scores2}{Surname}{Brady}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{FirstName}{Clare}\relax
+\DTLnewdbentry{scores2}{Score}{45}\relax
+\DTLnewdbentry{scores2}{StudentNo}{104356}\relax
+\DTLnewdbentry{scores2}{Surname}{Verdon}\relax
+\DTLnewrow{scores2}
+\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{van der }}\relax
+\DTLnewdbentry{scores2}{FirstName}{Henk}\relax
+\DTLnewdbentry{scores2}{Score}{71}\relax
+\DTLnewrow{scores2}\relax
+\DTLnewdbentry{scores2}{Surname}{\switchargs{Mere}{de la }}\relax
+\DTLnewdbentry{scores2}{FirstName}{Jos}\relax
+\DTLnewdbentry{scores2}{Score}{58}\relax
+Now sort the data, and put it in table (this is the same code
+as in the previous example:
+\begin{verbatim}
+\begin{table}[htbp]
+\caption{Student scores (influencing the sort order)}
+\centering
+\DTLsort*{Surname,FirstName}{scores}%
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)%
+\DTLforeach{scores}{%
+\firstname=FirstName,\surname=Surname,\score=Score}{%
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+\end{verbatim}
+This produces \autoref{tab:influencesort}.
+
+\begin{table}[htbp]
+\caption{Student scores (influencing the sort order)}\label{tab:influencesort}
+\centering
+\DTLsort*{Surname,FirstName}{scores2}\relax
+\begin{tabular}{llr}
+\bfseries Surname &
+\bfseries First Name &
+\bfseries Score (\%)\relax
+\DTLforeach{scores2}{\firstname=FirstName,\surname=Surname,\score=Score}{\relax
+\\
+\surname & \firstname & \score}
+\end{tabular}
+\end{table}
+
+\end{example}
+
+\section{Saving a Database to an External File}
+\label{sec:savedb}
+
+\begin{definition}[\DescribeMacro{\DTLsavedb}]%
+\cs{DTLsavedb}\marg{db name}\marg{filename}
+\end{definition}
+This writes the database called \meta{db name} to a file called
+\meta{filename}. The separator and delimiter characters used
+are as given by \ics{DTLsetseparator} (or \ics{DTLsettabseparator})
+and \ics{DTLsetdelimiter}. For example:
+\begin{verbatim}
+\DTLsettabdelimiter
+\DTLsavedb{scores}{scores.txt}
+\end{verbatim}
+will create a file called "scores.txt" and will save the data in a
+tab separated format. (The delimiters will only be used if a
+given entry contains the separator character.)
+
+\begin{definition}[\DescribeMacro{\DTLsavetexdb}]%
+\cs{DTLsavetexdb}\marg{db name}\marg{filename}
+\end{definition}
+This writes the database called \meta{db name} to a \LaTeX\ file
+called \meta{filename}, where the database is stored as
+a combination of \ics{DTLnewdb}, \ics{DTLnewrow} and
+\ics{DTLnewdbentry} commands. This means that the file is in a
+user-friendly format, but may be so to load, particularly if the
+database is large. If you are more concerned with speed rather than
+readability you can use:
+\begin{definition}[\DescribeMacro{\DTLsaverawdb}]%
+\cs{DTLsaverawdb}\marg{db name}\marg{filename}
+\end{definition}
+This saves the database to \meta{filename} in its internal
+representation, which makes it faster to load. Fragile commands
+cause a~problem for \cs{DTLsaverawdb} so if your database contains
+any use:
+\begin{definition}[\DescribeMacro{\DTLprotectedsaverawdb}]%
+\cs{DTLprotectedsaverawdb}\marg{db name}\marg{filename}
+\end{definition}
+instead. The \app{datatooltk} application
+can read and write this raw format. To load a file in this format
+you can just use \cs{input} or you can use:
+\begin{definition}
+\cs{DTLloaddbtex}\marg{cs}\marg{file}
+\end{definition}
+This checks for the file's existence and assigns the database name to the
+control sequence \meta{cs}.
+
+Databases saved using \cs{DTLsavetexdb}, \cs{DTLsaverawdb} and
+\cs{DTLprotectedsaverawdb} can be loaded using \LaTeX's standard
+\ics{input} command. As from version 2.15, the last line of the
+database file defines
+\begin{definition}[\DescribeMacro{\dtllastloadeddb}]
+\cs{dtllastloadeddb}
+\end{definition}
+to the name of the database, in case it's required.
+
+Databases saved using \cs{DTLsaverawdb} and
+\cs{DTLprotectedsaverawdb} can also be loaded and edited by
+\app{datatooltk} (see page~\pageref{datatooltk}).
+
+\section{Deleting or Clearing a Database}\label{sec:deletedb}
+
+A database can be cleared or deleted when its contents are no
+longer required.
+\begin{definition}[\DescribeMacro{\DTLcleardb}]
+\cs{DTLcleardb}\marg{db name}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgcleardb}]
+\cs{DTLgcleardb}\marg{db name}
+\end{definition}
+Clears the database given by \meta{db name}. The database is emptied
+but remains defined. The second form is required if you want a
+global effect.
+
+\begin{definition}[\DescribeMacro{\DTLdeletedb}]
+\cs{DTLdeletedb}\marg{db name}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLgdeletedb}]
+\cs{DTLgdeletedb}\marg{db name}
+\end{definition}
+Deletes (undefines) the database given by \meta{db name}. The second
+form is required if you want a global effect.
+
+\begin{important}
+Although \cs{DTLdeletedb} and \cs{DTLgdeletedb} undefine the macros
+associated with the database, they don't unassign the registers
+used. (\TeX\ doesn't provide a command that performs the reverse of
+commands such as \cs{newcount}.) If you want to keep making
+temporary databases, it's better to just define a single database
+(called, say, \texttt{temp}) and then just clear it rather than
+delete it and define a new database. For example, if you are
+iterating through a loop and want to have a temporary database
+on each iteration. In that case, define the database before the
+start of the loop and clear it on each iteration. If you are loading
+data from an external file, remember to use \ics{DTLnewdbonloadfalse}
+before \ics{DTLloaddb} (or \ics{DTLloadrawdb}).
+\end{important}
+
+\section{Advanced Database Commands}
+\label{sec:advanced}
+
+This section describes more advanced commands. Further details
+can be found in the documented code (datatool-code.pdf).
+
+\begin{definition}[\DescribeMacro{\DTLgetdatatype}]
+\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key}
+\end{definition}
+Gets the data type for the given key \meta{key} for the database
+given by \meta{db}. The data type is stored in \meta{cs} which
+must be a command name. The type will be one of:
+\begin{itemize}
+\item\DescribeMacro{\DTLunsettype}\cs{DTLunsettype} (not set),
+\item\DescribeMacro{\DTLstringtype}\cs{DTLstringtype} (string),
+\item\DescribeMacro{\DTLinttype}\cs{DTLinttype} (integer),
+\item\DescribeMacro{\DTLrealtype}\cs{DTLrealtype} (real number) or
+\item\DescribeMacro{\DTLcurrencytype}\cs{DTLcurrenttype} (currency).
+\end{itemize}
+
+\begin{definition}[\DescribeMacro{\DTLifdbexists}]
+\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part}
+\end{definition}
+Determines if the database given by \meta{db name} exists.
+
+\begin{definition}[\DescribeMacro{\DTLifhaskey}]
+\cs{DTLifhaskey}\marg{db name}\marg{key}\marg{true part}\marg{false part}
+\end{definition}
+This determines if the database given by \meta{db name} has
+any entries with the key given by \meta{key}. If so, it does
+\meta{true part} otherwise it does \meta{false part}.
+
+Each key has an associated column index. This can be obtained
+using:
+\begin{definition}[\DescribeMacro{\DTLgetcolumnindex}]
+\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key}
+\end{definition}
+where \meta{cs} is a command name, \meta{db} is the database label
+and \meta{key} is the key. The column index is stored in
+\meta{cs}.
+
+You can also do the reverse and find the key associated with a
+given column index:
+\begin{definition}[\DescribeMacro{\DTLgetkeyforcolumn}]
+\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index}
+\end{definition}
+The key is stored in \meta{key cs} (which must be a command name).
+
+There is also a full expandable way of obtaining the column
+index, but note that no check is performed to determine
+if the database exists, or if it contains the given key:
+\begin{definition}[\DescribeMacro{\dtlcolumnindex}]
+\cs{dtlcolumnindex}\marg{db name}\marg{key}
+\end{definition}
+
+\begin{definition}[\DescribeMacro{\DTLgetkeydata}]
+\cs{DTLgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs}
+\end{definition}
+Gets data for given key in database \meta{db}: the column index is
+stored in \meta{col cs} (as \cs{DTLgetcolumnindex}), the type is
+stored in \meta{type cs} (as \cs{DTLgetdatatype}) and the header
+is stored in \meta{header cs}.
+
+\begin{definition}[\DescribeMacro{\DTLgetvalue}]
+\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c}
+\end{definition}
+This gets the value for row given by index \meta{r} and column
+given by \meta{c} for the database \meta{db} and stores it in
+\meta{cs} which must be a command name. If you want to get the
+value by key rather than column index you can use
+\cs{dtlcolumnindex}. For example, the following gets the value
+for row~3 with key \texttt{Surname} from the database
+\texttt{data} and stores in \cs{myval}:
+\begin{verbatim}
+\DTLgetvalue{\myval}{data}{3}{\dtlcolumnindex{data}{Surname}}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLgetlocation}]
+\cs{DTLgetlocation}\marg{row cs}\marg{column cs}\marg{database}%
+\marg{value}
+\end{definition}
+Assigns \meta{row cs} and \meta{column cs} to the indices of the
+first entry in \meta{database} that matches \meta{value}.
+
+\begin{definition}[\DescribeMacro{\DTLgetvalueforkey}]
+\cs{DTLgetvalueforkey}\marg{cmd}\marg{key}\marg{db name}\marg{ref
+ key}\marg{ref value}
+\end{definition}
+This (globally) sets \meta{cmd} (a control sequence) to the
+value of the key specified by \meta{key} in the first row
+of the database called \meta{db name} which contains the key
+\meta{ref key} which has the value \meta{value}.
+
+\begin{definition}[\DescribeMacro{\DTLfetch}]
+\cs{DTLfetch}\marg{db name}\marg{column1 name}\marg{column1
+value}\marg{column2 name}
+\end{definition}
+This fetches and displays the value for \meta{column2 name} in the
+first row where the value of \meta{column1 name} is \meta{column1
+value}. (Note that all arguments are expanded.) So, for example, if
+you have a column labelled ``regnum'' and a column labelled
+``tutor'', then to fetch and display the value of the tutor in the
+row where ``regnum'' is ``12345'' from the database called
+``students'' you can do:
+\begin{verbatim}
+\DTLfetch{students}{regnum}{12345}{tutor}
+\end{verbatim}
+See \autoref{ex:join} on page~\pageref{ex:join}.
+
+\begin{definition}[\DescribeMacro{\DTLassign}]
+\cs{DTLassign}\marg{db name}\marg{row idx}\marg{assign list}
+\end{definition}
+This (globally) assigns the list of commands in \meta{assign list}
+for row \meta{row idx} in database \meta{db name}, where
+\meta{assign list} has the same format as in \ics{DTLforeach}.
+
+\begin{definition}
+\cs{DTLassignfirstmatch}\marg{db name}\marg{col key}\marg{value}\marg{assign list}
+\end{definition}
+This is similar to \cs{DTLassign} except that it applies to the
+first row in the given database where the column identified by the
+label \meta{col key} has the given value. Note that no expansion is
+performed in the match. The value must be an exact match.
+
+\begin{definition}
+\cs{xDTLassignfirstmatch}\marg{db name}\marg{col key}\marg{value}\marg{assign list}
+\end{definition}
+This is like \cs{DTLassignfirstmatch} but performs a~\emph{one-level}
+expansion on \meta{value}.
+
+Two rows can be swapped using:
+\begin{definition}[\DescribeMacro{\DTLswaprows}]%
+\cs{DTLswaprows}\marg{db name}\marg{row1 index}\marg{row2 index}
+\end{definition}
+where \meta{row1 index} and \meta{row2 index} are the indices
+of the rows to be swapped. For example:
+\begin{verbatim}
+\DTLswaprows{scores}{3}{5}
+\end{verbatim}
+will swap the third and fifth rows.
+
+\begin{example}{Two Database Rows Per Tabular Row
+(Column-Wise)}{ex:twoblocks}
+This example adapts \autoref{ex:2rows} so that the list is ordered
+vertically rather than horizontally.
+\begin{verbatim}
+\begin{table}[htbp]
+ \caption{Two database rows per tabular row (column-wise)}
+ \centering
+ % store half number of rows
+ \edef\maxrows{\DTLrowcount{scores}}%
+ \DTLdiv{\halfrowidx}{\maxrows}{2}
+ \begin{tabular}{llcllc}
+ \bfseries First Name &
+ \bfseries Surname &
+ \bfseries Score (\%) &
+ \bfseries First Name &
+ \bfseries Surname &
+ \bfseries Score (\%)%
+ \DTLforeach*[\value{DTLrowi}<\halfrowidx]{scores}%
+ {\firstname=FirstName,\surname=Surname,\score=Score}%
+ {%
+ \\%
+ \firstname & \surname & \score
+ &
+ \edef\currentrowidx{\arabic{DTLrowi}}%
+ \DTLadd{\rowidxII}{\halfrowidx}{\currentrowidx}%
+ \DTLassign{scores}{\rowidxII}%
+ {\firstnameII=FirstName,\surnameII=Surname,\scoreII=Score}%
+ \firstnameII & \surnameII & \scoreII
+ }%
+ \end{tabular}
+\end{table}
+\end{verbatim}
+
+This produces \autoref{tab:twoblocks}.
+
+\begin{table}[htbp]
+ \caption{Two database rows per tabular row (column-wise)}
+ \label{tab:twoblocks}
+ \centering
+ % store half number of rows
+ \edef\maxrows{\DTLrowcount{scores}}%
+ \DTLdiv{\halfrowidx}{\maxrows}{2}
+ \begin{tabular}{llcllc}
+ \bfseries First Name &
+ \bfseries Surname &
+ \bfseries Score (\%) &
+ \bfseries First Name &
+ \bfseries Surname &
+ \bfseries Score (\%)%
+ \DTLforeach*[\value{DTLrowi}<\halfrowidx]{scores}%
+ {\firstname=FirstName,\surname=Surname,\score=Score}%
+ {%
+ \\%
+ \firstname & \surname & \score
+ &
+ \edef\currentrowidx{\arabic{DTLrowi}}%
+ \DTLadd{\rowidxII}{\halfrowidx}{\currentrowidx}%
+ \DTLassign{scores}{\rowidxII}{\firstnameII=FirstName,\surnameII=Surname,\scoreII=Score}%
+ \firstnameII & \surnameII & \scoreII
+ }%
+ \end{tabular}
+\end{table}
+\end{example}
+
+\subsection{Operating on Current Row}
+\label{sec:currentrow}
+
+If you want to select from or edit a particular row in a database without having
+to iterate through the database using \cs{DTLforeach}, you can use
+the commands described in this section. Remember that the row index
+is a reference to the internal data and is unrelated to references
+in the original source (such as line numbers in a CSV file).
+
+\begin{definition}[\DescribeMacro{\DTLgetrowindex}]
+\cs{DTLgetrowindex}\marg{row cs}\marg{db name}\marg{col
+idx}\marg{value}
+\end{definition}
+Gets the row index of the first row in database \meta{db name} where
+the value for column \meta{col idx} matches \meta{value} and stores
+the result in \meta{row cs}, which must be a control sequence.
+An error message is given if not found.
+\begin{definition}[\DescribeMacro{\dtlgetrowindex}]
+\cs{dtlgetrowindex}\marg{row cs}\marg{db name}\marg{col
+idx}\marg{value}
+\end{definition}
+Similar to \cs{DTLgetrowindex} but doesn't produce an error if no match is
+found. You can test the result by using \cs{ifx}\meta{row
+cs}\cs{dtlnovalue}. For example:
+\begin{verbatim}
+\dtlgetrowindex{\myrowidx}{data}{\dtlcolumnindex{data}{Surname}}{Smith}
+\ifx\myrowidx\dtlnovalue
+ Not Found
+\else
+ Found in row \myrowidx.
+\fi
+\end{verbatim}
+
+If you want \meta{value} to be fully expanded before testing
+you can use
+\begin{definition}[\DescribeMacro{\xdtlgetrowindex}]
+\cs{xdtlgetrowindex}\marg{row cs}\marg{db name}\marg{col
+idx}\marg{value}
+\end{definition}
+(The \sty{etoolbox} package provides \cs{expandonce} if you
+only want one level of expansion. See the \sty{etoolbox} manual for
+further details.)
+
+\begin{definition}[\DescribeMacro{\dtlgetrow}]
+\cs{dtlgetrow}\marg{db name}\marg{row idx}
+\end{definition}
+Gets the row with index \meta{row idx} from the database \meta{db
+name}. The required row is stored in the token register
+\begin{definition}[\DescribeMacro{\dtlcurrentrow}]
+\cs{dtlcurrentrow}
+\end{definition}
+the preceding rows are stored in the token register
+\begin{definition}[\DescribeMacro{\dtlbeforerow}]
+\cs{dtlbeforerow}
+\end{definition}
+the following rows are stored in the token register
+\begin{definition}[\DescribeMacro{\dtlafterrow}]
+\cs{dtlafterrow}
+\end{definition}
+the row index, \meta{row idx}, is stored in the register
+\begin{definition}[\DescribeMacro{\dtlrownum}]
+\cs{dtlrownum}
+\end{definition}
+and the database name is stored in the control sequence
+\begin{definition}[\DescribeMacro{\dtldbname}]
+\cs{dtldbname}
+\end{definition}
+\begin{important}
+No check is made in \cs{dtlgetrow} to see
+if the database exists or if the row index is valid. You will probably get a \qt{Missing \{
+inserted} error if you misspell the database name and a \qt{Runaway
+argument} error if you specify a row index that is out of range.
+\end{important}
+
+\begin{definition}[\DescribeMacro{\dtlgetrowforvalue}]
+\cs{dtlgetrowforvalue}\marg{db name}\marg{column index}\marg{value}
+\end{definition}
+Like \cs{dtlgetrow}, but this gets the row where the entry in column
+\meta{column index} matches \meta{value}. This command produces an
+error if no match is found. \textbf{Note that no expansion is
+performed when matching \meta{value}.} If you want \meta{value}
+expanded before comparison, use:
+\begin{definition}[\DescribeMacro{\edtlgetrowforvalue}]
+\cs{edtlgetrowforvalue}\marg{db name}\marg{column index}\marg{value}
+\end{definition}
+
+You can use the commands below to access or edit \cs{dtlcurrentrow}, but
+they won't change the database. Instead, once you've finished
+editing \cs{dtlcurrentrow}, you need to reconstruct the database
+token by recombining \cs{dtlbeforerow}, \cs{dtlcurrentrow} and
+\cs{dtlafterrow} using:
+\begin{definition}[\DescribeMacro{\dtlrecombine}]
+\cs{dtlrecombine}
+\end{definition}
+Alternatively, to recombine omitting the current row:
+\begin{definition}[\DescribeMacro{\dtlrecombineomitcurrent}]
+\cs{dtlrecombineomitcurrent}
+\end{definition}
+(This removes the current row from the database, shifting the row
+indices in \cs{dtlafterrow}.) Note that these recombining commands
+assume that you haven't altered \cs{dtlrownum}, \cs{dtldbname},
+\cs{dtlbeforerow} and \cs{dtlafterrow}.
+
+\begin{important}
+\cs{dtlcurrentrow} stores the row information using \sty{datatool}'s
+internal row syntax, described in the documented code (datatool-code.pdf).
+Don't explicitly modify \cs{dtlcurrentrow} unless you have a good
+understanding of the syntax.
+\end{important}
+
+\begin{definition}[\DescribeMacro{\dtlgetentryfromcurrentrow}]
+\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col idx}
+\end{definition}
+Gets the value from \cs{dtlcurrentrow} for the column given by
+\meta{col idx} (an integer) and stores in \meta{cs}, which must be a
+control sequence.
+
+\begin{definition}[\DescribeMacro{\dtlreplaceentryincurrentrow}]
+\cs{dtlreplaceentryincurrentrow}\marg{new value}\marg{col idx}
+\end{definition}
+Replaces the value in \cs{dtlcurrentrow} for the column given by
+\meta{col idx} (an integer) with \meta{new value}.
+\begin{important}
+The new value doesn't get expanded.
+\end{important}
+
+\begin{definition}[\DescribeMacro{\dtlremoveentryincurrentrow}]
+\cs{dtlremoveentryincurrentrow}\marg{col idx}
+\end{definition}
+Removes the value in \cs{dtlcurrentrow} for the column given by
+\meta{col idx}.
+
+\begin{definition}[\DescribeMacro{\dtlswapentriesincurrentrow}]
+\cs{dtlswapentriesincurrentrow}\marg{col1 idx}\marg{col2 idx}
+\end{definition}
+Swaps entries in columns \meta{col1 idx} and \meta{col2 idx} in
+\cs{dtlcurrentrow} (where \meta{col1 idx} and \meta{col2 idx} are
+the column indices).
+
+\begin{definition}[\DescribeMacro{\dtlappendentrytocurrentrow}]
+\cs{dtlappendentrytocurrentrow}\marg{key}\marg{value}
+\end{definition}
+Appends \meta{value} to the current row for column given by
+\meta{key}. (Produces an error if there is already an entry for that
+column in the current row.)
+
+\begin{definition}[\DescribeMacro{\dtlupdateentryincurrentrow}]
+\cs{dtlupdateentryincurrentrow}\marg{key}\marg{value}
+\end{definition}
+Behaves like \cs{dtlappendentrytocurrentrow} if the current row
+doesn't contain an entry for the column given by \meta{key},
+otherwise behaves like \cs{dtlreplaceentryincurrentrow}.
+
+\begin{example}{Joining Two Databases in a Single Table}{ex:join}
+\DTLnewdb{cmp101}\DTLnewrow{cmp101}\relax
+\DTLnewdbentry{cmp101}{regnum}{12345}\relax
+\DTLnewdbentry{cmp101}{Autumn Marks}{80}\relax
+\DTLnewdbentry{cmp101}{Spring Marks}{85}\relax
+\DTLnewrow{cmp101}\relax
+\DTLnewdbentry{cmp101}{regnum}{12346}\relax
+\DTLnewdbentry{cmp101}{Autumn Marks}{70}\relax
+\DTLnewdbentry{cmp101}{Spring Marks}{90}\relax
+\DTLnewrow{cmp101}\relax
+\DTLnewdbentry{cmp101}{regnum}{12347}\relax
+\DTLnewdbentry{cmp101}{Autumn Marks}{75}\relax
+\DTLnewdbentry{cmp101}{Spring Marks}{60}\relax
+\DTLnewdb{students}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12344}\relax
+\DTLnewdbentry{students}{name}{Mary Brown}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12345}\relax
+\DTLnewdbentry{students}{name}{Joe Bloggs}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12346}\relax
+\DTLnewdbentry{students}{name}{Jane Doe}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12347}\relax
+\DTLnewdbentry{students}{name}{John Smith}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12348}\relax
+\DTLnewdbentry{students}{name}{Alice Jones}\relax
+Suppose a lecturer has a CSV file for a particular course that
+contains student registration numbers and marks for the Autumn and
+Spring semesters. The file is called, say, \texttt{cmp101.csv} and
+contains the following:
+
+\vskip\baselineskip
+\begin{ttfamily}\par
+regnum,Autumn Marks,Spring Marks\par
+\DTLforeach*{cmp101}{\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}
+{\RegNum,\Autumn,\Spring\par}
+\end{ttfamily}
+\vskip\baselineskip\noindent
+
+This only contains the student registration numbers, not their
+names, but suppose there's another CSV file that contains the
+registration numbers and names for all students at the department
+(or university). This file called, say, \texttt{students.csv} may
+look something like:
+
+\vskip\baselineskip
+\begin{ttfamily}\par
+regnum,name\par
+\DTLforeach*{students}{\RegNum=regnum,\Name=name}
+{\RegNum,\Name\par}
+\end{ttfamily}
+\vskip\baselineskip\noindent
+
+Now suppose the lecturer wants a table of all the students on course
+CMP101 listing each student's name and marks. Here's the code:
+\begin{verbatim}
+\DTLloaddb{cmp101}{cmp101.csv}% load course data
+\DTLloaddb{students}{students.csv}% load student data
+
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}
+ \centering
+ \begin{tabular}{lrr}
+ \bfseries Name & \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}%
+ {\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}%
+ {\\\DTLfetch{students}{regnum}{\RegNum}{name} & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+\end{verbatim}
+
+The result is shown in \autoref{tab:join}.
+
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}\label{tab:join}
+ \centering
+ \begin{tabular}{lrr}
+ \bfseries Name & \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}{\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}
+ {\\\DTLfetch{students}{regnum}{\RegNum}{name} & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+
+Let's suppose now that the \texttt{students.csv} file has the first
+name and surname in separate columns rather than single columns. So
+the CSV file looks like:
+\DTLcleardb{students}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12344}\relax
+\DTLnewdbentry{students}{forename}{Mary}\relax
+\DTLnewdbentry{students}{surname}{Brown}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12345}\relax
+\DTLnewdbentry{students}{forename}{Joe}\relax
+\DTLnewdbentry{students}{surname}{Bloggs}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12346}\relax
+\DTLnewdbentry{students}{forename}{Jane}\relax
+\DTLnewdbentry{students}{surname}{Doe}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12347}\relax
+\DTLnewdbentry{students}{forename}{John}\relax
+\DTLnewdbentry{students}{surname}{Smith}\relax
+\DTLnewrow{students}\relax
+\DTLnewdbentry{students}{regnum}{12348}\relax
+\DTLnewdbentry{students}{forename}{Alice}\relax
+\DTLnewdbentry{students}{surname}{Jones}\relax
+
+\vskip\baselineskip
+\begin{ttfamily}\par
+regnum,forename,surname\par
+\DTLforeach*{students}{\RegNum=regnum,\Forename=forename,\Surname=surname}
+{\RegNum,\Forename,\Surname\par}
+\end{ttfamily}
+\vskip\baselineskip\noindent
+
+You may be tempted to replace
+\begin{verbatim}
+\DTLfetch{students}{regnum}{\RegNum}{name}
+\end{verbatim}
+with
+\begin{verbatim}
+\DTLfetch{students}{regnum}{\RegNum}{forename}\space
+\DTLfetch{students}{regnum}{\RegNum}{surname}
+\end{verbatim}
+in the above code, but this is inefficient as it requires two
+searches for the same row. Instead, you can do:
+\begin{verbatim}
+\DTLfetch{students}{regnum}{\RegNum}{forename}\space
+\dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+\Surname
+\end{verbatim}
+This can be done because
+\begin{verbatim}
+\DTLfetch{students}{regnum}{\RegNum}{forename}
+\end{verbatim}
+is equivalent to
+\begin{verbatim}
+\edtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
+\dtlgetentryfromcurrentrow
+ {\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}%
+\dtlcurrentvalue
+\end{verbatim}
+This means that \cs{dtlcurrentrow} has already been set by
+\cs{DTLfetch} so we can just do another
+\cs{dtlgetentryfromcurrentrow} for the surname field.
+The new code for the table is now:
+
+\begin{verbatim}
+\DTLloaddb{cmp101}{cmp101.csv}% load course data
+\DTLloaddb{students}{students.csv}% load student data
+
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}
+ \centering
+ \begin{tabular}{lrr}
+ \bfseries Name & \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}%
+ {\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}%
+ {\\%
+ \DTLfetch{students}{regnum}{\RegNum}{forename}\space
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \Surname
+ & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+\end{verbatim}
+
+The result is shown in \autoref{tab:join2}.
+
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}\label{tab:join2}
+ \centering
+ \begin{tabular}{lrr}
+ \bfseries Name & \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}%
+ {\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}%
+ {\\%
+ \DTLfetch{students}{regnum}{\RegNum}{forename}\space
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \Surname
+ & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+
+\textbf{Caveat:} be careful of scoping issues. Suppose you want the
+first name and surname in separate columns, you may consider doing:
+\begin{verbatim}
+ \DTLfetch{students}{regnum}{\RegNum}{forename}%
+ &
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \Surname
+\end{verbatim}
+(and adding an extra column to the \env{tabular} environment).
+However this will result in undefined values for \cs{Surname} as
+\cs{dtlcurrentrow} is only locally set. After the \verb|&| special
+character \cs{dtlcurrentrow} has lost its value as it's no longer in the same
+scope. You can fix this problem in a~number of ways. Firstly you can
+make \cs{dtlcurrentrow} global after \cs{DTLfetch} via
+\begin{verbatim}
+\global\dtlcurrentrow=\dtlcurrentrow
+\end{verbatim}
+or you could move the column break to just before \cs{Surname} and
+make \cs{Surname} global:
+\begin{verbatim}
+ \DTLfetch{students}{regnum}{\RegNum}{forename}%
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \global\let\Surname\Surname
+ &
+ \Surname
+\end{verbatim}
+There are other possibilities as well, but the first method is
+probably the best, especially if you have multiple columns you want
+to fetch.
+
+Here's the updated code:
+\begin{verbatim}
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}
+ \centering
+ \begin{tabular}{llrr}
+ \bfseries Forename & \bfseries Surname &
+ \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}%
+ {\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}%
+ {\\%
+ \DTLfetch{students}{regnum}{\RegNum}{forename}%
+ \global\dtlcurrentrow=\dtlcurrentrow
+ &
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \Surname
+ & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+\end{verbatim}
+The result is shown in \autoref{tab:join3}.
+
+\begin{table}[htbp]
+ \caption{Student Marks (Joining Databases)}\label{tab:join3}
+ \centering
+ \begin{tabular}{llrr}
+ \bfseries Forename & \bfseries Surname &
+ \bfseries Autumn Marks & \bfseries Spring Marks%
+ \DTLforeach*{cmp101}%
+ {\RegNum=regnum,\Autumn=Autumn Marks,\Spring=Spring Marks}%
+ {\\%
+ \DTLfetch{students}{regnum}{\RegNum}{forename}%
+ \global\dtlcurrentrow=\dtlcurrentrow
+ &
+ \dtlgetentryfromcurrentrow{\Surname}{\dtlcolumnindex{students}{surname}}%
+ \Surname
+ & \Autumn & \Spring}%
+ \end{tabular}
+\end{table}
+\end{example}
+
+\subsection{Advanced Iteration}
+\label{sec:advancediter}
+
+The \ics{DTLforeach} command described in \sectionref{sec:dbforeach}
+has some limitations, especially when trying to iterate through
+large databases. This section describes lower-level user commands
+that may be used for iteration instead of \cs{DTLforeach}.
+
+\begin{definition}[\DescribeMacro{\dtlforeachkey}]%
+\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type
+cs},\meta{header cs})\cs{in}\marg{db}\cs{do}\marg{body}
+\end{definition}
+This iterates through all the keys in the database given by
+\meta{db}. In each iteration, \meta{key cs} is set to the key,
+\meta{col cs} is set to the column index, \meta{type cs} is set to
+the data type (as for \cs{DTLgetdatatype}), \meta{header cs} is set
+to the header for that column, and then \meta{body} is done. Note
+that \meta{key cs}, \meta{col cs}, \meta{type cs} and \meta{header
+cs} must all be control sequences. No check is performed to
+determine if that control sequence already exists, and the control
+sequences are defined globally (since it's likely that
+\cs{dtlforeachkey} may be used within a \env{tabular} environment),
+so you need to make sure you don't override an existing command of
+the same name.
+
+\begin{definition}[\DescribeMacro{\dtlforcolumn}]%
+\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body}
+\end{definition}
+This iterates through the column given by \meta{key} in the
+database given by \meta{db} and applies \meta{body}. In each
+iteration, \meta{cs} (which must be a control sequence) is set to
+the current element in the column and may be used in \meta{body}.
+Alternatively, if you want to identify the column by its index
+rather than its key, use:
+\begin{definition}[\DescribeMacro{\dtlforcolumnidx}]%
+\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col index}\marg{body}
+\end{definition}
+Both \cs{dtlforcolumn} and \cs{dtlforcolumnidx} have a starred
+version that doesn't check for the existence of the given database.
+You may use \ics{dtlbreak} within \meta{body} to break out of the loop
+at the end of the current iteration.
+
+An alternative to \cs{DTLforeach} is to use \TeX's primitive
+\ics{loop} with \ics{DTLgetvalue}, but this may not be faster.
+For example, suppose I have a CSV
+file with a single column (labelled \qt{Word}) with 1000 rows of
+data (where the CSV file is called \texttt{test-data-1000.csv}).
+First, let's use the unstarred version of \cs{DTLforeach}:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000.csv}
+
+\begin{document}
+\DTLforeach{data}{\Word=Word}{\Word.\par}
+\end{document}
+\end{verbatim}
+On my 64bit Linux computer, this document took 4.942s to compile.
+Result from \texttt{time pdflatex test}:
+\begin{verbatim}
+real 0m4.942s
+user 0m4.934s
+sys 0m0.015s
+\end{verbatim}
+Now using the starred version of \cs{DTLforeach}:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000.csv}
+
+\begin{document}
+\DTLforeach*{data}{\Word=Word}{\Word.\par}
+\end{document}
+\end{verbatim}
+This took 2.138s to compile:
+\begin{verbatim}
+real 0m2.138s
+user 0m2.122s
+sys 0m0.020s
+\end{verbatim}
+Now using \TeX's \cs{loop}:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000.csv}
+
+\begin{document}
+
+\newcount\rowctr
+\loop
+ \advance\rowctr by 1\relax
+ \DTLgetvalue{\Word}{data}{\rowctr}{1}%
+ \Word.\par
+\ifnum\rowctr<\DTLrowcount{data}
+\repeat
+
+\end{document}
+\end{verbatim}
+(This takes advantage of the fact that I know I only have one column
+of data, so I only need to reference column~1 in \cs{DTLgetvalue}.)
+This takes 2.638s to compile:
+\begin{verbatim}
+real 0m2.638s
+user 0m2.622s
+sys 0m0.020s
+\end{verbatim}
+which is slightly longer than using \cs{DTLforeach*} (but not nearly
+as long as using the unstarred version). Another possible method is
+to use \cs{dtlgetrow} and \cs{dtlgetentryfromcurrentrow}:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000.csv}
+
+\begin{document}
+
+\newcount\rowctr
+\loop
+ \advance\rowctr by 1\relax
+ \dtlgetrow{data}{\rowctr}%
+ \dtlgetentryfromcurrentrow{\Word}{1}%
+ \Word.\par
+\ifnum\rowctr<\DTLrowcount{data}
+\repeat
+
+\end{document}
+\end{verbatim}
+This took 3.596s to compile:
+\begin{verbatim}
+real 0m3.596s
+user 0m3.582s
+sys 0m0.019s
+\end{verbatim}
+Another possibility is to use \cs{dtlforcolumnidx}, described above:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000.csv}
+
+\begin{document}
+
+\dtlforcolumnidx{\Word}{data}{1}{\Word.\par}
+
+\end{document}
+\end{verbatim}
+This took 2.093s to compile:
+\begin{verbatim}
+real 0m2.093s
+user 0m2.083s
+sys 0m0.013s
+\end{verbatim}
+So if you only want to iterate through one column, this is the
+fastest method, but it's still more efficient to pre-process the
+data using an external script that creates a \texttt{.tex} file that
+can be \cs{input} into the document.
+
+Note that the build time increases with extra columns, \emph{even if
+they're not required in the document}. For example, I created a new
+CSV file called \texttt{test-data-1000-5.csv} that had four extra
+columns (which were actually duplicates of the first column with
+different headers, for simplicity). Just iterating through the first
+column to obtain the same PDF as previously significantly increases
+the time taken. The only modification to the above examples was an
+edit to the \cs{DTLloaddb} line:
+\begin{verbatim}
+\DTLloaddb{data}{test-data-1000-5.csv}
+\end{verbatim}
+The fastest method using \cs{dtlforcolumnidx} took 25.688s:
+\begin{verbatim}
+real 0m25.688s
+user 0m25.712s
+sys 0m0.013s
+\end{verbatim}
+Using \cs{DTLforeach*} took 25.725s:
+\begin{verbatim}
+real 0m25.725s
+user 0m25.744s
+sys 0m0.018s
+\end{verbatim}
+The unstarred version took 35.665s:
+\begin{verbatim}
+real 0m35.665s
+user 0m35.692s
+sys 0m0.022s
+\end{verbatim}
+Using \cs{loop} and \cs{DTLgetvalue} took 27.844s:
+\begin{verbatim}
+real 0m27.844s
+user 0m27.866s
+sys 0m0.019s
+\end{verbatim}
+Using \cs{loop} and \cs{dtlgetrow} took 31.770s:
+\begin{verbatim}
+real 0m31.770s
+user 0m31.785s
+sys 0m0.028s
+\end{verbatim}
+
+On the other hand, if I want to only iterate through, say, the last
+100 rows of the data, it's simpler to use \cs{loop}. For example:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000-5.csv}
+
+\begin{document}
+\newcount\rowctr
+\rowctr=\numexpr\DTLrowcount{data}-100\relax
+\loop
+ \advance\rowctr by 1\relax
+ \DTLgetvalue{\Word}{data}{\rowctr}{1}%
+ \Word.\par
+\ifnum\rowctr<\DTLrowcount{data}
+\repeat
+\end{document}
+\end{verbatim}
+This took 25.124s:
+\begin{verbatim}
+real 0m25.124s
+user 0m25.138s
+sys 0m0.023s
+\end{verbatim}
+The equivalent using \cs{DTLforeach} is:
+\begin{verbatim}
+\batchmode
+\documentclass{article}
+
+\usepackage{datatool}
+
+\DTLloaddb{data}{test-data-1000-5.csv}
+
+\begin{document}
+\newcount\firstidx
+\firstidx=\numexpr\DTLrowcount{data}-100\relax
+\DTLforeach*{data}{\Word=Word}%
+ {\ifnum\DTLcurrentindex>\firstidx\relax\Word.\par\fi}
+\end{document}
+\end{verbatim}
+(Remember that the row count can't be used in the optional argument
+of \cs{DTLforeach} as it's only incremented when the condition is
+true.) This took 26.375s:
+\begin{verbatim}
+real 0m26.375s
+user 0m26.381s
+sys 0m0.029s
+\end{verbatim}
+This takes longer because it's still iterating over every row of the
+database and is applying the condition to each row.
+
+\minisec{Summary}
+\begin{itemize}
+\item If possible, use an external script to pre-process the data so
+that you can simply \cs{input} valid \LaTeX\ code into the document.
+\item If you only want to iterate through one column of the data,
+use \cs{dtlforcolumnidx}.
+\item Remove\footnote{Naturally, make a copy of the original data, if
+necessary.}\ unwanted columns and\slash or rows from the CSV file (and sort, if
+necessary) using the spreadsheet application (or whatever) that was
+used to generate the original CSV file.
+\end{itemize}
+
+\chapter{Creating an index, glossary or list of acronyms
+(\texorpdfstring{\sty{datagidx}}{datagidx} package)}
+\label{sec:datagidx}
+
+The \sty{datagidx} package is provided as an alternative to the
+\sty{glossaries} package. Rather than relying on an external
+indexing application, such as \app{xindy} or
+\app{makeindex}, it uses the database mechanism of the
+\sty{datatool} package. \emph{\sty{datagidx} and \sty{glossaries}
+are not compatible.} (Note: \sty{glossaries} version 4.04 now has an
+option that uses \TeX\ to sort the glossaries instead of using
+\app{makeindex} or \app{xindy}.)
+
+First a repeat of the caveat at the start of this manual:
+\begin{important}
+Use the right tool for the right job.
+\end{important}
+Don't expect \sty{datagidx} to perform as efficiently as an
+application that is designed specifically to sort and collate entries.
+
+If, however, you are happy to exchange efficiency for the
+convenience of not having to invoke an external application in
+between \LaTeX\ runs, read on.
+
+Sections~\ref{sec:newgidx} and~\ref{sec:newterm} describe how to
+create and populate a database that's used to store terms or
+acronyms. By default the database is sorted when it's displayed
+using \ics{printterms} (see section~\ref{sec:printterms}). This is
+where the main inefficiency lies in this package. A~faster
+alternative is to use \app{datatooltk} (see page~\pageref{datatooltk})
+and its \texttt{datagidx} plugin, which will allow you to enter
+terms in a graphical environment and sort the terms. This way, you
+only need to sort the database after you enter a new term and the
+sorting is done by a more efficient language than \TeX. Note that
+this means returning to using an external helper application, but it
+only needs to be used when you add a new term rather than between
+each pair of \LaTeX\ runs.
+
+Once you've edited and sorted the database in \app{datatooltk},
+you can then just load it using:
+\begin{definition}[\DescribeMacro{\loadgidx}]
+\cs{loadgidx}\oarg{options}\marg{filename}\marg{title}
+\end{definition}
+where \meta{filename} is the name of the file saved in
+\app{datatooltk}. The remaining arguments \meta{options} and
+\meta{title} are the same as for \cs{newgidx}, described in
+section~\ref{sec:newgidx}. This command automatically sets the
+default database to the loaded database. You can change the default
+database using \cs{DTLgidxSetDefaultDB}, described in
+section~\ref{sec:newterm}.
+
+Since \cs{loadgidx} is intended for use with presorted databases,
+the \csopt{loadgidx}{sort} key defaults to nothing.
+
+\begin{important}
+If you've opted to use \sty{datagidx} over \sty{glossaries} because
+you don't want to install Perl, then don't bother with
+\app{datatooltk} because, although it's a Java application, it requires
+Perl for the plugins.
+\end{important}
+
+\section{Defining Index/Glossary Databases}
+\label{sec:newgidx}
+
+\begin{important}
+The databases and their associated entries described here can only
+be defined in the preamble. This is because the database must be set
+up before the auxiliary file is read. If you don't want to lose your
+place by constantly returning to the preamble to add a new term
+while you edit your document, consider putting all your definitions
+in a separate file which can be \cs{input} in the preamble.
+You can then switch between files without losing your place
+(provided you are using a decent text editor). Alternatively, use
+\app{datatooltk}'s \texttt{datagidx} plugin as described above.
+\end{important}
+
+First you need to define a customised database that will be used to
+store the entries in your index, glossary or list of acronyms:
+\begin{definition}[\DescribeMacro\newgidx]
+\cs{newgidx}\oarg{options}\marg{label}\marg{title}
+\end{definition}
+This defines a new database with a unique label and a title.
+For example:
+\begin{verbatim}
+\newgidx{index}{Index}
+\end{verbatim}
+I can now identify this database using the label \texttt{index}. The
+title ``Index'' is the default heading when the database is
+displayed using \cs{printterms} (see \autoref{sec:printterms}).
+
+The optional argument \meta{options} should be a key=value list.
+Available options:
+\begin{description}
+\item[\csopt{newgidx}{showgroups}] Boolean option that indicates
+whether or not to insert group headings (and a group separator)
+between index groups, if headings are supported by the given style.
+If no value is supplied, \textsf{true} is assumed.
+
+\item[\csopt{newgidx}{style}] The style to use. The value should
+be the name of the style. Available styles are listed in
+\autoref{sec:indexstyles}.
+
+\item[\csopt{newgidx}{sort}] How to sort the database. See
+\autoref{sec:indexsort} for further details.
+
+\item[\csopt{newgidx}{balance}] This is a boolean option that
+is only applied if \csopt{printterms}{columns} is greater than~1.
+If \textsf{true}, the columns are balanced. If \textsf{false}, the
+columns aren't balanced. If no value is specified, \textsf{true} is
+assumed. If \verb|balance=false| and \verb|columns=2|
+\ics{twocolumn} is used instead of \env{multicols*}.
+
+\item[\csopt{newgidx}{heading}] The heading at the start of the
+index/glossary.
+
+\item[\csopt{newgidx}{postheading}] What to put immediately after
+the heading.
+
+\end{description}
+
+\section{Locations}
+\label{sec:locations}
+
+Each term in an index or glossary database has an associated
+location list. This is initially null. When you display the database
+using \ics{printterms} (see \autoref{sec:printterms}) only those
+entries with a non-null location list or with a ``see''
+cross-reference are displayed. The location by default is the page
+number on which the entry has been used. This may be changed to
+another counter by redefining
+\begin{definition}[\DescribeMacro\DTLgidxCounter]
+\cs{DTLgidxCounter}
+\end{definition}
+to the name of the required counter. For example:
+\begin{verbatim}
+\renewcommand*{\DTLgidxCounter}{section}
+\end{verbatim}
+The \styfmt{datagidx} package knows about the following counter
+styles: \texttt{arabic}, \texttt{roman}, \texttt{Roman},
+\texttt{alph} and \texttt{Alph}. If your location counter uses a
+different style, you will need to add a new location type. This will
+only work if the counter uses a command that expands to another
+command that takes a number as its argument. For example, suppose I
+want to use small caps Roman numeral page numbering. I need to
+define a command (say \cs{myscroman}) that takes a counter name as
+its argument but expands to another command that takes a number as
+its argument, like this:
+\begin{verbatim}
+\newcommand*{\myscroman}[1]{\myscrromannum{\value{#1}}}
+\newcommand*{\myscromannum}[1]{\textsc{\romannumeral#1}}
+\end{verbatim}
+Note that the font changing command \cs{textsc} is in the definition
+of \cs{myscromannum} not in the definition of \cs{myscroman}.
+The page counter can now be changed so that it uses \cs{myscroman}:
+\begin{verbatim}
+\renewcommand*{\thepage}{\myscroman{page}}
+\end{verbatim}
+I now have to indicate that \cs{myscromannum} is a valid location
+type using:
+\begin{definition}[\DescribeMacro\DTLgidxAddLocationType]
+\cs{DTLgidxAddLocationType}\marg{cs name}
+\end{definition}
+where \meta{cs name} is the name of the control sequence without the
+initial backslash. Like this:
+\begin{verbatim}
+\DTLgidxAddLocationType{myscromannum}
+\end{verbatim}
+Note that this is the command that takes a number as its argument
+(\cs{myscromannum}) not the command that takes a counter name as its
+argument (\cs{myscroman}).
+
+As with \app{makeindex} and \app{xindy}, locations may have
+a compositor. The default compositor is a full stop but may be
+changed by redefining
+\begin{definition}[\DescribeMacro\DTLgidxSetCompositor]
+\cs{DTLgidxSetCompositor}
+\end{definition}
+Alternatively, you can use the package option \pkgopt{compositor}.
+
+\section{Defining Terms}
+\label{sec:newterm}
+
+Once you have defined the database, you can now define terms
+associated with that database using
+\begin{definition}[\DescribeMacro\newterm]
+\cs{newterm}\oarg{options}\marg{name}
+\end{definition}
+where \meta{name} is the term and \meta{options} is a
+comma-separated list of \meta{key}=\meta{value} options. The
+following keys are available:
+\begin{description}
+\item[\csopt{newterm}{database}] Identifies the database in which to
+store this term. For example:
+\begin{verbatim}
+\newterm[database=index]{reptile}
+\end{verbatim}
+It can be somewhat cumbersome having to keep typing the database for
+each new term. Instead you can identify the default database using
+\begin{definition}[\DescribeMacro\DTLgidxSetDefaultDB]
+\cs{DTLgidxSetDefaultDB}\marg{label}
+\end{definition}
+\textbf{Note:} the argument \meta{label} is not expanded.
+
+Example:
+\begin{verbatim}
+ % define two indexes:
+ \newgidx{index}{Index}
+ \newgidx{people}{People}
+ % Set "index" as the default database:
+ \DTLgidxSetDefaultDB{index}
+ % This batch of terms will be added to database "index":
+ \newterm{reptile}
+ \newterm{mammal}
+ \newterm{insect}
+ % Set "people" as the default database:
+ \DTLgidxSetDefaultDB{people}
+ % This batch of terms will be added to database "people":
+ \newterm{Bob}
+ \newterm{Mary}
+ \newterm{Jane}
+\end{verbatim}
+
+\item[\csopt{newterm}{label}] A unique identifying label. This
+should not contain any active characters. If omitted, the label is
+extracted from \meta{name} (see below).
+
+\item[\csopt{newterm}{sort}] The sort key. If omitted, this is
+extracted from \meta{name} (see below).
+
+\item[\csopt{newterm}{parent}] The parent entry, if this is a
+sub-term. An entry may only have one parent. If you want the same
+term to appear under two different parents, you'll have to define
+two separate terms with the same name but different parents (and
+different labels). This is the only way to avoid ambiguity with the
+hyperlinks (if enabled).
+
+\item[\csopt{newterm}{text}] How the entry should appear in the
+document text. This is \meta{name} by default. If this option is
+used, \meta{name} indicates how the entry should appear in the
+index, glossary or list of acronyms.
+
+\item[\csopt{newterm}{description}] An optional description. This is
+usually not required for an index but needed for a glossary.
+
+\item[\csopt{newterm}{plural}] The plural form of the term. If
+omitted this is formed by appending ``s'' to \meta{name} (or the
+value of the \csopt{newterm}{text} key if supplied).
+
+\item[\csopt{newterm}{symbol}] An associated symbol if required.
+
+\item[\csopt{newterm}{short}] An associated short form if required.
+(Default \meta{name}.)
+
+\item[\csopt{newterm}{long}] An associated long form if required.
+(Default \meta{name}.)
+
+\item[\csopt{newterm}{shortplural}] An associated short plural if
+required. (Default formed by appending ``s'' to the value of the
+\csopt{newterm}{short} key.)
+
+\item[\csopt{newterm}{longplural}] An associated long plural if
+required. (Default formed by appending ``s'' to the value of the
+\csopt{newterm}{long} key.)
+
+\item[\csopt{newterm}{see}] A cross-reference to a synonym. The
+value should be the label of another entry. This entry will not have
+a location list, just the reference to the other term.
+
+\item[\csopt{newterm}{seealso}] A cross-reference to a closely
+related term. This entry should have both a location list and a
+reference to the other term.
+
+\end{description}
+
+If the \csopt{label} or \csopt{sort} key are omitted, \sty{datagidx}
+tries to form sensible defaults. At the moment, this involves
+stripping certain commands (\ics{MakeUppercase},
+\ics{MakeLowercase},
+\ics{MakeTextUppercase}, \ics{MakeTextLowercase}, \ics{acronymfont},
+\ics{textsc}, \ics{textbf}, \ics{textmd}, \ics{textit},
+\ics{textsl}, \ics{textrm}, \ics{texttt}, \ics{textsf}, \ics{emph},
+\ics{ensuremath} and \ics{textsuperscript}), stripping accents
+and replacing certain control characters or control sequences
+(\verb|~| is replace with a space and \verb|\&| is replaced with
+\ics{andname} (if defined) or ``and'' (if \cs{andname} isn't
+defined)). The Greek letter commands (\ics{alpha} etc) are converted
+to their name.
+
+Examples:
+\begin{enumerate}
+\item \ics{ensuremath} is stripped and \ics{alpha} is converted to
+``alpha'' so the following:
+\begin{verbatim}
+\newterm{\ensuremath{\alpha}}
+\end{verbatim}
+sets both the label and sort to \texttt{alpha} but the name and text
+fields are set to \verb|\ensuremath{\alpha}|.
+
+\item Accent commands are stripped so the following:
+\begin{verbatim}
+\newterm{mac\'edoine}
+\end{verbatim}
+sets both the label and sort fields to \texttt{macedoine} but the
+name and text fields are set to \verb|mac\'edoine|.
+
+\begin{important}
+The first letter must be grouped if it's an accent or ligature or a
+character outside the range \texttt{a}\ldots\texttt{z} or
+\texttt{A}\ldots\texttt{Z}.
+\end{important}
+
+\item This example must have the sort and label fields set manually
+because the first letter has an accent:
+\begin{verbatim}
+\newterm[label=elite,sort=elite]{{\'e}lite}
+\end{verbatim}
+
+\item The same applies if you are using the \sty{inputenc} package:
+\begin{verbatim}
+\newterm[label=elite,sort=elite]{{é}lite}
+\end{verbatim}
+
+\item The same applies to plural terms set explicitly:
+\begin{verbatim}
+\newterm
+ [%
+ plural={{Å“}sophagi},%
+ label={oesophagus},%
+ sort={oesophagus}%
+ ]
+ {{Å“}sophagus}
+\end{verbatim}
+
+\item Commands such as \ics{oe} aren't dealt with, so you must
+manually set the label and sort key:
+\begin{verbatim}
+\newterm[label=manoeuvre,sort=manoeuvre]{man\oe uvre}
+\end{verbatim}
+
+\item The same applies if you are using the \sty{inputenc} package:
+\begin{verbatim}
+\newterm[label=manoeuvre,sort=manoeuvre]{manœuvre}
+\end{verbatim}
+
+\begin{important}
+Take care if any of the values to fields contain a comma or equal
+sign. The value must be grouped.
+\end{important}
+
+\item This term contains a comma in some of the fields:
+\begin{verbatim}
+\newterm
+ [%
+ label={comma},%
+ sort={,},%
+ text={comma (,)}%
+ plural={commas (,)}%
+ ]
+ {, (comma)}
+\end{verbatim}
+In the text, the entry is \texttt{comma (,)} but in the index the
+entry is sorted according to the comma symbol and is displayed as
+\texttt{, (comma)}.
+
+\end{enumerate}
+
+\subsection{Commands to Assist Sorting}
+
+There are some situations where you will have to specify the sort
+key, for example:
+\begin{verbatim}
+\newterm
+[
+ sort={Ten Downing Street}
+]
+{10 Downing Street}
+\end{verbatim}
+
+However, there are some commands provided to help set the default
+sort for entries that are sorted differently from the way they are
+typeset in the index/glossary, which can help reduce the number of times you
+need to explicitly set the sort field.
+
+\begin{definition}[\DescribeMacro\DTLgidxParen]
+\cs{DTLgidxParen}\marg{text}
+\end{definition}
+This command is provided for parenthetical material that should be
+typeset in the index, but should not contribute to the sort unless
+there is an identical entry without parenthetical material.
+
+For example:
+\begin{verbatim}
+\newterm{0\DTLgidxParen{zero}}
+\end{verbatim}
+This term is typeset as \texttt{0 (zero)}, but has the sort and
+label fields set to \texttt{0}.
+
+The default sort used is word-order sorting. This has a special
+number group for entries where the sort field consists solely of
+digits and they are sorted numerically rather than by string
+comparison. Using \cs{DTLgidxParen} in this manner, the following
+terms will appear in numerical order in the index:
+\begin{verbatim}
+\newterm{0\DTLgidxParen{zero}}
+\newterm{1\DTLgidxParen{one}}
+\newterm{2\DTLgidxParen{two}}
+\newterm{3\DTLgidxParen{three}}
+\newterm{10\DTLgidxParen{ten}}
+\newterm{100\DTLgidxParen{one hundred}}
+\newterm{20\DTLgidxParen{twenty}}
+\end{verbatim}
+If \cs{DTLgidxParen} was not used and the parentheses were
+explicitly included, e.g.\ \texttt{0 (zero)}, then the entries would
+be placed in the symbol group instead and be sorted according to
+string (so \texttt{10 (ten)} would come before \texttt{2 (two)}).
+
+\begin{definition}[\DescribeMacro\DTLgidxPlace]
+\cs{DTLgidxPlace}\marg{country/county}\marg{city/town}
+\end{definition}
+Use this command to indicate a place. For example:
+\begin{verbatim}
+\newterm{\DTLgidxPlace{USA}{New York}}
+\end{verbatim}
+This sets the label and name to \texttt{New York, USA}, the text
+field is set to just \texttt{New York} and the sort field is set to
+\verb|New York\datatoolplacecomma USA| (see \autoref{sec:sort}).
+
+\begin{definition}[\DescribeMacro\DTLgidxSubject]
+\cs{DTLgidxSubject}\marg{subject}\marg{text}
+\end{definition}
+Use this to indicate a subject, concept or object. Example:
+\begin{verbatim}
+\newterm{\DTLgidxSubject{population}{New York}}
+\end{verbatim}
+Both the label and name fields default to \texttt{New York,
+population}, the text field defaults to \texttt{population} and the
+sort field is set to \verb|New York\datatoolsubjectcomma population|
+(see \autoref{sec:sort}).
+
+\begin{definition}[\DescribeMacro\DTLgidxName]
+\cs{DTLgidxName}\marg{forename(s)}\marg{surname}
+\end{definition}
+Use this command to index a person. The entry will be sorted
+according to the surname then the forenames. The entry will be
+displayed as \meta{surname}, \meta{forename(s)} in the index but
+will be displayed as \meta{forename(s)} \meta{surname} when
+referenced in the document. The label, on the other hand, is set to
+just the surname. Example:
+\begin{verbatim}
+\newterm{\DTLgidxName{Donald E.}{Knuth}}
+\end{verbatim}
+This sets the name field to \texttt{Knuth, Donald E.}, the text
+field to \texttt{Donald E. Knuth}, the label to \texttt{Knuth} and the sort field to
+\texttt{Knuth\ics{datatoolpersoncomma} Donald E.} (see
+\autoref{sec:sort}).
+
+A person's title (such as ``Dr'') should typically not affect the
+sort, unless there is another person with the same surname and
+forenames (or initials) without a title. To assist this, you can
+identify a person's title using:
+\begin{definition}[\DescribeMacro\DTLgidxRank]
+\cs{DTLgidxRank}\marg{title}\marg{forename(s)/initial(s)}
+\end{definition}
+Using examples from the Oxford Style Manual:
+\begin{verbatim}
+\newterm[label=AliceMeynell]{\DTLgidxName{Meynell}{Alice}}
+\newterm[label=DrMeynell]{\DTLgidxName{Meynell}{\DTLgidxRank{Dr}{A.}}}
+\newterm[label=AMeynell]{\DTLgidxName{Meynell}{A.}}
+\end{verbatim}
+Here the labels must be set as the surnames are identical for each
+entry, but the entries will be sorted in the order: ``Meynell, A.'',
+``Meynell, Dr~A.'' and ``Meynell, Alice''.
+
+You can use
+\begin{definition}[\DescribeMacro\DTLgidxNameNum]
+\cs{DTLgidxNameNum}\marg{number}
+\end{definition}
+to indicate a number associated with a name. The number is typeset
+as an uppercase Roman numeral in the text, but is sorted
+numerically.
+
+For example:
+\begin{verbatim}
+\newterm{James~\DTLgidxNameNum{1}}
+\end{verbatim}
+This is typeset as \verb|James~I|, but gets the label
+\texttt{James I} (note no tilde) and the sort field is set to
+\texttt{James 01}. This means that if I want to index all the Kings
+whose name is James, they will appear in the correct order in the
+index.
+
+If a term contains a variant of ``Mac'' you can also use:
+\begin{definition}[\DescribeMacro\DTLgidxMac]
+\cs{DTLgidxMac}\marg{text}
+\end{definition}
+The entry will be typeset with \meta{text} but the sort key will
+have \meta{text} replaced with \texttt{Mac}. Examples:
+\begin{verbatim}
+\newterm{\DTLgidxName{Joe}{\DTLgidxMac{Mc}Cullers}}
+\newterm{\DTLgidxName{Bob}{\DTLgidxMac{M'}Fingal}}
+\newterm{\DTLgidxMac{Mc}Carthyism}
+\newterm{\DTLgidxMac{Mc}Guffin}
+\end{verbatim}
+
+Similarly saints can be identified using:
+\begin{definition}[\DescribeMacro\DTLgidxSaint]
+\cs{DTLgidxSaint}\marg{text}
+\end{definition}
+Examples:
+\begin{verbatim}
+\newterm{\DTLgidxSaint{St} Julian}
+\newterm{\DTLgidxName{Q.}{\DTLgidxSaint{St}~John-Smythe}}
+\newterm{\DTLgidxPlace{\DTLgidxSaint{St}~Andrews}{Fife}}
+\end{verbatim}
+These will be sorted according to \texttt{Saint Julian},
+\verb|Saint John-Smythe\datatoolpersoncomma Q.| and
+\verb|Saint Andrews\datatoolplacecomma Fife|.
+
+Particles, such as ``de'', ``von'' or ``of'' are usually ignored
+when sorting. These can be identified using:
+\begin{definition}[\DescribeMacro\DTLgidxParticle]
+\cs{DTLgidxParticle}\marg{text}
+\end{definition}
+Examples:
+\begin{verbatim}
+\newterm{\DTLgidxName{Fred}{\DTLgidxParticle{de}{Winter}}}
+\newterm{\DTLgidxName{Gustav}{\DTLgidxParticle{von}{Aschenbach}}}
+\end{verbatim}
+Here the names are sorted according to
+\verb|Winter\datatoolpersoncomma Fred| and
+\verb|Aschenbach\datatoolpersoncomma Gustav| but the labels are set
+to \texttt{deWinter} and \texttt{vonAschenbach}.
+
+A person can also be indicated by their office, for example ``Henry,
+scribe of Bury St~Edmunds''. For this, you can use:
+\begin{definition}[\DescribeMacro\DTLgidxOffice]
+\cs{DTLgidxOffice}\marg{office}\marg{name}
+\end{definition}
+Here the label defaults to just \meta{name}, so you may need to set
+the label manually to ensure uniqueness. Examples:
+\begin{verbatim}
+\newterm
+[
+ label={HenrySonJohn}
+]
+{\DTLgidxOffice{son \DTLgidxParticle{of}{John}}{Henry}}
+
+\newterm
+[
+ label={HenryBeaumont}
+]
+{\DTLgidxOffice{bishop \DTLgidxParticle{of}{Bayeux}}{Henry
+\DTLgidxParticle{de}{Beaumont}}}
+
+\newterm
+[
+ label={HenryScribe}
+]
+{\DTLgidxOffice{scribe \DTLgidxParticle{of}{Bury}
+ \DTLgidxSaint{St}~Edmunds}{Henry}}
+
+
+\end{verbatim}
+
+You can hook into the mechanism that sets the default sort key by
+adding to the definition of
+\begin{definition}[\DescribeMacro\newtermlabelhook]
+\cs{newtermlabelhook}
+\end{definition}
+You can use \sty{etoolbox}'s \ics{appto} command to append to this
+hook. For example, suppose you want to index the terms \verb|\TeX|,
+\verb|e\TeX| and \verb|pdf\TeX|, but you want the terms to have the
+label and sort fields to be just \verb|TeX|, \verb|eTeX| and
+\verb|pdfTeX|, then you can add to the hook so that it automatically
+converts \ics{TeX} to just \texttt{TeX}:
+\begin{verbatim}
+\appto\newtermlabelhook{\def\TeX{TeX}}
+\end{verbatim}
+(Note that it's important to use the local \ics{def} rather than the
+global \ics{gdef} to ensure the redefinition is localised.)
+
+Now the terms can simply be defined using:
+\begin{verbatim}
+\newterm{\TeX}
+\newterm{e\TeX}
+\newterm{pdf\TeX}
+\end{verbatim}
+
+To assist in using this mechanism, the following commands are
+available (these commands may also be used in the mandatory argument
+of \cs{newterm}):
+\begin{definition}[\DescribeMacro\DTLgidxNoFormat]
+\cs{DTLgidxNoFormat}\marg{text}
+\end{definition}
+This commands simply does its argument, so any commands that should
+be stripped from the label or sort field without the loss of their
+argument can be \ics{let} to \cs{DTLgidxNoFormat}. For example,
+suppose you want to define a command called, say, \cs{appname} that
+you want to use to identify application names, like this:
+\begin{verbatim}
+\newcommand*{\app}[1]{\texttt{#1}}
+\end{verbatim}
+This command needs to be stripped from the label and sort, so it can
+be added to the hook like this:
+\begin{verbatim}
+\appto\newtermlabelhook{\let\app\DTLgidxNoFormat}
+\end{verbatim}
+Now you can define terms like this:
+\begin{verbatim}
+\newterm{\app{makeindex}}
+\newterm{\app{xindy}}
+\end{verbatim}
+The label and sort keys are then set to \texttt{makeindex} (for the
+first term) and \texttt{xindy} (for the second term).
+
+\begin{definition}[\DescribeMacro\DTLgidxGobble]
+\cs{DTLgidxGobble}\marg{text}
+\end{definition}
+This command discards its argument, so it can be used if you not
+only want to strip a command but also its argument from the label
+and sort fields.
+
+For example, suppose you want some terms to have a footnote (both in the
+index/glossary and in the document text) but the footnote shouldn't
+form part of the sort or label fields. You can add to the hook like
+this:
+\begin{verbatim}
+\appto\newtermlabelhook{\let\footnote\DTLgidxGobble}
+\end{verbatim}
+Now you can define some terms with footnotes:
+\begin{verbatim}
+\newterm{foo\footnote{a note about foo}}
+\newterm{bar\footnote{a note about bar}}
+\end{verbatim}
+The label and sort keys are then set to \texttt{foo} (for the first
+term) and \texttt{bar} (for the second term).
+
+\begin{definition}[\DescribeMacro\DTLgidxIgnore]
+\cs{DTLgidxIgnore}
+\end{definition}
+This is similar to \cs{DTLgidxGobble} but only affects the sort key
+not the label. Example:
+\begin{verbatim}
+\newterm{de\DTLgidxIgnore{-}escalate}
+\end{verbatim}
+This is displayed as \texttt{de-escalate} and gets the label
+\texttt{de-escalate} but is sorted according to \texttt{deescalate}.
+
+\begin{definition}[\DescribeMacro\DTLgidxStripBackslash]
+\cs{DTLgidxStripBackslash}\marg{control sequence}
+\end{definition}
+This can be used to ``stringify'' a control sequence and remove the
+leading backslash. For example, suppose you want to index the
+ampersand symbol (\&) but you want to sort it according to the
+actual symbol \verb|&|, you can do:
+\begin{verbatim}
+\newterm
+ [%
+ label={amp},
+ sort={\DTLgidxStripBackslash{\&}},
+ text={ampersand (\&)},
+ plural={ampersands (\&)},
+ ]
+ {\& (ampersand)}
+\end{verbatim}
+
+\section{Referencing Terms}
+\label{sec:useentry}
+
+You can reference terms using
+\begin{definition}[\DescribeMacro\useentry]
+\cs{useentry}\marg{label}\marg{field}
+\end{definition}
+This fetches the given field for the term identified by
+\meta{label}, displays it and marks the term as having been used.
+Example, suppose I have previous (in the preamble) defined the term
+``reptile'' using:
+\begin{verbatim}
+\newterm{reptile}
+\end{verbatim}
+I can now reference this term in the document:
+\begin{verbatim}
+\useentry{reptile}{Text}
+\end{verbatim}
+or if I want the plural, I can use:
+\begin{verbatim}
+\useentry{reptile}{Plural}
+\end{verbatim}
+There are also uppercase versions:
+\begin{definition}[\DescribeMacro\Useentry]
+\cs{Useentry}\marg{label}\marg{field}
+\end{definition}
+This makes the first letter uppercase (using the \sty{mfirstuc}
+package) or to make the whole text uppercase use:
+\begin{definition}[\DescribeMacro\USEentry]
+\cs{USEentry}\marg{label}\marg{field}
+\end{definition}
+
+If you use the \sty{hyperref} package, the above commands will
+automatically create hyperlinks to the relevant entry in the
+index/glossary. You can suppress this action by using one of the
+following analogous commands instead:
+\begin{definition}[\DescribeMacro\useentrynl]
+\cs{useentrynl}\marg{label}\marg{field}
+\end{definition}
+\begin{definition}[\DescribeMacro\Useentrynl]
+\cs{Useentrynl}\marg{label}\marg{field}
+\end{definition}
+\begin{definition}[\DescribeMacro\USEentrynl]
+\cs{USEentrynl}\marg{label}\marg{field}
+\end{definition}
+
+You can also specify your own custom text:
+\begin{definition}[\DescribeMacro\glslink]
+\cs{glslink}\marg{label}\marg{text}
+\end{definition}
+
+In all the above commands, the \meta{label} argument may optionally
+start with \oarg{format}, where format is the name of a control
+name \emph{without} the preceding backslash. This command will be
+applied to this location in the entry's location list when it's
+displayed in the index/glossary.
+
+For example:
+\begin{verbatim}
+\useentry{[textbf]reptile}{Text}
+\end{verbatim}
+Note that the command (\cs{textbf} in the above example) should take
+one argument (the location). If you attempt to use, say, a
+declaration (such as \cs{bfseries}) the effect won't be localised.
+
+You can display the value of a field without indexing it using:
+\begin{definition}[\DescribeMacro\glsdispentry]
+\cs{glsdispentry}\marg{label}\marg{field}
+\end{definition}
+To make the first letter uppercase, use:
+\begin{definition}[\DescribeMacro\Glsdispentry]
+\cs{Glsdispentry}\marg{label}\marg{field}
+\end{definition}
+The above commands aren't expandable. If you want to fetch a value
+without displaying or using it, you can use:
+\begin{definition}[\DescribeMacro\DTLgidxFetchEntry]
+\cs{DTLgidxFetchEntry}\marg{cs}\marg{label}\marg{field}
+\end{definition}
+where \meta{cs} is a control sequence, \meta{label} is the label
+that uniquely identifies the entry and \meta{field} is the required
+field. The value of that field is stored in \meta{cs}.
+
+The predefined database fields are:
+\begin{description}
+\item[Name] How the term appears in the index/glossary (as specified
+by the mandatory argument of \ics{newterm}).
+\item[Text] The value of the \csopt{newterm}{text} field.
+\item[Plural] The value of the \csopt{newterm}{plural} field.
+\item[Description] The value of the \csopt{newterm}{description}
+field.
+\item[Symbol] The value of the \csopt{newterm}{symbol} field.
+\item[Long] The value of the \csopt{newterm}{long} field.
+\item[Short] The value of the \csopt{newterm}{short} field.
+\item[LongPlural] The value of the \csopt{newterm}{longplural}
+field.
+\item[ShortPlural] The value of the \csopt{newterm}{shortplural}
+field.
+\item[See] The value of the \csopt{newterm}{see} field.
+\item[SeeAlso] The value of the \csopt{newterm}{seealso} field.
+\item[Sort] The value of the \csopt{newterm}{sort} field.
+\item[Parent] The value of the \csopt{newterm}{parent} field.
+\item[Label] The entry's unique identifying label.
+\item[Used] Has the value 1 (entry has been used) or either 0 or
+undefined (entry hasn't been used).
+\item[Location] The entry's location list (picked up from the last
+\LaTeX\ run).
+\end{description}
+
+In addition, there are some fields designed for internal use:
+\texttt{Child}, \texttt{FirstId} and \texttt{CurrentLocation}.
+
+You can add an entry to the index/glossary without displaying any
+text using:
+\begin{definition}[\DescribeMacro\glsadd]
+\cs{glsadd}\marg{label}
+\end{definition}
+As with \cs{useentry}, \meta{label} maybe in the form
+\oarg{format}\marg{label} where \meta{format} is the name of a
+control sequence \emph{without} the leading backslash.
+
+You can also add all entries from a particular database using
+\begin{definition}[\DescribeMacro\glsaddall]
+\cs{glsaddall}\marg{db name}
+\end{definition}
+where \meta{db name} is the name of the database.
+
+Unlike the commands of the same name provided by the
+\sty{glossaries} package, here there is a difference between
+\cs{glsaddall} and using \cs{glsadd} on all entries in the database.
+In the case of \cs{glsadd} a location is added to the location list
+for that entry. However in the case of \cs{glsaddall} no location is
+added to each entry's location list, but the location list is set to
+non-null so the entry will appear in the index/glossary.
+
+\subsection{Shortcut Commands}
+
+There are some shortcuts to common fields (if you are used to the
+\sty{glossaries} package, note that these commands have different
+formats to the commands provided by \sty{glossaries} with the same
+name):
+\begin{definition}[\DescribeMacro\gls]
+\cs{gls}\marg{label}
+\end{definition}
+This is equivalent to \cs{useentry}\marg{label}\verb|{Text}|.
+\begin{definition}[\DescribeMacro\glspl]
+\cs{glspl}\marg{label}
+\end{definition}
+This is equivalent to \cs{useentry}\marg{label}\verb|{Plural}|.
+\begin{definition}[\DescribeMacro\glsnl]
+\cs{glsnl}\marg{label}
+\end{definition}
+This is equivalent to \cs{useentrynl}\marg{label}\verb|{Text}|.
+\begin{definition}[\DescribeMacro\glsplnl]
+\cs{glsplnl}\marg{label}
+\end{definition}
+This is equivalent to \cs{useentrynl}\marg{label}\verb|{Plural}|.
+
+\begin{definition}[\DescribeMacro\Gls]
+\cs{Gls}\marg{label}
+\end{definition}
+This is equivalent to \cs{Useentry}\marg{label}\verb|{Text}|.
+\begin{definition}[\DescribeMacro\Glspl]
+\cs{Glspl}\marg{label}
+\end{definition}
+This is equivalent to \cs{Useentry}\marg{label}\verb|{Plural}|.
+\begin{definition}[\DescribeMacro\Glsnl]
+\cs{Glsnl}\marg{label}
+\end{definition}
+This is equivalent to \cs{Useentrynl}\marg{label}\verb|{Text}|.
+\begin{definition}[\DescribeMacro\Glsplnl]
+\cs{Glsplnl}\marg{label}
+\end{definition}
+This is equivalent to \cs{Useentrynl}\marg{label}\verb|{Plural}|.
+
+\begin{definition}[\DescribeMacro\glssym]
+\cs{glssym}\marg{label}
+\end{definition}
+This is equivalent to \cs{useentry}\marg{label}\verb|{Symbol}|.
+\begin{definition}[\DescribeMacro\Glssym]
+\cs{Glssym}\marg{label}
+\end{definition}
+This is equivalent to \cs{Useentry}\marg{label}\verb|{Symbol}|.
+
+\section{Adding Extra Fields}
+
+You can add new fields to the index/glossary database using:
+\begin{definition}[\DescribeMacro\newtermaddfield]
+\cs{newtermaddfield}\oarg{db list}\marg{field name}\marg{key
+name}\marg{default value}
+\end{definition}
+The optional argument \meta{db list} is a comma-separated list of
+databases that should have this new field. If omitted, the field
+will be added to all the defined databases. The argument \meta{field
+name} is the label to give this new column in the database(s). The
+argument \meta{key name} is the name of the new key to use in the
+optional argument of \ics{newterm}. The final argument \meta{default
+value} is the default value if the key isn't used. Within
+\meta{default value}, you may use
+\begin{definition}[\DescribeMacro\field]
+\cs{field}\marg{key}
+\end{definition}
+to indicate the value of another key.
+
+
+For example, suppose I want to be able to specify an alternative
+plural. I can add a new field like this:
+\begin{verbatim}
+\newtermaddfield{AltPlural}{altplural}{}
+\end{verbatim}
+This adds a new column with the label \texttt{AltPlural} to each
+defined index/glossary database and adds a new key called
+\texttt{altplural} that I can now use in \ics{newterm}. The default
+is set to empty. Now I can define terms with an alternative plural:
+\begin{verbatim}
+\newterm[altplural=kine]{cow}
+\end{verbatim}
+In the document, I can use \verb|\gls{cow}| to display ``cow'',
+\verb|\glspl{cow}| to display ``cows'' and
+\verb|\useentry{cow}{AltPlural}| to display ``kine''. To make life a
+little easier, I can define a new command to save typing:
+\begin{verbatim}
+\newcommand*{\glsaltpl}[1]{\useentry{#1}{AltPlural}}
+\end{verbatim}
+Now I can just do \verb|\glsaltpl{cow}| to display ``kine''.
+
+Here's another example. Suppose I want to add a field that produces
+the past tense of a verb. In this case, the default should be formed
+by appending ``ed'' to the \csopt{newterm}{text} field. The new
+field can be defined as follows:
+\begin{verbatim}
+\newtermaddfield{Ed}{ed}{\field{text}ed}
+\end{verbatim}
+This adds a new column labelled ``Ed'' and defines a new key called
+``ed'' that can be used with \ics{newterm}. Now I can defined some
+verbs:
+\begin{verbatim}
+\newterm{jump}
+\newterm[ed=went]{go}
+\end{verbatim}
+
+Let's define a convenience command to access this field:
+\begin{verbatim}
+\newcommand*{\glsed}[1]{\useentry{#1}{Ed}}
+\end{verbatim}
+This new field can now be referenced in the document:
+\begin{verbatim}
+He \glsed{jump} over the gate.
+She \glsed{go} to the shop.
+\end{verbatim}
+The above will be displayed as: He jumped over the gate. She went to
+the shop.
+
+\section{Acronyms}
+
+You may have noticed that you can specify \csopt{newterm}{short} and
+\csopt{newterm}{long} fields when you define a new term. There is a
+convenient shortcut command which uses \ics{newterm} to define an
+acronym. The syntax is:
+\begin{definition}[\DescribeMacro\newacro]
+\cs{newacro}\oarg{options}\marg{short}\marg{long}
+\end{definition}
+This is a shortcut for
+\begin{alltt}
+\ics{newterm}
+ [%
+ description=\{\ics{capitalisewords}\marg{long}\},%
+ short=\{\cs{acronymfont}\marg{short}\},%
+ long=\marg{long},%
+ text=\{\cs{DTLgidxAcrStyle}\marg{long}\{\cs{acronymfont}\marg{short}\}\},%
+ plural=\{\cs{DTLgidxAcrStyle}\{\meta{long}s\}\{\cs{acronymfont}\{\meta{short}s\}\}\},%
+ sort=\marg{short},%
+ \meta{options}%
+ ]%
+ {\ics{MakeTextUppercase}\marg{short}}
+\end{alltt}
+where \ics{capitalisewords} is defined in \sty{mfirstuc}
+(automatically loaded by \styfmt{datagidx}) and
+\ics{MakeTextUppercase} is defined in \sty{textcase} (automatically
+loaded by \styfmt{datagidx}). The other commands used are defined by
+\styfmt{datagidx}:
+\begin{definition}[\DescribeMacro\acronymfont]
+\cs{acronymfont}
+\end{definition}
+By default this just typesets its argument but can be redefined if
+the acronyms need to be typeset in a certain style (such as small
+caps).
+\begin{definition}[\DescribeMacro\DTLgidxAcrStyle]
+\cs{DTLgidxAcrStyle}\marg{long}\marg{short}
+\end{definition}
+This governs how the acronym is typeset in the \csopt{newterm}{text}
+field. This defaults to: \meta{long} (\meta{short}).
+
+\subsection{Using Acronyms}
+
+You can use terms that represent acronyms via commands such as
+\ics{useentry}. For example, if you define the following in the
+preamble:
+\begin{verbatim}
+\newacro{css}{cascading style sheet}
+\end{verbatim}
+then later in the text you can use:
+\begin{verbatim}
+\useentry{css}{Short}
+\end{verbatim}
+to access the short form and
+\begin{verbatim}
+\useentry{css}{Long}
+\end{verbatim}
+to access the long form. You can also use
+\begin{verbatim}
+\useentry{css}{Text}
+\end{verbatim}
+(or \verb|\gls{css}|) to access the full version. However with
+acronyms you generally only want the full form on first use and just
+the short form on subsequent use. The following commands are
+provided to do that. The singular form is obtained using:
+\begin{definition}[\DescribeMacro\acr]
+\cs{acr}\marg{label}
+\end{definition}
+The plural form is obtained using:
+\begin{definition}[\DescribeMacro\acrpl]
+\cs{acrpl}\marg{label}
+\end{definition}
+
+Note that, unlike the \sty{glossaries} package, \cs{acr} isn't the
+same as \cs{gls}. With \styfmt{datagidx}, \cs{gls} always references
+the \csopt{newterm}{text} field. There is no ``first'' field.
+
+\begin{important}
+Take care when using acronyms with \cls{beamer}. Using overlays can
+cause problems with first use expansions.
+\end{important}
+
+As a general rule, you're not supposed to capitalise the first
+letter of an acronym (especially if it is displayed in small caps) but if you need to
+you can use:
+\begin{definition}[\DescribeMacro\Acr]
+\cs{Acr}\marg{label}
+\end{definition}
+and
+\begin{definition}[\DescribeMacro\Acrpl]
+\cs{Acrpl}\marg{label}
+\end{definition}
+
+\subsection{Unsetting and Resetting Acronyms}
+
+You can reset a term so it's marked as not used with:
+\begin{definition}[\DescribeMacro\glsreset]
+\cs{glsreset}\marg{label}
+\end{definition}
+or you can unset a term so it's marked as used with:
+\begin{definition}[\DescribeMacro\glsunset]
+\cs{glsunset}\marg{label}
+\end{definition}
+
+You can reset all the terms defined in a given database using:
+\begin{definition}[\DescribeMacro\glsresetall]
+\cs{glsresetall}\marg{db name}
+\end{definition}
+or unset all the terms defined in a given database using:
+\begin{definition}[\DescribeMacro\glsunsetall]
+\cs{glsunsetall}\marg{db name}
+\end{definition}
+where \meta{db name} is the name of the database as supplied when
+the database was defined using \ics{newgidx}.
+
+\section{Conditionals}
+
+You can test if a term exists using
+\begin{definition}[\DescribeMacro\iftermexists]
+\cs{iftermexists}\marg{label}\marg{true part}\marg{false part}
+\end{definition}
+You can test if a term has been used using:
+\begin{definition}[\DescribeMacro\ifentryused]
+\cs{ifentryused}\marg{label}\marg{true part}\marg{false part}
+\end{definition}
+
+\section{Displaying the Index or Glossary}
+\label{sec:printterms}
+
+The index or glossary can be displayed using
+\begin{definition}[\DescribeMacro\printterms]
+\cs{printterms}\oarg{options}
+\end{definition}
+You will need to run \LaTeX\ at least twice to ensure your
+index/glossary is up-to-date. The first run will only display any
+entries that have a ``See'' field defined.
+
+The optional argument \meta{options} is a comma-separated list of
+\meta{key}=\meta{value} options. Available keys:
+\begin{description}
+\item[\csopt{printterms}{database}] The name of the database (as
+given in \ics{newgidx}).
+
+\item[\csopt{printterms}{postdesc}] This may have the value
+\textsf{dot} (put a full stop after the description) or
+\textsf{none} (don't put a full stop after the description).
+
+\item[\csopt{printterms}{prelocation}] This indicates what to put
+before the location list. Available values:
+\begin{description}
+\item[\textsf{none}] Nothing.
+\item[\textsf{enspace}] An en-space.
+\item[\textsf{space}] An ordinary space.
+\item[\textsf{dotfill}] A dotted line (\ics{dotfill}).
+\item[\textsf{hfill}] Expandable space (\ics{hfill}).
+\end{description}
+
+\item[\csopt{printterms}{location}] This indicates how to display
+the location list. Available values:
+\begin{description}
+\item[\textsf{hide}] Don't display the location list.
+\item[\textsf{list}] Display the location list.
+\item[\textsf{first}] Only display the first location in the list.
+\end{description}
+
+\item[\csopt{printterms}{symboldesc}] How to format the symbol in
+relation to the description. Available values:
+\begin{description}
+\item[\textsf{symbol}] Display the symbol but not the description.
+\item[\textsf{desc}] Display the description but not the symbol
+field.
+\item[\textsf{(symbol) desc}] Display the symbol (if defined) in parentheses
+followed by the description.
+\item[\textsf{desc (symbol)}] Display the description followed by
+the symbol (if defined) in parentheses.
+\item[\textsf{symbol desc}] Display the symbol (if defined) followed
+by the description.
+\item[\textsf{desc symbol}] Display the description followed by the
+symbol (if defined).
+\end{description}
+
+\item[\csopt{printterms}{columns}] This should be a positive number
+that indicates the page column layout. If the value is greater
+than~1, the \env{multicols} environment is used (defined in the
+\sty{multicol} package, which is automatically loaded).
+
+\item[\csopt{printterms}{namecase}] Indicates whether any case
+change should be applied to the entry's name field. Available
+values:
+\begin{description}
+\item[\textsf{nochange}] Don't apply a case change.
+\item[\textsf{uc}] Convert the name to uppercase.
+\item[\textsf{lc}] Convert the name to lowercase.
+\item[\textsf{firstuc}] Convert the first letter to uppercase (using
+\ics{makefirstuc} defined in \sty{mfirstuc}).
+\item[\textsf{capitalise}] Capitalise initial letters of each word
+in the name (using \ics{capitalisewords} defined in \sty{mfirstuc}).
+\end{description}
+
+\item[\csopt{printterms}{namefont}] The font changing command to
+apply to the name. (Include the initial backslash.) Declarations may
+be used.
+
+\item[\csopt{printterms}{postname}] What to put after the name.
+
+\item[\csopt{printterms}{see}] Indicates how the cross-reference
+(given in the ``See'' field) should be displayed. Available values:
+\begin{description}
+\item[\textsf{comma}] Insert a comma followed by a space in front of
+the cross-reference.
+\item[\textsf{brackets}] Insert a space before the cross-reference
+and put the cross-reference in parentheses.
+\item[\textsf{dot}] Insert a full stop followed by a space in front
+of the cross-reference.
+\item[\textsf{space}] Insert a space before the cross-reference.
+\item[\textsf{nosep}] Don't insert anything before the
+cross-reference.
+\item[\textsf{semicolon}] Insert a semi-colon followed by a space in
+front of the cross-reference.
+\item[\textsf{location}] Display the cross-reference in the same way
+as a location.
+\end{description}
+
+\item[\csopt{printterms}{child}] Indicates whether child entries
+should have their name displayed. Available values: \textsf{named}
+(display the child's name) and \textsf{noname} (don't display the
+child's name).
+
+\item[\csopt{printterms}{showgroups}] Boolean option that indicates
+whether or not to insert group headings (and a group separator)
+between index groups, if headings are supported by the given style.
+If no value is supplied, \textsf{true} is assumed.
+
+\item[\csopt{printterms}{style}] The style to use. The value should
+be the name of the style. Available styles are listed in
+\autoref{sec:indexstyles}.
+
+\item[\csopt{printterms}{symbolwidth}] Some of the styles allow you
+to specify a width for the symbol field. This width can be specified
+with this option. The value will be ignored by some of the styles.
+
+\item[\csopt{printterms}{locationwidth}] Some of the styles allow you
+to specify a width for the location field. This width can be specified
+with this option. The value will be ignored by some of the styles.
+
+\item[\csopt{printterms}{childsort}] A boolean option that indicates
+whether or not the child entries should be sorted. If \textsf{true}, the
+child entries are listed using the same sort order as the sort
+applied to the database. If \textsf{false}, the child entries are
+listed in the order they were defined. If the value is missing,
+\textsf{true} is assumed.
+
+\item[\csopt{printterms}{heading}] The heading at the start of the
+index/glossary.
+
+\item[\csopt{printterms}{postheading}] What to put immediately after
+the heading.
+
+\item[\csopt{printterms}{sort}] How to sort the database. See
+\autoref{sec:indexsort} for further details.
+
+\item[\csopt{printterms}{balance}] This is a boolean option that
+is only applied if \csopt{printterms}{columns} is greater than~1.
+If \textsf{true}, the columns are balanced. If \textsf{false}, the
+columns aren't balanced. If no value is specified, \textsf{true} is
+assumed.
+
+\item[\csopt{printterms}{condition}] This specifies a boolean
+condition (as used by \ics{DTLforeach}) so you can display only
+those entries where the condition is met. For example, to only
+display entries starting with ``H'' (not including any entry that is
+just the letter ``H'') you can do:
+\begin{verbatim}
+\printterms[condition={\DTLisiopenbetween{\Name}{H}{I}}]
+\end{verbatim}
+\end{description}
+
+\subsection{Index or Glossary Styles}
+\label{sec:indexstyles}
+
+The index or glossary style is given by the
+\csopt{newgidx,printterms}{style} key in the optional argument of
+\ics{newgidx} or \ics{printterms}. The following styles are
+available:
+
+\begin{description}
+\item[index]
+The ``index'' style is a basic style for an index. This style
+accepts the \csopt{printterms}{locationwidth} and
+\csopt{printterms}{symbolwidth} keys in \ics{printterms}. This is
+the default style.
+
+\item[indexalign]
+The ``indexalign'' style is similar to the ``index'' style but
+aligns the descriptions.
+
+\item[align]
+The ``align'' style aligns the fields. This style
+accepts the \csopt{printterms}{locationwidth} and
+\csopt{printterms}{symbolwidth} keys in \ics{printterms}.
+
+\item[gloss]
+The ``gloss'' style is a basic glossary style. This style uses
+\begin{definition}[\DescribeMacro\DTLgidxChildSep]
+\cs{DTLgidxChildSep}
+\end{definition}
+as the separator between child entries (defaults to a space) and
+\begin{definition}[\DescribeMacro\DTLgidxPostChild]
+\cs{DTLgidxPostChild}
+\end{definition}
+to indicate what to put after the list of child entries (defaults to
+nothing).
+
+\item[dict]
+The ``dict'' style is designed for dictionary-like glossaries. This
+assumes a hierarchical structure where the top level entries have a
+name. The next level is used to indicate a category (such as
+``adjective'' or ``noun''). If there is only one meaning for the
+term, this level also has a description. If there is more than one
+meaning, each meaning should be a child of the category entry. Only
+third level entries are numbered. No further levels are expected.
+The symbol field is ignored.
+
+If \csopt{printterms}{showgroups} is set, the group headers will be
+placed in a \ics{chapter} (if defined) or in a \ics{section} (if
+\ics{chapter} isn't defined).
+
+This style uses:
+\begin{definition}[\DescribeMacro\DTLgidxCategoryNameFont]
+\cs{DTLgidxCategoryNameFont}\marg{text}
+\end{definition}
+The font used to display the name of the category (first child
+level).
+\begin{definition}[\DescribeMacro\DTLgidxCategorySep]
+\cs{DTLgidxCategorySep}
+\end{definition}
+The category separator. (Defaults to a space).
+\begin{definition}[\DescribeMacro\DTLgidxSubCategorySep]
+\cs{DTLgidxSubCategorySep}
+\end{definition}
+The category separator. (Defaults to a space).
+\begin{definition}[\DescribeMacro\DTLgidxDictPostItem]
+\cs{DTLgidxDictPostItem}
+\end{definition}
+Indicates what to do at the end of each top-level item. (Defaults to
+\cs{par}).
+
+The indentation is given by the length register
+\begin{definition}[\DescribeMacro\datagidxdictindent]
+\cs{datagidxdictindent}
+\end{definition}
+This value defaults to 1em.
+
+\end{description}
+
+For additional commands that affect the style of the indexes or
+glossaries, see the documented code \texttt{datatool-code.pdf}.
+
+\subsection{Sorting the Index or Glossary Database}
+\label{sec:indexsort}
+
+By default the index/glossary databases are sorted according to the
+\texttt{Sort} field using the \ics{dtlwordindexcompare} handler (see
+\autoref{sec:sort}). Note that the \emph{entire} database is sorted,
+which is less efficient that using external indexing applications,
+such as \app{makeindex} or \app{xindy}, which only sort the
+terms that have been used in the document. In addition, the sorting
+algorithm used by \styfmt{datatool} is less efficient than that used
+by a custom-built sorting and collation application.
+
+The database is sorted at the start of \ics{printterms} according to
+the value of the \csopt{printterms}{sort} key supplied by
+\ics{printterms}. To completely suppress the sorting, set this key
+to empty. Example:
+\begin{verbatim}
+\printterms[database=index,sort={},showgroups=false]
+\end{verbatim}
+Note that in the above, I also switched off the group headers as
+they don't make sense with an unsorted index or glossary.
+
+If you want to use a different comparison handler, you can set the
+\csopt{printterms}{sort} key to the required sort command, where you
+can use
+\begin{definition}[\DescribeMacro\DTLgidxCurrentdb]
+\cs{DTLgidxCurrentdb}
+\end{definition}
+to indicate the current database.
+
+For example, to sort using letter rather than word comparison:
+\begin{verbatim}
+\printterms[database=index,
+ sort={\dtlsort{Sort}{\DTLgidxCurrentdb}{\dtlletterindexcompare}}]
+\end{verbatim}
+
+You may recall from earlier that the index/glossary databases have a
+column labelled ``FirstId''. This can be used if you want to sort
+the database according to the order of usage. Example:
+\begin{verbatim}
+\printterms[database=index,
+ sort={\dtlsort{FirstId}{\DTLgidxCurrentdb}{\dtlcompare}}]
+\end{verbatim}
+Note that here I've used the \ics{dtlcompare} handler (which is the
+fastest handler) as I'm only concerned with a numerical rather than
+a string comparison.
+
+The default value of the \csopt{printterms}{sort} key is actually:
+\begin{verbatim}
+\dtlsort{Sort,FirstId}{\DTLgidxCurrentdb}{\dtlwordindexcompare}}
+\end{verbatim}
+This means that entries with duplicate ``Sort'' fields are then
+sorted according to use.
+
+\subsubsection{Optimization}
+\label{sec:optimize}
+
+If you have used \app{xindy} or \app{makeindex}, you'll be
+familiar with the document creation process. The document is first
+compiled, then the indexing application is run to sort and collate
+the entries, then the document is compiled again (and possible once
+more). This involves two (or three) \LaTeX\ runs and one sort and
+collate run. With the \styfmt{datagidx} package, the sorting and
+collation is done every \LaTeX\ run. For a large index, this can be
+quite slow. If you're not editing the index or glossary, you might
+prefer not to have to keep sorting the database whenever you update
+the document. To assist this, \styfmt{datagidx} provides the
+\pkgopt{optimize} package option. This may take the following
+values:
+\begin{description}
+\item[\pkgoptval{off}{optimize}] Don't use the optimize facility.
+(The index/glossary databases will be sorted every run, unless the
+sort is switched off by setting the \csopt{printterms}{sort} key to
+empty.)
+
+\item[\pkgoptval{low}{optimize}] Use the ``low'' optimize setting.
+This only sorts the index/glossary databases every other run.
+(Assuming that the sorting is done via the \cs{printterms}{sort} key
+rather than explicitly using \ics{dtlsort} or \ics{DTLsort}
+somewhere else in the document.) Don't use this option if sorting
+the databases makes the document out-of-date. (For example, the
+group headers use sectioning commands.)
+
+\item[\pkgoptval{high}{optimize}] Use the ``high'' optimize setting.
+This sorts the index/glossary databases on the first run, then
+writes the sorted databases to external files, which are read in on
+subsequent runs. Again this assumes that the sorting is done via the
+\cs{printterms}{sort} key. Don't use this option if you want to edit
+the index/glossary database.
+\end{description}
+
+\section{Package Options}
+\label{sec:datagidxoptions}
+
+The following package options are available for \styfmt{datagidx}:
+\begin{description}
+\item[\pkgopt{utf8}] A boolean option (same as for
+\sty{datatool-base}). If you both load \sty{inputenc} with UTF-8
+support and you use accent commands like \cs{'} or \cs{c} then make
+sure you have at least version 2.05 of \sty{mfirstuc} if you want to
+use commands like \cs{Gls}.
+
+\item[\pkgopt{optimize}] Sets the optimization. (See
+\autoref{sec:optimize}.)
+
+\item[\pkgopt{columns}] Sets the default number of columns to use
+for the indexes or glossaries. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{child}] Sets whether or not to show the name in child
+entries, where the style supports this option. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{namecase}] Sets the case change for the entry's name.
+(See \autoref{sec:printterms}.)
+
+\item[\pkgopt{namefont}] Sets the font for the entry's name.
+(See \autoref{sec:printterms}.)
+
+\item[\pkgopt{postname}] Indicates what to put after the entry's name.
+(See \autoref{sec:printterms}.)
+
+\item[\pkgopt{postdesc}] Indicates what to put after the entry's
+description. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{prelocation}] Indicates what to put before the entry's
+location. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{location}] Indicates how to display the entry's
+location. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{see}] Indicates how to display the entry's
+cross-reference list. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{symboldesc}] Indicates how to display the entry's
+symbol in relation to the description. (See \autoref{sec:printterms}.)
+
+\item[\pkgopt{compositor}] Sets the location compositor. (See
+\autoref{sec:locations}.)
+
+\item[\pkgopt{draft}] Displays additional information, such as
+target names.
+
+\item[\pkgopt{final}] Hides the draft information.
+
+\item[\pkgopt{verbose}] Use \sty{datatool}'s verbose mode.
+
+\item[\pkgopt{nowarn}] A boolean option that suppresses
+\sty{datagidx}'s rerun warnings.
+
+\end{description}
+
+\begin{example}{Creating an Index}{ex:index}
+In this document, I have used the \sty{datagidx} package and the
+\sty{hyperref} package. In the preamble, I have the following:
+\begin{verbatim}
+\usepackage{datagidx}
+\usepackage[colorlinks]{hyperref}
+
+\newgidx{index}{Index}% define a database for the index
+
+\DTLgidxSetDefaultDB{index}% set this as the default
+
+\newterm{mac\'edoine}
+\newterm{macram\'e}
+\newterm[label=elite]{{\'e}lite}
+\newterm{reptile}
+\newterm[seealso={reptile}]{crocodylian}
+
+\newterm
+ [%
+ parent=crocodylian
+ ]
+ {crocodile}
+
+\newterm
+ [%
+ parent=crocodylian
+ ]
+ {alligator}
+
+\newterm
+ [%
+ parent=crocodylian,
+ description={(also cayman)}
+ ]
+ {caiman}
+
+\newterm[see={caiman}]{cayman}
+\end{verbatim}
+
+Now here's some code to go in the document:
+\begin{verbatim}
+Here are some words containing accents: \gls{macedoine},
+\gls{macrame} and \gls{elite}. \Gls{elite} requires extra care as it
+starts with an accented letter. A \gls{crocodylian} is a family of
+\glspl{reptile} consisting of \glspl{crocodile}, \glspl{alligator} and
+\glspl{caiman}.
+\end{verbatim}
+This produces the following:
+
+Here are some words containing accents: \gls{macedoine},
+\gls{macrame} and \gls{elite}. \Gls{elite} requires extra care as it
+starts with an accented letter. A \gls{crocodylian} is a family of
+\glspl{reptile} consisting of \glspl{crocodile}, \glspl{alligator} and
+\glspl{caiman}.
+
+The index can then be displayed using:
+\begin{verbatim}
+\printterms[heading={\section*},database=index]
+\end{verbatim}
+This requires two runs to ensure the index is up-to-date. The
+resulting index is as follows:
+
+\printterms
+ [
+ heading={\section*},
+ database={gidx-index}
+ ]
+
+\par\vskip\baselineskip\noindent
+Here's the code if you want to add the letter groups (I've also
+added a dotted line before the location):
+\begin{verbatim}
+\printterms
+ [
+ heading={\section*},
+ database=index,
+ prelocation=dotfill,
+ showgroups
+ ]
+\end{verbatim}
+which produces:
+\printterms
+ [
+ heading={\section*},
+ database=gidx-index,
+ prelocation=dotfill,
+ showgroups
+ ]
+
+\end{example}
+
+\chapter{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)}
+\label{sec:datapie}
+
+The \sty{datapie} package is not loaded by the \sty{datatool} package,
+so you need to explicitly load \sty{datapie} if you want to use any of the
+commands defined in this section. You will also need to have the
+\sty{pgf}/\sty{tikz} packages installed. The \sty{datapie} package
+may be given the following options:
+\begin{description}
+\item[{\pkgopt{color}}] Colour option (default).
+\item[{\pkgopt{gray}}] Grey scale option.
+\item[{\pkgopt{rotateinner}}]
+Rotate inner labels so that they are aligned
+with the pie chart radial axis.
+\item[{\pkgopt{norotateinner}}]
+Don't rotate inner labels (default).
+\item[{\pkgopt{rotateouter}}]
+Rotate outer labels so that they are aligned
+with the pie chart radial axis.
+\item[{\pkgopt{norotateouter}}]
+Don't rotate outer labels (default).
+\end{description}
+
+Numerical information contained in a database created by the
+\sty{datatool} package can be converted into a pie chart using
+\begin{definition}[\DescribeMacro{\DTLpiechart}]%
+\cs{DTLpiechart}\oarg{condition}\marg{settings list}\marg{db name}\marg{values}
+\end{definition}\noindent
+where \meta{db name} is the name of the database, and
+\meta{condition} has the same form as the optional argument
+to \ics{DTLforeach} described in \autoref{sec:dbforeach}. If
+\meta{condition} is false, that information is omitted from the
+construction of the pie chart. The argument \meta{values} is a
+comma separated list of \meta{cmd}"="\meta{key} pairs, the same
+as that required by the penultimate argument of \ics{DTLforeach}.
+The \meta{settings list} is a comma separated list of
+\meta{setting}=\meta{value} pairs, where \meta{setting} can be any of
+the following:
+\begin{description}
+\item[\csopt{DTLpiechart}{variable}]
+This specifies the control sequence to use that
+contains the value used to construct the pie chart. The control
+sequence must be one of the control sequences to appear in
+the assignment list \meta{values}. This setting is required.
+
+\item[\csopt{DTLpiechart}{start}]
+This is the starting angle of the first segment. The
+value is 0 by default.
+
+\item[\csopt{DTLpiechart}{radius}]
+This is the radius of the pie chart. The default value
+is 2cm.
+
+\item[\csopt{DTLpiechart}{innerratio}]
+The distance from the centre of the
+pie chart to the point where the inner labels are placed is given
+by this value multiplied by the radius. The default value is 0.5.
+
+\item[\csopt{DTLpiechart}{outerratio}]
+The distance from the centre of the
+pie chart to the point where the outer labels are placed is given
+by this value multiplied by the radius. The default value is 1.25.
+
+\item[\csopt{DTLpiechart}{cutawayratio}]
+The distance from the centre of the pie chart
+to the point of cutaway segments is given by this value multiplied
+by the radius. The default value is 0.2.
+
+\item[\csopt{DTLpiechart}{inneroffset}]
+This is the absolute distance from the centre
+of the pie chart to the point where the inner labels are placed.
+You should use only one or other of \csopt{DTLpiechart}{innerratio}
+and \csopt{DTLpiechart}{inneroffset}, not both. If you also want to
+specify the radius, you must use \csopt{DTLpiechart}{radius}
+before \csopt{DTLpiechart}{inneroffset}. If omitted, the inner
+offset is obtained from the radius multiplied by the
+\csopt{DTLpiechart}{innerratio} value.
+
+\item[\csopt{DTLpiechart}{outeroffset}]
+This is the absolute distance from the centre
+of the pie chart to the point where the outer labels are placed.
+You should use only one or other of \csopt{DTLpiechart}{outerratio}
+and \csopt{DTLpiechart}{outeroffset}, not both. If you also want to
+specify the radius, you must use \csopt{DTLpiechart}{radius}
+before \csopt{DTLpiechart}{outeroffset}. If omitted, the outer
+offset is obtained from the radius multiplied by the
+\csopt{DTLpiechart}{outerratio} value.
+
+\item[\csopt{DTLpiechart}{cutawayoffset}]
+This is the absolute distance from the centre of
+the pie chart to the point of the cutaway segments. You should use
+only one or other of \csopt{DTLpiechart}{cutawayratio} and
+\csopt{DTLpiechart}{cutawayoffset}, not both. If
+you also want to specify the radius, you must use
+\csopt{DTLpiechart}{ratio} before
+\csopt{DTLpiechart}{cutawayoffset}. If omitted, the cutaway offset
+is obtained from the ratio multiplied by the
+\csopt{DTLpiechart}{cutawayratio} value.
+
+\item[\csopt{DTLpiechart}{cutaway}]
+This is a list of cutaway segments. This should be
+a comma separated list of individual numbers, or number ranges
+(separated by a dash). For example "cutaway={1,3}" will separate
+the first and third segments from the rest of the pie chart, offset
+by the value of the \csopt{DTLpiechart}{cutawayoffset} setting,
+whereas "cutaway={1-3}" will separate the
+first three segments from the rest of the pie chart. If omitted,
+the pie chart will be whole.
+
+\item[\csopt{DTLpiechart}{innerlabel}]
+The value of this is positioned in the middle of each segment at a
+distance of \csopt{DTLpiechart}{inneroffset} from the centre
+of the pie chart. The default is the same as the value of
+\csopt{DTLpiechart}{variable}.
+
+\item[\csopt{DTLpiechart}{outerlabel}]
+The value of this is positioned at a distance of
+\csopt{DTLpiechart}{outeroffset} from the centre of the pie chart.
+The default is empty.
+
+\item[\csopt{DTLpiechart}{rotateinner}] This is a boolean setting,
+so it can only take the values "true" and "false". If the value is
+omitted "true" is assumed. If true, the inner labels are rotated
+along the spokes of the pie chart, otherwise the inner labels are not
+rotated. There are analogous package options
+\pkgopt{rotateinner} and \pkgopt{norotateinner}.
+
+\item[\csopt{DTLpiechart}{rotateouter}]
+This is a boolean setting, so it can only take
+the values "true" and "false". If the value is omitted "true" is
+assumed. If true, the outer labels are rotated along the spokes of
+the pie chart, otherwise the outer labels are not rotated.
+There are analogous package options
+\pkgopt{rotateouter} and \pkgopt{norotateouter}.
+
+\end{description}
+
+\begin{example}{A Pie Chart}{ex:piechart}
+This example loads data from a file called "fruit.csv" which contains
+the following:
+\begin{verbatim}
+Name,Quantity
+"Apples",30
+"Pears",25
+"Lemons,Limes",40.5
+"Peaches",34.5
+"Cherries",20
+\end{verbatim}
+First load the data:
+\begin{verbatim}
+\DTLloaddb{fruit}{fruit.csv}
+\end{verbatim}
+\DTLnewdb{fruit}\relax
+\DTLnewrow{fruit}\relax
+\DTLnewdbentry{fruit}{Name}{Apples}\relax
+\DTLnewdbentry{fruit}{Quantity}{30}\relax
+\DTLnewrow{fruit}\relax
+\DTLnewdbentry{fruit}{Name}{Pears}\relax
+\DTLnewdbentry{fruit}{Quantity}{25}\relax
+\DTLnewrow{fruit}\relax
+\DTLnewdbentry{fruit}{Name}{Lemons,Limes}\relax
+\DTLnewdbentry{fruit}{Quantity}{40.5}\relax
+\DTLnewrow{fruit}\relax
+\DTLnewdbentry{fruit}{Name}{Peaches}\relax
+\DTLnewdbentry{fruit}{Quantity}{34.5}\relax
+\DTLnewrow{fruit}\relax
+\DTLnewdbentry{fruit}{Name}{Cherries}\relax
+\DTLnewdbentry{fruit}{Quantity}{20}\relax
+Now create a pie chart in a figure:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart}
+\end{figure}
+\end{verbatim}
+This creates \autoref{fig:piechart}. The colours used are the
+defaults. See \autoref{ex:piecolours} for an example that changes
+the default colours.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart}
+\label{fig:piechart}
+\end{figure}
+
+There are no outer labels by default, but they can be set
+using the \csopt{DTLpiechart}{outerlabel} setting.
+The following sets the outer label to the value of the "Name" key:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart (outer labels set)}
+\end{figure}
+\end{verbatim}
+This creates \autoref{fig:piechartouter}.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name}{fruit}
+{\name=Name,\quantity=Quantity}
+\caption{A pie chart (outer labels set)}
+\label{fig:piechartouter}
+\end{figure}
+
+You may prefer the labels to be rotated. The following
+switches on the rotation for the inner and outer labels:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name,%
+rotateinner,rotateouter}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart (rotation enabled)}
+\end{figure}
+\end{verbatim}
+This creates \autoref{fig:piechartrot}.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name
+,rotateinner,rotateouter}{fruit}
+{\name=Name,\quantity=Quantity}
+\caption{A pie chart (rotation enabled)}
+\label{fig:piechartrot}
+\end{figure}
+\end{example}
+
+\begin{example}{Separating Segments from the Pie Chart}{ex:cutaway}
+You may want to separate one or more segments from the pie chart,
+perhaps to emphasize them. You can do this using the
+\csopt{DTLpiechart}{cutaway}
+setting. The following separates the first and third segments
+from the pie chart:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name,%
+cutaway={1,3}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:piecutaway}.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name
+,cutaway={1,3}}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments}
+\label{fig:piecutaway}
+\end{figure}
+
+Alternatively I can specify a range of segments. The following
+separates the first two segments:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name,%
+cutaway={1-2}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:piecutaway2}.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name
+,cutaway={1-2}}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1-2\}})}
+\label{fig:piecutaway2}
+\end{figure}
+
+Notice the difference between \autoref{fig:piecutaway2} and
+\autoref{fig:piecutaway3} which was produced using:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name,%
+cutaway={1,2}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})}
+\end{figure}
+\end{verbatim}
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,outerlabel=\name
+,cutaway={1,2}}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart with cutaway segments (\texttt{cutaway=\{1,2\}})}
+\label{fig:piecutaway3}
+\end{figure}
+
+\end{example}
+
+\section{Pie Chart Variables}
+
+\begin{definition}[\DescribeMacro{\DTLpievariable}]%
+\cs{DTLpievariable}
+\end{definition}
+This command is set to the variable given by the
+\csopt{DTLpiechart}{variable} setting in the \meta{settings list}
+argument of \cs{DTLpiechart}. The \csopt{DTLpiechart}{innerlabel}
+is set to \cs{DTLpievariable} by default.
+
+\begin{definition}[\DescribeMacro{\DTLpiepercent}]%
+\cs{DTLpiepercent}
+\end{definition}
+This command is set to the percentage value of \cs{DTLpievariable}.
+The percentage value is rounded to \meta{n} digits, where \meta{n}
+is the value of the \LaTeX\ counter
+\desctr{DTLpieroundvar}.
+
+\begin{example}{Changing the Inner and Outer Labels}{ex:pielabels}
+This example uses the database defined in \autoref{ex:piechart}.
+The inner label is now set to the percentage value, rather than
+the actual value, and the outer label is set to the name with
+the actual value in parentheses.
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,%
+innerlabel={\DTLpiepercent\%},%
+outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart (changing the labels)}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:piechartlabels}.
+
+\begin{figure}[htbp]
+\centering
+\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart (changing the labels)}
+\label{fig:piechartlabels}
+\end{figure}
+\end{example}
+
+\section{Pie Chart Label Formatting}
+
+\begin{definition}[\DescribeMacro{\DTLdisplayinnerlabel}]%
+\cs{DTLdisplayinnerlabel}\marg{text}
+\end{definition}
+This governs how the inner label is formatted, where \meta{text}
+is the text of the inner label. The default is to just do \meta{text}.
+
+\begin{definition}[\DescribeMacro{\DTLdisplayouterlabel}]%
+\cs{DTLdisplayouterlabel}\marg{text}
+\end{definition}
+This governs how the outer label is formatted, where \meta{text}
+is the text of the outer label. The default is to just do \meta{text}.
+
+\begin{example}{Changing the Inner and Outer Label
+Format}{ex:pielabelformat}
+This example extends \autoref{ex:pielabels}.
+The inner and outer labels are now both typeset in a sans-serif
+font:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+\DTLpiechart{variable=\quantity,%
+innerlabel={\DTLpiepercent\%},%
+outerlabel={\name\ (\DTLpievariable)}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{A pie chart (changing the label format)}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:piechartlabelformat}.
+
+\begin{figure}[htbp]
+\centering
+\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+\renewcommand*{\DTLdisplayouterlabel}[1]{\textsf{#1}}
+\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+\%},outerlabel={\name\ (\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
+\caption{A pie chart (changing the label format)}
+\label{fig:piechartlabelformat}
+\end{figure}
+\end{example}
+
+\section{Pie Chart Colours}
+
+The \sty{datapie} package predefines colours for the first
+eight segments of the pie chart. If you require more than
+eight segments or if you want to change the default colours, you
+will need to use
+\begin{definition}[\DescribeMacro{\DTLsetpiesegmentcolor}]%
+\cs{DTLsetpiesegmentcolor}\marg{n}\marg{color}
+\end{definition}\noindent
+The first argument \meta{n} is the segment index (starting from 1),
+and the second argument \meta{color} is a colour specifier as used
+in commands such as \cs{color}.
+
+It is a good idea to set the colours so that each segment colour
+is somehow relevant to whatever the segment represents. For
+example, in the previous examples of pie charts depicting fruit,
+some of default colours were inappropriate. Whilst red is
+appropriate for apples and green is appropriate for pears, blue
+doesn't really correspond to lemons or limes.
+
+\begin{definition}[\DescribeMacro{\DTLdopiesegmentcolor}]%
+\cs{DTLdopiesegmentcolor}\marg{n}
+\end{definition}
+This sets the current text colour to that of the \meta{n}th
+segment.
+
+\begin{definition}[\DescribeMacro{\DTLdocurrentpiesegmentcolor}]%
+\cs{DTLdocurrentpiesegmentcolor}
+\end{definition}
+This sets the current text colour to that of the current pie
+segment. This command may only be used within a pie chart, or
+within the body of \ics{DTLforeach}.
+
+\begin{definition}[\DescribeMacro{\DTLpieoutlinecolor}]%
+\cs{DTLpieoutlinecolor}
+\end{definition}
+This sets the outline colour for the pie chart. The default is
+black.
+
+\begin{definition}[\DescribeMacro{\DTLpieoutlinewidth}]%
+\cs{DTLpieoutlinewidth}
+\end{definition}
+This is a length that governs the line width of the outline. The
+default value is 0pt, but can be changed using \cs{setlength}.
+The outline is only drawn if \cs{DTLpieoutlinewidth} is greater
+than 0pt.
+
+\begin{example}{Pie Segment Colours}{ex:piecolours}
+This example extends \autoref{ex:pielabelformat}.
+It sets the outline thickness to 2pt, and
+the outer label is now set in the same colour as the fill colour
+of the segment to which it belongs. The third segment (lemons and
+limes) is set to yellow and the fourth segment (peaches) is set
+to pink. In addition, a legend is created using \ics{DTLforeach}.
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\setlength{\DTLpieoutlinewidth}{2pt}
+\DTLsetpiesegmentcolor{3}{yellow}
+\DTLsetpiesegmentcolor{4}{pink}
+\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+\renewcommand*{\DTLdisplayouterlabel}[1]{%
+\DTLdocurrentpiesegmentcolor
+\textsf{\shortstack{#1}}}
+\DTLpiechart{variable=\quantity,%
+innerlabel={\DTLpiepercent\%},%
+outerlabel={\name\\(\DTLpievariable)}}{fruit}{%
+\name=Name,\quantity=Quantity}
+\begin{tabular}[b]{ll}
+\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}%
+\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+\name
+}
+\end{tabular}
+\caption{A pie chart (using segment colours and outline)}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:piesegcolour}. (The format of the
+outer label has been changed to use \cs{shortstack} to
+prevent the outer labels from taking up so much horizontal
+space. The \csopt{DTLpiechart}{outerlabel} setting has also been
+modified to use "\\" after the name to move the percentage value onto
+the next row.)
+
+\begin{figure}[htbp]
+\centering
+\setlength{\DTLpieoutlinewidth}{2pt}
+\DTLsetpiesegmentcolor{3}{yellow}
+\DTLsetpiesegmentcolor{4}{pink}
+\renewcommand*{\DTLdisplayinnerlabel}[1]{\textsf{#1}}
+\renewcommand*{\DTLdisplayouterlabel}[1]{\relax
+\DTLdocurrentpiesegmentcolor
+\textsf{\shortstack{#1}}}
+\DTLpiechart{variable=\quantity,innerlabel={\DTLpiepercent
+\%},outerlabel={\name\\(\DTLpievariable)}}{fruit}{\name=Name,\quantity=Quantity}
+\begin{tabular}[b]{ll}
+\DTLforeach{fruit}{\name=Name}{\DTLiffirstrow{}{\\}\relax
+\DTLdocurrentpiesegmentcolor\rule{10pt}{10pt} &
+\name
+}
+\end{tabular}
+\caption{A pie chart (using segment colours and outline)}
+\label{fig:piesegcolour}
+\end{figure}
+\end{example}
+
+\section{Adding Extra Commands Before and After the Pie Chart}
+
+The pie charts created using \ics{DTLpiechart} are placed inside
+a \env{tikzpicture} environment (defined by the \sty{tikz} package).
+
+\begin{definition}[\DescribeMacro{\DTLpieatbegintikz}]%
+\cs{DTLpieatbegintikz}
+\end{definition}
+The macro \cs{DTLpieatbegintikz} is called at the start of the
+\env{tikzpicture} environment, allowing you to change the
+\env{tikzpicture} settings. By default \cs{DTLpieatbegintikz}
+does nothing, but you can redefine it to, say, scale the pie
+chart (but be careful not to distort the chart).
+
+\begin{definition}[\DescribeMacro{\DTLpieatendtikz}]%
+\cs{DTLpieatendtikz}
+\end{definition}
+The macro \cs{DTLpieatendtikz} is called at the end of the
+\env{tikzpicture} environment, allowing you add additional
+graphics to the pie chart. This does nothing by default.
+
+\begin{example}{Adding Information to the Pie Chart}{ex:piescale}
+This example modifies \autoref{ex:piechart}. It redefines
+\cs{DTLpieatendtikz} to add an annotated arrow.
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\renewcommand*{\DTLpieatendtikz}{%
+\draw[<-] (45:1.5cm) -- (40:2.5cm)node[right]{Apples};}
+\DTLpiechart{variable=\quantity}{fruit}{%
+\name=Name,\quantity=Quantity}
+\caption{An annotated pie chart}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:pieannote}. (Note that the centre
+of the pie chart is the origin of the TikZ picture.)
+
+\begin{figure}[htbp]
+\centering
+\renewcommand*{\DTLpieatendtikz}{%
+\draw[<-] (45:1.5cm) -- (40:2.5cm)node[right]{Apples};}
+\DTLpiechart{variable=\quantity}{fruit}{\name=Name,\quantity=Quantity}
+\caption{An annotated pie chart}
+\label{fig:pieannote}
+\end{figure}
+\end{example}
+
+\chapter{Scatter and Line Plots (\texorpdfstring{\sty{dataplot}}{dataplot}
+package)}
+\label{sec:dataplot}
+
+The \sty{dataplot} package provides commands for creating
+scatter or line plots from databases. It uses the pgf/TikZ plot
+handler library to create the plots. See the \sty{pgf} manual for
+more detail on pgf streams and plot handles. The \sty{dataplot}
+package is not loaded by \sty{datatool} so if you want to use
+it you need to load it explicitly using "\usepackage{dataplot}".
+
+
+\begin{definition}[\DescribeMacro{\DTLplot}]%
+\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings}
+\end{definition}
+This command creates a plot (inside a \env{tikzpicture} environment)
+of all the data given in the databases listed in \meta{db list},
+which should be a comma separated list of database names.
+The optional argument \meta{condition} is the same as that for
+\ics{DTLforeach}. The \meta{settings} argument is a comma separated
+list of \meta{setting}"="\meta{value} pairs. There are two settings
+that must be specified \csopt{DTLplot}{x} and \csopt{DTLplot}{y}.
+The other settings are optional. Note that any value that contains
+a comma, must be enclosed in braces. For example
+"colors={red,cyan,blue}". Note where any setting requires
+a number, or list of numbers (such as \csopt{DTLplot}{bounds})
+the number must be supplied in standard decimal notation (i.e.\
+no currency, no number groups, and a full stop as the decimal
+point). Available settings are as follows:
+\begin{description}
+\item[\csopt{DTLplot}{x}] The database key
+that specifies the $x$ co-ordinates. This setting is required.
+
+\item[\csopt{DTLplot}{y}] The database key that specifies
+the $y$ co-ordinates. This setting is required.
+
+\item[\csopt{DTLplot}{markcolors}] A comma separated list of colour
+names for the markers. An empty value will use the current colour.
+
+\item[\csopt{DTLplot}{linecolors}] A comma separated list of colour
+names for the plot lines. An empty value will use the current colour.
+
+\item[\csopt{DTLplot}{colors}] A comma separated list of colour
+names for the lines and markers.
+
+\item[\csopt{DTLplot}{marks}] A comma separated list of
+code to generate plot marks. (This should typically be a list
+of \cs{pgfuseplotmark} commands, see the \sty{pgf} manual for
+further details.) You may use \cs{relax} as an element
+of the list to suppress markers for the corresponding plot.
+For example: "marks={\pgfuseplotmark{o},\relax}" will use an
+open circle marker for the first database, and no markers for the
+second database listed in \meta{db list}.
+
+\item[\csopt{DTLplot}{lines}] A comma separated list of
+line style settings. (This should typically be a list of
+\cs{pgfsetdash} commands, see the \sty{pgf} manual for
+further details on how to set the line style.) An empty value
+will use the current line style.
+You may use \cs{relax} as an element
+of the list to suppress line for the corresponding plot.
+For example: "lines={\relax,\pgfsetdash{}{0pt}}"
+will have no lines for the first database, and a solid line
+for the second database listed in \meta{db list}.
+
+\item[\csopt{DTLplot}{width}] The width of the plot. This must
+be a length. The plot width does not include outer tick marks or
+labels.
+
+\item[\csopt{DTLplot}{height}] The height of the plot. This must
+be a length. The plot height does not include outer tick marks
+or labels.
+
+\item[\csopt{DTLplot}{style}] This setting governs whether
+to use lines or markers in the plot, and may take one of
+the following values: "both" (lines and markers),
+"lines" (only lines) or "markers" (only markers). The default is
+"markers".
+
+\item[\csopt{DTLplot}{axes}] This setting governs whether
+to display the axes, and may take one of
+the following values: "both", "x", "y" or "none". If no value
+is specified, "both" is assumed.
+
+\item[\csopt{DTLplot}{box}] This setting governs whether
+or not to surround the plot in a box. It is a boolean setting,
+taking only the values "true" and "false". If no value is
+specified, "true" is assumed.
+
+\item[\csopt{DTLplot}{xtics}] This setting governs whether
+or not to display the $x$ tick marks. It is a boolean setting,
+taking only the values "true" and "false". If no value is
+specified "true" is assumed. If the \csopt{DTLplot}{axes}
+setting is set to "both" or "x", this value will automatically
+be set to "true", otherwise it will be set to "false".
+
+\item[\csopt{DTLplot}{ytics}] This setting governs whether
+or not to display the $y$ ticks. It is a boolean setting,
+taking only the values "true" and "false". If no value is
+specified "true" is assumed. If the \csopt{DTLplot}{axes}
+setting is set to "both" or "y", this value will automatically
+be set to "true", otherwise it will be set to "false".
+
+
+\item[\csopt{DTLplot}{xminortics}] This setting governs whether
+or not to display the $x$ minor tick marks. It is a boolean
+setting, taking only the values "true" and "false". If no value is
+specified "true" is assumed. This setting also sets the
+$x$ major tick marks on if the value is "true".
+
+\item[\csopt{DTLplot}{yminortics}] This setting governs whether
+or not to display the $y$ minor tick marks. It is a boolean
+setting, taking only the values "true" and "false". If no value is
+specified "true" is assumed. This setting also sets the
+$y$ major tick marks on if the value is "true".
+
+\item[\csopt{DTLplot}{xticdir}] This sets the $x$ tick direction,
+and may only take the values "in" or "out".
+
+\item[\csopt{DTLplot}{yticdir}] This sets the $y$ tick direction,
+and may only take the values "in" or "out".
+
+\item[\csopt{DTLplot}{ticdir}] This sets the $x$ and $y$ tick
+direction, and may only take the values "in" or "out".
+
+\item[\csopt{DTLplot}{bounds}] The value must be in the form
+\meta{min x}","\meta{min y}","\meta{max x}","\meta{max y}. This
+sets the graph bounds to the given values. If omitted the
+bounds are computed from the maximum and minimum values of the
+data. For example
+\begin{verbatim}
+\DTLplot{data1,data2}{x=Height,y=Weight,bounds={0,0,10,20}}
+\end{verbatim}
+Note that the \csopt{DTLplot}{bounds} setting overrides
+the \csopt{DTLplot}{minx}, \csopt{DTLplot}{maxx},
+\csopt{DTLplot}{miny} and \csopt{DTLplot}{maxy} settings.
+
+\item[\csopt{DTLplot}{minx}] The value is the minimum value
+of the $x$ axis.
+
+\item[\csopt{DTLplot}{miny}] The value is the minimum value
+of the $y$ axis.
+
+\item[\csopt{DTLplot}{maxx}] The value is the maximum value
+of the $x$ axis.
+
+\item[\csopt{DTLplot}{maxy}] The value is the maximum value
+of the $y$ axis.
+
+\item[\csopt{DTLplot}{xticpoints}] The value must be a comma
+separated list of decimal numbers indicating where to put the
+$x$ tick marks. If omitted, the $x$ tick marks are placed at
+equal intervals along the $x$ axis such that each interval is
+not less than the length given by \ics{DTLmintickgap}.
+This setting overrides \csopt{DTLplot}{xticgap}.
+
+\item[\csopt{DTLplot}{xticgap}] This value specifies the
+gap between the $x$ tick marks.
+
+\item[\csopt{DTLplot}{yticpoints}] The value must be a comma
+separated list of decimal numbers indicating where to put the
+$y$ tick marks. If omitted, the $y$ tick marks are placed at
+equal intervals along the $y$ axis such that each interval is
+not less than the length given by \ics{DTLmintickgap}.
+This setting overrides \csopt{DTLplot}{yticgap}.
+
+\item[\csopt{DTLplot}{yticgap}] This value specifies the
+gap between the $y$ tick marks.
+
+\item[\csopt{DTLplot}{grid}] This is a boolean value that
+specifies whether or not to display the grid. If no value
+is given, "true" is assumed. The minor grid lines are only
+displayed if the minor tick marks are set.
+
+\item[\csopt{DTLplot}{xticlabels}] The value must be a comma
+separated list of labels for each $x$ tick mark. If omitted,
+the labels are the value of the $x$ tick position, rounded
+\meta{n} digits after the decimal point, where \meta{n} is
+given by the value of the counter \ctr{DTLplotroundXvar}.
+
+\item[\csopt{DTLplot}{yticlabels}] The value must be a comma
+separated list of labels for each $y$ tick mark. If omitted,
+the labels are the value of the $y$ tick position, rounded
+\meta{n} digits after the decimal point, where \meta{n} is
+given by the value of the counter \ctr{DTLplotroundYvar}.
+
+\item[\csopt{DTLplot}{xlabel}] The value is the label for
+the $x$ axis. If omitted, the axis has no label.
+
+\item[\csopt{DTLplot}{ylabel}] The value is the label for
+the $y$ axis. If omitted, the axis has no label.
+
+\item[\csopt{DTLplot}{legend}] This setting governs whether
+or not to display the legend, and where it should be displayed.
+It may take one of the following values "none" (don't display
+the legend), "north", "northeast", "east", "southeast", "south",
+"southwest", "west" or "northwest". If the value is omitted,
+"northeast" is assumed.
+
+\item[\csopt{DTLplot}{legendlabels}] The value must be a comma
+separated list of labels for the legend. If omitted, the database
+names are used.
+
+\end{description}
+
+\begin{example}{A Basic Graph}{ex:basicplot}
+Suppose you have a file called "groupa.csv" that contains the
+following:
+\DTLnewdb{groupa}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.54}\relax
+\DTLnewdbentry{groupa}{Weight}{48.0}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.55}\relax
+\DTLnewdbentry{groupa}{Weight}{45.4}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.56}\relax
+\DTLnewdbentry{groupa}{Weight}{58.0}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.56}\relax
+\DTLnewdbentry{groupa}{Weight}{50.2}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.57}\relax
+\DTLnewdbentry{groupa}{Weight}{46.0}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.58}\relax
+\DTLnewdbentry{groupa}{Weight}{48.3}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.59}\relax
+\DTLnewdbentry{groupa}{Weight}{56.5}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.59}\relax
+\DTLnewdbentry{groupa}{Weight}{58.1}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.60}\relax
+\DTLnewdbentry{groupa}{Weight}{60.9}\relax
+\DTLnewrow{groupa}\relax
+\DTLnewdbentry{groupa}{Height}{1.62}\relax
+\DTLnewdbentry{groupa}{Weight}{56.3}\relax
+\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+Height,Weight
+\DTLforeach{groupa}{\x=Height,\y=Weight}{\x,\y
+}\end{ttfamily}\par\noindent
+First load this into a database called "groupa":
+\begin{verbatim}
+\DTLloaddb{groupa}{groupa.csv}
+\end{verbatim}
+The data can now be converted into a scatter plot as follows:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa}{x=Height,y=Weight}
+\caption{A scatter plot}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:basicplot}.
+
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa}{x=Height,y=Weight}
+\caption{A scatter plot}
+\label{fig:basicplot}
+\end{figure}
+
+Alternatively, you can use the \csopt{DTLplot}{style} setting
+to change it into a line plot:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+\caption{A line plot}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:basiclineplot}.
+
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa}{x=Height,y=Weight,style=lines}
+\caption{A line plot}
+\label{fig:basiclineplot}
+\end{figure}
+\end{example}
+
+\begin{example}{Plotting Multiple Data Sets}{ex:2db}
+In this example, I shall use the database called "groupa" defined
+in \autoref{ex:basicplot}, and another database called "groupb"
+which is loaded from the file "groupb.csv" which contains the
+following:
+\DTLnewdb{groupb}
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.54}\relax
+\DTLnewdbentry{groupb}{Weight}{48.4}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.54}\relax
+\DTLnewdbentry{groupb}{Weight}{42.0}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.55}\relax
+\DTLnewdbentry{groupb}{Weight}{64.0}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.56}\relax
+\DTLnewdbentry{groupb}{Weight}{58.2}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.56}\relax
+\DTLnewdbentry{groupb}{Weight}{49.0}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.57}\relax
+\DTLnewdbentry{groupb}{Weight}{40.3}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.58}\relax
+\DTLnewdbentry{groupb}{Weight}{51.5}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.58}\relax
+\DTLnewdbentry{groupb}{Weight}{63.1}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.59}\relax
+\DTLnewdbentry{groupb}{Weight}{74.9}\relax
+\DTLnewrow{groupb}\relax
+\DTLnewdbentry{groupb}{Height}{1.59}\relax
+\DTLnewdbentry{groupb}{Weight}{59.3}\relax
+\begin{ttfamily}\obeylines\setlength{\parindent}{0pt}
+Height,Weight
+\DTLforeach{groupb}{\x=Height,\y=Weight}{\x,\y
+}\end{ttfamily}\par\noindent
+First load this into a database called "groupb":
+\begin{verbatim}
+\DTLloaddb{groupb}{groupb.csv}
+\end{verbatim}
+I can now plot both groups in the same graph, but I want a smaller
+graph than \autoref{fig:basicplot} and \autoref{fig:basiclineplot},
+so I am going to set the plot width and height to 3in:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+\caption{A scatter plot}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:2db}.
+
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa,groupb}{x=Height,y=Weight,width=3in,height=3in}
+\caption[A scatter plot (multiple datasets)]{A scatter plot}
+\label{fig:2db}
+\end{figure}
+
+Now let's add a legend using the \csopt{DTLplot}{legend} setting,
+with the legend labels "Group A" and "Group B",
+and set the $x$ tick intervals using \csopt{DTLplot}{xticpoints}
+setting. I am also going to set the $x$ axis label to
+"Height (m)" and the $y$ axis label to "Weight (kg)", and place
+a box around the plot.
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa,groupb}{x=Height,y=Weight,
+width=3in,height=3in,legend,legendlabels={Group A,Group B},
+xlabel={Height (m)},ylabel={Weight (kg)},box,
+xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+\caption{A scatter plot}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:legend}.
+
+\begin{figure}[htbp]
+\centering
+\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+width=3in,height=3in,legendlabels={Group A,Group B},
+xlabel={Height (m)},ylabel={Weight (kg)},box,
+xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+\caption[A scatter plot (with a legend)]{A scatter plot}
+\label{fig:legend}
+\end{figure}
+\end{example}
+
+\section{Adding Information to the Plot}
+
+The \sty{datatool} package provides two hooks used at the beginning
+and end of the \env{tikzpicture} environment:
+\begin{definition}[\DescribeMacro{\DTLplotatbegintikz}]%
+\cs{DTLplotatbegintikz}
+\end{definition}\noindent
+and
+\begin{definition}[\DescribeMacro{\DTLplotatendtikz}]%
+\cs{DTLplotatendtikz}
+\end{definition}
+They are both defined to do nothing by default, but can be redefined
+to add commands to the image. The unit vectors are set prior to
+using these hooks, so you can use the same co-ordinates as those
+in the data sets. However, to reduce the problem of exceeding \TeX's
+maximum dimension, \cs{DTLplot} scales the plot which may distort
+plot marks. To get around this use
+\begin{definition}[\DescribeMacro{\dtlplothandlermark}]
+\cs{dtlplothandlermark}\marg{pgf code}
+\end{definition}
+instead of \ics{pgfplothandlermark}\marg{pgf code}. (See
+\autoref{ex:multikey}.) Note that \cs{dtlplothandlermark} is only
+intended for use within the definition of \cs{DTLplotatbegintikz} or
+\cs{DTLplotatendtikz}. If used elsewhere it will produce a warning
+and act as though you'd just used \cs{pgfplothandlermark}.
+
+\begin{definition}[\DescribeMacro{\DTLaddtoplotlegend}]%
+\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{text}
+\end{definition}
+This adds a new row to the plot legend where \meta{marker} is
+code to produce the marker, \meta{line style} is code to set
+the line style and \meta{text} is a textual label. You can
+use \cs{relax} to suppress the marker or line. For example:
+\begin{verbatim}
+\DTLaddtoplotlegend{\pgfuseplotmark{x}}{\relax}{Some Data}
+\end{verbatim}
+Note that the legend is plotted before \cs{DTLplotatendtikz},
+so if you want to add information to the legend you will need
+to do the in \cs{DTLplotatstarttikz}.
+
+\begin{example}{Adding Information to a Plot}{ex:addtoplot}
+Returning to the plots created in \autoref{ex:2db}, suppose
+I now want to annotate the plot, say I want to draw your notice
+to a particular point, say the point (1.58,48.3), then I can
+redefine \cs{DTLplotatendtikz} to draw an annotated arrow to
+that point:
+\begin{verbatim}
+\renewcommand*{\DTLplotatendtikz}{%
+\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+ node[below]{interesting point};
+}
+\end{verbatim}
+So \autoref{fig:legend} now looks like \autoref{fig:annote}.
+(Obviously, \cs{DTLplotatendtikz} needs to be redefined before
+using \cs{DTLplot}.)
+
+\begin{figure}[htbp]
+\renewcommand*{\DTLplotatendtikz}{%
+\draw[<-,line width=1pt] (1.58,48.3) -- (1.6,43)
+ node[below]{interesting point};
+}
+\centering
+\DTLplot{groupa,groupb}{x=Height,y=Weight,legend,
+width=3in,height=3in,legendlabels={Group A,Group B},box,
+xlabel={Height (m)},ylabel={Weight (kg)},
+xticpoints={1.54,1.55,1.56,1.57,1.58,1.59,1.60,1.61,1.62}}
+\caption[A scatter plot (using the end plot hook to annotate the
+plot)]{A scatter plot}
+
+\label{fig:annote}
+\end{figure}
+\end{example}
+
+\section{Global Plot Settings}
+
+\subsection{Lengths}
+This section describes the lengths that govern the appearance of
+the plot created using \ics{DTLplot}. These lengths can be
+changed using \cs{setlength}.
+
+\begin{definition}[\DescribeMacro{\DTLplotwidth}]%
+\cs{DTLplotwidth}
+\end{definition}
+This length governs the length of the $x$ axis. Note that the plot
+width does not include any outer tick marks or labels. The default
+value is 4in.
+
+\begin{definition}[\DescribeMacro{\DTLplotheight}]%
+\cs{DTLplotheight}
+\end{definition}
+This length governs the length of the $y$ axis. Note that the plot
+height does not include any outer tick marks or labels. The default
+value is 4in
+
+\begin{definition}[\DescribeMacro{\DTLticklength}]%
+\cs{DTLticklength}
+\end{definition}
+This governs the length of the tick marks. The default value is
+5pt.
+
+\begin{definition}[\DescribeMacro{\DTLminorticklength}]%
+\cs{DTLminorticklength}
+\end{definition}
+This governs the length of the minor tick marks. The default value is
+2pt.
+
+\begin{definition}[\DescribeMacro{\DTLticklabeloffset}]%
+\cs{DTLticklabeloffset}
+\end{definition}
+This governs the distance from the axis to the tick labels. The
+default value is 8pt.
+
+\begin{definition}[\DescribeMacro{\DTLmintickgap}]%
+\cs{DTLmintickgap}
+\end{definition}
+This is the minimum distance allowed between tick marks. If the
+plot width or height is less than this distance there will only
+be tick marks at either end of the axis. The default value is
+20pt.
+
+\begin{definition}[\DescribeMacro{\DTLlegendxoffset}]%
+\cs{DTLlegendxoffset}
+\end{definition}
+This is the horizontal distance from the border of the plot to the
+outer border of the legend. The default value is 10pt.
+
+\begin{definition}[\DescribeMacro{\DTLlegendyoffset}]%
+\cs{DTLlegendyoffset}
+\end{definition}
+This is the vertical distance from the border of the plot to the
+outer border of the legend. The default value is 10pt.
+
+\subsection{Counters}
+These counters govern the appearance of plots
+created using \ics{DTLplot}. The value of the counters can be
+changed using \cs{setcounter}.
+
+\begin{definition}[\DescribeCounter{DTLplotroundXvar}]
+\ctrfmt{DTLplotroundXvar}
+\end{definition}
+Unless you specify your own tick labels, the $x$ tick labels will
+be given by the tick points rounded to \meta{n} digits after the
+decimal point, where \meta{n} is the value of the counter
+\ctrfmt{DTLplotroundXvar}.
+
+\begin{definition}[\DescribeCounter{DTLplotroundYvar}]
+\ctrfmt{DTLplotroundYvar}
+\end{definition}
+Unless you specify your own tick labels, the $y$ tick labels will
+be given by the tick points rounded to \meta{n} digits after the
+decimal point, where \meta{n} is the value of the counter
+\ctrfmt{DTLplotroundYvar}.
+
+\subsection{Macros}
+These macros govern the appearance of plots created using
+\ics{DTLplot}. They can be changed using \cs{renewcommand}.
+
+\begin{definition}[\DescribeMacro{\DTLplotmarks}]%
+\cs{DTLplotmarks}
+\end{definition}
+This must be a comma separated list of \sty{pgf} code to create the
+plot marks. \ics{DTLplot} cycles through this list for each
+database listed. The \sty{pgf} package provides convenient commands
+for generating plots using \cs{pgfuseplotmark}. See the \sty{pgf}
+manual for more details.
+
+\begin{definition}[\DescribeMacro{\DTLplotmarkcolors}]%
+\cs{DTLplotmarkcolors}
+\end{definition}
+This must be a comma separated list of defined colours to apply to the
+plot marks. \ics{DTLplot} cycles through this list for each database
+listed. If this macro is set to empty, the current colour will
+be used instead.
+
+\begin{definition}[\DescribeMacro{\DTLplotlines}]%
+\cs{DTLplotlines}
+\end{definition}
+This must be a comma separated list of \sty{pgf} code to set the
+style of the plot lines. \ics{DTLplot} cycles through this list for
+each database listed. Dash patterns can be set using \cs{pgfsetdash},
+see the \sty{pgf} manual for more details. If \cs{DTLplotlines} is
+set to empty the current line style will be used instead.
+
+\begin{definition}[\DescribeMacro{\DTLplotlinecolors}]%
+\cs{DTLplotlinecolors}
+\end{definition}
+This must be a comma separated list of defined colours to apply to the
+plot lines. \cs{DTLplot} cycles through this list for each database
+listed. If this macro is set to empty, the current colour will
+be used instead. The default is the same as \cs{DTLplotmarkcolors}.
+
+\begin{definition}[\DescribeMacro{\DTLXAxisStyle}]%
+\cs{DTLXAxisStyle}
+\end{definition}
+This governs the style of the $x$ axis. It is passed as the optional
+argument to the TikZ \cs{draw} command. By default it is just "-"
+which is a solid line style with no start or end arrows. The $x$
+axis line starts from the bottom left corner of the plot and extends
+to the bottom right corner of the plot. So if you want the $x$ axis
+to have an arrow head at the right end, you can do:
+\begin{verbatim}
+\renewcommand*{\DTLXAxisStyle}{->}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLYAxisStyle}]%
+\cs{DTLYAxisStyle}
+\end{definition}
+This governs the style of the $y$ axis. It is analogous to
+\cs{DTLXAxisStyle} described above.
+
+\begin{definition}[\DescribeMacro{\DTLmajorgridstyle}]%
+\cs{DTLmajorgridstyle}
+\end{definition}
+This specifies the format of the major grid lines.
+It may be set to any TikZ setting that you can pass to the
+optional argument of \cs{draw}. The default value is
+"color=gray,-" which indicates a grey solid line.
+
+\begin{definition}[\DescribeMacro{\DTLminorgridstyle}]%
+\cs{DTLminorgridstyle}
+\end{definition}
+This specifies the format of the minor grid lines.
+It may be set to any TikZ setting that you can pass to the
+optional argument of \cs{draw}. The default value is
+"color=gray,loosely dotted" which indicates a grey dotted line.
+
+\begin{definition}[\DescribeMacro{\DTLformatlegend}]%
+\cs{DTLformatlegend}\marg{legend}
+\end{definition}
+This formats the entire legend, which is passed as the argument.
+The default is to set the legend with
+a white background, a black frame.
+
+\section{Adding to a Plot Stream}
+
+\begin{definition}[\DescribeMacro{\DTLplotstream}]%
+\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key}
+\end{definition}
+This adds points to a stream from the database called \meta{db name}
+where the $x$ co-ordinates are given by the key \meta{x key}
+and the $y$ co-ordinates are given by the key \meta{y key}.
+(\ics{DTLconverttodecimal} is used to convert locale dependent
+values to a standard decimal that is recognised by the
+\sty{pgf} package.)
+The optional argument \meta{condition} is the same as that
+for \ics{DTLforeach}.
+
+\begin{example}{Adding to a Plot Stream}{ex:plotstream}
+Suppose you have a CSV file called "data.csv" containing the
+following:
+\begin{verbatim}
+x,y
+0,0
+1,1
+2,0.5
+1.5,0.3
+\end{verbatim}
+\DTLnewdb{data}\relax
+\DTLnewrow{data}\relax
+\DTLnewdbentry{data}{x}{0}\relax
+\DTLnewdbentry{data}{y}{0}\relax
+\DTLnewrow{data}\relax
+\DTLnewdbentry{data}{x}{1}\relax
+\DTLnewdbentry{data}{y}{1}\relax
+\DTLnewrow{data}\relax
+\DTLnewdbentry{data}{x}{2}\relax
+\DTLnewdbentry{data}{y}{0.5}\relax
+\DTLnewrow{data}\relax
+\DTLnewdbentry{data}{x}{1.5}\relax
+\DTLnewdbentry{data}{y}{0.3}\relax
+First load the file into a database called "data":
+\begin{verbatim}
+\DTLloaddb{data}{data.csv}
+\end{verbatim}
+Now create a figure containing this data:
+\begin{verbatim}
+\begin{figure}[tbhp]
+\centering
+\begin{tikzpicture}
+\pgfplothandlermark{\pgfuseplotmark{o}}
+\pgfplotstreamstart
+\DTLplotstream{data}{x}{y}%
+\pgfplotstreamend
+\pgfusepath{stroke}
+\end{tikzpicture}
+\caption{Adding to a plot stream}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:plotstream}.
+
+\begin{figure}[tbhp]
+\centering
+\begin{tikzpicture}
+\pgfplothandlermark{\pgfuseplotmark{o}}
+\pgfplotstreamstart
+\DTLplotstream{data}{x}{y}%
+\pgfplotstreamend
+\pgfusepath{stroke}
+\end{tikzpicture}
+\caption{Adding to a plot stream}
+\label{fig:plotstream}
+\end{figure}
+\end{example}
+
+\begin{example}{Plotting Multiple Keys in the Same
+Database}{ex:multikey}
+Suppose I have conducted two time to growth experiments. For each
+experiment, I have recorded the log count at set times, and I have
+recorded this information in the same data file called, say,
+"growth.csv" which contains the following:
+\begin{verbatim}
+Time,Experiment 1,Experiment 2
+0,3.73,3.6
+23,3.67,3.7
+60,4.9,3.8
+\end{verbatim}
+\DTLnewdb{growth}\DTLnewrow{growth}\relax
+\DTLnewdbentry{growth}{Time}{0}\relax
+\DTLnewdbentry{growth}{Experiment 1}{3.73}\relax
+\DTLnewdbentry{growth}{Experiment 2}{3.6}\relax
+\DTLnewrow{growth}\relax
+\DTLnewdbentry{growth}{Time}{23}\relax
+\DTLnewdbentry{growth}{Experiment 1}{3.67}\relax
+\DTLnewdbentry{growth}{Experiment 2}{3.7}\relax
+\DTLnewrow{growth}\relax
+\DTLnewdbentry{growth}{Time}{60}\relax
+\DTLnewdbentry{growth}{Experiment 1}{4.9}\relax
+\DTLnewdbentry{growth}{Experiment 2}{3.8}\relax
+I can load the data into a database using:
+\begin{verbatim}
+\DTLloaddb{growth}{growth.csv}
+\end{verbatim}
+However, I'd like to plot both results on the same graph. Since they
+are contained in the same database, I can't use the method I used
+in \autoref{ex:2db}. Instead I can use a combination of
+\ics{DTLplot} and \ics{DTLplotstream}:
+\begin{verbatim}
+\begin{figure}[tbhp]
+\centering
+ % compute bounds
+\DTLminforkeys{growth}{Time}{\minX}
+\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+\DTLmaxforkeys{growth}{Time}{\maxX}
+\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+ % round x tick labels to 1 d.p.
+\setcounter{DTLplotroundXvar}{1}
+ % redefine \DTLplotatbegintikz to plot the data for Experiment 1
+\renewcommand*{\DTLplotatbegintikz}{%
+ % set plot mark
+ \dtlplothandlermark{\color{green}\pgfuseplotmark{x}}
+ % start plot stream
+ \pgfplotstreamstart
+ % add data from Experiment 1 to plot stream
+ \DTLplotstream{growth}{Time}{Experiment 1}%
+ % end plot stream
+ \pgfplotstreamend
+ % stroke path
+ \pgfusepath{stroke}
+ % add information to legend (no line is require so use \relax)
+ \DTLaddtoplotlegend{\color{green}%
+ \pgfuseplotmark{x}}{\relax}{Experiment 1}
+}
+ % now plot the data for Experiment 2
+\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+xlabel={Time},ylabel={Log Count},
+legendlabels={Experiment 2}}
+\caption{Time to growth data}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:multikey}.
+Notes:
+\begin{itemize}
+\item I redefined \ics{DTLplotatbegintikz} in order to add
+the new plot to the legend, since \ics{DTLplotatendtikz} is
+used after the legend is plotted. The $x$ and $y$ unit vectors
+are set before \ics{DTLplotatbegintikz} so I don't need to
+worry about the co-ordinates, however I've had to use
+\ics{dtlplothandlermark} instead of \ics{pgfplothandlermark}
+to prevent the plot marks from being distorted.
+\item I have used \ics{DTLminforkeys} and \ics{DTLmaxforkeys} to
+determine the bounds since \ics{DTLplot} won't take the data
+for Experiment~1 into account when computing the bounds.
+\end{itemize}
+
+\begin{figure}[htbp]
+\DTLminforkeys{growth}{Time}{\minX}
+\DTLminforkeys{growth}{Experiment 1,Experiment 2}{\minY}
+\DTLmaxforkeys{growth}{Time}{\maxX}
+\DTLmaxforkeys{growth}{Experiment 1,Experiment 2}{\maxY}
+\setcounter{DTLplotroundXvar}{1}
+\renewcommand*{\DTLplotatbegintikz}{%
+\dtlplothandlermark{\color{green}\pgfuseplotmark{x}}
+\pgfplotstreamstart
+\DTLplotstream{growth}{Time}{Experiment 1}%
+\pgfplotstreamend
+\pgfusepath{stroke}
+\DTLaddtoplotlegend{\color{green}\pgfuseplotmark{x}}{\relax}{Experiment 1}
+}
+\centering
+\DTLplot{growth}{x=Time,y=Experiment 2,legend,
+width=3in,height=3in,bounds={\minX,\minY,\maxX,\maxY},
+xlabel={Time},ylabel={Log Count},
+legendlabels={Experiment 2}}
+\caption[Time to growth data (plotting from the same database using
+different keys)]{Time to growth data}
+\label{fig:multikey}
+\end{figure}
+\end{example}
+
+\chapter{Bar Charts (\texorpdfstring{\sty{databar}}{databar}
+package)}
+\label{sec:databar}
+
+The \sty{databar} package provides commands for creating bar charts.
+It is not loaded by the \sty{datatool} package, so if you want to
+use it you will need to load it explicitly using
+"\usepackage{databar}". You must also have the \sty{pgf} package
+installed.
+
+Bar charts can either be vertical or horizontal, the default is
+vertical. In this section the $x$ axis refers to the horizontal
+axis when plotting a vertical bar chart and to the vertical axis
+when plotting a horizontal bar chart. The $x$ axis units are in
+increments of one bar. The $y$ axis refers to the vertical axis
+when plotting a vertical bar chart and to the horizontal axis when
+plotting a horizontal bar chart. The $y$ axis uses the same
+co-ordinates as the data. The bars may have an upper and lower
+label. In a vertical bar chart, the lower label is placed below
+the $x$ axis and the upper label is placed above the top of the bar.
+In a horizontal bar chart, the lower label is placed to the left of
+the $x$ axis and the upper label is placed to the right of the
+end of the bar. (This is actually a misnomer as it is possible
+for the ``upper'' label to be below the ``lower'' label if a
+bar has a negative value, however the bars are considered to
+be anchored on the $x$ axis, and the other end of the bar is
+considered to be the ``upper'' end, regardless of its
+direction.)
+
+The \sty{databar} package options are as follows:
+\begin{description}
+\item[{\pkgopt{color}}] Created coloured bar charts
+(default).
+
+\item[{\pkgopt{gray}}] Created grey scale bar charts.
+
+\item[{\pkgopt{vertical}}] Created vertical bar charts
+(default).
+
+\item[{\pkgopt{horizontal}}] Created horizontal bar charts.
+\end{description}
+
+
+
+\begin{definition}[\DescribeMacro{\DTLbarchart}]%
+\cs{DTLbarchart}\oarg{condition}\marg{settings}\marg{db name}\marg{values}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLmultibarchart}]%
+\cs{DTLmultibarchart}\oarg{condition}\marg{settings}\marg{db name}\marg{values}
+\end{definition}
+These commands both create a bar chart from the information in
+the database \meta{db name}, where \meta{condition} is the same
+as the optional argument for \ics{DTLforeach} described in
+\autoref{sec:dbforeach}, and \meta{values} is the same as the
+penultimate argument of \ics{DTLforeach}. The \meta{settings}
+argument is a \meta{setting}"="\meta{value} list of settings. The
+first command, \cs{DLTbarchart}, will draw a bar chart for a
+given column of data in the database, whereas the second command,
+\cs{DTLmultibarchart}, will draw a bar chart that is divided into
+groups of bars where each bar within a group represents data from
+several columns of a given row in the database.
+
+The \csopt{DTLbarchart}{variable} setting is
+required for \cs{DTLbarchart} and the
+\csopt{DTLmultibarchart}{variables}, the other settings are
+optional (though some may only be used for one of
+\cs{DTLbarchart} and \cs{DLTmultibarchart}), and are as follows:
+
+\begin{description}
+\item[\csopt{DTLbarchart}{variable}]
+This specifies the control sequence to use that
+contains the value used to construct the bar chart. The control
+sequence must be one of the control sequences to appear in
+the assignment list \meta{values}. This setting is required
+for \cs{DTLbarchart}, and is unavailable for \cs{DTLmultibarchart}.
+
+\item[\csopt{DTLmultibarchart}{variables}]
+This specifies a list of control sequences to use which
+contain the values used to construct the bar chart. Each control
+sequence must be one of the control sequences to appear in
+the assignment list \meta{values}. This setting is required
+for \cs{DTLmultibarchart}, and is unavailable for
+\cs{DTLbarchart}.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{max}]
+This specifies the maximum value on the $y$ axis. (This should
+be a standard decimal value.)
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{length}]
+This specifies the overall length of the $y$ axis, and must
+be a dimension.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{maxdepth}]
+This must be a zero or negative number. It specifies the maximum
+depth of the $y$ axis. (This should be a standard decimal value.)
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{axes}]
+This setting specifies which axes to display. This may take one
+of the following values: "both", "x", "y" or "none".
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{barlabel}]
+This setting specifies the lower bar label. When used with
+\cs{DTLmultibarchart} it indicates the group label.
+
+\item[\csopt{DTLmultibarchart}{multibarlabels}]
+This setting should contain a comma separated list of labels
+for each bar within a group for \cs{DTLmultibarchart}. This
+setting is not available for \cs{DTLbarchart}.
+
+\item[\csopt{DTLbarchart}{upperbarlabel}]
+This setting specifies the upper bar label. This setting
+is not available for \cs{DTLmultibarchart}.
+
+\item[\csopt{DTLmultibarchart}{uppermultibarlabels}]
+This setting must be a comma separated list of upper bar
+labels for each bar within a group. This setting is not
+available for \cs{DTLbarchart}.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{yticpoints}]
+This must be a comma separated list of tick locations for the
+$y$ axis. (These should be standard decimal values.)
+This setting overrides \csopt{DTLbarchart}{yticgap}.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{yticgap}]
+This specifies the gap between the $y$ tick marks. (This should
+be a standard decimal value.)
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{yticlabels}]
+This must be a comma separated list of tick labels for the
+$y$ axis.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{ylabel}]
+This specifies the label for the $y$ axis.
+
+\item[\csopt{DTLmultibarchart}{groupgap}] This specifies
+the gap between groups when using \cs{DTLmultibarchart}.
+This value is given as a multiple of the bar width. The
+default value is 1, which indicates a gap of one bar width.
+This setting is not available for \cs{DTLbarchart}.
+
+\item[\csopt{DTLbarchart,DTLmultibarchart}{verticalbars}]
+This is a boolean setting, so it can only take the values
+"true" (do a vertical bar chart) or "false" (do a horizontal
+bar chart). If the value is omitted, "true" is assumed.
+\end{description}
+
+\begin{example}{A Basic Bar Chart}{ex:barchart}
+Recall \autoref{ex:piechart} defined a database called "fruit".
+This example will be using that database to plot a bar chart.
+The following plots a basic vertical bar chart:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+\caption{A basic bar chart}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:barchart}.
+
+\begin{figure}[htbp]
+\centering
+\DTLbarchart{variable=\theQuantity}{fruit}{\theQuantity=Quantity}
+\caption{A basic bar chart}
+\label{fig:barchart}
+\end{figure}
+\end{example}
+
+\section{Changing the Appearance of a Bar Chart}
+
+
+\begin{definition}[\DescribeMacro{\DTLbarchartlength}]%
+\cs{DTLbarchartlength}
+\end{definition}
+This specifies the total length of the $y$ axis. You must use
+\cs{setlength} to change this value. The default value is 3in.
+
+\begin{definition}[\DescribeMacro{\DTLbarwidth}]%
+\cs{DTLbarwidth}
+\end{definition}
+This specifies the width of each bar. You must use \cs{setlength}
+to change this value. The default value is 1cm.
+
+\begin{definition}[\DescribeMacro{\DTLbarlabeloffset}]%
+\cs{DTLbarlabeloffset}
+\end{definition}
+This specifies the distance from the $x$ axis to the lower bar label.
+You must use \cs{setlength} to change this value. The default value
+is 10pt.
+
+\begin{definition}[\DescribeCounter{DTLbarroundvar}]
+\ctrfmt{DTLbarroundvar}
+\end{definition}
+The $y$ tick labels are rounded to \meta{n} digits after the
+decimal point, where \meta{n} is given by the value of the
+counter \ctrfmt{DTLbarroundvar}. You must use \cs{setcounter}
+to change this value.
+
+\begin{definition}[\DescribeMacro{\DTLsetbarcolor}]%
+\cs{DTLsetbarcolor}\marg{n}\marg{color}
+\end{definition}
+This sets the \meta{n}th bar colour to \meta{color}.
+Only the first eight bars have a colour defined by default. If you
+need more than eight bars, you will need to define more bar colours.
+It is recommended that you set the colour of each bar to
+correspond with whatever the bar represents.
+
+\begin{definition}[\DescribeMacro{\DTLdobarcolor}]%
+\cs{DTLdobarcolor}\marg{n}
+\end{definition}
+This sets the current colour to the colour of the \meta{n}th bar.
+
+\begin{definition}[\DescribeMacro{\DTLbaroutlinecolor}]%
+\cs{DTLbaroutlinecolor}
+\end{definition}
+This macro contains the colour of the bar outlines. This defaults
+to "black".
+
+\begin{definition}[\DescribeMacro{\DTLbaroutlinewidth}]%
+\cs{DTLbaroutlinewidth}
+\end{definition}
+This length specifies the line width for the bar outlines. If it
+is 0pt, the outline is not drawn. The default value is 0pt.
+
+
+\begin{definition}[\DescribeMacro{\DTLbaratbegintikz}]%
+\cs{DTLbaratbegintikz}
+\end{definition}
+This specifies any additional commands to add to the start of
+the plot. It defaults to nothing, and is called after the
+unit vectors are set.
+
+\begin{definition}[\DescribeMacro{\DTLbaratendtikz}]%
+\cs{DTLbaratendtikz}
+\end{definition}
+This specifies any additional commands to add to the end of
+the plot. It defaults to nothing.
+
+\begin{definition}[\DescribeMacro{\DTLeverybarhook}]%
+\cs{DTLeverybarhook}
+\end{definition}
+The specifies code to apply at every bar. Within the definition
+of \cs{DTLeverybarhook} you can use the commands
+\DescribeMacro{\DTLstartpt}\cs{DTLstartpt} (the start
+of the bar), \DescribeMacro{\DTLmidpt}\cs{DTLmidpt}
+(the mid point of the bar) and
+\DescribeMacro{\DTLendpt}\cs{DTLendpt} (the end of the bar). For
+example (using the earlier "fruit" database):
+\begin{verbatim}
+\renewcommand*{\DTLeverybarhook}{%
+\pgftext[at=\DTLmidpt]{\insertName\space(\insertValue)}%
+}
+\DTLbarchart{variable=\insertValue,axes=both,
+ylabel=Quantity,max=50,verticalbars=false
+}%
+{fruit}{\insertValue=Value,\insertName=Name}
+\end{verbatim}
+This puts the name followed by the quantity in brackets in the
+middle of the bar.
+
+\begin{definition}[\DescribeMacro{\ifDTLverticalbars}]%
+\cs{ifDTLverticalbars}
+\end{definition}
+This conditional governs whether the chart uses vertical or
+horizontal bars.
+
+\begin{definition}[\DescribeMacro{\DTLbarXlabelalign}]%
+\cs{DTLbarXlabelalign}
+\end{definition}
+This specifies the text alignment of the lower bar labels. This
+defaults to "left,rotate=-90" if you use the \pkgopt{vertical}
+package option or the \csopt{DTLbarchart}{verticalbars} setting,
+and defaults to "right" if you use the \pkgopt{horizontal}
+package option or the \csopt{DTLbarchart}{verticalbars}"=false"
+setting.
+
+\begin{definition}[\DescribeMacro{\DTLbarYticklabelalign}]%
+\cs{DTLbarYlabelalign}
+\end{definition}
+This specifies the text alignment of the $y$ axis labels. This
+defaults to "right" for vertical bar charts and "center" for
+horizontal bar charts.
+
+\begin{definition}[\DescribeMacro{\DTLbardisplayYticklabel}]%
+\cs{DTLbardisplayYticklabel}\marg{text}
+\end{definition}
+This specifies how to display the $y$ tick label. The argument
+is the tick label.
+
+\begin{definition}[\DescribeMacro{\DTLdisplaylowerbarlabel}]%
+\cs{DTLdisplaylowerbarlabel}\marg{text}
+\end{definition}
+This specifies how to display the lower bar label for
+\cs{DTLbarchart} and the lower bar group label for
+\cs{DTLmultibarchart}. The argument is the label.
+
+\begin{definition}[\DescribeMacro{\DTLdisplaylowermultibarlabel}]%
+\cs{DTLdisplaylowermultibarlabel}\marg{text}
+\end{definition}
+This specifies how to display the lower bar label for
+\cs{DTLmultibarchart}. The argument is the label. This
+command is ignored by \cs{DTLbarchart}.
+
+\begin{definition}[\DescribeMacro{\DTLdisplayupperbarlabel}]%
+\cs{DTLdisplayupperbarlabel}\marg{text}
+\end{definition}
+This specifies how to display the upper bar label for
+\cs{DTLbarchart} and the upper bar group label for
+\cs{DTLmultibarchart}. The argument is the label.
+
+\begin{definition}[\DescribeMacro{\DTLdisplayuppermultibarlabel}]%
+\cs{DTLdisplayuppermultibarlabel}\marg{text}
+\end{definition}
+This specifies how to display the upper bar label for
+\cs{DTLmultibarchart}. The argument is the label. This
+command is ignored by \cs{DTLbarchart}.
+
+\begin{example}{A Labelled Bar Chart}{ex:annotebarchart}
+This example extends \autoref{ex:barchart} so that the chart is
+a bit more informative (which is after all the whole point of
+a chart). This chart now has a label below each bar, as well
+as a label above the bar. The lower label uses the value of the
+"Name" key, and the upper label uses the quantity. I have also
+set the outline width so each bar has a border.
+\begin{verbatim}
+\begin{figure}[htbp]
+\setlength{\DTLbaroutlinewidth}{1pt}
+\centering
+\DTLbarchart{variable=\theQuantity,barlabel=\theName,%
+upperbarlabel=\theQuantity}{fruit}{%
+\theQuantity=Quantity,\theName=Name}
+\caption{A bar chart}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:annotebarchart}.
+
+\begin{figure}[htbp]
+\centering
+\setlength{\DTLbaroutlinewidth}{1pt}
+\DTLbarchart{variable=\theQuantity,barlabel=\theName,
+upperbarlabel=\theQuantity}{fruit}{\theQuantity=Quantity,\theName=Name}
+\caption[A bar chart (labelled)]{A bar chart}
+\label{fig:annotebarchart}
+\end{figure}
+\end{example}
+
+\begin{example}{Profit/Loss Bar Chart}{ex:profit}
+Suppose I have a file called "profits.csv" that looks like:
+\DTLnewdb{profits}
+\DTLnewrow{profits}
+\DTLnewdbentry{profits}{Year}{2000}\relax
+\DTLnewdbentry{profits}{Profit}{\protect\pounds2,525}\relax
+\DTLnewrow{profits}
+\DTLnewdbentry{profits}{Year}{2001}\relax
+\DTLnewdbentry{profits}{Profit}{\protect\pounds3,752}\relax
+\DTLnewrow{profits}
+\DTLnewdbentry{profits}{Year}{2002}\relax
+\DTLnewdbentry{profits}{Profit}{-\protect\pounds1,520}\relax
+\DTLnewrow{profits}
+\DTLnewdbentry{profits}{Year}{2003}\relax
+\DTLnewdbentry{profits}{Profit}{\protect\pounds1,270}\relax
+\begin{verbatim}
+Year,Profit
+2000,\pounds2,535
+2001,\pounds3,752
+2002,-\pounds1,520
+2003,\pounds1,270
+\end{verbatim}
+First I can load this file into a database called "profits":
+\begin{verbatim}
+\DTLloaddb{profits}{profits.csv}
+\end{verbatim}
+Now I can plot the data as a bar chart:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+ % Set the width of each bar to 10pt
+\setlength{\DTLbarwidth}{10pt}
+ % Set the outline width to 1pt
+\setlength{\DTLbaroutlinewidth}{1pt}
+ % Round the $y$ tick labels to integers
+\setcounter{DTLbarroundvar}{0}
+ % Adjust the tick label offset
+\setlength{\DTLticklabeloffset}{20pt}
+ % Change the y tick label alignment
+\renewcommand*{\DTLbarYticklabelalign}{left}
+ % Rotate the y tick labels
+\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+ % Set the bar colours depending on the value of \theProfit
+\DTLforeach{profits}{\theProfit=Profit}{%
+\ifthenelse{\DTLislt{\theProfit}{0}}
+{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+ % Do the bar chart
+\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+ylabel={Profit/Loss (\pounds)},verticalbars=false,
+maxdepth=-2000,max=4000}{profits}
+{\theProfit=Profit,\theYear=Year}
+\caption{Profits for 2000--2003}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:profits}. Notes:
+\begin{enumerate}
+\item This example uses \cs{rotatebox}, so the \sty{graphics}
+or \sty{graphicx} package is required.
+\item The $y$ tick labels are too wide to fit horizontally
+so they have been rotated to avoid overlapping with their
+neighbour.
+\item Rotating the $y$ tick labels puts them too close to
+the $y$ axis, so \ics{DTLticklabeloffset} is made larger to
+compensate.
+\item Remember not to use \cs{year} as an assignment command
+as this command already exists!
+\item Before the bar chart is created I have iterated through
+the database, setting the bar colour to red or blue
+depending on the value of \cs{theProfit}.
+\end{enumerate}
+
+Both \cs{DTLbarchart} and \cs{DTLmultibarchart} set the following
+macros, which may be used in \cs{DTLbaratbegintikz} and
+\cs{DTLbaratendtikz}:
+\begin{definition}[\DescribeMacro{\DTLbarchartwidth}]%
+\cs{DTLbarchartwidth}
+\end{definition}
+This is the overall width of the bar chart. In the case of
+\cs{DTLbarchart} this is just the number of bars. In the case
+of \cs{DTLmultibarchart} it is computed as:
+\begin{displaymath}
+m \times n + (m-1)\times g
+\end{displaymath}
+where $m$ is the number of bar groups (i.e.\ the number of rows
+of data), $n$ is the number of bars within a group (i.e.\
+the number of commands listed in the
+\csopt{DTLmultibarchart}{variables}) setting and $g$ is the
+group gap (as specified by the \csopt{DTLmultibarchart}{groupgap} setting).
+
+\begin{definition}[\DescribeMacro{\DTLnegextent}]%
+\cs{DTLnegextent}
+\end{definition}
+This is set to the negative extent of the bar chart. (This value
+may either be zero or negative, and corresponds to the
+\csopt{DTLbarchart,DTLmultibarchart}{maxdepth} setting.)
+
+\begin{definition}[\DescribeMacro{\DTLbarmax}]%
+\cs{DTLbarmax}
+\end{definition}
+This is set to the maximum extent of the bar chart. (This value
+corresponds to the
+\csopt{DTLbarchart,DTLmultibarchart}{max} setting.)
+
+\begin{figure}[htbp]
+\centering
+\setlength{\DTLbarwidth}{10pt}
+\setlength{\DTLbaroutlinewidth}{1pt}
+\setlength{\DTLticklabeloffset}{20pt}
+\setcounter{DTLbarroundvar}{0}
+\renewcommand*{\DTLbarYticklabelalign}{left}
+\renewcommand*{\DTLbardisplayYticklabel}[1]{\rotatebox{-45}{#1}}
+\DTLforeach{profits}{\theProfit=Profit}{\relax
+\ifthenelse{\DTLislt{\theProfit}{0}}
+{\DTLsetbarcolor{\DTLcurrentindex}{red}}
+{\DTLsetbarcolor{\DTLcurrentindex}{blue}}}
+\DTLbarchart{variable=\theProfit,upperbarlabel=\theYear,
+ylabel={Profit/Loss (\pounds)},verticalbars=false,
+maxdepth=-2000,max=4000
+}{profits}
+{\theProfit=Profit,\theYear=Year}
+\caption[Profits for 2000--2003 (a horizontal bar chart)]{Profits for
+2000--2003}
+\label{fig:profits}
+\end{figure}
+
+\end{example}
+
+\begin{example}{A Multi-Bar Chart}{ex:multibar}
+This example uses the "marks" database described in
+\autoref{ex:editdb}.
+Recall that this database stores student marks for three
+assignments. The keys for the assignment marks are
+\texttt{Assignment 1}, \texttt{Assignment 2} and
+\texttt{Assignment 3}, respectively. I can convert this
+data into a bar chart using the following:
+\begin{verbatim}
+\begin{figure}[htbp]
+\centering
+\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+barlabel={\firstname\ \surname}}{marks}{%
+\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,%
+\assignII=Assignment 2,\assignIII=Assignment 3}
+\caption{Student marks}
+\end{figure}
+\end{verbatim}
+This produces \autoref{fig:multibar}. Notes:
+\begin{enumerate}
+\item I used "variables={\assignI,\assignII,\assignIII}" to
+set the variable to use for each bar within a group. This means
+that there will be three bars in each group.
+\item I have set the bar width to 10pt, otherwise the chart
+will be too wide.
+\item I used "uppermultibarlabels={\assignI,\assignII,\assignIII}"
+to set the upper labels for each bar within a group. This
+will print the assignment mark above the relevant bar.
+\item I used "barlabel={\firstname\ \surname}" to place the
+student's name below the group corresponding to that student.
+\end{enumerate}
+
+\begin{figure}[htbp]
+\centering
+\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+barlabel={\firstname\ \surname}}{marks}
+{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3}
+\caption[Student marks (a multi-bar chart)]{Student
+marks}\label{fig:multibar}
+\end{figure}
+
+Recall that \autoref{ex:editdb} computed the average score over
+for each student, and saved it with the key "Average". This
+information can be added to the bar chart. It might also be
+useful to compute the average over all students and add this
+information to the chart. This is done as follows:
+\begin{verbatim}
+ \begin{figure}[htbp]
+ \centering
+ % compute the overall mean
+ \DTLmeanforkeys{marks}{Average}{\overallmean}
+ % round it to 2 decimal places
+ \DTLround{\overallmean}{\overallmean}{2}
+ % draw a grey dotted line indicating the overall mean
+ % covering the entire width of the bar chart
+ \renewcommand*{\DTLbaratendtikz}{%
+ \draw[lightgray,loosely dotted] (0,\overallmean) --
+ (\DTLbarchartwidth,\overallmean)
+ node[right,black]{Average (\overallmean)};}
+ % Set the lower bar labels to draw a brace across the current
+ % group, along with the student's name and average score
+ \renewcommand*{\DTLdisplaylowerbarlabel}[1]{%
+ \tikz[baseline=(current bounding box.center)]{
+ \draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);}
+ \DTLround{\theMean}{\theMean}{2}%
+ \shortstack{#1\\(Average: \theMean)}}
+ % draw the bar chart
+ \DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+ barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+ barlabel={\firstname\ \surname}}{marks}
+ {\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,%
+ \assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average}
+ \caption{Student marks}
+ \end{figure}
+\end{verbatim}
+which produces \autoref{fig:multibarmean}. Notes:
+\begin{enumerate}
+\item I've used the TikZ snake library to create a brace, so
+I need to put
+\begin{verbatim}
+\usetikzlibrary{snakes}
+\end{verbatim}
+in the preamble. See the \sty{pgf} manual for more details on
+how to use this library.
+
+\item I used \ics{DTLbargroupwidth} to indicate the width of
+each bar group.
+
+\item I used \ics{DTLbarchartwidth} to indicate the width of the
+entire bar chart
+\end{enumerate}
+
+\begin{figure}[htbp]
+\centering
+\DTLmeanforkeys{marks}{Average}{\overallmean}
+\DTLround{\overallmean}{\overallmean}{2}
+\renewcommand*{\DTLbaratendtikz}{\draw[lightgray,loosely dotted] (0,\overallmean) --
+(\DTLbarchartwidth,\overallmean) node[right,black]{Average (\overallmean)};}
+\renewcommand*{\DTLdisplaylowerbarlabel}[1]{\relax
+\tikz[baseline=(current bounding box.center)]{
+\draw[snake=brace,rotate=-90](0,0) -- (\DTLbargroupwidth,0);}
+\DTLround{\theMean}{\theMean}{2}\relax
+\shortstack{#1\\(Average: \theMean)}}
+\DTLmultibarchart{variables={\assignI,\assignII,\assignIII},
+barwidth=10pt,uppermultibarlabels={\assignI,\assignII,\assignIII},
+barlabel={\firstname\ \surname}}{marks}
+{\surname=Surname,\firstname=FirstName,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII=Assignment 3,\theMean=Average}
+\caption[Student marks (annotating a bar chart)]{Student marks}
+\label{fig:multibarmean}
+\end{figure}
+
+\end{example}
+
+\chapter{Converting a \texorpdfstring{\BibTeX}{BibTeX} database
+into a \texorpdfstring{\sty{datatool}}{datatool} database
+(\texorpdfstring{\sty{databib}}{databib} package)}
+\label{sec:databib}
+
+The \sty{databib} package provides the means of converting a \BibTeX\
+database into a \sty{datatool} database. The database can then be
+sorted using \cs{DTLsort}, described in \autoref{sec:sort}.
+For example, you may want to sort the bibliography in
+reverse chronological order. Once you have sorted the bibliography,
+you can display it using \cs{DTLbibliography}, described in
+\autoref{sec:thebib}, or you can iterate through the database
+using \cs{DTLforeachbibentry}, described in \autoref{sec:foreachbib}.
+
+Note that the \sty{databib}
+package is not automatically loaded by \sty{datatool}, so if
+you want to use it, you must load it using
+"\usepackage{databib}".
+
+\begin{important}
+The purpose of this package is to provide a means for
+authors to format their own bibliography style where there is no
+bibliography style file available that produces the desired results.
+The \cs{DTLsort} macro uses a much less efficient sorting algorithm
+than \BibTeX, and loading the bibliography as a \sty{datatool}
+database is much slower than loading a standard \filetype{bbl} file. If
+you have a large database, and you are worried that \LaTeX\ may have
+become stuck, try using the \pkgopt{verbose} option to \sty{datatool}
+or use the command \cs{dtlverbosetrue}. This will print informative
+messages to the console and transcript file, to let you know what's
+going on.
+\end{important}
+
+\section{\texorpdfstring{\BibTeX}{BibTeX}: An Overview}
+\label{sec:bibtex}
+This document assumes that you have at least some passing
+familiarity with \BibTeX, but here follows a brief refresher.
+
+\BibTeX\ is an external application used in conjunction with \LaTeX.
+When you run \BibTeX, you need to specify the name of the document's
+auxiliary file (without the \filetype{aux} extension). \BibTeX\ then reads
+this file and looks for the commands \cs{bibstyle} (which indicates
+which bibliography style (\filetype{bst}) file to load), \cs{bibdata}
+(which indicates which bibliography database (\filetype{bib}) files to
+load) and \cs{citation} (produced by \cs{cite} and \cs{nocite}, which
+indicates which entries should be included in the bibliography).
+\BibTeX\ then creates a file with the extension \filetype{bbl} which
+contains the bibliography, formatted according to the layout defined
+in the bibliography style file.
+
+In general, given a document called, say, \texttt{mydoc.tex}, you
+will have to perform the following steps to ensure that the
+bibliography and all citations are up-to-date:
+\begin{enumerate}
+\item
+\begin{verbatim}
+latex mydoc
+\end{verbatim}
+This writes the citation information to the auxiliary file.
+The bibliography currently doesn't exists, so it isn't displayed.
+Citations will appear in the document as ?? since the internal
+cross-references don't exist yet.
+
+\item
+\begin{verbatim}
+bibtex mydoc
+\end{verbatim}
+This reads the auxiliary file, and creates a file with the extension
+\filetype{bbl} which typically contains the typeset bibliography.
+
+\item
+\begin{verbatim}
+latex mydoc
+\end{verbatim}
+Now that the \filetype{bbl} file exists, the bibliography can be input
+into the document. The internal cross-referencing information for the
+bibliography can now be written to the auxiliary file.
+
+\item
+\begin{verbatim}
+latex mydoc
+\end{verbatim}
+The cross-referencing information can be read from the auxiliary
+file.
+\end{enumerate}
+
+\subsection{\texorpdfstring{\BibTeX}{BibTeX} database}
+
+The bibliographic data required by \BibTeX\ must be stored in
+a file with the extension \filetype{bib}, where each entry is stored
+in the form:\par\vskip\baselineskip\noindent
+{\obeylines
+\noindent\texttt{@}\meta{entry\_type}\verb|{|\meta{cite\_key}\texttt,
+ \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\"\texttt,
+ \mbox{}\vdots
+ \meta{field\_name} \texttt{=} \char`\"\meta{value}\char`\"
+\noindent\verb|}|
+}
+\par\vskip\baselineskip\noindent
+Note that curly braces "{" and "}" may be used instead of \verb|"|
+and \verb|"|.
+
+The entry type, given by \meta{entry\_type} above, indicates
+the type of document. This may be one of: "article", "book",
+"booklet", "inbook", "incollection", "inproceedings"\footnote
+{Note that \texttt{conference} is a synonym for \texttt{inproceedings}.},
+"manual",
+"mastersthesis", "misc", "phdthesis", "proceedings", \linebreak
+"techreport" or "unpublished".
+
+The \meta{cite\_key} above is a unique label identifying this
+entry, and is the label used in the argument of \cs{cite} or
+\cs{nocite}. The available fields depends on the entry type, for
+example, the field "journal" is required for the "article" entry
+type, but is ignored for the "inproceedings" entry type. The standard
+fields are: "address", "author", "booktitle", "chapter", "edition",
+"editor", "howpublished", "institution", "journal", "key", "month",
+"note", "number", "organization", "pages", "publisher", "school",
+"series", "title", "type", "volume" and "year".
+
+Author and editor names must be entered in one of the following
+ways:
+\begin{enumerate}
+\item \meta{First names} \meta{von part} \meta{Surname}, \meta{Jr part}
+
+The \meta{von part} is optional and is identified by the name(s)
+starting with lowercase letters. The final comma followed by
+\meta{Jr part} is also optional. Examples:
+\begin{verbatim}
+author = "Henry James de Vere"
+\end{verbatim}
+In the above, the first names are Henry James, the ``von part'' is
+de and the surname is Vere. There is no ``junior part''.
+\begin{verbatim}
+author = "Mary-Jane Brown, Jr"
+\end{verbatim}
+In the above, the first name is Mary-Jane, there is no von part,
+the surname is Brown and the junior part is Jr.
+\begin{verbatim}
+author = "Peter {Murphy Allen}"
+\end{verbatim}
+In the above, the first name is Peter, and the surname is Murphy
+Allen. Note that in this case, the surname must be grouped, otherwise
+Murphy would be considered part of the forename.
+\begin{verbatim}
+author = "Maria Eliza {\uppercase{d}e La} Cruz"
+\end{verbatim}
+In the above, the first name is Maria Eliza, the von part is
+De La, and the surname is Cruz. In this case, the von part starts
+with an uppercase letter, but specifying
+\begin{verbatim}
+author = "Maria Eliza De La Cruz"
+\end{verbatim}
+would make \BibTeX\ incorrectly classify ``Maria Eliza De La'' as
+the first names, and the von part would be empty. Since \BibTeX\
+doesn't understand \LaTeX\ commands, using "{\uppercase{d}e La}"
+will trick \BibTeX\ into thinking that it starts with a lower
+case letter.
+
+\item \meta{von part} \meta{Surname}, \meta{Forenames}
+
+Again the \meta{von part} is optional, and is determined by the
+case of the first letter. For example:
+\begin{verbatim}
+author = "de Vere, Henry James"
+\end{verbatim}
+\end{enumerate}
+
+Multiple authors or editors should be separated by the key word
+"and", for example:
+\begin{verbatim}
+author = "Michel Goossens and Frank Mittlebach and Alexander Samarin"
+\end{verbatim}
+
+Below is an example of a book entry:
+\begin{verbatim}
+@book{latexcomp,
+ title = "The \LaTeX\ Companion",
+ author = "Michel Goossens and Frank Mittlebach and
+ Alexander Samarin",
+ publisher = "Addison-Wesley",
+ year = 1994
+}
+\end{verbatim}
+Note that numbers may be entered without delimiters, as in "year = 1994".
+There are also some predefined strings, including those for the month
+names. You should always use these strings instead of the actual
+month name, as the way the month name is displayed depends on the
+bibliography style. For example:
+\begin{verbatim}
+@article{Cawley2007b,
+author = "Gavin C. Cawley and Nicola L. C. Talbot",
+title = "Preventing over-fitting in model selection via {B}ayesian
+ regularisation of the hyper-parameters",
+journal = "Journal of Machine Learning Research",
+volume = 8,
+pages = "841--861",
+month = APR,
+year = 2007
+}
+\end{verbatim}
+
+You can concatenate strings using the "#" character, for example:
+\begin{verbatim}
+month = JUL # "~31~--~" # AUG # "~4",
+\end{verbatim}
+Depending on the bibliography style, this may be displayed as:
+July~31~--~August~4, or it may be displayed as:
+Jul~31~--~Aug~4. For further information, see~\cite{Goossens}.
+
+\section{Loading a \texorpdfstring{\sty{databib}}{databib}
+database}
+\label{sec:loadbbl}
+
+The \sty{databib} package always requires the \texttt{databib.bst}
+bibliography style file (which is supplied with this bundle).
+You need to use \cs{cite} or \cs{nocite} as usual. If you want to
+add all entries in the \filetype{bib} file to the \sty{datatool} database,
+you can use "\nocite{*}".
+
+\begin{definition}[\DescribeMacro{\DTLloadbbl}]%
+\cs{DTLloadbbl}\oarg{bbl name}\marg{db name}\marg{bib list}
+\end{definition}
+This command performs several functions:
+
+\begin{enumerate}
+\item it writes the following line in the auxiliary file:
+\begin{verbatim}
+\bibstyle{databib}
+\end{verbatim}
+which tells \BibTeX\ to use the \texttt{databib.bst}
+\BibTeX\ style file,
+
+\item it writes \cs{bibdata}\marg{bib list} to the
+auxiliary file, which tells \BibTeX\ which \filetype{bib} files to use,
+
+\item it creates a \sty{datatool} database called \meta{db name},
+
+\item it loads the file \meta{bbl name} if it exists. (The value
+defaults to \cs{jobname}".bbl", which is the usual name for
+a \filetype{bbl} file.) If the \filetype{bbl} file doesn't exist, the
+database \meta{db name} will remain empty.
+\end{enumerate}
+
+You then need to run your document through \LaTeX\ (or PDF\LaTeX)
+and then run \BibTeX\ on the auxiliary file, as described in
+\autoref{sec:bibtex}. This will create a \filetype{bbl} file which
+contains all the commands required to add the bibliography information
+to the \sty{datatool} database called \meta{db name}. The next
+time you \LaTeX\ your document, this file will be read, and the
+information will be added to \meta{db name}.
+
+\begin{important}
+Note that \cs{DTLloadbbl} doesn't generate any text. Once you have
+loaded the data, you can display the bibliography uses
+\cs{DTLbibliography} (described below) or you can iterate through it
+using \cs{DTLforeachbibentry} described in \autoref{sec:foreachbib}.
+\end{important}
+
+Note that the \texttt{databib.bst} \BibTeX\ style file provides
+the following additional fields: "isbn", "doi", "pubmed", "url"
+and "abstract".
+However these fields are ignored by the three predefined
+\sty{databib} styles ("plain", "abbrv" and "alpha"). If you
+want these fields to be displayed in the bibliography you will
+need to modify the bibliography style (see \autoref{sec:modbibstyle}).
+
+\section{Displaying a \texorpdfstring{\sty{databib}}{databib}
+database}
+\label{sec:thebib}
+
+A \sty{databib} database which has been loaded using
+\cs{DTLloadbbl} (described in \autoref{sec:loadbbl}) can be
+displayed using:
+\begin{definition}[\DescribeMacro{\DTLbibliography}]
+\cs{DTLbibliography}\oarg{conditions}\marg{db name}
+\end{definition}\noindent
+where \meta{db name} is the name of the database.
+
+Within the optional argument \meta{condition}, you may use any of the
+commands that may be used within the optional argument of
+\cs{DTLforeach} \emph{In addition}, you may use the following
+commands:
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldexists}]%
+\cs{DTLbibfieldexists}\marg{field label}
+\end{definition}
+This tests whether the field with the given label exists for the
+current entry.
+The field label may be one of: "Address", "Author",
+"BookTitle", "Chapter", "Edition", "Editor", "HowPublished",
+"Institution", "Journal", "Key", "Month", "Note", "Number",
+"Organization", "Pages", "Publisher", "School", "Series",
+"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed",
+"Abstract", "Url" or "Eprints".
+
+For example, suppose you have loaded a \sty{databib} database
+called "mybib" using \cs{DTLloadbbl} (described in
+\autoref{sec:loadbbl}) then the following bibliography will only
+include those entries which have a "Year" field:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldexists{Year}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldiseq}]%
+\cs{DTLbibfieldiseq}\marg{field label}\marg{value}
+\end{definition}
+This tests whether the value of the field given by
+\meta{field label} equals \meta{value}. If the field doesn't
+exist for the current entry, this evaluates to false.
+For example, the following will produce a bibliography which
+only contains entries which have the "Year" field set to 2004:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldiseq{Year}{2004}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldcontains}]%
+\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string}
+\end{definition}
+This tests whether the value of the field given by \meta{field label}
+contains \meta{sub string}. For example, the following will produce
+a bibliography which only contains entries where the author field
+contains the name "Knuth":
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldcontains{Author}{Knuth}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldislt}]%
+\cs{DTLbibfieldislt}\marg{field label}\marg{value}
+\end{definition}
+This tests whether the value of the field given by \meta{field label}
+is less than \meta{value}. If the field doesn't exist for the
+current entry, this evaluates to false.
+For example, the following will produce a bibliography which only
+contains entries whose "Year" field is less than 1983:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldislt{Year}{1983}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldisle}]%
+\cs{DTLbibfieldisle}\marg{field label}\marg{value}
+\end{definition}
+This tests whether the value of the field given by \meta{field label}
+is less than or equal to \meta{value}. If the field doesn't exist
+for the current entry, this evaluates to false.
+For example, the following will produce a bibliography which only
+contains entries whose "Year" field is less than or equal to 1983:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldisle{Year}{1983}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldisgt}]%
+\cs{DTLbibfieldisgt}\marg{field label}\marg{value}
+\end{definition}
+This tests whether the value of the field given by \meta{field label}
+is greater than \meta{value}. If the field doesn't exist for the
+current entry, this evaluates to false.
+For example, the following will produce a bibliography which only
+contains entries whose "Year" field is greater than 1983:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldisgt{Year}{1983}]{mybib}
+\end{verbatim}
+
+\begin{definition}[\DescribeMacro{\DTLbibfieldisge}]%
+\cs{DTLbibfieldisge}\marg{field label}\marg{value}
+\end{definition}
+This tests whether the value of the field given by \meta{field label}
+is greater than or equal to \meta{value}. If the field doesn't exist
+for the current entry, this evaluates to false.
+For example, the following will produce a bibliography which only
+contains entries whose "Year" field is greater than or equal to 1983:
+\begin{verbatim}
+\DTLbibliography[\DTLbibfieldisge{Year}{1983}]{mybib}
+\end{verbatim}
+
+Note that \cs{DTLbibliography} uses \cs{DTLforeachbibentry}
+(described in \autoref{sec:foreachbib}) so you may also use
+test the value of the counter \ctr{DTLbibrow} within
+\meta{conditions}. You may also use the boolean commands defined
+by the \sty{ifthen} package, such as \ics{not}.
+
+\begin{example}{Creating a list of publications since a given year}{ex:bibsince2000}
+Suppose my boss has asked me to produce a list of my
+publications in reverse chronological order, but doesn't want any
+publications published prior
+to the year 2000. I have a file called "nlct.bib" which contains
+all my publications which I keep in the directory
+\verb!$HOME/texmf/bibtex/bib/!. I could look through this file,
+work out the labels for all the publications whose year field
+is greater or equal to 2000, and
+create a file with a \cs{nocite} command containing all those labels
+in a comma separated list in reverse chronological order,
+but I really can't be bothered to do that.
+Instead, I can create the following document:
+\begin{verbatim}
+\documentclass{article}
+\usepackage{databib}
+\begin{document}
+\nocite{*}
+\DTLloadbbl{mybib}{nlct}
+\DTLsort{Year=descending,Month=descending}{mybib}
+\DTLbibliography[\DTLbibfieldisge{Year}{2000}]{mybib}
+\end{document}
+\end{verbatim}
+Suppose I save this file as "mypubs.tex", then I need to do:
+\begin{verbatim}
+latex mypubs
+bibtex mypubs
+latex mypubs
+\end{verbatim}
+Notes:
+\begin{enumerate}
+\item "\nocite{*}" is used to add all the citations in the
+bibliography file ("nlct.bib" in this case) to the \sty{databib}
+database.
+
+\item "\DTLloadbbl{mybib}{nlct}" does the following:
+\begin{enumerate}
+\item writes the line
+\begin{verbatim}
+\bibstyle{databib}
+\end{verbatim}
+to the auxiliary file. This tells \BibTeX\ to use "databib.bst"
+(which is supplied with this package). You therefore shouldn't
+use \cs{bibliographystyle}.
+
+\item writes the line
+\begin{verbatim}
+\bibdata{nlct}
+\end{verbatim}
+to the auxiliary file. This tells \BibTeX\ that the bibliography
+data is stored in the file "nlct.bib". Since I have placed this
+file in \TeX's search path, \BibTeX\ will be able to find it.
+
+\item creates a \sty{datatool} database called "mybib".
+
+\item if the \filetype{bbl} file ("mypubs.bbl" in this example) exists,
+it loads this file (which adds the bibliography data to the
+database), otherwise it does nothing further.
+
+\end{enumerate}
+
+\item In my \BibTeX\ database ("nlct.bib" in this example), I
+have remembered to use the \BibTeX\ month macros: "jan", "feb"
+etc. This means that the months are stored in the database in
+the form \cs{DTLmonthname}\marg{nn}, where \meta{nn} is a two
+digit number from 01 to 12. \cs{DTLsort} ignores command names
+when it compares strings, which means I can not only sort by
+year, but also by month\footnote{as long as I haven't put anything
+before the month name in the bibliography file, e.g.\
+\mbox{\texttt{month = "2~" \# apr}} will sort by 2~03, instead of
+03}.
+
+\item Once I have loaded and sorted my database, I can then
+display it using \cs{DTLbibliography}. This uses the style
+given by the \sty{databib} \pkgopt{style} package option,
+or the \cs{DTLbibliographystyle} command, both of which are
+described in \autoref{sec:bibstyle}.
+
+\item I have filtered the bibliography using the optional
+argument\linebreak "[\DTLbibfieldisge{Year}{2000}]", which checks if the
+year field of the current entry is greater than or equal to
+2000. (Note that if an entry has no year field, the condition
+evaluates to false, and the entry will be omitted from the
+bibliography.)
+
+\item If the bibliography database is large, sorting and creating
+the bibliography may take a while. Using \sty{databib} is much
+slower than using a standard \BibTeX\ style file.
+\end{enumerate}
+\end{example}
+
+\begin{example}{Creating a list of my 10 most recent
+publications}{ex:top10bib}
+Suppose now my boss has asked me to produce a list of my ten most
+recent publications (in reverse chronological order).
+As in the previous example, I have a file called "nlct.bib"
+which contains all my publications. I can create the required
+document as follows:
+\begin{verbatim}
+\documentclass{article}
+\usepackage{databib}
+\begin{document}
+\nocite{*}
+\DTLloadbbl{mybib}{nlct}
+\DTLsort{Year=descending,Month=descending}{mybib}
+\DTLbibliography[\value{DTLbibrow}<10]{mybib}
+\end{document}
+\end{verbatim}
+\end{example}
+
+\section{Changing the bibliography style}
+\label{sec:bibstyle}
+The style of the bibliography produced using \cs{DTLbibliography}
+depends on the \pkgopt{style}
+package option, or can be set using
+\begin{definition}[\DescribeMacro{\DTLbibliographystyle}]%
+\cs{DTLbibliographystyle}\marg{style}
+\end{definition}
+Note that this is \emph{not} the same as \cs{bibliographystyle},
+as the \sty{databib} package uses its custom \texttt{databib.bst}
+bibliography style file.
+
+Example:
+\begin{verbatim}
+\usepackage[style=plain]{databib}
+\end{verbatim}
+This sets the plain bibliography style. This is, in fact, the
+default style, so it need not be specified.
+
+Available styles are: "plain", "abbrv" and "alpha". These are similar to the
+standard \BibTeX\ styles of the same name, but are by no means
+identical. The most notable difference is that these styles
+do not sort the bibliography. It is up to you to sort the
+bibliography using \cs{DTLsort} (described in \autoref{sec:sort}).
+
+\subsection{Modifying an existing style}
+\label{sec:modbibstyle}
+
+This section describes some of the commands which are used to
+format the bibliography. You can choose whichever predefined
+style best fits your required style, and then modify the commands
+described in this section. A description of the remaining
+commands not listed in this section can be found in
+\autoref{sec:src:bibnames}, \autoref{sec:src:displaybib}
+and \autoref{sec:src:bibstyle}.
+
+\begin{definition}[\DescribeMacro{\DTLformatauthor}]%
+\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLformateditor}]%
+\cs{DTLformateditor}\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+\end{definition}
+These commands are used to format an author/editor's name,
+respectively. The list of authors and editors are stored in
+the \sty{databib} database as a comma separated list of
+\marg{von part}\marg{surname}\marg{jr part}\marg{forenames}
+data. This ensures that when you sort on the Author or Editor
+field, the names will be sorted by the first author or editor's
+surname.
+
+Within \cs{DTLformatauthor} and \cs{DTLformateditor}, you may
+use the following commands:
+\begin{definition}[\DescribeMacro{\DTLformatforenames}]%
+\cs{DTLformatforenames}\marg{forenames}
+\end{definition}
+This is used by the "plain" style to display the author's
+forenames\footnote{It also checks
+whether \meta{forenames} ends with a full stop using
+\cs{DTLcheckendsperiod} to prevent a sentence ending full stop
+from following an abbreviation full stop}.
+
+\begin{definition}[\DescribeMacro{\DTLformatabbrvforenames}]%
+\cs{DTLformatabbrvforenames}\marg{forenames}
+\end{definition}
+This is used by the "abbrv" style to display the author's
+initials (which are determined from \meta{forenames}).
+Note that if any of the authors has a name starting with an
+accent, the accented letter must be grouped in order for this
+command to work. For example:
+\begin{verbatim}
+author = "{\'E}lise {\"E}awyn Edwards",
+\end{verbatim}
+The initials are formed using \cs{DTLstoreinitials} described
+in \autoref{sec:strings}, so if you want to change the way the
+initials are displayed (e.g.\ put a space between them) you will
+need to redefine the commands used by \cs{DTLstoreinitials} (such
+as \cs{DTLbetweeninitials}).
+
+\begin{definition}[\DescribeMacro{\DTLformatsurname}]%
+\cs{DTLformatsurname}\marg{surname}
+\end{definition}
+This displays its argument by default\footnote{It also checks
+whether the surname ends with a full stop using
+\cs{DTLcheckendsperiod}}.
+
+\begin{definition}[\DescribeMacro{\DTLformatvon}]%
+\cs{DTLformatvon}\marg{von part}
+\end{definition}
+If the \meta{von part} is empty, this command does nothing,
+otherwise it displays its argument followed by a
+non-breakable space.
+\begin{definition}[\DescribeMacro{\DTLformatjr}]%
+\cs{DTLformatjr}\marg{jr part}
+\end{definition}
+If the \meta{jr part} is empty, this command displays nothing,
+otherwise it displays a comma followed by its argument\footnote
+{again, it also checks \meta{jr part} to determine if it ends
+with a full stop}.
+
+For example, suppose you want the author's surname to appear
+first in small capitals, followed by a comma and the forenames. This
+can be achieved by redefining \cs{DTLformatauthor} as follows:
+\begin{verbatim}
+\renewcommand*{\DTLformatauthor}[4]{%
+\textsc{\DTLformatvon{#1}%
+\DTLformatsurname{#2}\DTLformatjr{#3}},
+\DTLformatforenames{#4}%
+}
+\end{verbatim}
+
+\begin{definition}[\DescribeCounter{DTLmaxauthors}]
+\ctrfmt{DTLmaxauthors}
+\end{definition}
+The counter \ctrfmt{DTLmaxauthors} is used to determine the
+maximum number of authors to display for a given entry. If the
+entry's author list contains more than that number of authors,
+\cs{etalname} is used, the definition of which is given in
+\autoref{sec:src:bibnames}. The default value of
+\ctrfmt{DTLmaxauthors} is \theDTLmaxauthors.
+
+\begin{definition}[\DescribeCounter{DTLmaxeditors}]
+\ctrfmt{DTLmaxeditors}
+\end{definition}
+The \ctrfmt{DTLmaxeditors} counter is analogous to the
+\ctrfmt{DTLmaxauthors} counter. It is used to determine the
+maximum number of editor names to display. The default value
+of \ctrfmt{DTLmaxeditors} is \theDTLmaxeditors.
+
+\DescribeMacro{\DTLandlast}
+Within a list of author or editor names, \cs{DTLandlast} is
+used between the last two names, otherwise
+\DescribeMacro{\DTLandnotlast}\cs{DTLandnotlast} is used between
+names.
+However, if there are only two author or editor names,
+\DescribeMacro{\DTLtwoand}\cs{DTLtwoand}
+is used instead of \cs{DTLandlast}.
+
+\DescribeMacro\DTLbibitem
+The command \cs{DTLbibitem} is used at the start of each
+bibliography item. It uses \cs{bibitem} to provide a marker,
+such as [1], and writes the citation information to the
+\texttt{.aux} file.
+
+\DescribeMacro\DTLmbibitem
+The command \cs{DTLmbibitem} is analogous to \cs{DTLbibitem} but is
+for use with \cs{DTLmbibliography}.
+
+\DescribeMacro{\DTLendbibitem}
+The command \cs{DTLendbibitem} is a hook provided to add
+additional information at the end of each bibliography item.
+This does nothing by default, but if you want to display the
+additional fields provided by the "databib.bst" style file,
+you can redefine \cs{DTLendbibitem} so that it displays a
+particular field, if it is defined. Within this command, you
+may use the commands \cs{DTLbibfield}, \cs{DTLifbibfieldexist}
+and \cs{DTLifanybibfieldexist}, which are described in
+\autoref{sec:foreachbib}. For example, if you have used the
+"abstract" field in any of your entries, you can display the
+abstract as follows:
+\begin{verbatim}
+\renewcommand{\DTLendbibitem}{%
+\DTLifbibfieldexists{Abstract}{\DTLpar\textbf{Abstract}
+\begin{quote}\DTLbibfield{Abstract}\end{quote}}{}}
+\end{verbatim}
+(Note that \cs{DTLpar} needs to be used instead of
+\cs{par}.)
+
+\begin{example}{Compact bibliography}{ex:compactbib}
+Suppose I don't have much space in my document, and I need to
+produce a compact bibliography. Firstly, I can use the
+bibliography style "abbrv", either through the package option:
+\begin{verbatim}
+\usepackage[style=abbrv]{databib}
+\end{verbatim}
+or using:
+\begin{verbatim}
+\DTLbibliographystyle{abbrv}
+\end{verbatim}
+Once I have set the style, I can further modify it thus:
+\begin{verbatim}
+\renewcommand*{\andname}{\&}
+\renewcommand*{\editorname}{ed.}
+\renewcommand*{\editorsname}{eds.}
+\renewcommand*{\pagesname}{pp.}
+\renewcommand*{\pagename}{p.}
+\renewcommand*{\volumename}{vol.}
+\renewcommand*{\numbername}{no.}
+\renewcommand*{\editionname}{ed.}
+\renewcommand*{\techreportname}{T.R.}
+\renewcommand*{\mscthesisname}{MSc thesis}
+\end{verbatim}
+Now I can load\footnote{I can load the bibliography earlier, but
+obviously the bibliography should only be displayed after the
+bibliography styles have been set, otherwise they will have no
+effect} and display the bibliography:
+\begin{verbatim}
+ % create a database called mybib from the information given
+ % in mybib1.bib and mybib2.bib
+ \DTLloadbbl{mybib}{mybib1,mybib2}
+ % display the bibliography
+ \DTLbibliography{mybib}
+\end{verbatim}
+\end{example}
+
+\begin{example}{Highlighting a given author}{ex:highlightauthor}
+Suppose my boss wants me to produce a list of all my publications
+(which I have stored in the file "nlct.bib", as in
+\autoref{ex:bibsince2000}). Most of my
+publications have multiple co-authors, but suppose my boss would
+like me to highlight my name so that when he skims through
+the document, he can easily see my name in the list of
+co-authors. I can do this by redefining \cs{DTLformatauthor}
+so that it checks if the given surname matches mine. (This
+assumes that none of the other co-author's share my surname.)
+\begin{verbatim}
+\renewcommand*{\DTLformatauthor}[4]{%
+{\DTLifstringeq{#2}{Talbot}{\bfseries }{}%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}}
+\end{verbatim}
+Notes:
+\begin{enumerate}
+\item I have used \cs{DTLifstringeq} (described in
+\autoref{sec:ifconditions}) to perform the string comparison.
+\item If one or more of my co-authors shared the same surname as
+me, I would also have had to check the first name, however there
+is regrettably a lack of consistency in my \filetype{bib} file when
+it comes to my forenames. Sometimes my name is given as
+\texttt{Nicola L. C. Talbot}, sometimes the middle initials
+are omitted, \texttt{Nicola Talbot}, or sometimes, just initials
+are used, \texttt{N. L. C. Talbot}. This can cause problems
+when checking the forenames, but as long as the other authors
+who share the same surname as me, don't also share the same
+first initial, I can use \cs{DTLifStartsWith} or \cs{DTLisPrefix},
+which are described in \autoref{sec:ifconditions} and
+\autoref{sec:ifthen}, respectively. Using the first approach
+I can do:
+\begin{verbatim}
+\renewcommand*{\DTLformatauthor}[4]{%
+{\DTLifstringeq{#2}{Talbot}{\DTLifStartsWith{#4}{N}{\bfseries }{}}{}%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}}
+\end{verbatim}
+Using the second approach I can do:
+\begin{verbatim}
+\renewcommand*{\DTLformatauthor}[4]{%
+{\ifthenelse{\DTLiseq{#2}{Talbot}\and
+\DTLisPrefix{#4}{N}}{\bfseries }{}%
+\DTLformatforenames{#4}
+\DTLformatvon{#1}%
+\DTLformatsurname{#2}%
+\DTLformatjr{#3}}}
+\end{verbatim}
+
+\item I have used a group to localise the effect of \cs{bfseries}.
+\end{enumerate}
+\end{example}
+
+\section{Iterating through a
+\texorpdfstring{\sty{databib}}{databib} database}
+\label{sec:foreachbib}
+
+\cs{DTLbibliography} (described in \autoref{sec:thebib}) may still
+not meet your needs. For example, you may be required
+to list journal papers and conference proceedings in separate
+sections. In which case, you may find it easier to iterate through
+the bibliography using:
+\begin{definition}[\DescribeMacro{\DTLforeachbibentry}]%
+\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text}
+\end{definition}
+\begin{definition}[\DescribeMacro{\DTLforeachbibentry*}]%
+\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text}
+\end{definition}
+This iterates through the \sty{databib} database called
+\meta{db name} and does \meta{text} if \meta{condition} is met.
+As with \cs{DTLforeach}, the starred version is read-only.
+
+\cs{DTLforeachbibentry} only makes local assignments, which means that it's unsuitable to display the references
+in a~\env{tabular}-like environment (for example, the
+\env{europecv} environment provided by the \cls{europecv} class). It's also a~short command, so
+\meta{text} can't contain any paragraph breaks. Instead you can use
+the analogous commands:
+\begin{definition}[\DescribeMacro{\gDTLforeachbibentry}]%
+\cs{gDTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text}
+\end{definition}
+\begin{definition}[\DescribeMacro{\gDTLforeachbibentry*}]%
+\cs{gDTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text}
+\end{definition}
+
+For each row of the database, the following commands are set:
+\begin{itemize}
+\item \cs{DBIBcitekey} \DescribeMacro{\DBIBcitekey}This is the
+unique label which identifies the current entry (as used in the
+argument of \cs{cite} and \cs{nocite}).
+
+\item \cs{DBIBentrytype} \DescribeMacro{\DBIBentrytype}This
+is the current entry type, and will be one of: "article", "book",
+"booklet", "inbook", "incollection", "inproceedings",
+"manual", "mastersthesis", "misc", "phdthesis", "proceedings",
+"techreport" or "unpublished". (Note that even if you used the
+entry type "conference" in your \filetype{bib} file, its entry type
+will be set to "inproceedings").
+\end{itemize}
+
+The remaining fields may be accessed using:
+\begin{definition}[\DescribeMacro{\DTLbibfield}]%
+\cs{DTLbibfield}\marg{field label}
+\end{definition}\noindent
+where \meta{field label} may be one of: "Address", "Author",
+"BookTitle", "Chapter", "Edition", "Editor", "HowPublished",
+"Institution", "Journal", "Key", "Month", "Note", "Number",
+"Organization", "Pages", "Publisher", "School", "Series",
+"Title", "Type", "Volume", "Year", "ISBN", "DOI", "PubMed",
+"Abstract" or "Url".
+
+Alternatively, you can assign the value of a field to a control
+sequence \meta{cs} using:
+\begin{definition}[\DescribeMacro\DTLbibfieldlet]
+\cs{DTLbibfieldlet}\marg{cs}\marg{field label}
+\end{definition}
+
+You can determine if a field exists for a given entry using
+\begin{definition}[\DescribeMacro{\DTLifbibfieldexists}]%
+\cs{DTLifbibfieldexists}\marg{field label}\marg{true part}\marg{false
+part}
+\end{definition}
+If the field given by \meta{field label} exists for the current
+bibliography entry, it does \meta{true part}, otherwise it
+does \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLifbibanyfieldexists}]%
+\cs{DTLifanybibfieldexists}\marg{field label list}\marg{true
+part}\marg{false part}
+\end{definition}
+This is similar to \cs{DTLifbibfieldexists} except that the
+first argument is a list of field names. If one or more of
+the fields given in \meta{field label list} exists for the
+current bibliography item, this does \meta{true part}, otherwise
+it does \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\DTLformatbibentry}]%
+\cs{DTLformatbibentry}
+\end{definition}
+This formats the bibliography entry for the current row. It
+checks for the existence of the command
+\cs{DTLformat}\meta{entry type}, where \meta{entry type}
+is given by \cs{DBIBentrytype}. These commands are defined
+by the bibliography style. There is also a~version for use with
+\cs{gDTLforeachbibentry}:
+\begin{definition}[\DescribeMacro{\gDTLformatbibentry}]%
+\cs{gDTLformatbibentry}
+\end{definition}
+It's also possible to use \cs{DTLformatbibentry} for a specific key,
+rather than using it within \ics{DTLforeachbibentry} using:
+\begin{definition}
+\cs{DTLformatthisbibentry}\marg{db}\marg{cite key}
+\end{definition}
+where \meta{db} is the database name and \meta{cite key} is the
+citation label. Note that none of these three commands use
+\cs{bibitem}. You can manually insert \cs{bibitem}\marg{cite key}
+in front of the command, or you can use:
+\begin{definition}
+\cs{DTLcustombibitem}\marg{marker code}\marg{ref text}\marg{cite key}
+\end{definition}
+This is like \cs{bibitem}\oarg{text}\marg{cite key} except that it uses
+\meta{marker code} instead of \cs{item}\oarg{text} and it uses
+\meta{ref text} instead of \verb|\the\value{\@listctr}|.
+
+\begin{definition}[\DescribeMacro{\DTLcomputewidestbibentry}]%
+\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db
+name}\marg{bib label}\marg{cmd}
+\end{definition}
+This computes the widest bibliography entry over all entries
+satisfying \meta{conditions} in the database \meta{db name},
+where the label is given by \meta{bib label}, and the result
+is stored in \meta{cmd}, which may then be used in the
+argument of the \env{thebibliography} environment.
+
+The counter \desctr{DTLbibrow} keeps track of the current
+bibliography entry. This is reset at the start of each
+\cs{DTLforeachbibentry} and is incremented if \meta{conditions}
+is met.
+
+Within the optional argument \meta{condition}, you may use any of the
+commands that may be used within the optional argument of
+\cs{DTLbibliography}, described in \autoref{sec:thebib}.
+
+\begin{example}{Separate List of Journals and Conference Papers}{ex:jcbib}
+Suppose now my boss has decided that I need to produce a list
+of all my publications, but they need to be separated so that
+all the journal papers appear in one section, and all the
+conference papers appear in another section. The journal papers
+need to be labelled [J1], [J2] and so on, while the conference
+papers need to be labelled [C1], [C2] and so on. (My boss isn't
+interested in any of my other publications!) Again, all my
+publications are stored in the \BibTeX\ database "nlct.bib". The
+following creates the required document:
+\begin{verbatim}
+\documentclass{article}
+\usepackage{databib}
+\begin{document}
+\nocite{*}
+\DTLloadbbl{mybib}{nlct}
+
+\renewcommand*{\refname}{Journal Papers}
+\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{article}}
+{mybib}{J\theDTLbibrow}{\widest}
+
+\begin{thebibliography}{\widest}
+\DTLforeachbibentry[\equal{\DBIBentrytype}{article}]{mybib}{%
+\bibitem[J\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry}
+\end{thebibliography}
+
+\renewcommand*{\refname}{Conference Papers}
+\DTLcomputewidestbibentry{\equal{\DBIBentrytype}{inproceedings}}
+{mybib}{C\theDTLbibrow}{\widest}
+
+\begin{thebibliography}{\widest}
+\DTLforeachbibentry[\equal{\DBIBentrytype}{inproceedings}]{mybib}{%
+\bibitem[C\theDTLbibrow]{\DBIBcitekey} \DTLformatbibentry}
+\end{thebibliography}
+
+\end{document}
+\end{verbatim}
+\end{example}
+
+\section{Multiple Bibliographies}
+\label{sec:multibib}
+
+It is possible to have more than one bibliography in a document,
+but it then becomes necessary to have a separate auxiliary file
+for each bibliography, and each auxiliary file must then be
+passed to \BibTeX. In order to do this, you need to use
+\begin{definition}[\DescribeMacro{\DTLmultibibs}]%
+\cs{DTLmultibibs}\marg{name list}
+\end{definition}
+where \meta{name list} is a comma separated list of names,
+\meta{name}. For each \meta{name}, this command creates an
+auxiliary file called \meta{name}".aux" (note that this
+command may only be used in the preamble).
+
+When you want to cite an entry for a given bibliography named
+in \cs{DTLmultibibs}, you must use:
+\begin{definition}[\DescribeMacro{\DTLcite}]%
+\cs{DTLcite}\oarg{text}\marg{mbib}\marg{cite key list}
+\end{definition}\noindent
+This is analogous to \cs{cite}\oarg{text}\marg{cite key list},
+but writes the \cs{citation} command to \meta{mbib}".aux" instead
+of to the document's main auxiliary file. It also ensures that
+the cross-referencing labels are based on \meta{mbib}, to allow
+you to have the same reference in more than one bibliography
+without incurring a ``multiply defined'' warning message. Note
+that you can still use \cs{cite} to add citation information to
+the main auxiliary file.
+
+If you want to add an entry to the bibliography without producing
+any text, you can use
+\begin{definition}[\DescribeMacro{\DTLnocite}]
+\cs{DTLnocite}\marg{mbib}\marg{cite key list}
+\end{definition}\noindent
+which is analogous to \cs{nocite}\marg{cite key list}, where
+again the citation information is written to \meta{mbib}".aux"
+instead of the document's main auxiliary file.
+
+Note that for both \cs{DTLcite} and \cs{DTLnocite} the
+\meta{mbib} part must be one of the names listed in
+\cs{DTLmultibibs}.
+
+\begin{definition}[\DescribeMacro{\DTLloadmbbl}]%
+\cs{DTLloadmbbl}\marg{mbib}\marg{db name}\marg{bib list}
+\end{definition}
+This is analogous to \cs{DTLloadbbl}\marg{db name}\marg{bib list}
+described in \autoref{sec:loadbbl}. (Again \meta{mbib} must be
+one of the names listed in \cs{DTLmultibibs}.) This creates
+a new \sty{datatool} database called \meta{db name} and loads the
+bibliography information from \meta{mbib}".bbl" (if it exists).
+
+\begin{definition}[\DescribeMacro{\DTLmbibliography}]%
+\cs{DTLmbibliography}\oarg{condition}\marg{mbib}\marg{db name}
+\end{definition}
+This is analogous to \cs{DTLbibliography}\oarg{condition}\marg{db name},
+but is required when displaying a bibliography in which elements have
+been cited using \cs{DTLcite} and \cs{DTLnocite}.
+
+\begin{example}{Multiple Bibliographies}{ex:multibib}
+Suppose I need to create a document which contains a section listing
+all my publications, but I also need to have separate sections
+covering each of my research topics, with a mini-bibliography
+at the end of each section. As in the earlier examples, all my
+publications are stored in the file "nlct.bib" which is somewhere
+on \TeX's path. Note that there will be some duplication as the
+references in the mini-bibliographies will also appear in the
+main bibliography at the end of the document, but using
+\cs{DTLcite} and \cs{DTLmbibliography} ensures that all the
+cross-referencing labels (and hyperlinks if they are enabled)
+are unique.
+\begin{verbatim}
+\documentclass{article}
+\usepackage{databib}
+\DTLmultibibs{kernel,food}
+\begin{document}
+\section{Kernel methods}
+In this section I'm going to describe some research work into
+kernel methods, and in the process I'm going to cite some related
+papers \DTLcite{kernel}{Cawley2007a,Cawley2006a}.
+
+\DTLloadmbbl{kernel}{kernelDB}{nlct}
+\DTLmbibliography{kernel}{kernelDB}
+
+\section{Food research}
+
+In this section I'm going to describe some research work
+in the area of food safety, and in the process, I'm going
+to cite some related papers \DTLcite{food}{Peck1999,Barker1999a}
+
+\DTLloadmbbl{food}{foodDB}{nlct}
+\DTLmbibliography{food}{foodDB}
+
+\cite{*}
+\renewcommand{\refname}{Complete List of Publications}
+\DTLloadbbl{fullDB}{nlct}
+\DTLbibliography{fullDB}
+\end{document}
+\end{verbatim}
+Notes:
+\begin{enumerate}
+\item This will create the files "kernel.aux" and "food.aux".
+These will have to be passed to \BibTeX, in addition to the
+documents main auxiliary file. So, if my document is called
+"researchwork.tex", then I need to do:
+\begin{verbatim}
+latex researchwork
+bibtex researchwork
+bibtex kernel
+bibtex food
+latex researchwork
+latex researchwork
+\end{verbatim}
+
+\item "\cite{*}" is used to add all the entries in the bib file
+to the main bibliography database. As before, \cs{DTLloadbbl}
+and \cs{DTLbibliography} are used to load and display the main
+bibliography.
+\end{enumerate}
+\end{example}
+
+\begin{important}
+Don't try to directly input the ".bbl" file using \cs{input} (or
+\cs{include}) instead of using \cs{DTLloadbbl} or \cs{DTLloadmbbl}
+as these commands store the name of the required database and
+initialise the database before loading the \texttt{.bbl} file.
+Similarly, don't just copy the contents of the ".bbl" file into your
+document without first defining the database using \ics{DTLnewdb}
+and setting \ics{DTLBIBdbname} to the name of the database.
+\end{important}
+
+\chapter{Referencing People (\sty{person} package)}
+\label{sec:person}
+
+Sometimes when mail-merging, it may be necessary to reference a
+person by their pronoun which can lead to the cumbersome and
+impersonal ``he/she'' construct. The \sty{person} package
+allows you to define a person by their full name, familiar name and
+gender. You can then use the commands described in
+\autoref{sec:refperson} to produce the appropriate pronoun.
+
+This can also be useful for other types of documents, such as an
+order of service for a baptism or funeral. Since the
+document is much the same from one person to the next, documents of
+this nature are frequently simply copied and a search and replace
+edit is used to change the relevant text. However this can lead to
+errors (especially if the previous person's name was Mary!) With
+the \sty{person} package, you need only change the definition of
+the person by modifying the arguments of \cs{newperson}.
+
+\section{Defining and Undefining People}
+
+A person is defined (globally) using the command:
+\begin{definition}[\DescribeMacro{\newperson}]
+\cs{newperson}\oarg{label}\marg{full name}\marg{familiar name}\marg{gender}
+\end{definition}
+The optional argument is a unique label identifying this person,
+in the event that there is more than one person. If \meta{label}
+is omitted \texttt{anon} is used. (This is also the case for
+subsequent commands that take an optional label.)
+The gender may be any of those given by
+\begin{definition}[\DescribeMacro{\malelabels}]
+\cs{malelabels}
+\end{definition}
+or
+\begin{definition}[\DescribeMacro{\femalelabels}]
+\cs{femalelabels}
+\end{definition}
+The default definition of \cs{malelabels} is \texttt{\malelabels}
+and the default definition of \cs{femalelabels} is
+\texttt{\femalelabels}. You can add extra identifiers using
+\begin{definition}[\DescribeMacro{\addmalelabel}]
+\cs{addmalelabel}\marg{identifier}
+\end{definition}
+or
+\begin{definition}[\DescribeMacro{\addfemalelabel}]
+\cs{addfemalelabel}\marg{identifier}
+\end{definition}
+For example:
+\begin{verbatim}
+\addmalelabel{boy}
+\addfemalelabel{girl}
+\end{verbatim}
+
+The total number of defined people is given by:
+\begin{definition}[\DescribeMacro{\thepeople}]
+\cs{thepeople}
+\end{definition}
+
+A person can be undefined using:
+\begin{definition}[\DescribeMacro{\removeperson}]
+\cs{removeperson}\oarg{label}
+\end{definition}
+where the person is given by \meta{label}.
+
+If more than one person has been defined, they can all be
+removed using:
+\begin{definition}[\DescribeMacro{\removeallpeople}]
+\cs{removeallpeople}
+\end{definition}
+or you can remove a subset using:
+\begin{definition}[\DescribeMacro{\removepeople}]
+\cs{removepeople}\marg{list}
+\end{definition}
+where \meta{list} is a comma-separated list of labels.
+
+\section{Displaying Information}
+\label{sec:refperson}
+
+Once a person has been defined, you can display their name using:
+\begin{definition}[\DescribeMacro{\personfullname}]
+\cs{personfullname}\oarg{label}
+\end{definition}
+where \meta{label} is the unique label used in the optional
+argument to \cs{newperson}. The person's familiar name is displayed
+using:
+\begin{definition}[\DescribeMacro{\personname}]
+\cs{personname}\oarg{label}
+\end{definition}
+The person's pronoun (``he'' or ``she'') is displayed using:
+\begin{definition}[\DescribeMacro{\personpronoun}]
+\cs{personpronoun}\oarg{label}
+\end{definition}
+The objective pronoun (``him'' or ``her'') is displayed using:
+\begin{definition}[\DescribeMacro{\personobjpronoun}]
+\cs{personobjpronoun}\oarg{label}
+\end{definition}
+The possessive adjective (``his'' or ``her'') is displayed using:
+\begin{definition}[\DescribeMacro{\personpossadj}]
+\cs{personpossadj}\oarg{label}
+\end{definition}
+The possessive pronoun ``his'' or ``hers'' is displayed using:
+\begin{definition}[\DescribeMacro{\personposspronoun}]
+\cs{personposspronoun}\oarg{label}
+\end{definition}
+The person's relationship to their parent (``son'' or ``daughter'')
+is displayed using:
+\begin{definition}[\DescribeMacro{\personchild}]
+\cs{personchild}\oarg{label}
+\end{definition}
+The person's relationship to their child (``mother'' or ``father'')
+is displayed using:
+\begin{definition}[\DescribeMacro{\personparent}]
+\cs{personparent}\oarg{label}
+\end{definition}
+The person's relationship to their sibling (``brother'' or
+``sister'') is displayed using:
+\begin{definition}[\DescribeMacro{\personsibling}]
+\cs{personsibling}\oarg{label}
+\end{definition}
+
+If the word occurs at the start of a sentence, you will need one
+of the following commands, which are as the above, except the
+first letter is converted to upper case:
+\begin{definition}[\DescribeMacro{\Personpronoun}]
+\cs{Personpronoun}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personobjpronoun}]
+\cs{Personobjpronoun}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personpossadj}]
+\cs{Personpossadj}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personposspronoun}]
+\cs{Personposspronoun}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personchild}]
+\cs{Personchild}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personparent}]
+\cs{Personparent}\oarg{label}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Personsibling}]
+\cs{Personsibling}\oarg{label}
+\end{definition}
+
+\begin{example}{Order of Service (Memorial)}{ex:memorial}
+This example is for a memorial order of service.
+
+\begin{verbatim}
+\documentclass{article}
+
+\usepackage{person}
+
+\newperson{Jane Doe}{Jane}{female}
+
+\begin{document}
+\begin{center}
+\Large
+In Memory of \personfullname
+\end{center}
+
+We are gathered here to remember our \personsibling\ \personname.
+\Personpronoun\ will be much missed, and \personpossadj\
+family are in our prayers.
+\end{document}
+\end{verbatim}
+
+\newperson{Jane Doe}{Jane}{female}
+\begin{center}
+\Large
+In Memory of \personfullname
+\end{center}
+
+We are gathered here to remember our \personsibling\ \personname.
+\Personpronoun\ will be much missed, and \personpossadj\
+family are in our prayers.
+\removeperson
+
+\end{example}
+
+If there is more than one person, you will need to use the
+optional argument \meta{label} to \cs{newperson} to uniquely
+identify each person. You can then list all of the people's full
+or familiar names using:
+\begin{definition}[\DescribeMacro{\peoplefullname}]
+\cs{peoplefullname}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peoplename}]
+\cs{peoplename}
+\end{definition}
+Note that if there is only one person defined, these commands behave
+the same as \cs{personfullname}\oarg{label} and
+\cs{personname}[\meta{label}].
+
+Similarly for the pronouns:
+\begin{definition}[\DescribeMacro{\peoplepronoun}]
+\cs{peoplepronoun}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peoplepronoun}]
+\cs{Peoplepronoun}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peopleobjpronoun}]
+\cs{peopleobjpronoun}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peopleobjpronoun}]
+\cs{Peopleobjpronoun}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peoplepossadj}]
+\cs{peoplepossadj}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peoplepossadj}]
+\cs{Peoplepossadj}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peopleposspronoun}]
+\cs{peopleposspronoun}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peopleposspronoun}]
+\cs{Peopleposspronoun}
+\end{definition}
+where, again, if only one person has been defined, each of these
+commands is equivalent to
+\cs{person}\ldots\oarg{label} or
+\cs{Person}\ldots\oarg{label}. If more than
+one person has been defined, these commands will display
+they/them/their/theirs or They/Them/Their/Theirs, as appropriate.
+
+Likewise for relationship commands:
+\begin{definition}[\DescribeMacro{\peoplechild}]
+\cs{peoplechild}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peoplechild}]
+\cs{Peoplechild}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peopleparent}]
+\cs{peopleparent}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peopleparent}]
+\cs{Peopleparent}
+\end{definition}
+\begin{definition}[\DescribeMacro{\peoplesibling}]
+\cs{peoplesibling}
+\end{definition}
+\begin{definition}[\DescribeMacro{\Peoplesibling}]
+\cs{Peoplesibling}
+\end{definition}
+
+\begin{example}{Order of Service (Baptism)}{ex:baptism}
+In this example two people are defined.
+\begin{verbatim}
+\documentclass{article}
+
+\usepackage{person}
+
+\newperson[john]{John Joseph}{John}{male}
+\newperson[jane]{Jane Mary}{Jane}{female}
+
+\begin{document}
+\begin{center}
+\Large
+Baptism of \peoplefullname.
+\end{center}
+
+Today we welcome \peoplename\ into God's family, may He guide
+and protect \peopleobjpronoun.
+\end{document}
+\end{verbatim}
+
+This is produces the following text:
+
+\newperson[john]{John Joseph}{John}{male}
+\newperson[jane]{Jane Mary}{Jane}{female}
+
+\begin{center}
+\Large
+Baptism of \peoplefullname.
+\end{center}
+
+Today we welcome \peoplename\ into God's family, may He guide
+and protect \peopleobjpronoun.
+\removeallpeople
+\end{example}
+
+\begin{example}{Mail Merging Using Appropriate Gender}{ex:personmerge}
+In this example I have a CSV file called \texttt{students.csv}
+containing the following:
+\begin{verbatim}
+FirstName,Surname,Gender,Parent,Address
+John,"Smith, Jr",M,Mr and Mrs Smith,1 The Street\\Newtown
+Jane,Brown,F,Ms Brown,2 The Avenue\\Oldtown
+Andy,Brown,male,Mr Brown and Miss Sepia,3 The Road\\Newtown
+Z\"oe,Adams,f,Mr and Mrs Adams,5 The Street\\Newtown
+Roger,Brady,m,Mrs Brady,6 The Avenue\\Oldtowm
+Clare,Vernon,female,Mr Vernon,7 The Close\\Anytown
+\end{verbatim}
+Suppose I have to write to each student's parents regarding their
+child. I can load the information using \ics{DTLloaddb} (described
+in \autoref{sec:loaddb}). I can then iterate through the database
+and define the student as a person and use the commands defined in
+the \sty{person} package to display the correct gender related text.
+I could give each person a unique label based on the row count
+(\ics{DTLcurrentindex}), but since I don't need to reuse the
+information, I can use the default "anon" label and undefine the
+person when no longer required.
+
+Note that in the CSV file, the gender label isn't consistent.
+For some students the gender is identified by a single letter
+(``m'' or ``f'') and for others the gender is identified by a
+complete word (``male'' or ``female''). There's also no regard
+for case. This doesn't matter to \ics{newperson} as all the
+identifiers used are listed in \ics{malelabels} and
+\ics{femalelabels}.
+
+The following is an example letter sent to all parents:
+\begin{verbatim}
+\documentclass{letter}
+\usepackage{person}
+
+% load student information from file "students.csv"
+\DTLloaddb{students}{students.csv}
+\begin{document}
+% Iterate through the student database:
+\DTLforeach{students}{\FirstName=FirstName,\Surname=Surname,%
+\Gender=Gender,\Parent=Parent,\Address=Address}{%
+% Define "anon":
+ \newperson{\FirstName\space\Surname}{\FirstName}{\Gender}%
+% Do the letter:
+ \begin{letter}{\Parent\\\Address}
+ \opening{Dear \Parent}
+ Your \personchild\ \personname\ has been awarded a
+ place. We look forward to seeing \personobjpronoun\
+ on \personpossadj\ arrival.
+ \closing{Yours Sincerely}
+ \end{letter}
+% Undefine "anon":
+ \removeperson
+}
+\end{document}
+\end{verbatim}
+
+The body of the first letter appears as follows:
+\newperson{John Smith Jr}{John}{m}
+\par\vskip\baselineskip
+
+ Your \personchild\ \personname\ has been awarded a
+ place. We look forward to seeing \personobjpronoun\
+ on \personpossadj\ arrival.
+
+\removeperson
+\par\vskip\baselineskip
+Whereas the body of the second letter appears as follows:
+\newperson{Jane Brown}{Jane}{f}
+\par\vskip\baselineskip
+
+ Your \personchild\ \personname\ has been awarded a
+ place. We look forward to seeing \personobjpronoun\
+ on \personpossadj\ arrival.
+
+\removeperson
+\end{example}
+
+\section{Advanced Commands}
+
+This section describes additional commands provided by the
+\sty{person} package. More detail can be found in
+the documented code (datatool-code.pdf).
+
+\subsection{Conditionals}
+
+\begin{definition}[\DescribeMacro{\ifpersonexists}]
+\cs{ifpersonexists}\marg{label}\marg{true part}\marg{false part}
+\end{definition}
+Tests if the person identified by \meta{label} has been defined.
+If true, do \meta{true part} otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\ifmale}]
+\cs{ifmale}\marg{label}\marg{true part}\marg{false part}
+\end{definition}
+Test if the person identified by \meta{label} is male.
+If true, do \meta{true part} otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\iffemale}]
+\cs{iffemale}\marg{label}\marg{true part}\marg{false part}
+\end{definition}
+Test if the person identified by \meta{label} is female.
+If true, do \meta{true part} otherwise do \meta{false part}.
+
+\begin{definition}[\DescribeMacro{\ifallmale}]
+\cs{ifallmale}\oarg{label list}\marg{true part}\marg{false part}
+\end{definition}
+Tests if all the people listed in \meta{label list} are male.
+If true, do \meta{true part} otherwise do \meta{false part}.
+If \meta{label list} is omitted, applied to all defined people.
+\begin{definition}[\DescribeMacro{\ifallfemale}]
+\cs{ifallfemale}\oarg{label list}\marg{true part}\marg{false part}
+\end{definition}
+Likewise to test if all the people tested are female.
+
+To determine if a string is an allowed male label:
+\begin{definition}[\DescribeMacro{\ifmalelabel}]
+\cs{ifmalelabel}\marg{identifier}\marg{true part}\marg{false part}
+\end{definition}
+where \meta{identifier} is the string to be tested. If true, do
+\meta{true part} otherwise do \meta{false part}.
+For example:
+\begin{verbatim}
+\def\gender{M}
+\ifmalelabel{\gender}{male}{not male}
+\end{verbatim}
+Similarly to for an allowed female label:
+\begin{definition}[\DescribeMacro{\iffemalelabel}]
+\cs{iffemalelabel}\marg{identifier}\marg{true part}\marg{false part}
+\end{definition}
+For example:
+\begin{verbatim}
+\ifmalelabel{\gender}{Male}{%
+ \iffemalelabel{\gender}{Female}%
+ {Undefined Gender}%
+}
+\end{verbatim}
+
+\subsection{Iterating Through Defined People}
+
+You can iterate through all defined people using:
+\begin{definition}[\DescribeMacro{\foreachperson}]
+\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{do}\marg{body}
+\end{definition}
+At each iteration, \meta{name cs}, \meta{full name cs},
+\meta{gender cs} and \meta{label cs} are set to the current person's
+name, full name, gender and label, respectively. (These arguments
+must all be command names.) Note that the gender is set to
+the definition of \DescribeMacro{\malename}\cs{malename} or
+\DescribeMacro{\femalename}\cs{femalename}, as appropriate.\footnote{Predefined names provided by the \sty{person} package are described
+in the documented code (datatool-code.pdf).} Once these
+commands are set, \meta{body} is applied.
+
+If you only want to iterate through a subset of defined people,
+you can use:
+\begin{definition}
+\cs{foreachperson}(\meta{name cs},\meta{full name cs},\meta{gender cs},\meta{label cs})\cs{in}\marg{list}\cs{do}\marg{body}
+\end{definition}
+where \meta{list} is a comma-separated list of labels.
+
+\subsection{Accessing Individual Information}
+
+\begin{definition}[\DescribeMacro{\getpersongender}]
+\cs{getpersongender}\marg{cs}\marg{label}
+\end{definition}
+Gets the gender of the person identified by \meta{label} and
+stores in \meta{cs} (which must be a command name). This
+sets \meta{cs} to the definition of \ics{malename} or
+\ics{femalename} as appropriate.
+
+\begin{definition}[\DescribeMacro{\getpersonname}]
+\cs{getpersonname}\marg{cs}\marg{label}
+\end{definition}
+Gets the name of the person identified by \meta{label} and
+stores in \meta{cs} (which must be a command name).
+
+\begin{definition}[\DescribeMacro{\getpersonfullname}]
+\cs{getpersonfullname}\marg{cs}\marg{label}
+\end{definition}
+Gets the full name of the person identified by \meta{label} and
+stores in \meta{cs} (which must be a command name).
+
+\clearpage
+\phantomsection
+\addcontentsline{toc}{chapter}{\bibname}
+\DTLbibliography{docbib}
+
+\clearpage
+\phantomsection
+\addcontentsline{toc}{chapter}{Acknowledgements}
+\chapter*{Acknowledgements}
+
+Many thanks to Morten~H\o gholm for providing a much more
+efficient way of storing the information in databases which
+has significantly improved the time it takes to \LaTeX\ documents
+containing large databases.
+
+\clearpage
+\phantomsection
+\addcontentsline{toc}{chapter}{\indexname}
+\PrintIndex
+
+\end{document}