%\iffalse % datatool.dtx generated using makedtx version 0.94b (c) Nicola Talbot % Command line args: % -macrocode "databib.bst" % -src "datatool\.sty\Z=>datatool.sty" % -src "datapie\.sty\Z=>datapie.sty" % -src "dataplot\.sty\Z=>dataplot.sty" % -src "databar\.sty\Z=>databar.sty" % -src "databib\.sty\Z=>databib.sty" % -src "databib\.bst\Z=>databib.bst" % -src "person\.sty\Z=>person.sty" % -author "Nicola Talbot" % -dir "source" % -setambles ".*\.bst=>\nopreamble\usepreamble\defaultpreamble\nopostamble" % -comment "databib.bst" % -doc "datatool-manual.tex" % -codetitle "datatool.sty" % datatool % Created on 2009/11/15 15:10 %\fi %\iffalse %<*package> %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % %\fi % \iffalse % Doc-Source file to use with LaTeX2e % Copyright (C) 2009 Nicola Talbot, all rights reserved. % \fi % \iffalse %<*driver> \documentclass[a4paper]{ltxdoc} \usepackage{dox} \usepackage{ifthen} \usepackage[verbose=false]{datatool} \usepackage{datapie,databar,databib,person} \usepackage{textcomp} \usepackage{graphicx} \usepackage{colortbl} \usepackage{cmap} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \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} \usetikzlibrary{snakes} %hyperindex conflicts with doc %(end up with |usage|hyperpage in indexentry) %This unfortunately means that the changes section doesn't %have active links, but at least it will keep makeindex happy. \renewcommand{\usage}[1]{\textit{\hyperpage{#1}}} \renewcommand{\main}[1]{\hyperpage{#1}} \newcommand{\see}[2]{\emph{see} #1} \makeatletter \def\index@prologue{\section*{Index}} % commands are too wide for a 3 column index \def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi \columnseprule \z@ \columnsep 35\p@ \twocolumn[\index@prologue]% \IndexParms \let\item\@idxitem \ignorespaces} \def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi} \makeatother \RecordChanges \PageIndex \CheckSum{16375} \newcommand*{\sty}[1]{\textsf{#1}} \newcommand*{\env}[1]{\textsf{#1}} \newcommand*{\ext}[1]{\texttt{#1}} \definecolor{defbackground}{rgb}{0.8,1,1} \makeatletter \newcommand*{\setting}[2]{\textsf{#2}\relax \@for\thiscmd:=#1\do{% \edef\doindex{\noexpand\index {\thiscmd\space settings=\noexpand\cs{\thiscmd} settings>#2=\noexpand \textsf{#2}|hyperpage}}\doindex }} \makeatother \newsavebox\defsbox \newlength\defwidth \newenvironment{definition}[1][]{% \def\defarg{#1}% \setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}% \begin{lrbox}{\defsbox}% \setlength\defwidth\linewidth \addtolength\defwidth{-2\fboxrule}% \addtolength\defwidth{-2\fboxsep}% \begin{minipage}{\defwidth}\flushleft }{% \end{minipage} \end{lrbox}% \vskip10pt \noindent \defarg\fcolorbox{black}{defbackground}{\usebox\defsbox}% \vskip10pt \noindent \ignorespacesafterend } \newlength\tmplength \newcommand{\importantpar}{\relax \settowidth{\hangindent}{\bfseries\Huge$\bigtriangleup$\space}\relax \settoheight{\tmplength}{\bfseries\Huge$\bigtriangleup$}\relax \addtolength{\tmplength}{-0.5\baselineskip}\relax \hskip-\hangindent \smash{\raisebox{-\tmplength}{\bfseries \raisebox{3pt}{\large!}$\!$\makebox[0pt]{\Huge$\bigtriangleup$}\relax }}\relax \hskip0.5\hangindent \hangafter=-2\relax } \doxitem{Counter}{counter}{counters} \newcommand*{\ctrfmt}[1]{\texttt{#1}} \newcommand*{\ctr}[1]{\ctrfmt{#1}\SpecialMainCounterIndex{#1}} \newcommand*{\desctr}[1]{\ctrfmt{#1}\DescribeCounter{#1}} \newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} \newcommand*{\pkgopt}[2][datatool]{\textsf{#2}\index {#1 package options=\textsf{#1} package options>#2=\textsf{#2}|hyperpage}} \newcommand*{\cmdopt}[2]{\textsf{#2}\index{#1 options=\cs{#1} options>#2=\textsf{#2}|hyperpage}} \newcounter{example} \newcommand*{\examplename}{example} \makeatletter \newenvironment{example}[2]{\refstepcounter{example}\label{#2}% \par\vskip10pt\noindent \textbf{\large Example \theexample\ (#1)}% \addcontentsline{loe}{section}{\protect\numberline{\theexample}#1}% \nopagebreak\par\vskip10pt\nopagebreak }% {\begin{center}\rule{2in}{1pt}\end{center}} \newcommand*{\listofexamples}{\section*{List of Examples}% \@starttoc{loe}} \makeatother %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} \begin{document} \DocInput{datatool.dtx} \end{document} % %\fi %\MakeShortVerb{"} %\DeleteShortVerb{\|} % % \title{datatool v 2.03: Databases and data manipulation} % \author{Nicola L.C. Talbot\\[10pt] %School of Computing Sciences\\ %University of East Anglia\\ %Norwich. Norfolk\\ %NR4 7TJ. United Kingdom.\\ %\url{http://theoval.cmp.uea.ac.uk/~nlct/}} % % \date{15th November 2009} % \maketitle % %\pdfbookmark[1]{Contents}{contents} %\tableofcontents %\pdfbookmark[1]{List of Examples}{examples} %\listofexamples %\pdfbookmark[1]{List of Figures}{figures} %\listoffigures %\pdfbookmark[1]{List of Tables}{tables} %\listoftables % % \section{Introduction} % % \changes{1.0}{2007 July 22}{Initial version} %The \sty{datatool} bundle consists of the following %packages: \sty{datatool}, \sty{datapie}, \sty{dataplot}, %\sty{databar} and \sty{databib}. % %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. %\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} package, enabling fixed point %arithmetic to be performed on elements of the database. %\item Names can be converted to initials. %\item Strings can be tested to determine if they are all %upper or lower case. %\item String comparisons (both case sensitive and case insensitive) %can be performed. %\end{itemize} % %The \sty{datapie} package 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} % %The \sty{databar} package 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.) % %The \sty{dataplot} package can be used to convert a database into %a two dimensional plot using markers and/or lines. Three dimensional %plots are currently not supported. % %The \sty{databib} package can be used to convert a \BibTeX\ database %into a \sty{datatool} database. % %\section{Data Types} %\label{sec:datatypes} % %The \sty{datatool} 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} %Note that scientific notation is not supported, and the number group %character may not be used after the decimal character. % %\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} % %\subsection{Conditionals} %\label{sec:ifconditions} % %The following conditionals are provided by the \sty{datatool} %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 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 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}. % %\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 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 \cs{DTLifnumclosedbetween}, otherwise it is equivalent to %\cs{DTLifstringclosedbetween} (when using \cs{DTLifclosedbetween}) %or %\cs{DTLifstringclosedbetween*} (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}) %\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}. % %\subsection{\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. % %\section{Fixed Point Arithmetic} %\label{sec:fp} % %The \sty{datatool} package uses the \sty{fp} 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} package. 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} package. 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 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} package provides convenience commands which %use \cs{DTLconverttodecimal}, and then use the basic macros provided %by the \sty{fp} package. The resulting value is then converted %back into the locale format using %\cs{DTLdecimaltolocale} or \cs{DTLdecimaltocurrency}. % % %\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} %\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. % %\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. % %\section{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}} % %\section{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. % %\importantpar 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{Thanks to Morten H\o gholm %for the suggestion.} 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. % %\subsection{Creating a New Database} %\label{sec:newdb} % %\begin{definition}[\DescribeMacro{\DTLnewdb}]% %\cs{DTLnewdb}\marg{db name} %\end{definition} %This command creates a new empty database called \meta{db name}. 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}\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} % %\subsection{Loading a Database from an External ASCII File} %\label{sec:loaddb} % %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} %This creates a new database called \meta{db name}, and fills %it with the entries given in the file \meta{filename}. %The 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 key=value list of options. Available options are: %\begin{description} %\item[\cmdopt{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[\cmdopt{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[\cmdopt{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} %\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} %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} % %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 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 the same as \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} % %\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}. % %\importantpar 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. % %\subsection{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}\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. % %\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 figures. % %\item[label] The label for this table. % %\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 \cmdopt{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} % %\importantpar 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. % %In addition to the \cs{dtl}\meta{type}"align" commands above, you %can also modify the \env{tabular} column styles by redefining %\DescribeMacro{\dtlbeforecols}\cs{dtlbeforecols}, %\DescribeMacro{\dtlbetweencols}\cs{dtlbetweencols} and %\DescribeMacro{\dtlaftercols}\cs{dtlaftercols}. 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{\dtldisplaystarttab}]% %\cs{dtldisplaystarttab} %\end{definition} %This is a hook to add something at the beginning of the %\env{tabular} environment. This defaults to nothing. % %\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. % %\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. % %\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. % %\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} % %\subsection{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{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}. % %\importantpar 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. % %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{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}{% %\\ %\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{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. % %\importantpar 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. % %\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{\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 \autoref{sec:code:loops}. % %\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 %\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}{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} %\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 %\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 \cmdopt{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} % %\subsection{Null Values} %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. %(Note that a null value is not the same as an empty value.) % %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 command name, %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{example}{Null 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. % %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 no null values, but has an 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} %\end{example} % %\subsection{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. % %In the body of the \ics{DTLforeach} loop,\footnote{Only the %unstarred version of \cs{DTLforeach}; the starred version is %read-only.}\ you can use the following to edit the current row: %\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}{\surname=Surname,\firstname=FirstName,\average %=Average,\assignI=Assignment 1,\assignII=Assignment 2,\assignIII %=Assignment 3}{\\\surname %& \firstname & \assignI & \assignII & \assignIII & %\DTLround{\average}{\average}{2}\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}\average}\relax %\end{tabular} %\end{table} % %\end{example} % %\subsection{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} % %\subsection{Sorting a Database} %\label{sec:sort} % %\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} %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. (String comparisons %are made using the command \cs{dtlcompare} or \cs{dtlicompare} %described in \autoref{src:dtlcompare}.) % %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} % %\subsection{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. % %\subsection{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} %Clears the database given by \meta{db name}. The database is emptied %but remains defined. % %\begin{definition}[\DescribeMacro{\DTLdeletedb}] %\cs{DTLdeletedb}\marg{db name} %\end{definition} %Deletes (undefines) the database given by \meta{db name}. % %\subsection{Advanced Database Commands} % %This section describes more advanced commands. Further details %can be found in \autoref{sec:code:datatool}. % %\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{\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{\dtlforcolumnindex}]% %\cs{dtlforcolumnindex}\marg{cs}\marg{db}\marg{col index}\marg{body} %\end{definition} % %\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}. % %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{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 do \meta{true part} otherwise do false %part. (Does a one level expansion on \meta{list}, but no %expansion on \meta{element}.) % %\section{Pie Charts (\texorpdfstring{\sty{datapie}}{datapie} package)} % %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[datapie]{color}}] Colour option (default). %\item[{\pkgopt[datapie]{gray}}] Grey scale option. %\item[{\pkgopt[datapie]{rotateinner}}] %Rotate inner labels so that they are aligned %with the pie chart radial axis. %\item[{\pkgopt[datapie]{norotateinner}}] %Don't rotate inner labels (default). %\item[{\pkgopt[datapie]{rotateouter}}] %Rotate outer labels so that they are aligned %with the pie chart radial axis. %\item[{\pkgopt[datapie]{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[\setting{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[\setting{DTLpiechart}{start}] %This is the starting angle of the first segment. The %value is 0 by default. % %\item[\setting{DTLpiechart}{radius}] %This is the radius of the pie chart. The default value %is 2cm. % %\item[\setting{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 ratio. The default value is 0.5. % %\item[\setting{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 ratio. The default value is 1.25. % %\item[\setting{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 ratio. The default value is 0.2. % %\item[\setting{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 \setting{DTLpiechart}{innerratio} %and \setting{DTLpiechart}{inneroffset}, not both. If you also want to %specify the radius, you must use \setting{DTLpiechart}{ratio} %before \setting{DTLpiechart}{inneroffset}. If omitted, the inner %offset is obtained from the ratio multiplied by the %\setting{DTLpiechart}{innerratio} value. % %\item[\setting{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 \setting{DTLpiechart}{outerratio} %and \setting{DTLpiechart}{outeroffset}, not both. If you also want to %specify the radius, you must use \setting{DTLpiechart}{ratio} %before \setting{DTLpiechart}{outeroffset}. If omitted, the outer %offset is obtained from the ratio multiplied by the %\setting{DTLpiechart}{outerratio} value. % %\item[\setting{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 \setting{DTLpiechart}{cutawayratio} and %\setting{DTLpiechart}{cutawayoffset}, not both. If %you also want to specify the radius, you must use %\setting{DTLpiechart}{ratio} before %\setting{DTLpiechart}{cutawayoffset}. If omitted, the cutaway offset %is obtained from the ratio multiplied by the %\setting{DTLpiechart}{cutawayratio} value. % %\item[\setting{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 \setting{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[\setting{DTLpiechart}{innerlabel}] %The value of this is positioned in the middle of each segment at a %distance of \setting{DTLpiechart}{inneroffset} from the centre %of the pie chart. The default is the same as the value of %\setting{DTLpiechart}{variable}. % %\item[\setting{DTLpiechart}{outerlabel}] %The value of this is positioned at a distance of %\setting{DTLpiechart}{outeroffset} from the centre of the pie chart. %The default is empty. % %\item[\setting{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[datapie]{rotateinner} and \pkgopt[datapie]{norotateinner}. % %\item[\setting{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[datapie]{rotateouter} and \pkgopt[datapie]{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}. % %\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 \setting{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 %\setting{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} % %\subsection{Pie Chart Variables} % %\begin{definition}[\DescribeMacro{\DTLpievariable}]% %\cs{DTLpievariable} %\end{definition} %This command is set to the variable given by the %\setting{DTLpiechart}{variable} setting in the \meta{settings list} %argument of \cs{DTLpiechart}. The \setting{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} % %\subsection{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} % %\subsection{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}\meta{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 \setting{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} % %\subsection{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} % %\section{Scatter and Line Plots (\texorpdfstring{\sty{dataplot}}{dataplot} %package)} % %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 \setting{DTLplot}{x} and \setting{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 \setting{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[\setting{DTLplot}{x}] The database key %that specifies the $x$ co-ordinates. This setting is required. % %\item[\setting{DTLplot}{y}] The database key that specifies %the $y$ co-ordinates. This setting is required. % %\item[\setting{DTLplot}{markcolors}] A comma separated list of colour %names for the markers. An empty value will use the current colour. % %\item[\setting{DTLplot}{linecolors}] A comma separated list of colour %names for the plot lines. An empty value will use the current colour. % %\item[\setting{DTLplot}{colors}] A comma separated list of colour %names for the lines and markers. % %\item[\setting{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[\setting{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[\setting{DTLplot}{width}] The width of the plot. This must %be a length. The plot width does not include outer tick marks or %labels. % %\item[\setting{DTLplot}{height}] The height of the plot. This must %be a length. The plot height does not include outer tick marks %or labels. % %\item[\setting{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[\setting{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[\setting{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[\setting{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 \setting{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[\setting{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 \setting{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[\setting{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[\setting{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[\setting{DTLplot}{xticdir}] This sets the $x$ tick direction, %and may only take the values "in" or "out". % %\item[\setting{DTLplot}{yticdir}] This sets the $y$ tick direction, %and may only take the values "in" or "out". % %\item[\setting{DTLplot}{ticdir}] This sets the $x$ and $y$ tick %direction, and may only take the values "in" or "out". % %\item[\setting{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 \setting{DTLplot}{bounds} setting overrides %the \setting{DTLplot}{minx}, \setting{DTLplot}{maxx}, %\setting{DTLplot}{miny} and \setting{DTLplot}{maxy} settings. % %\item[\setting{DTLplot}{minx}] The value is the minimum value %of the $x$ axis. % %\item[\setting{DTLplot}{miny}] The value is the minimum value %of the $y$ axis. % %\item[\setting{DTLplot}{maxx}] The value is the maximum value %of the $x$ axis. % %\item[\setting{DTLplot}{maxy}] The value is the maximum value %of the $y$ axis. % %\item[\setting{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 \setting{DTLplot}{xticgap}. % %\item[\setting{DTLplot}{xticgap}] This value specifies the %gap between the $x$ tick marks. % %\item[\setting{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 \setting{DTLplot}{yticgap}. % %\item[\setting{DTLplot}{yticgap}] This value specifies the %gap between the $y$ tick marks. % %\item[\setting{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[\setting{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[\setting{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[\setting{DTLplot}{xlabel}] The value is the label for %the $x$ axis. If omitted, the axis has no label. % %\item[\setting{DTLplot}{ylabel}] The value is the label for %the $y$ axis. If omitted, the axis has no label. % %\item[\setting{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[\setting{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.55}\relax %\DTLnewdbentry{groupa}{Weight}{45.4}\relax %\DTLnewrow{groupa}\relax %\DTLnewdbentry{groupa}{Height}{1.54}\relax %\DTLnewdbentry{groupa}{Weight}{48.0}\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 \setting{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 \setting{DTLplot}{legend} setting, %with the legend labels "Group A" and "Group B", %and set the $x$ tick intervals using \setting{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} % %\subsection{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. % %\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} % %\subsection{Global Plot Settings} % %\subsubsection{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. % %\subsubsection{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}. % %\subsubsection{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. % %\subsection{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 % % computer 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 %\setcounter{DTLplotroundXvar}{0} % % redefine \DTLplotatbegintikz to plot the data for Experiment 1 %\renewcommand*{\DTLplotatbegintikz}{% % % set plot mark %\pgfplothandlermark{\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. %\item I set the counter \ctr{DTLplotroundXvar} to zero %otherwise the $x$ axis would have looked too cluttered. %\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}{0} %\renewcommand*{\DTLplotatbegintikz}{% %\pgfplothandlermark{\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} % %\section{Bar Charts (\texorpdfstring{\sty{databar}}{databar} %package)} % %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[databar]{color}}] Created coloured bar charts %(default). % %\item[{\pkgopt[databar]{gray}}] Created grey scale bar charts. % %\item[{\pkgopt[databar]{vertical}}] Created vertical bar charts %(default). % %\item[{\pkgopt[databar]{horizontal}}] Created horizontal bar charts. %\end{description} % % % %\begin{definition}[\DescribeMacro{\DTLbarchart}]% %\cs{DTLbarchart}\oarg{condition}\marg{db name}\marg{settings}\marg{values} %\end{definition} %\begin{definition}[\DescribeMacro{\DTLmultibarchart}]% %\cs{DTLmultibarchart}\oarg{condition}\marg{db name}\marg{settings}\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 \setting{DTLbarchart}{variable} setting is %required for \cs{DTLbarchart} and the %\setting{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[\setting{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[\setting{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[\setting{DTLbarchart,DTLmultibarchart}{max}] %This specifies the maximum value on the $y$ axis. (This should %be a standard decimal value.) % %\item[\setting{DTLbarchart,DTLmultibarchart}{length}] %This specifies the overall length of the $y$ axis, and must %be a dimension. % %\item[\setting{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[\setting{DTLbarchart,DTLmultibarchart}{axes}] %This setting specifies which axes to display. This may take one %of the following values: "both", "x", "y" or "none". % %\item[\setting{DTLbarchart,DTLmultibarchart}{barlabel}] %This setting specifies the lower bar label. When used with %\cs{DTLmultibarchart} it indicates the group label. % %\item[\setting{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[\setting{DTLbarchart}{upperbarlabel}] %This setting specifies the upper bar label. This setting %is not available for \cs{DTLmultibarchart}. % %\item[\setting{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[\setting{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 \setting{DTLbarchart}{yticgap}. % %\item[\setting{DTLbarchart,DTLmultibarchart}{yticgap}] %This specifies the gap between the $y$ tick marks. (This should %be a standard decimal value.) % %\item[\setting{DTLbarchart,DTLmultibarchart}{yticlabels}] %This must be a comma separated list of tick labels for the %$y$ axis. % %\item[\setting{DTLbarchart,DTLmultibarchart}{ylabel}] %This specifies the label for the $y$ axis. % %\item[\setting{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[\setting{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} % %\subsection{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[databar]{vertical} %package option or the \setting{DTLbarchart}{verticalbars} setting, %and defaults to "right" if you use the \pkgopt[databar]{horizontal} %package option or the \setting{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 %\setting{DTLmultibarchart}{variables}) setting and $g$ is the %group gap (as specified by the \setting{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 %\setting{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 %\setting{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} % %\section{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{DTLforeachbib}, 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}". % %\importantpar 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 \ext{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. % %\subsection{\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 \ext{aux} extension). \BibTeX\ then reads %this file and looks for the commands \cs{bibstyle} (which indicates %which bibliography style (\ext{bst}) file to load), \cs{bibdata} %(which indicates which bibliography database (\ext{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 \ext{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 %\ext{bbl} which typically contains the typeset bibliography. % %\item %\begin{verbatim} %latex mydoc %\end{verbatim} %Now that the \ext{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} % %\subsubsection{\texorpdfstring{\BibTeX}{BibTeX} database} % %The bibliographic data required by \BibTeX\ must be stored in %a file with the extension \ext{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}. % %\subsection{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 \ext{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 \ext{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 \ext{bbl} file.) If the \ext{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 \ext{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}. % %\importantpar 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}. % %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}). % %\subsection{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" or "Url". % %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 \ext{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[databib]{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}<11]{mybib} %\end{document} %\end{verbatim} %\end{example} % %\subsection{Changing the bibliography style} %\label{sec:bibstyle} %The style of the bibliography produced using \cs{DTLbibliography} %depends on the \pkgopt[databib]{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}). % %\subsubsection{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{\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 \ext{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} % %\subsection{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{\DTLforeachbib}]% %\cs{DTLforeachbib}\oarg{condition}\marg{db name}\marg{text} %\end{definition} %\begin{definition}[\DescribeMacro{\DTLforeachbib*}]% %\cs{DTLforeachbib*}\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. % %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 \ext{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". % %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. % %\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{DTLforeachbib} 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} % %\subsection{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} % %\importantpar 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. % %\section{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}. % %\subsection{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. % %\subsection{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} % %\subsection{Advanced Commands} % %This section describes additional commands provided by the %\sty{person} package. More detail can be found in %\autoref{sec:code:person}. % %\subsubsection{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} % %\subsubsection{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 \autoref{sec:code:peoplenames}.} 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. % %\subsubsection{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). % % \StopEventually{\clearpage\phantomsection %\addcontentsline{toc}{section}{\refname} % \DTLbibliography{docbib} %\addcontentsline{toc}{section}{Acknowledgements} %\section*{Acknowledgements} % %Many thanks to Morten~H\o gholm for suggesting 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. % %\phantomsection %\addcontentsline{toc}{section}{Change History}\PrintChanges %\clearpage %\phantomsection %\addcontentsline{toc}{section}{Index}\PrintIndex %} % % % %\section{datatool.sty} %\iffalse % \begin{macrocode} %<*datatool.sty> % \end{macrocode} %\fi %\label{sec:code:datatool} %\subsection{Package Declaration} % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{datatool}[2009/11/15 v2.03 (NLCT)] % \end{macrocode} % Load required packages: % \begin{macrocode} \RequirePackage{xkeyval} \RequirePackage{ifthen} \RequirePackage{xfor} \RequirePackage{fp} \RequirePackage{substr} % \end{macrocode} %\changes{2.0}{2009 February 27}{added etex as a required package} % \begin{macrocode} \RequirePackage{etex} % \end{macrocode} % %\subsection{Package Options} %\begin{macro}{\@dtl@separator} % The data separator character (comma by default) is stored in % \cs{@dtl@separator}. % This is the separator used in external data files, not in the % \LaTeX\ code, which always uses a comma separator. % \begin{macrocode} \newcommand*{\@dtl@separator}{,} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsetseparator} %\begin{definition} %\cs{DTLsetseparator}\marg{char} %\end{definition} % The sets \cs{@dtl@separator}, and constructs the relevent macros % that require this character to be hardcoded into their definition. % \begin{macrocode} \newcommand*{\DTLsetseparator}[1]{% \renewcommand*{\@dtl@separator}{#1}% \@dtl@construct@lopoffs } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsettabseparator} %\cs{DTLsettabseparator} makes it easier to set a tab separator. % \begin{macrocode} \begingroup \catcode`\ 12 \gdef\DTLsettabseparator{% \catcode`\ 12 \DTLsetseparator{ }% } \endgroup % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@delimiter} % The data delimiter character (double quote by default) is stored % in \cs{@dtl@delimiter}. This is used in external data files, not % in the \LaTeX\ code. % \begin{macrocode} \begingroup \catcode`\"12\relax \gdef\@dtl@delimiter{"} \endgroup % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsetdelimiter} %\begin{definition} %\cs{DTLsetdelimiter}\marg{char} %\end{definition} % This sets the delimiter. % \begin{macrocode} \newcommand*\DTLsetdelimiter[1]{% \renewcommand*{\@dtl@delimiter}{#1}% \@dtl@construct@lopoffs} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@construct@lopoff} %\begin{definition} %\cs{@dtl@construct@lopoff}\meta{separator char}\meta{delimiter char} %\end{definition} % This defines %\begin{definition} % \cs{@dtl@lopoff}\meta{first element}\meta{sep}\meta{rest of list}\cs{to}\meta{cmd1}\meta{cmd2} %\end{definition}\noindent %for the current separator and delimiter. % \begin{macrocode} \edef\@dtl@construct@lopoff#1#2{% \noexpand\long\noexpand\def\noexpand\@dtl@lopoff#1##1##2\noexpand \to##3##4{% \noexpand\ifx#2##1\noexpand\relax \noexpand\@dtl@qlopoff#1##1##2\noexpand\to##3##4\relax \noexpand\else \noexpand\@dtl@lop@ff#1##1##2\noexpand\to##3##4\relax \noexpand\fi }} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@construct@qlopoff} %\begin{definition} % \cs{@dtl@construct@qlopoff}\meta{separator char}\meta{delimiter char} %\end{definition} % This constructs \cs{@dtl@qlopoff} to be used % when the entry is surrounded by the current delimiter value. % \begin{macrocode} \edef\@dtl@construct@qlopoff#1#2{% \noexpand\long\noexpand\def\noexpand\@dtl@qlopoff#1#2##1#2#1##2\noexpand \to##3##4{% \noexpand\def##4{##1}\noexpand\def##3{#1##2}% }} % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@construct@lop@ff} %\begin{definition} % \cs{@dtl@construct@lop@ff}\meta{separator char} %\end{definition} % This constructs \cs{@dtl@lop@ff} to be used when % the entry isn't surrouded by the delimiter. % \begin{macrocode} \edef\@dtl@construct@lop@ff#1{% \noexpand\long\noexpand\def\noexpand\@dtl@lop@ff#1##1#1##2\noexpand \to##3##4{% \noexpand\def##4{##1}\noexpand\def##3{#1##2}% }} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@construct@lopoffs} %\begin{definition} %\cs{@dtl@construct@lopoffs} %\end{definition} % This constructs all the lopoff macros % using the given separator and delimiter characters. % \begin{macrocode} \newcommand{\@dtl@construct@lopoffs}{% \edef\@dtl@chars{{\@dtl@separator}{\@dtl@delimiter}}% \expandafter\@dtl@construct@lopoff\@dtl@chars \expandafter\@dtl@construct@qlopoff\@dtl@chars \expandafter\@dtl@construct@lop@ff\expandafter{\@dtl@separator}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@decimal} % The current decimal character is stored in \cs{@dtl@decimal}. % \begin{macrocode} \newcommand*{\@dtl@decimal}{.} % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@numbergroupchar} % The current number group character is stored in % \cs{@dtl@numbergroupchar}. % \begin{macrocode} \newcommand*{\@dtl@numbergroupchar}{,} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsetnumberchars} %\begin{definition} %\cs{DTLsetnumberchars}\marg{number group char}\marg{decimal char} %\end{definition} % This sets the decimal character and number group % characters. % \begin{macrocode} \newcommand*{\DTLsetnumberchars}[2]{% \renewcommand*{\@dtl@numbergroupchar}{#1}% \renewcommand*{\@dtl@decimal}{#2}% \@dtl@construct@getnums \@dtl@construct@stripnumgrpchar{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@construct@getintfrac} %\begin{definition} %\cs{@dtl@construct@getintfrac}\marg{char} %\end{definition} % This constructs the macros for extracting integer and % fractional parts from a real number using the decimal character % \meta{char}. % %\begin{definition} % \cs{DTLconverttodecimal}\marg{num}\marg{cmd} %\end{definition} % \cs{DTLconverttodecimal} will convert locale dependent \meta{num} % a decimal number in a form that can be used in the % macros defined in the \sty{fp} package. The resulting % number is stored in \meta{cmd}. This command has to be redefined % whenever the decimal and number group characters are changed % as they form part of the command definitions. % \begin{macrocode} \edef\@dtl@construct@getintfrac#1{% \noexpand\def\noexpand\@dtl@getintfrac##1#1##2\noexpand\relax{% \noexpand\@dtl@get@intpart{##1}% \noexpand\def\noexpand\@dtl@fracpart{##2}% \noexpand\ifx\noexpand\@empty\noexpand\@dtl@fracpart \noexpand\def\noexpand\@dtl@fracpart{0}% \noexpand\else \noexpand\@dtl@getfracpart##2\noexpand\relax \noexpand\@dtl@choptrailingzeroes{\noexpand\@dtl@fracpart}% \noexpand\fi }% \noexpand\def\noexpand\@dtl@getfracpart##1#1\noexpand\relax{% \noexpand\def\noexpand\@dtl@fracpart{##1}% }% \noexpand\def\noexpand\DTLconverttodecimal##1##2{% \noexpand\dtl@ifsingle{##1}% {\noexpand\expandafter\noexpand\toks@\noexpand\expandafter{##1}% \noexpand\edef\noexpand\@dtl@tmp{\noexpand\the\noexpand\toks@}}% {\noexpand\def\noexpand\@dtl@tmp{##1}}% \noexpand\@dtl@standardize@currency\noexpand\@dtl@tmp \noexpand\ifx\noexpand\@dtl@org@currency\noexpand\@empty \noexpand\else \noexpand\let\noexpand\@dtl@currency\noexpand\@dtl@org@currency \noexpand\fi \noexpand\expandafter \noexpand\@dtl@getintfrac\noexpand\@dtl@tmp#1\noexpand\relax \noexpand\edef##2{\noexpand\@dtl@intpart.\noexpand\@dtl@fracpart}}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@construct@getnums} % The following calls the above with the relevant % decimal character: % \begin{macrocode} \newcommand*{\@dtl@construct@getnums}{% \expandafter\@dtl@construct@getintfrac\expandafter{\@dtl@decimal}} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@get@intpart} % The following gets the integer part (adjusting for % repeating +/- signs if necessary.) % Sets \cs{@dtl@intpart}. % \begin{macrocode} \newcommand*{\@dtl@get@intpart}[1]{% \@dtl@tmpcount=1\relax \def\@dtl@intpart{#1}% \ifx\@dtl@intpart\@empty \def\@dtl@intpart{0}% \else \def\@dtl@intpart{}% \@dtl@get@int@part#1.\relax% \fi \ifnum\@dtl@tmpcount<0\relax \edef\@dtl@intpart{-\@dtl@intpart}% \fi \@dtl@strip@numgrpchar{\@dtl@intpart}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@get@int@part} % \begin{macrocode} \def\@dtl@get@int@part#1#2\relax{% \def\@dtl@argi{#1}% \def\@dtl@argii{#2}% \ifx\protect#1\relax% \let\@dtl@get@nextintpart=\@dtl@get@int@part \else \expandafter\ifx\@dtl@argi\$% \let\@dtl@get@nextintpart=\@dtl@get@int@part \else \ifx-#1% \multiply\@dtl@tmpcount by -1\relax \let\@dtl@get@nextintpart=\@dtl@get@int@part \else \if\@dtl@argi+% \let\@dtl@get@nextintpart=\@dtl@get@int@part \else \def\@dtl@intpart{#1}% \ifx.\@dtl@argii \let\@dtl@get@nextintpart=\@gobble \else \let\@dtl@get@nextintpart=\@dtl@get@next@intpart \fi \fi \fi \fi \fi \@dtl@get@nextintpart#2\relax } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@get@next@intpart} % \begin{macrocode} \def\@dtl@get@next@intpart#1.\relax{% \edef\@dtl@intpart{\@dtl@intpart#1}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@choptrailingzeroes} %\begin{definition} % \cs{@dtl@choptrailingzeroes}\marg{cmd} %\end{definition} % Chops trailing zeroes from number given by \meta{cmd}. % \begin{macrocode} \newcommand*{\@dtl@choptrailingzeroes}[1]{% \def\@dtl@tmpcpz{}% \expandafter\@dtl@chop@trailingzeroes#1\@nil% \let#1=\@dtl@tmpcpz } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@chop@trailingzeroes} % Trailing zeroes are chopped using a recursive algorithm. % \cs{@dtl@tmpcpz} needs to be set before using this. (The chopped % number is put in this control sequence.) % \begin{macrocode} \def\@dtl@chop@trailingzeroes#1#2\@nil{% \FPifeq{#2}{0}% \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% \let\@dtl@chopzeroesnext=\@dtl@gobbletonil \else \edef\@dtl@tmpcpz{\@dtl@tmpcpz#1}% \let\@dtl@chopzeroesnext=\@dtl@chop@trailingzeroes \fi \@dtl@chopzeroesnext#2\@nil } % \end{macrocode} %\end{macro} % No-op macro to end recursion: %\begin{macro}{\@dtl@gobbletonil} % \begin{macrocode} \def\@dtl@gobbletonil#1\@nil{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@truncatedecimal} %\begin{definition} %\cs{dtl@truncatedecimal}\meta{cmd} %\end{definition} %Truncates decimal given by \meta{cmd} to an integer (assumes the % number is in decimal format with full stop as decimal point.) % \begin{macrocode} \newcommand*{\dtl@truncatedecimal}[1]{% \expandafter\@dtl@truncatedecimal#1.\@nil#1} % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@truncatedecimal} % \begin{macrocode} \def\@dtl@truncatedecimal#1.#2\@nil#3{% \def#3{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@strip@numgrpchar} %\begin{definition} % \cs{@dtl@strip@numgrpchar}\marg{cmd} %\end{definition} % Strip the number group character from the number given by % \meta{cmd}. % \begin{macrocode} \newcommand*{\@dtl@strip@numgrpchar}[1]{% \def\@dtl@stripped{}% \edef\@dtl@do@stripnumgrpchar{% \noexpand\@@dtl@strip@numgrpchar#1\@dtl@numbergroupchar \noexpand\relax}% \@dtl@do@stripnumgrpchar \let#1=\@dtl@stripped } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@construct@stripnumgrpchar} % The following macro constructs \cs{@@dtl@strip@numgrpchar}. % \begin{macrocode} \edef\@dtl@construct@stripnumgrpchar#1{% \noexpand\def\noexpand\@@dtl@strip@numgrpchar##1#1##2\noexpand\relax{% \noexpand\expandafter\noexpand\toks@\noexpand\expandafter {\noexpand\@dtl@stripped}% \noexpand\edef\noexpand\@dtl@stripped{\noexpand\the\noexpand\toks@ ##1}% \noexpand\def\noexpand\@dtl@tmp{##2}% \noexpand\ifx\noexpand\@dtl@tmp\noexpand\@empty \noexpand\let\noexpand\@dtl@next=\noexpand\relax \noexpand\else \noexpand\let\noexpand\@dtl@next=\noexpand\@@dtl@strip@numgrpchar \noexpand\fi \noexpand\@dtl@next##2\noexpand\relax }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdecimaltolocale} %\begin{definition} % \cs{DTLdecimaltolocale}\marg{number}\marg{cmd} %\end{definition} % Define command to convert a decimal number into the locale % dependent format. Stores result in \meta{cmd} which must be % a control sequence. % \begin{macrocode} \newcommand*{\DTLdecimaltolocale}[2]{% \edef\@dtl@tmpdtl{#1}% \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax \FPifeq{\@dtl@fracpart}{0}% \edef#2{\@dtl@intpart}% \else \edef#2{\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@decimaltolocale} % Convert the integer part (store in \cs{@dtl@intpart}) % \begin{macrocode} \def\@dtl@decimaltolocale#1.#2\relax{% \@dtl@decimaltolocaleint{#1}% \def\@dtl@fracpart{#2}% \ifx\@dtl@fracpart\@empty \def\@dtl@fracpart{0}% \else \@dtl@decimaltolocalefrac#2\relax \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@decimaltolocaleint} % \begin{macrocode} \def\@dtl@decimaltolocaleint#1{% \@dtl@tmpcount=0\relax \@dtl@countdigits#1.\relax \@dtl@numgrpsepcount=\@dtl@tmpcount\relax \divide\@dtl@numgrpsepcount by 3\relax \multiply\@dtl@numgrpsepcount by 3\relax \advance\@dtl@numgrpsepcount by -\@dtl@tmpcount\relax \ifnum\@dtl@numgrpsepcount<0\relax \advance\@dtl@numgrpsepcount by 3\relax \fi \def\@dtl@intpart{}% \@dtl@decimal@to@localeint#1.\relax } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@countdigits} % Counts the number of digits until "#2" is a full stop. % (increments \cs{@dtl@tmpcount}.) % \begin{macrocode} \def\@dtl@countdigits#1#2\relax{% \advance\@dtl@tmpcount by 1\relax \ifx.#2\relax \let\@dtl@countnext=\@gobble \else \let\@dtl@countnext=\@dtl@countdigits \fi \@dtl@countnext#2\relax } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@decimal@to@localeint} % \begin{macrocode} \def\@dtl@decimal@to@localeint#1#2\relax{% \advance\@dtl@numgrpsepcount by 1\relax \ifx.#2\relax \edef\@dtl@intpart{\@dtl@intpart#1}% \let\@dtl@localeintnext=\@gobble \else \ifnum\@dtl@numgrpsepcount=3\relax \edef\@dtl@intpart{\@dtl@intpart#1\@dtl@numbergroupchar}% \@dtl@numgrpsepcount=0\relax \else \ifnum\@dtl@numgrpsepcount>3\relax \@dtl@numgrpsepcount=0\relax \fi \edef\@dtl@intpart{\@dtl@intpart#1}% \fi \let\@dtl@localeintnext=\@dtl@decimal@to@localeint \fi \@dtl@localeintnext#2\relax } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@decimaltolocalefrac} % Convert the fractional part (store in \cs{@dtl@fracpart}) % \begin{macrocode} % \end{macrocode} \def\@dtl@decimaltolocalefrac#1.\relax{% \def\@dtl@fracpart{#1}% \@dtl@choptrailingzeroes{\@dtl@fracpart}% } %\end{macro} % %\begin{macro}{\DTLdecimaltocurrency} %\begin{definition} % \cs{DTLdecimaltocurrency}\marg{number}\marg{cmd} %\end{definition} % This converts a decimal number into the locale % dependent currency format. Stores result in \meta{cmd} which must be % a control sequence. % \begin{macrocode} \newcommand*{\DTLdecimaltocurrency}[2]{% \edef\@dtl@tmpdtl{#1}% \expandafter\@dtl@decimaltolocale\@dtl@tmpdtl.\relax \dtl@truncatedecimal\@dtl@tmpdtl \@dtl@tmpcount=\@dtl@tmpdtl\relax \expandafter\@dtl@toks\expandafter{\@dtl@currency}% \FPifeq{\@dtl@fracpart}{0}% \ifnum\@dtl@tmpcount<0\relax \@dtl@tmpcount = -\@dtl@tmpcount\relax \edef#2{-\the\@dtl@toks\the\@dtl@tmpcount\@dtl@decimal00}% \else \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal00}% \fi \else \ifnum\@dtl@tmpcount<0\relax \@dtl@tmpcount = -\@dtl@tmpcount\relax \ifnum\@dtl@fracpart<10\relax \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount \@dtl@decimal\@dtl@fracpart0}% \else \edef#2{-\the\@dtl@toks\number\@dtl@tmpcount \@dtl@decimal\@dtl@fracpart}% \fi \else \ifnum\@dtl@fracpart<10\relax \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart0}% \else \edef#2{\the\@dtl@toks\@dtl@intpart\@dtl@decimal\@dtl@fracpart}% \fi \fi \fi } % \end{macrocode} %\end{macro} % % Set the defaults: % \begin{macrocode} \@dtl@construct@lopoffs \@dtl@construct@getnums \expandafter\@dtl@construct@stripnumgrpchar\expandafter {\@dtl@numbergroupchar} % \end{macrocode} % Define key for package option \pkgopt{separator}. % \begin{macrocode} \define@key{datatool.sty}{separator}{% \DTLsetseparator{#1}} % \end{macrocode} % Define key for package option \pkgopt{delimiter}. % \begin{macrocode} \define@key{datatool.sty}{delimiter}{% \DTLsetdelimiter{#1}} % \end{macrocode} % Define key for package option \pkgopt{verbose}. (This also % switches the \sty{fp} messages on/off) % \begin{macrocode} \define@boolkey{datatool.sty}[dtl]{verbose}[true]{% \ifdtlverbose \FPmessagestrue\else \FPmessagesfalse\fi} % \end{macrocode} %\begin{macro}{\dtl@message} %\begin{definition} %\cs{dtl@message}\marg{message string} %\end{definition} % Displays message only if the verbose option is set. % \begin{macrocode} \newcommand*{\dtl@message}[1]{% \ifdtlverbose\typeout{#1}\fi} % \end{macrocode} %\end{macro} % Process package options: % \begin{macrocode} \ProcessOptionsX % \end{macrocode} % %\begin{macro}{\DTLpar} % Many of the commands used by this package are short commands. % This means that you can't use \cs{par} % in the data. To get around this, define the robust command % \cs{DTLpar} to use instead. % \begin{macrocode} \DeclareRobustCommand\DTLpar{\@par} % \end{macrocode} %\end{macro} % % \subsection{Determining Data Types} % The control sequence \cs{@dtl@checknumerical} checks the data % type of its argument, and sets \cs{@dtl@datatype} to 0 if % the argument is a string, 1 if the argument is an integer % or 2 if the argument is a real number. First define % \cs{@dtl@datatype}: %\begin{macro}{\@dtl@datatype} % \begin{macrocode} \newcount\@dtl@datatype % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@tmpcount} % Define temporary count register % \begin{macrocode} \newcount\@dtl@tmpcount % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@tmplength} % Define temporary length register: % \begin{macrocode} \newlength\dtl@tmplength % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@numgrpsepcount} % Define count register to count the digits between the number % group separators. % \begin{macrocode} \newcount\@dtl@numgrpsepcount % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@checknumerical} %\begin{definition} %\cs{@dtl@checknumerical}\marg{arg} %\end{definition} % Checks if \meta{arg} is numerical % (includes decimal numbers, but not scientific notation.) % Sets \cs{@dtl@datatype}, as described above. % \begin{macrocode} \newcommand{\@dtl@checknumerical}[1]{% \@dtl@numgrpsepfalse \def\@dtl@tmp{#1}% \ifx\@empty#1\@empty \@dtl@datatype=0\relax \else \dtl@ifsingle{#1}% {\expandafter\toks@\expandafter{#1}% \edef\@dtl@tmp{\the\toks@}}% {\def\@dtl@tmp{#1}}% \@dtl@tmpcount=0\relax \@dtl@datatype=0\relax \@dtl@numgrpsepcount=2\relax \@dtl@standardize@currency\@dtl@tmp \ifx\@dtl@org@currency\@empty \else \let\@dtl@currency\@dtl@org@currency \fi \expandafter\@dtl@checknumericalstart\@dtl@tmp\@nil\@nil \fi \ifnum\@dtl@numgrpsepcount>-1\relax \if@dtl@numgrpsep \ifnum\@dtl@numgrpsepcount=3\relax \else \@dtl@datatype=0\relax \fi \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@checknumericalstart} % Check first character for checknumerical process to see if % it's a plus or minus sign. % \begin{macrocode} \def\@dtl@checknumericalstart#1#2\@nil\@nil{% \ifx#1\protect \@dtl@checknumericalstart#2\@nil\@nil\relax \else \ifx-#1\relax \def\@dtl@tmp{#2}% \ifx\@empty\@dtl@tmp \@dtl@datatype=0\relax \else \ifnum\@dtl@datatype=0\relax \@dtl@datatype=1\relax \fi \@dtl@checknumericalstart#2\@nil\@nil\relax \fi \else \ifx+#1\relax \def\@dtl@tmp{#2}% \ifx\@empty\@dtl@tmp \@dtl@datatype=0\relax \else \ifnum\@dtl@datatype=0\relax \@dtl@datatype=1\relax \fi \@dtl@checknumericalstart#2\@nil\@nil\relax \fi \else \def\@dtl@tmp{#1}% \ifx#1\$\relax \@dtl@datatype=3\relax \@dtl@checknumericalstart#2\@nil\@nil\relax \else \ifx\@empty\@dtl@tmp \@dtl@datatype=0\relax \else \ifnum\@dtl@datatype=0\relax \@dtl@datatype=1\relax \fi \@dtl@checknumericalloop#1#2\@nil\@nil\relax \fi \fi \fi \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\if@dtl@numgrpsep} % The conditional \cs{if@dtl@numgrpsep} is set the first time % \cs{@dtl@checknumericalloop} encounters the number group % separator. % \begin{macrocode} \newif\if@dtl@numgrpsep % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@ifDigitOrDecimalSep} % Check if argument is either a digit or the decimal separator. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\@dtl@ifDigitOrDecimalSep}[3]{% \ifx0#1\relax #2% \else \ifx1#1\relax #2% \else \ifx2#1\relax #2% \else \ifx3#1\relax #2% \else \ifx4#1\relax #2% \else \ifx5#1\relax #2% \else \ifx6#1\relax #2% \else \ifx7#1\relax #2% \else \ifx8#1\relax #2% \else \ifx9#1\relax #2% \else \expandafter\ifx\@dtl@decimal#1\relax #2% \else #3% \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@checknumericalloop} % Check numerical loop. This iterates through each character % until \cs{@nil} is reached, or invalid character found. % Increments \cs{@dtl@tmpcount} each time it encounters a % decimal character.\changes{1.01}{2007 Aug 17}{fixed bug caused % by commands occuring within text being tested} % \begin{macrocode} \def\@dtl@checknumericalloop#1#2\@nil{% \def\@dtl@tmp{#1}% \ifx\@nnil\@dtl@tmp\relax \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% \else \@dtl@ifDigitOrDecimalSep{#1}{% \let\@dtl@chcknumnext=\@dtl@checknumericalloop% \expandafter\ifx\@dtl@decimal#1\relax \if@dtl@numgrpsep \ifnum\@dtl@numgrpsepcount=3\relax \@dtl@numgrpsepcount=-1\relax \else \@dtl@datatype=0\relax \let\@dtl@chcknumnext=\@dtl@checknumericalnoop \fi \else \@dtl@numgrpsepcount=-1\relax \fi \else \ifnum\@dtl@numgrpsepcount=-1\relax \else \advance\@dtl@numgrpsepcount by 1\relax \fi \fi }{% \ifx\@dtl@numbergroupchar\@dtl@tmp\relax \@dtl@numgrpseptrue \ifnum\@dtl@numgrpsepcount<3\relax \@dtl@datatype=0\relax \let\@dtl@chcknumnext=\@dtl@checknumericalnoop \else \@dtl@numgrpsepcount=0\relax \fi \else \@dtl@datatype=0\relax \let\@dtl@chcknumnext=\@dtl@checknumericalnoop \fi }% \ifx\@dtl@decimal\@dtl@tmp\relax \ifnum\@dtl@datatype<3\relax \@dtl@datatype=2\relax \fi \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount>1\relax \@dtl@datatype=0\relax \let\@dtl@chcknumnext=\@dtl@checknumericalnoop% \fi \fi \fi \@dtl@chcknumnext#2\@nil } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@checknumericalnoop} % End loop % \begin{macrocode} \def\@dtl@checknumericalnoop#1\@nil#2{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumerical} %\begin{definition} %\cs{DTLifnumerical}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % Tests the first argument, if % its numerical do second argument, otherwise do third argument. % \begin{macrocode} \newcommand{\DTLifnumerical}[3]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=0\relax#3\else#2\fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifreal} %\begin{definition} %\cs{DTLifreal}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % Tests the first argument, if % it's a real number (not an integer) do second argument, % otherwise do third argument. % \begin{macrocode} \newcommand{\DTLifreal}[3]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=2\relax #2\else #3\fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifint} %\begin{definition} %\cs{DTLifint}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % Tests the first argument, if % it's an integer do second argument, % otherwise do third argument. % \begin{macrocode} \newcommand{\DTLifint}[3]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=1\relax #2\else #3\fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstring} %\begin{definition} %\cs{DTLifstring}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % Tests the first argument, if % it's a string do second argument, % otherwise do third argument. % \begin{macrocode} \newcommand{\DTLifstring}[3]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=0\relax #2\else #3\fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifcurrency} %\begin{definition} %\cs{DTLifcurrency}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % Tests the first argument, if % it starts with the currency symbol do second argument, % otherwise do third argument. % \begin{macrocode} \newcommand{\DTLifcurrency}[3]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=3\relax #2\else #3\fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifcurrencyunit} %\begin{definition} %\cs{DTLifcurrencyunit}\marg{arg}\marg{symbol}\marg{true % part}\marg{false part} %\end{definition} % This tests if \meta{arg} is currency, and uses the currency unit % \meta{symbol}. If true do third argument, otherwise % do fourth argument. % \begin{macrocode} \newcommand*{\DTLifcurrencyunit}[4]{% \@dtl@checknumerical{#1}% \ifnum\@dtl@datatype=3\relax \ifthenelse{\equal{\@dtl@org@currency}{#2}}{#3}{#4}% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifcasedatatype} %\begin{definition} %\cs{DTLifcasedatatype}\marg{arg}\marg{string case}\marg{int %case}\marg{real case}\marg{currency case} %\end{definition} % If \meta{arg} is a string, do \meta{string case}, if \meta{arg} % is an integer do \meta{int case}, if \meta{arg} is a real number, % do \meta{real case}, if \meta{arg} is currency, do \meta{curreny %case}. % \begin{macrocode} \newcommand{\DTLifcasedatatype}[5]{% \@dtl@checknumerical{#1}% \ifcase\@dtl@datatype #2% string \or #3% integer \or #4% number \or #5% currency \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testbothnumerical} %\begin{definition} %\cs{dtl@testbothnumerical}\marg{arg1}\marg{arg2} %\end{definition} % Tests if both arguments are numerical. This sets % the conditional \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testbothnumerical}[2]{% \dtl@ifsingle{#1}{% \edef\@dtl@tmp{#1}}{% \def\@dtl@tmp{#1}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \edef\@dtl@firsttype{\number\@dtl@datatype}% \dtl@ifsingle{#2}{% \edef\@dtl@tmp{#2}}{% \def\@dtl@tmp{#2}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \multiply\@dtl@datatype by \@dtl@firsttype\relax \ifnum\@dtl@datatype>0\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumlt} %\begin{definition} %\cs{DTLifnumlt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\end{definition} % Determines if \marg{num1} $<$ \marg{num2}. Both numbers % need to have the decimal separator changed to a dot % to ensure that it works with \cs{FPiflt} % \begin{macrocode} \newcommand*{\DTLifnumlt}[4]{% \DTLconverttodecimal{#1}{\@dtl@numi}% \DTLconverttodecimal{#2}{\@dtl@numii}% \FPiflt{\@dtl@numi}{\@dtl@numii}% #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\label{src:dtlcompare} %\begin{macro}{\dtlcompare} %\begin{definition} %\cs{dtlcompare}\marg{count}\marg{string1}\marg{string2} %\end{definition} % Compares \meta{string1} and \meta{string2}, and stores the % result in the count register \meta{count}. The result may be % one of: %\par\vskip\baselineskip\noindent %\begin{tabular}{rl} %-1 & if \meta{string1} is considered to be less than %\meta{string2}\\ %0 & if \meta{string1} is considered to be the same as %\meta{string2}\\ %1 & if \meta{string1} is considered to be greater than %\meta{string2} %\end{tabular} %\par\vskip\baselineskip\noindent %Note that for the purposes of string comparisons, commands within %\meta{string1} and \meta{string2} are ignored, except for %\cs{space} and "~", which are both treated as a space (character %code 32.) The following %examples assume that the count register \cs{mycount} has been %defined as follows: %\begin{verbatim} %\newcount\mycount %\end{verbatim} %\newcount\mycount\par\noindent %\textbf{Examples:} %\begin{enumerate} %\item %\begin{verbatim} %\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{Z\"oe}{Zoe}\number\mycount, since the accent %command is ignored. % %\item %\begin{verbatim} %\dtlcompare{\mycount}{foo}{Foo}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{foo}{Foo}\number\mycount, since the comparison %is case sensitive, however, note the following example: %\item %\begin{verbatim} %\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount %\end{verbatim} %which produces: %\dtlcompare{\mycount}{foo}{\uppercase{f}oo}\number\mycount, since %the \cs{uppercase} command is ignored. % %\item You can ``trick'' \cs{dtlcompare} using a command which doesn't %output any text. Suppose you have defined the following command: %\begin{verbatim} %\newcommand*{\noopsort}[1]{} %\end{verbatim} %\providecommand*{\noopsort}[1]{} %then "\noopsort{a}foo" produces the text: \noopsort{a}foo, however %the following %\begin{verbatim} %\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{\noopsort{a}foo}{bar}\number\mycount, %since the command \cs{noopsort} is disregarded when the comparison %is made, so \cs{dtlcompare} just compares "{a}foo" with "bar", and %since "a" is less than "b", the first string is considered to be less %than the second string. % %\item Note that this also means that: %\begin{verbatim} %\def\mystr{abc}% %\dtlcompare{\mycount}{\mystr}{abc}\number\mycount %\end{verbatim} %produces: %\def\mystr{abc}\relax %\dtlcompare{\mycount}{\mystr}{abc}\number\mycount, since the command %\cs{mystr} is disregarded, which means that \cs{dtlcompare} is %comparing an empty string with the string "abc". % %\item Spaces count in the comparison: %\begin{verbatim} %\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{ab cd}{abcd}\number\mycount, %but sequential spaces are treated as a single space: %\begin{verbatim} %\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{ab cd}{ab cd}\number\mycount. % %\item As usual, spaces following command names are ignored, so %\begin{verbatim} %\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{ab\relax cd}{ab cd}\number\mycount. % %\item "~" and \cs{space} are considered to be the same as a % space: %\begin{verbatim} %\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount %\end{verbatim} %produces: %\dtlcompare{\mycount}{ab cd}{ab~cd}\number\mycount. %\end{enumerate} %\changes{1.01}{2007 Aug 17}{replaces \cs{compare} (no % longer using compare.tex)} % \begin{macrocode} \newcommand*{\dtlcompare}[3]{% \dtl@subnobrsp{#2}{\@dtl@argA}% \dtl@subnobrsp{#3}{\@dtl@argB}% \ifx\@dtl@argA\@empty \ifx\@dtl@argB\@empty #1=0\relax \else #1=-1\relax \fi \else \ifx\@dtl@argB\@empty #1=1\relax \else \DTLsubstituteall{\@dtl@argA}{ }{\space }% \DTLsubstituteall{\@dtl@argB}{ }{\space }% \expandafter\dtl@getfirst\@dtl@argA\end \let\dtl@firstA=\dtl@first \let\dtl@restA=\dtl@rest \expandafter\dtl@getfirst\@dtl@argB\end \let\dtl@firstB=\dtl@first \let\dtl@restB=\dtl@rest \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}% \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}% \ifnum\dtl@codeA=-1\relax \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtlcompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}% \dtl@donext \else \protected@edef\dtl@donext{% \noexpand\dtlcompare {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext \fi \else \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtlcompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}% \dtl@donext \else \ifnum\dtl@codeA<\dtl@codeB #1=-1\relax \else \ifnum\dtl@codeA>\dtl@codeB #1=1\relax \else \ifx\dtl@restA\@empty \ifx\dtl@restB\@empty #1=0\relax \else #1=-1\relax \fi \else \ifx\restB\@empty #1=1\relax \else \protected@edef\dtl@donext{% \noexpand\dtlcompare {\noexpand#1}{\dtl@restA}{\dtl@restB}}% \dtl@donext \fi \fi \fi \fi \fi \fi }{% \protected@edef\dtl@donext{% \noexpand\dtlcompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext }}{% \protected@edef\dtl@donext{% \noexpand\dtlcompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext }% \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@getfirst} % Gets the first object, and stores in \cs{dtl@first}. The remainder % is stored in \cs{dtl@rest}. % \begin{macrocode} \def\dtl@getfirst#1#2\end{% \def\dtl@first{#1}% \ifx\dtl@first\@empty \def\dtl@rest{#2}% \else \dtl@ifsingle{#1}{\def\dtl@rest{#2}}{\dtl@getfirst#1#2\end}% \fi } % \end{macrocode} %\end{macro} % Count registers to store character codes: % \begin{macrocode} \newcount\dtl@codeA \newcount\dtl@codeB % \end{macrocode} %\begin{macro}{\dtl@setcharcode} %\begin{definition} %\cs{dtl@setcharcode}\marg{c}\marg{count register} %\end{definition} % Sets \meta{count register} to the character code of \meta{c}, or to % -1 if \meta{c} is a control sequence, unless \meta{c} is either % \cs{space} or |~| in which case it sets \meta{count register} % to the character code of the space character. % \begin{macrocode} \newcommand*{\dtl@setcharcode}[2]{% \def\@dtl@tmp{#1}% \ifx\@dtl@tmp\@empty #2=-1\relax \else \ifx#1\space\relax #2=`\ \relax \else \ifx#1~\relax #2=`\ \relax \else \ifcat\noexpand#1\relax% #2=-1\relax \else #2=`#1\relax \fi \fi \fi \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@setlccharcode} %\begin{definition} %\cs{dtl@setlccharcode}\marg{c}\marg{count register} %\end{definition} % As \cs{dtl@setlccharcode} except it sets \meta{count register} % to the lower case character code of \meta{c}, unless \meta{c} % is a control sequence, in which case it does the same as % \cs{dtl@setcharcode}. % \begin{macrocode} \newcommand*{\dtl@setlccharcode}[2]{% \def\@dtl@tmp{#1}% \ifx\@dtl@tmp\@empty #2=-1\relax \else \ifx#1\space\relax #2=`\ \relax \else \ifx#1~\relax #2=`\ \relax \else \ifcat\noexpand#1\relax% #2=-1\relax \else #2=\lccode`#1\relax \fi \fi \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\dtlicompare} %\begin{definition} %\cs{dtlicompare}\marg{count}\marg{string1}\marg{string2} %\end{definition} % As \cs{dtlcompare} but ignores case. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\dtlicompare}[3]{% \dtl@subnobrsp{#2}{\@dtl@argA}% \dtl@subnobrsp{#3}{\@dtl@argB}% \ifx\@dtl@argA\@empty \ifx\@dtl@argB\@empty #1=0\relax \else #1=-1\relax \fi \else \ifx\@dtl@argB\@empty #1=1\relax \else \DTLsubstituteall{\@dtl@argA}{ }{\space }% \DTLsubstituteall{\@dtl@argB}{ }{\space }% \expandafter\dtl@getfirst\@dtl@argA\end \let\dtl@firstA=\dtl@first \let\dtl@restA=\dtl@rest \expandafter\dtl@getfirst\@dtl@argB\end \let\dtl@firstB=\dtl@first \let\dtl@restB=\dtl@rest \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% \expandafter\dtl@setlccharcode\expandafter{\dtl@firstA}{\dtl@codeA}% \expandafter\dtl@setlccharcode\expandafter{\dtl@firstB}{\dtl@codeB}% \ifnum\dtl@codeA=-1\relax \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtlicompare{\noexpand#1}{\dtl@restA}{\dtl@restB}}% \dtl@donext \else \protected@edef\dtl@donext{% \noexpand\dtlicompare {\noexpand#1}{\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext \fi \else \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtlicompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@restB}}% \dtl@donext \else \ifnum\dtl@codeA<\dtl@codeB #1=-1\relax \else \ifnum\dtl@codeA>\dtl@codeB #1=1\relax \else \ifx\dtl@restA\@empty \ifx\dtl@restB\@empty #1=0\relax \else #1=-1\relax \fi \else \ifx\restB\@empty #1=1\relax \else \protected@edef\dtl@donext{% \noexpand\dtlicompare {\noexpand#1}{\dtl@restA}{\dtl@restB}}% \dtl@donext \fi \fi \fi \fi \fi \fi }{% \protected@edef\dtl@donext{% \noexpand\dtlicompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext }}{% \protected@edef\dtl@donext{% \noexpand\dtlicompare {\noexpand#1}{\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext }% \fi \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstringlt} %\begin{definition} %\cs{DTLifstringlt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\end{definition} % String comparison (Starred version ignores case) %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifstringlt}{\@ifstar\@sDTLifstringlt\@DTLifstringlt} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifstringlt}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount<0\relax #3% \else #4% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifstringlt}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount<0\relax #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLiflt} %\begin{definition} %\cs{DTLiflt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} %\end{definition} % Does \cs{DTLifnumlt} if both \meta{arg1} and \meta{arg2} are % numerical, otherwise do \cs{DTLifstringlt} (unstarred version) % or \cs{DTLifstringlt*} (starred version). %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLiflt}{\@ifstar\@sDTLiflt\@DTLiflt} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLiflt}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumlt{#1}{#2}{#3}{#4}% \else \@DTLifstringlt{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLiflt}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumlt{#1}{#2}{#3}{#4}% \else \@sDTLifstringlt{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumgt} %\begin{definition} %\cs{DTLifnumgt}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\end{definition} % Determines if \marg{num1} $>$ \marg{num2}. Both numbers % need to have the decimal separator changed to a dot % to ensure that it works with \cs{FPifgt} % \begin{macrocode} \newcommand*{\DTLifnumgt}[4]{% \DTLconverttodecimal{#1}{\@dtl@numi}% \DTLconverttodecimal{#2}{\@dtl@numii}% \FPifgt{\@dtl@numi}{\@dtl@numii}% #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstringgt} %\begin{definition} %\cs{DTLifstringgt}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\end{definition} % String comparison (starred version ignores case) %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifstringgt}{\@ifstar\@sDTLifstringgt\@DTLifstringgt} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifstringgt}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount>0\relax #3% \else #4% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifstringgt}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount>0\relax #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifgt} %\begin{definition} %\cs{DTLifgt}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} %\end{definition} % Does \cs{DTLifnumgt} if both \meta{arg1} and \meta{arg2} are % numerical, otherwise do \cs{DTLifstringgt} or \cs{DTLifstringgt*}. %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifgt}{\@ifstar\@sDTLifgt\@DTLifgt} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifgt}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumgt{#1}{#2}{#3}{#4}% \else \@DTLifstringgt{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifgt}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumgt{#1}{#2}{#3}{#4}% \else \@sDTLifstringgt{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumeq} %\begin{definition} %\cs{DTLifnumeq}\marg{num1}\marg{num2}\marg{true part}\marg{false part} %\end{definition} % Determines if \marg{num1} = \marg{num2}. Both numbers % need to have the decimal separator changed to a dot % to ensure that it works with \cs{FPifeq} % \begin{macrocode} \newcommand*{\DTLifnumeq}[4]{% \DTLconverttodecimal{#1}{\@dtl@numi}% \DTLconverttodecimal{#2}{\@dtl@numii}% \FPifeq{\@dtl@numi}{\@dtl@numii}% #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstringeq} %\begin{definition} %\cs{DTLifstringeq}\marg{string1}\marg{string2}\marg{true part}\marg{false part} %\end{definition} % String comparison (starred version ignores case) %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifstringeq}{\@ifstar\@sDTLifstringeq\@DTLifstringeq} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifstringeq}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount=0\relax #3% \else #4% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifstringeq}[4]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount=0\relax #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifeq} %\begin{definition} %\cs{DTLifeq}\marg{arg1}\marg{arg2}\marg{true part}\marg{false part} %\end{definition} % Does \cs{DTLifnumeq} if both \meta{arg1} and \meta{arg2} are % numerical, otherwise do \cs{DTLifstringeq} or \cs{DTLifstringeq*}. %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifeq}{\@ifstar\@sDTLifeq\@DTLifeq} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifeq}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumeq{#1}{#2}{#3}{#4}% \else \@DTLifstringeq{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifeq}[4]{% \dtl@testbothnumerical{#1}{#2}% \if@dtl@condition \DTLifnumeq{#1}{#2}{#3}{#4}% \else \@sDTLifstringeq{#1}{#2}{#3}{#4}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifSubString} %\begin{definition} %\cs{DTLifSubString}\marg{string}\marg{sub string}\marg{true %part}\marg{false part} %\end{definition} % If \meta{sub string} is contained in \meta{string} does %\meta{true part}, otherwise does \meta{false part}. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLifSubString}[4]{% \protected@edef\@dtl@tmp{\noexpand\dtl@testifsubstring {#1}{#2}}% \@dtl@tmp \if@dtl@condition #3% \else #4% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testifsubstring} % \begin{macrocode} \newcommand*{\dtl@testifsubstring}[2]{% \dtl@subnobrsp{#1}{\@dtl@argA}% \dtl@subnobrsp{#2}{\@dtl@argB}% \ifx\@dtl@argB\@empty \@dtl@conditiontrue \else \ifx\@dtl@argA\@empty \@dtl@conditionfalse \else \dtl@teststartswith{#1}{#2}% \if@dtl@condition \else \DTLsubstituteall{\@dtl@argA}{ }{\space }% \expandafter\dtl@getfirst\@dtl@argA\end \expandafter\dtl@ifsingle\expandafter{\dtl@first}{% \expandafter\dtl@testifsubstring\expandafter{\dtl@rest}{#2}% }{% \protected@edef\@dtl@donext{\noexpand\dtl@testifsubstring {\dtl@first\dtl@rest}{\@dtl@argB}}% \@dtl@donext }% \fi \fi \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifStartsWith} %\begin{definition} %\cs{DTLifStartsWith}\marg{string}\marg{substring}\marg{true %part}\marg{false part} %\end{definition} %If \meta{string} starts with \meta{substring}, this does %\meta{true part}, otherwise it does \meta{false part}. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLifStartsWith}[4]{% \@dtl@conditionfalse \protected@edef\@dtl@tmp{\noexpand\dtl@teststartswith{#1}{#2}}% \@dtl@tmp \if@dtl@condition #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@teststartswith} %\begin{definition} %\cs{dtl@teststartswith}\marg{string}\marg{prefix} %\end{definition} % Tests if \meta{string} starts with \meta{prefix}. This sets % \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@teststartswith}[2]{% \dtl@subnobrsp{#1}{\@dtl@argA}% \dtl@subnobrsp{#2}{\@dtl@argB}% \ifx\@dtl@argA\@empty \ifx\@dtl@argB\@empty \@dtl@conditiontrue \else \@dtl@conditionfalse \fi \else \ifx\@dtl@argB\@empty \@dtl@conditiontrue \else \DTLsubstituteall{\@dtl@argA}{ }{\space }% \DTLsubstituteall{\@dtl@argB}{ }{\space }% \expandafter\dtl@getfirst\@dtl@argA\end \let\dtl@firstA=\dtl@first \let\dtl@restA=\dtl@rest \expandafter\dtl@getfirst\@dtl@argB\end \let\dtl@firstB=\dtl@first \let\dtl@restB=\dtl@rest \expandafter\dtl@ifsingle\expandafter{\dtl@firstA}{% \expandafter\dtl@ifsingle\expandafter{\dtl@firstB}{% \expandafter\dtl@setcharcode\expandafter{\dtl@firstA}{\dtl@codeA}% \expandafter\dtl@setcharcode\expandafter{\dtl@firstB}{\dtl@codeB}% \ifnum\dtl@codeA=-1\relax \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}% \dtl@donext \else \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith {\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext \fi \else \ifnum\dtl@codeB=-1\relax \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith {\dtl@firstA\dtl@restA}{\dtl@restB}}% \dtl@donext \else \ifnum\dtl@codeA=\dtl@codeB \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith{\dtl@restA}{\dtl@restB}}% \dtl@donext \else \@dtl@conditionfalse \fi \fi \fi }{% \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% \dtl@donext }}{% \protected@edef\dtl@donext{% \noexpand\dtl@teststartswith {\dtl@firstA\dtl@restA}{\dtl@firstB\dtl@restB}}% }% \fi \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumclosedbetween} %\begin{definition} %\cs{DTLifnumclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. % \begin{macrocode} \newcommand*{\DTLifnumclosedbetween}[5]{% \DTLconverttodecimal{#1}{\@dtl@numi}% \DTLconverttodecimal{#2}{\@dtl@numii}% \DTLconverttodecimal{#3}{\@dtl@numiii}% \DTLifFPclosedbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstringclosedbetween} %\begin{definition} %\cs{DTLifstringclosedbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % String comparison (starred version ignores case) %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifstringclosedbetween}{% \@ifstar\@sDTLifstringclosedbetween\@DTLifstringclosedbetween} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifstringclosedbetween}[5]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \let\@dtl@dovalue\relax \ifnum\@dtl@tmpcount<0\relax \def\@dtl@dovalue{#5}% \fi \ifx\@dtl@dovalue\relax \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount>0\relax \def\@dtl@dovalue{#5}% \else \def\@dtl@dovalue{#4}% \fi \fi \@dtl@dovalue } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifstringclosedbetween}[5]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \let\@dtl@dovalue\relax \ifnum\@dtl@tmpcount<0\relax \def\@dtl@dovalue{#5}% \fi \ifx\@dtl@dovalue\relax \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount>0\relax \def\@dtl@dovalue{#5}% \else \def\@dtl@dovalue{#4}% \fi \fi \@dtl@dovalue } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifclosedbetween} %\begin{definition} %\cs{DTLifclosedbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Does \cs{DTLifnumclosedbetween} if \marg{arg}, \meta{min} and \meta{max} are % numerical, otherwise do \cs{DTLifstringclosedbetween} % or \cs{DTLifstringclosedbetween*}. %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifclosedbetween}{% \@ifstar\@sDTLifclosedbetween\@DTLifclosedbetween} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifclosedbetween}[5]{% \dtl@testbothnumerical{#2}{#3}% \if@dtl@condition \dtl@ifsingle{#1}{% \edef\@dtl@tmp{#1}}{% \def\@dtl@tmp{#1}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \ifnum\@dtl@datatype>0\relax \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}% \else \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% \fi \else \@DTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifclosedbetween}[5]{% \dtl@testbothnumerical{#2}{#3}% \if@dtl@condition \dtl@ifsingle{#1}{% \edef\@dtl@tmp{#1}}{% \def\@dtl@tmp{#1}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \ifnum\@dtl@datatype>0\relax \DTLifnumclosedbetween{#1}{#2}{#3}{#4}{#5}% \else \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% \fi \else \@sDTLifstringclosedbetween{#1}{#2}{#3}{#4}{#5}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifnumopenbetween} %\begin{definition} %\cs{DTLifnumopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Determines if \meta{min} $<$ \meta{num} $<$ \meta{max}. % \begin{macrocode} \newcommand*{\DTLifnumopenbetween}[5]{% \DTLconverttodecimal{#1}{\@dtl@numi}% \DTLconverttodecimal{#2}{\@dtl@numii}% \DTLconverttodecimal{#3}{\@dtl@numiii}% \DTLifFPopenbetween{\@dtl@numi}{\@dtl@numii}{\@dtl@numiii}{#4}{#5}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifstringopenbetween} %\begin{definition} %\cs{DTLifstringopenbetween}\marg{string}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % String comparison (starred version ignores case) %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifstringopenbetween}{% \@ifstar\@sDTLifstringopenbetween\@DTLifstringopenbetween} % \end{macrocode} % Unstarred version: % \begin{macrocode} \newcommand*{\@DTLifstringopenbetween}[5]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \let\@dtl@dovalue\relax \ifnum\@dtl@tmpcount>0\relax \else \def\@dtl@dovalue{#5}% \fi \ifx\@dtl@dovalue\relax \protected@edef\@dtl@tmpcmp{% \noexpand\dtlcompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount<0\relax \def\@dtl@dovalue{#4}% \else \def\@dtl@dovalue{#5}% \fi \fi \@dtl@dovalue } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifstringopenbetween}[5]{% \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#2}}% \@dtl@tmpcmp \let\@dtl@dovalue\relax \ifnum\@dtl@tmpcount>0\relax \else \def\@dtl@dovalue{#5}% \fi \ifx\@dtl@dovalue\relax \protected@edef\@dtl@tmpcmp{% \noexpand\dtlicompare{\noexpand\@dtl@tmpcount}{#1}{#3}}% \@dtl@tmpcmp \ifnum\@dtl@tmpcount<0\relax \def\@dtl@dovalue{#4}% \else \def\@dtl@dovalue{#5}% \fi \fi \@dtl@dovalue } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifopenbetween} %\begin{definition} %\cs{DTLifopenbetween}\marg{arg}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Does \cs{DTLifnumopenbetween} if \marg{arg}, \meta{min} and \meta{max} are % numerical, otherwise do \cs{DTLifstringopenbetween} % or \cs{DTLifstringopenbetween*}. %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLifopenbetween}{% \@ifstar\@sDTLifopenbetween\@DTLifopenbetween} % \end{macrocode} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLifopenbetween}[5]{% \dtl@testbothnumerical{#2}{#3}% \if@dtl@condition \dtl@ifsingle{#1}{% \edef\@dtl@tmp{#1}}{% \def\@dtl@tmp{#1}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \ifnum\@dtl@datatype>0\relax \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}% \else \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% \fi \else \@DTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% \fi } % \end{macrocode} % Starred version % \begin{macrocode} \newcommand*{\@sDTLifopenbetween}[5]{% \dtl@testbothnumerical{#2}{#3}% \if@dtl@condition \dtl@ifsingle{#1}{% \edef\@dtl@tmp{#1}}{% \def\@dtl@tmp{#1}}% \expandafter\@dtl@checknumerical\expandafter{\@dtl@tmp}% \ifnum\@dtl@datatype>0\relax \DTLifnumopenbetween{#1}{#2}{#3}{#4}{#5}% \else \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% \fi \else \@sDTLifstringopenbetween{#1}{#2}{#3}{#4}{#5}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifFPopenbetween} %\begin{definition} %\cs{DTLifFPopenbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Determines if \meta{min} $<$ \meta{num} $<$ \meta{max} where % all arguments are in standard fixed point notation. % \begin{macrocode} \newcommand*{\DTLifFPopenbetween}[5]{% \let\@dtl@dovalue\relax \FPifgt{#1}{#2}% \else \def\@dtl@dovalue{#5}% \fi \FPiflt{#1}{#3}% \ifx\@dtl@dovalue\relax \def\@dtl@dovalue{#4}% \fi \else \def\@dtl@dovalue{#5}% \fi \@dtl@dovalue } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifFPclosedbetween} %\begin{definition} %\cs{DTLifFPclosedbetween}\marg{num}\marg{min}\marg{max}\marg{true part}\marg{false part} %\end{definition} % Determines if \meta{min} $\leq$ \meta{num} $\leq$ \meta{max}. % \begin{macrocode} \newcommand*{\DTLifFPclosedbetween}[5]{% \let\@dtl@dovalue\relax \FPifgt{#1}{#3}% \def\@dtl@dovalue{#5}% \fi \FPiflt{#1}{#2}% \ifx\@dtl@dovalue\relax \def\@dtl@dovalue{#5}% \fi \else \def\@dtl@dovalue{#4}% \fi \@dtl@dovalue } % \end{macrocode} %\end{macro} % % The following conditionals are only meant to be used within % \cs{DTLforeach} as they depend on the counter % \texttt{DTLrow}\meta{n}. % %\begin{macro}{\DTLiffirstrow} %\begin{definition} %\cs{DTLiffirstrow}\marg{true part}\marg{false part} %\end{definition} % Test if the current row is the first row. (This takes % \meta{condition}, the optional argument of \cs{DTLforeach}, % into account, so it may not correspond to row~1 of the % database.) Can only be used in \cs{DTLforeachrow}. %\changes{2.0}{2009 February 27}{modified to have different % definition depending on location} % \begin{macrocode} \newcommand{\DTLiffirstrow}[2]{% \PackageError{datatool}{\string\DTLiffirstrow\space can only be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLiflastrow} %\begin{definition} %\cs{DTLiflastrow}\marg{true part}\marg{false part} %\end{definition} % Checks if the current row is the last row of the database. % It doesn't take the condition (the optional argument of % \cs{DTLforeach}) into account, so its possible it may never % do \meta{true part}, as the last row of the database may not % meet the condition. It is therefore not very useful and is % confusing since it behaves differently to \cs{DTLiffirstrow} % which does take the condition into account, so I have removed % its description from the main part of the manual. If you need % to use the optional argument of \cs{DTLforeach}, you will first % have to iterate through the database to count up the number % of rows which meet the condition, and then do another pass, % checking if the current row has reached that number. %\changes{1.01}{2007 Aug 17}{fixed bug} %\changes{2.0}{2009 February 27}{modified to have different % definition depending on location} % \begin{macrocode} \newcommand{\DTLiflastrow}[2]{% \PackageError{datatool}{\string\DTLiflastrow\space can only be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifoddrow} %\begin{definition} %\cs{DTLifoddrow}\marg{true part}\marg{false part} %\end{definition} % Determines whether the current row is odd (takes the optional % argument of \cs{DTLforeach} into account.) %\changes{2.0}{2009 February 27}{modified to have different % definition depending on location} % \begin{macrocode} \newcommand{\DTLifoddrow}[2]{% \PackageError{datatool}{\string\DTLifoddrow\space can only be used inside \string\DTLforeach}{}% } % \end{macrocode} %\end{macro} % % \subsection{ifthen Conditionals} % The following commands provide conditionals \cs{DTLis}\ldots\ % which can be used in \cs{ifthenelse}. First need to define % a new conditional: %\begin{macro}{\if@dtl@condition} % \begin{macrocode} \newif\if@dtl@condition % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testlt} % Command to test if first argument is less than second argument. % If either argument is a string, a case sensitive string comparison % is used instead. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testlt}[2]{% \DTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLislt} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLislt}[2]{% \TE@throw\noexpand\dtl@testlt{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testiclt} % Command to test if first argument is less than second argument. % If either argument is a string, a case insensitive string comparison % is used instead. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testiclt}[2]{% \@sDTLiflt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLisilt} % Provide conditional command for use in \cs{ifthenelse} %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisilt}[2]{% \TE@throw\noexpand\dtl@testiclt{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testgt} % Command to test if first number is greater than second number. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testgt}[2]{% \DTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisgt} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisgt}[2]{% \TE@throw\noexpand\dtl@testgt{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testicgt} % Command to test if first number is greater than second number % (ignores case). % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testicgt}[2]{% \@sDTLifgt{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisigt} % Provide conditional command for use in \cs{ifthenelse} %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisigt}[2]{% \TE@throw\noexpand\dtl@testicgt{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testeq} % Command to test if first number is equal to the second number. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testeq}[2]{% \DTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLiseq} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLiseq}[2]{% \TE@throw\noexpand\dtl@testeq{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testiceq} % Command to test if first number is equal to the second number % (ignores case). % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testiceq}[2]{% \@sDTLifeq{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisieq} % Provide conditional command for use in \cs{ifthenelse} %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisieq}[2]{% \TE@throw\noexpand\dtl@testiceq{#1}{#2}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLisSubString} % Tests if second argument is contained in first argument. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisSubString}[2]{% \TE@throw\noexpand\dtl@testifsubstring{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLisPrefix} % Tests if first argument starts with second argument. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisPrefix}[2]{% \TE@throw\noexpand\dtl@teststartswith{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testclosedbetween} % Command to test if first value lies between second and third % values. (End points included, case sensitive.) % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testclosedbetween}[3]{% \DTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisclosedbetween} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisclosedbetween}[3]{% \TE@throw\noexpand\dtl@testclosedbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testiclosedbetween} % Command to test if first value lies between second and third % values. (End points included, case ignored.) % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testiclosedbetween}[3]{% \@sDTLifclosedbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisiclosedbetween} % Provide conditional command for use in \cs{ifthenelse} %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisiclosedbetween}[3]{% \TE@throw\noexpand\dtl@testiclosedbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testopenbetween} % Command to test if first value lies between second and third % values. (End points excluded, case sensitive.) % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testopenbetween}[3]{% \DTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue }{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisopenbetween} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisopenbetween}[3]{% \TE@throw\noexpand\dtl@testopenbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testiopenbetween} % Command to test if first value lies between second and third % values. (End points excluded, case ignored.) % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testiopenbetween}[3]{% \@sDTLifopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue }{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisiopenbetween} % Provide conditional command for use in \cs{ifthenelse} %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLisiopenbetween}[3]{% \TE@throw\noexpand\dtl@testiopenbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testclosedbetween} % Command to test if first number lies between second and third % numbers. (End points included, all arguments are fixed point % numbers in standard format.) This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPclosedbetween}[3]{% \DTLifFPclosedbetween{#1}{#2}{#3}% {\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % Provide conditional command for use in \cs{ifthenelse} %\begin{macro}{\DTLisFPclosedbetween} % \begin{macrocode} \newcommand*{\DTLisFPclosedbetween}[3]{% \TE@throw\noexpand\dtl@testFPclosedbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testopenbetween} % Command to test if first number lies between second and third % numbers. (End points excluded, all arguments are fixed point % numbers in standard format.) This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPopenbetween}[3]{% \DTLifFPopenbetween{#1}{#2}{#3}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPopenbetween} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPopenbetween}[3]{% \TE@throw\noexpand\dtl@testFPopenbetween{#1}{#2}{#3}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testFPislt} % Command to test if first number is less than second % number where both numbers are in standard format. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPislt}[2]{% \FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPlt} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPlt}[2]{% \TE@throw\noexpand\dtl@testFPislt{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testFPisgt} % Command to test if first number is greater than second % number where both numbers are in standard format. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPisgt}[2]{% \FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPgt} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPgt}[2]{% \TE@throw\noexpand\dtl@testFPisgt{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testFPiseq} % Command to test if two numbers are equal, where both numbers % are in standard decimal format % \begin{macrocode} \newcommand*{\dtl@testFPiseq}[2]{% \FPifeq{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPeq} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPeq}[2]{% \TE@throw\noexpand\dtl@testFPiseq{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testFPislteq} % Command to test if first number is less than or equal to second % number where both numbers are in standard format. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPislteq}[2]{% \FPiflt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi \if@dtl@condition \else \dtl@testFPiseq{#1}{#2}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPlteq} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPlteq}[2]{% \TE@throw\noexpand\dtl@testFPislteq{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testFPisgteq} % Command to test if first number is greater than or equal to second % number where both numbers are in standard format. % This sets \cs{if@dtl@condition}. % \begin{macrocode} \newcommand*{\dtl@testFPisgteq}[2]{% \FPifgt{#1}{#2}\@dtl@conditiontrue\else\@dtl@conditionfalse\fi \if@dtl@condition \else \dtl@testFPiseq{#1}{#2}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisFPgteq} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisFPgteq}[2]{% \TE@throw\noexpand\dtl@testFPisgteq{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@teststring} % Command to test if argument is a string. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@teststring}[1]{% \DTLifstring{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisstring} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisstring}[1]{% \TE@throw\noexpand\dtl@teststring{#1}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testnumerical} % Command to test if argument is a numerical. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@testnumerical}[1]{% \DTLifnumerical{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisnumerical} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisnumerical}[1]{% \TE@throw\noexpand\dtl@testnumerical{#1}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testint} % Command to test if argument is an integer. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@testint}[1]{% \DTLifint{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisint} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisint}[1]{% \TE@throw\noexpand\dtl@testint{#1}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testreal} % Command to test if argument is a real. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@testreal}[1]{% \DTLifreal{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLisreal} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLisreal}[1]{% \TE@throw\noexpand\dtl@testreal{#1}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testcurrency} % Command to test if argument is a currency. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@testcurrency}[1]{% \DTLifcurrency{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLiscurrency} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLiscurrency}[1]{% \TE@throw\noexpand\dtl@testcurrency{#1}\noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@testcurrencyunit} % Command to test if argument is a currency with given unit. This sets % \cs{if@dtl@condition} % \begin{macrocode} \newcommand*{\dtl@testcurrencyunit}[2]{% \DTLifcurrencyunit{#1}{#2}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLiscurrencyunit} % Provide conditional command for use in \cs{ifthenelse} % \begin{macrocode} \newcommand*{\DTLiscurrencyunit}[2]{% \TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} % % \subsection{Defining New Databases} % As from v2.0, the internal structure of the database has changed % to make it more efficient.\footnote{Thanks to Morten H\o gholm % for the suggestion.} The database is now stored in a token % register instead of a macro. Each row is represented as:\par %\verb|\db@row@elt@w|% %\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% %\meta{column data}% %\verb|\db@row@id@w| \meta{row idx}\verb|\db@row@id@end@|% %\verb|\db@row@elt@end@|\par % where \meta{row idx} is the row index and \meta{column data} is % the data for each column in the row. Each column for a given % row is stored as:\par %\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|% %\verb|\db@col@elt@w| \meta{value}\verb|\db@col@elt@end@|% %\verb|\db@col@id@w| \meta{column idx}\verb|\db@col@id@end@|\par % where \meta{column idx} is the column index and \meta{value} % is the entry for the given column and row. % % Each row only has an associated index, but columns have % a unique identifying key as well as an associated index. Columns % also have an associated data type which may be: 0 (column % contains strings), 1 (column contains integers), 2 (column % contains real numbers), 3 (column contains currency) or % \meta{empty} (column contains no data). Since the key sometimes % has to be expanded, a header is also available in the event % that the user wants to use \cs{DTLdisplaydb} or % \cs{DTLdisplaylongdb} and requires a column header that would % cause problems if used as a key. The general column % information is stored in a token register where each column % has information stored in the form:\par %\verb|\db@plist@elt@w|% %\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% %\verb|\db@key@id@w| \meta{key}\verb|\db@key@id@end@|% %\verb|\db@type@id@w| \meta{type}\verb|\db@type@id@end@|% %\verb|\db@header@id@w| \meta{type}\verb|\db@header@id@end@|% %\verb|\db@col@id@w| \meta{index}\verb|\db@col@id@end@|% %\verb|\db@plist@elt@end@| % % The column name (\meta{key}) is mapped to the column index % using \cs{dtl@ci@}\meta{db}"@"\meta{key} where \meta{db} is % the database name. % %\begin{macro}{\DTLnewdb} %\begin{definition} % \cs{DTLnewdb}\marg{db name} %\end{definition} %\changes{2.0}{2009 February 27}{Changed way database is stored} % Initialises a database called \meta{name}. % \begin{macrocode} \newcommand*{\DTLnewdb}[1]{% % \end{macrocode} % Check if there is already a database with this name. % \begin{macrocode} \DTLifdbexists{#1}% {% \PackageError{datatool}{Database `#1' already exists}{}% }% {% % \end{macrocode} % Define new database. Add information message if in verbose % mode. % \begin{macrocode} \dtl@message{Creating database `#1'}% % \end{macrocode} % Define token register used to store the contents of the database. % \begin{macrocode} \expandafter\newtoks\csname dtldb@#1\endcsname % \end{macrocode} % Define token register used to store the column header information. % \begin{macrocode} \expandafter\newtoks\csname dtlkeys@#1\endcsname{}% % \end{macrocode} % Define count register used to store the row count. % \begin{macrocode} \expandafter\newcount\csname dtlrows@#1\endcsname % \end{macrocode} % Define count register used to store the column count. % \begin{macrocode} \expandafter\newcount\csname dtlcols@#1\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLcleardb} %\begin{definition} % \cs{DTLcleardb}\marg{db name} %\end{definition} % Clears the database. (Makes it empty, but still defined.) %\changes{2.03}{2009 November 15}{new} % \begin{macrocode} \newcommand*{\DTLcleardb}[1]{% \DTLifdbexists{#1}% {% \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do {% \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined }% \csname dtldb@#1\endcsname{}% \csname dtlkeys@#1\endcsname{}% \csname dtlrows@#1\endcsname=0\relax \csname dtlcols@#1\endcsname=0\relax }% {% \PackageError{Can't clear database `#1': database doesn't exist}{}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdeletedb} %\begin{definition} % \cs{DTLdeletedb}\marg{db name} %\end{definition} % Deletes a database. %\changes{2.03}{2009 November 15}{new} % \begin{macrocode} \newcommand*{\DTLdeletedb}[1]{% \DTLifdbexists{#1}% {% \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#1}\do {% \expandafter\let\csname dtl@ci@#1@\@dtl@key\endcsname\undefined }% \expandafter\let\csname dtldb@#1\endcsname\undefined \expandafter\let\csname dtlkeys@#1\endcsname\undefined \expandafter\let\csname dtlrows@#1\endcsname\undefined \expandafter\let\csname dtlcols@#1\endcsname\undefined }% {% \PackageError{Can't delete database `#1': database doesn't exist}{}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLrowcount} %\begin{definition} % \cs{DTLrowcount}\marg{db name} %\end{definition} % The number of rows in the database called \meta{db name}. % (Doesn't check if database exists.) % \begin{macrocode} \newcommand*{\DTLrowcount}[1]{% \expandafter\number\csname dtlrows@#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLcolumncount} %\begin{definition} % \cs{DTLcolumncount}\marg{db name} %\end{definition} % The number of columns in the database called \meta{db name}. % (Doesn't check if database exists.) %\changes{2.0}{2009 February 27}{new}% % \begin{macrocode} \newcommand*{\DTLcolumncount}[1]{% \expandafter\number\csname dtlcols@#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifdbempty} %\begin{definition} % \cs{DTLifdbempty}\marg{name}\marg{true part}\marg{false part} %\end{definition} % Check if named database is empty (i.e.\ no rows have been added). % \begin{macrocode} \newcommand{\DTLifdbempty}[3]{% \DTLifdbexists{#1}% {\@DTLifdbempty{#1}{#2}{#3}}% {\PackageError{Can't check if database `#1' is empty: database doesn't exist}{}{}}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@DTLifdbempty} %\begin{definition} % \cs{@sDTLifdbempty}\marg{name}\marg{true part}\marg{false part} %\end{definition} % Check if named existing database is empty. (No check performed % to determine if the database exists.) %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand{\@DTLifdbempty}[3]{% \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax #2% \else #3% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLnewrow} %\begin{definition} % \cs{DTLnewrow}\marg{db name} %\end{definition} % Add a new row to named database. The starred version doesn't % check for the existence of the database. % \begin{macrocode} \newcommand*{\DTLnewrow}{% \@ifstar\@sDTLnewrow\@DTLnewrow } % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLnewrow} %\begin{definition} % \cs{@DTLnewrow}\marg{db name} %\end{definition} % Add a new row to named database. (Checks for the existance % of the database.) % \begin{macrocode} \newcommand*{\@DTLnewrow}[1]{% \DTLifdbexists{#1}% {\@sDTLnewrow{#1}}% {\PackageErrors{datatool}{Can't add new row to database `#1': database doesn't exist}{}}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sDTLnewrow} %\begin{definition} % \cs{@DTLnewrow}\marg{db name} %\end{definition} % Add a new row to named existing database. (No check performed % to determine if the database exists.) %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@sDTLnewrow}[1]{% % \end{macrocode} % Increment row count. % \begin{macrocode} \global\advance\csname dtlrows@#1\endcsname by 1\relax % \end{macrocode} % Append an empty row to the database % \begin{macrocode} \toks@gput@right@cx{dtldb@#1}{% \noexpand\db@row@elt@w% \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname \noexpand\db@row@id@end@% \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname \noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% }% % \end{macrocode} % Display message on terminal and log file if in verbose mode. % \begin{macrocode} \dtl@message{New row added to database `#1'}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlcolumnnum} % Count register to keep track of column index. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcount\dtlcolumnnum % \end{macrocode} %\end{macro} %\begin{macro}{\dtlrownum} % Count register to keep track of row index. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcount\dtlrownum % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifhaskey} %\begin{definition} %\cs{DTLifhaskey}\meta{db name}\meta{key}\meta{true part}\meta{false % part} %\end{definition} % Checks if the named database \meta{db name} has a column with label % \meta{key}. If column exists, do \meta{true part} otherwise % do \meta{false part}. The starred version doesn't check if % the named database exists. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey} % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLifhaskey} % Unstarred version of \cs{DTLifhaskey} % \begin{macrocode} \newcommand{\@DTLifhaskey}[4]{% \DTLifdbexists{#1}% {% \@sDTLifhaskey{#1}{#2}{#3}{#4}% }% {% \PackageError{datatool}{Database `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\@sDTLifhaskey} % Starred version of \cs{DTLifhaskey} % \begin{macrocode} \newcommand{\@sDTLifhaskey}[4]{% \@ifundefined{dtl@ci@#1@#2}% {% % \end{macrocode} % Key not defined % \begin{macrocode} #4% }% {% % \end{macrocode} % Key defined % \begin{macrocode} #3% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetcolumnindex} %\begin{definition} %\cs{DTLgetcolumnindex}\marg{cs}\marg{db}\marg{key} %\end{definition} % Gets index for column with label \meta{key} from database % \meta{db} and stores in \meta{cs} which must be a control % sequence. % Unstarred version checks if database and key exist, unstarred % version doesn't perform any checks. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLgetcolumnindex}{% \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@getcolumnindex} % Unstarred version of \cs{DTLgetcolumnindex} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtl@getcolumnindex}[3]{% % \end{macrocode} % Check if database exists. % \begin{macrocode} \DTLifdbexists{#2}% {% % \end{macrocode} % Database exists. Now check if key exists. % \begin{macrocode} \@sDTLifhaskey{#2}{#3}% {% % \end{macrocode} % Key exists so go ahead and get column index. % \begin{macrocode} \@sdtl@getcolumnindex{#1}{#2}{#3}% }% {% % \end{macrocode} % Key doesn't exists in named database. % \begin{macrocode} \PackageError{datatool}{Database `#2' doesn't contain key `#3'}{}% }% }% {% % \end{macrocode} % Named database doesn't exist. % \begin{macrocode} \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@getcolumnindex} % Starred version of \cs{DTLgetcolumnindex}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@sdtl@getcolumnindex}[3]{% \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlcolumnindex} %\begin{definition} % \cs{dtlcolumnindex}\marg{db}\marg{key} %\end{definition} % Column index corresponding to \meta{key} in database \meta{db}. % (No check for existance of database or key.) %\changes{2.0}{2009 February 27}{new} %\changes{2.03}{2009 November 15}{renamed \cs{dtl@columnindex} to %\cs{dtlcolumnindex}} % \begin{macrocode} \newcommand*{\dtlcolumnindex}[2]{% \csname dtl@ci@#1@#2\endcsname } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetkeyforcolumn} %\begin{definition} %\cs{DTLgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} %\end{definition} % Gets the key associated with the given column index and stores % in \meta{key cs}. Unstarred version doesn't perform checks. % \begin{macrocode} \newcommand*{\DTLgetkeyforcolumn}{% \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlgetkeyforcolumn} % \begin{macrocode} \newcommand*{\@dtlgetkeyforcolumn}[3]{% \DTLifdbexists{#2}% {% % \end{macrocode} % Check if index is in range. % \begin{macrocode} \ifnum#3<1\relax \PackageError{datatool}{Invalid column index \number#3}{% Column indices start at 1}% \else \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax \PackageError{datatool}{Index \number#3\space out of range for database `#2'}{Database `#2' only has \expandafter\number\csname dtlcols@#2\endcsname\space columns}% \else \@sdtlgetkeyforcolumn{#1}{#2}{#3}% \fi \fi }% {% \PackageError{datatool}{Database `#2' doesn't exists}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sdtlgetkeyforcolumn} %\begin{definition} %\cs{@sdtlgetkeyforcolumn}\marg{key cs}\marg{db}\marg{column index} %\end{definition} % Gets the key associated with the given column index and stores % in \meta{key cs} % \begin{macrocode} \newcommand*{\@sdtlgetkeyforcolumn}[3]{% \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn {\noexpand#1}{#2}{\number#3}}% \@dtl@dogetkeyforcolumn } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@getkeyforcolumn} % Column index must be fully expanded before use. % \begin{macrocode} \newcommand*{\@dtl@getkeyforcolumn}[3]{% \def\@dtl@get@keyforcolumn##1% before stuff \db@plist@elt@w% start of block \db@col@id@w #3\db@col@id@end@% index \db@key@id@w ##2\db@key@id@end@% key \db@type@id@w ##3\db@type@id@end@% data type \db@header@id@w ##4\db@header@id@end@% header \db@col@id@w #3\db@col@id@end@% index \db@plist@elt@end@% end of block ##5\q@nil{\def#1{##2}}% \edef\@dtl@tmp{\expandafter\the\csname dtldb@#2\endcsname}% \expandafter\@dtl@getkeyforcolumn\@dtl@tmp \db@plist@elt@w% start of block \db@col@id@w #3\db@col@id@end@ index \db@key@id@w \@nil\db@key@id@end@% key \db@type@id@w \db@type@id@end@% data type \db@header@id@w \db@header@id@end@% header \db@col@id@w #3\db@col@id@end@% index \db@plist@elt@end@% end of block \q@nil } % \end{macrocode} %\end{macro} % % Define some commands to indicate the various data types a database % may contain. %\begin{macro}{\DTLunsettype} % Unknown data type. (All entries in the column are blank so the % type can't be determined.) %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\DTLunsettype{} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLstringtype} % Data type representing strings. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\DTLstringtype{0} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLinttype} % Data type representing integers. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\DTLinttype{1} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLrealtype} % Data type representing real numbers. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\DTLrealtype{2} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLcurrencytype} % Data type representing currency. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\DTLcurrencytype{3} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetdatatype} %\begin{definition} %\cs{DTLgetdatatype}\marg{cs}\marg{db}\marg{key} %\end{definition} % Gets data type associated with column labelled \meta{key} in % database \meta{db} and stores in \meta{cs}. Type may be: % \meta{empty} (unset), 0 (string), 1 (int), % 2 (real), 3 (currency). Unstarred version checks if the database % and key exist, starred version doesn't. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLgetdatatype}{% \@ifstar\@sdtlgetdatatype\@dtlgetdatatype } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlgetdatatype} % Unstarred version of \cs{DTLgetdatatype}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtlgetdatatype}[3]{% % \end{macrocode} % Check if database exists. % \begin{macrocode} \DTLifdbexists{#2}% {% % \end{macrocode} % Check if key exists in this database. % \begin{macrocode} \@sDTLifhaskey{#2}{#3}% {% % \end{macrocode} % Get data type for this database and key. % \begin{macrocode} \@sdtlgetdatatype{#1}{#2}{#3}% }% {% % \end{macrocode} % Key doesn't exist in this database. % \begin{macrocode} \PackageError{datatool}{Key `#3' undefined in database `#2'}{}% }% }% {% % \end{macrocode} % Database doesn't exist. % \begin{macrocode} \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sdtlgetdatatype} % Starred version of \cs{DTLgetdatatype}. This ensures that % the key is fully expanded before begin passed to % \cs{@dtl@getdatatype}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@sdtlgetdatatype}[3]{% \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}% {\expandafter\the\csname dtlkeys@#2\endcsname}% {\dtlcolumnindex{#2}{#3}}}% \@dtl@dogetdata } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@getdatatype} %\begin{definition} %\cs{@dtl@getdatatype}\marg{cs}\marg{data specs}\marg{column index} %\end{definition} % Column index must be expanded. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtl@getdatatype}[3]{% \def\@dtl@get@keydata##1% stuff before \db@plist@elt@w% start of key block \db@col@id@w #3\db@col@id@end@% column index \db@key@id@w ##2\db@key@id@end@% key id \db@type@id@w ##3\db@type@id@end@% data type \db@header@id@w ##4\db@header@id@end@% header \db@col@id@w #3\db@col@id@end@% column index \db@plist@elt@end@% end of key block ##5% stuff afterwards \q@nil{\def#1{##3}}% \@dtl@get@keydata#2\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@getprops} %\begin{definition} %\cs{@dtl@getprops}\marg{key cs}\marg{type cs}\marg{header toks}\marg{before toks}\marg{after toks}\marg{data specs}\marg{column index} %\end{definition} % Column index must be expanded. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtl@getprops}[7]{% \def\@dtl@get@keydata##1% stuff before \db@plist@elt@w% start of key block \db@col@id@w #7\db@col@id@end@% column index \db@key@id@w ##2\db@key@id@end@% key id \db@type@id@w ##3\db@type@id@end@% data type \db@header@id@w ##4\db@header@id@end@% header \db@col@id@w #7\db@col@id@end@% column index \db@plist@elt@end@% end of key block ##5% stuff afterwards \q@nil{% \def#1{##2}% key \def#2{##3}% data type #3={##4}% header #4={##1}% before stuff #5={##5}% after stuff }% \@dtl@get@keydata#6\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@before} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newtoks\@dtl@before % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@after} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newtoks\@dtl@after % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@colhead} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newtoks\@dtl@colhead % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@updatekeys} %\begin{definition} %\cs{@dtl@updatekeys}\marg{db}\marg{key}\marg{value} %\end{definition} % Adds key to database's key list if it doesn't exist. % The value is used to update the data type associated with that key. % Key must be fully expanded. Doesn't check if database exists. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtl@updatekeys}[3]{% % \end{macrocode} % Check if key already exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% % \end{macrocode} % Key exists, may need to update data type. First get the % column index. % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter =\dtlcolumnindex{#1}{#2}\relax % \end{macrocode} % Get the properties for this column % \begin{macrocode} \edef\@dtl@dogetprops{\noexpand\@dtl@getprops {\noexpand\@dtl@key}{\noexpand\@dtl@type}% {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% {\number\dtlcolumnnum}} \@dtl@dogetprops % \end{macrocode} % Is the value empty? % \begin{macrocode} \def\@dtl@tmp{#3}% \ifx\@dtl@tmp\@empty % \end{macrocode} % Leave data type as it is % \begin{macrocode} \else % \end{macrocode} % Make a copy of current data type % \begin{macrocode} \let\@dtl@oldtype\@dtl@type % \end{macrocode} % Check the data type for this entry (stored in \cs{@dtl@datatype}) % \begin{macrocode} \@dtl@checknumerical{#3}% % \end{macrocode} % If this column currently has no data type assigned to it % then use the new type. % \begin{macrocode} \ifx\@dtl@type\@empty \edef\@dtl@type{\number\@dtl@datatype}% \else % \end{macrocode} % This column already has an associated data type but it may % need updating. % \begin{macrocode} \ifcase\@dtl@datatype % string % \end{macrocode} % String overrides all other types % \begin{macrocode} \def\@dtl@type{0}% \or % int % \end{macrocode} % All other types override int, so leave it as it is % \begin{macrocode} \or % real % \end{macrocode} % Real overrides int, but not currency or string % \begin{macrocode} \ifnum\@dtl@type=1\relax \def\@dtl@type{2}% \fi \or % currency % \end{macrocode} % Currency overrides int and real but not string % \begin{macrocode} \ifnum\@dtl@type>0\relax \def\@dtl@type{3}% \fi \fi \fi % \end{macrocode} % Has the data type been updated? % \begin{macrocode} \ifx\@dtl@oldtype\@dtl@type % \end{macrocode} % No change needed % \begin{macrocode} \else % \end{macrocode} % Update required % \begin{macrocode} \toks@gconcat@middle@cx{dtlkeys@#1}% {\@dtl@before}% {% \noexpand\db@plist@elt@w% start of key block \noexpand\db@col@id@w \the\dtlcolumnnum \noexpand\db@col@id@end@% column index \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id \noexpand\db@type@id@w \@dtl@type \noexpand\db@type@id@end@% data type \noexpand\db@header@id@w \the\@dtl@colhead \noexpand\db@header@id@end@% header \noexpand\db@col@id@w \the\dtlcolumnnum \noexpand\db@col@id@end@% column index \noexpand\db@plist@elt@end@% end of key block }% {\@dtl@after}% \fi \fi }% {% % \end{macrocode} % Key doesn't exist. Increment column count. % \begin{macrocode} \expandafter\global\expandafter\advance \csname dtlcols@#1\endcsname by 1\relax \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax % \end{macrocode} % Set column index for this key % \begin{macrocode} \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{% \number\dtlcolumnnum}% % \end{macrocode} % Get data type for this entry (stored in \cs{@dtl@datatype}) % \begin{macrocode} \def\@dtl@tmp{#3}% \ifx\@dtl@tmp\@empty \edef\@dtl@type{}% don't know data type yet \else \@dtl@checknumerical{#3}% \edef\@dtl@type{\number\@dtl@datatype}% \fi % \end{macrocode} % Append to property list % \begin{macrocode} \toks@gput@right@cx{dtlkeys@#1}% {% \noexpand\db@plist@elt@w \noexpand\db@col@id@w \the\dtlcolumnnum \noexpand\db@col@id@end@ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@ \noexpand\db@type@id@w \@dtl@type \noexpand\db@type@id@end@ \noexpand\db@header@id@w #2\noexpand\db@header@id@end@ \noexpand\db@col@id@w \the\dtlcolumnnum \noexpand\db@col@id@end@ \noexpand\db@plist@elt@end@ }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsetheader} %\begin{definition} %\cs{DTLsetheader}\marg{db}\marg{key}\marg{header} %\end{definition} % Sets header for column given by \meta{key} in database \meta{db}. % Starred version doesn't check for existance of database or key. % \begin{macrocode} \newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader} % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLsetheader} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLsetheader}[3]{% % \end{macrocode} % Check if database exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check if key exists. % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sDTLsetheader{#1}{#2}{#3}% }% {% \PackageError{datatool}{Database `#1' doesn't contain key `#2'}{}% }% }% {% \PackageError{datatool}{Database `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sDTLsetheader} % Starred version % \begin{macrocode} \newcommand*{\@sDTLsetheader}[3]{% \expandafter\dtlcolumnnum\expandafter =\dtlcolumnindex{#1}{#2}\relax \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@setheaderforindex} %\begin{definition} %\cs{@dtl@setheaderforindex}\marg{db}\marg{column index}\marg{header} %\end{definition} % Sets the header for column given by \meta{column index} in % database \meta{db}. The header must be expanded. % \begin{macrocode} \newcommand*{\@dtl@setheaderforindex}[3]{% % \end{macrocode} % Get the properties for this column % \begin{macrocode} \edef\@dtl@dogetprops{\noexpand\@dtl@getprops {\noexpand\@dtl@key}{\noexpand\@dtl@type}% {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}% {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}% {\number#2}} \@dtl@dogetprops % \end{macrocode} % Store the header in \cs{@dtl@toks} % \begin{macrocode} \@dtl@colhead={#3}% % \end{macrocode} % Reconstruct property list % \begin{macrocode} \edef\@dtl@colnum{\number#2}\relax \toks@gconcat@middle@cx{dtlkeys@#1}% {\@dtl@before}% {% \noexpand\db@plist@elt@w% start of block \noexpand\db@col@id@w \@dtl@colnum \noexpand\db@col@id@end@% index \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key \noexpand\db@type@id@w \@dtl@type \noexpand\db@type@id@end@% data type \noexpand\db@header@id@w \the\@dtl@colhead \noexpand\db@header@id@end@% header \noexpand\db@col@id@w \@dtl@colnum \noexpand\db@col@id@end@% index \noexpand\db@plist@elt@end@% end of block }% {\@dtl@after}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlexpandnewvalue} % Expand new value before adding to database % \begin{macrocode} \newcommand*{\dtlexpandnewvalue}{% \def\@dtl@setnewvalue##1{\protected@edef\@dtl@tmp{##1}% \expandafter\@dtl@toks\expandafter{\@dtl@tmp}}% } % \end{macrocode} %\end{macro} %\begin{macro}{\dtlnoexpandnewvalue} % Don't expand new value before adding to database % \begin{macrocode} \newcommand*{\dtlnoexpandnewvalue}{% \def\@dtl@setnewvalue##1{\@dtl@toks{##1}}% } % \end{macrocode} % Do this by default: % \begin{macrocode} \dtlnoexpandnewvalue % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLnewdbentry} %\begin{definition} % \cs{DTLnewdbentry}\marg{db name}\marg{id}\marg{value}. %\end{definition} % Adds an entry to the last row (adds new row if database is empty) % and updates general column information if necessary. The % starred version doesn't check if the database exists. % \begin{macrocode} \newcommand{\DTLnewdbentry}{% \@ifstar\@sDTLnewdbentry\@DTLnewdbentry } % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLnewdbentry} % Unstarred version of \cs{DTLnewdbentry}. % \begin{macrocode} \newcommand{\@DTLnewdbentry}[3]{% \DTLifdbexists{#1}% {\@sDTLnewdbentry{#1}{#2}{#3}}% {\PackageError{datatool}{Can't add new entry to database `#1': database doesn't exist}{}}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@sDTLnewdbentry} % Starred version of \cs{DTLnewdbentry} (doesn't check if the database exists). % \begin{macrocode} \newcommand*{\@sDTLnewdbentry}[3]{% % \end{macrocode} % Update key list % \begin{macrocode} \@dtl@updatekeys{#1}{#2}{#3}% % \end{macrocode} % Get the column index % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter =\dtlcolumnindex{#1}{#2}\relax % \end{macrocode} % Get the current row: % \begin{macrocode} \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}% {\number\csname dtlrows@#1\endcsname}}% \dtl@dogetrow % \end{macrocode} % Check if this row already has an entry for the given column. % \begin{macrocode} \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow {\noexpand\dtl@entry}{\number\dtlcolumnnum}% }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue % \end{macrocode} % Store the value of this entry in \cs{@dtl@toks} %\changes{2.03}{2009 November 15}{value can be expanded before % adding to database}% % \begin{macrocode} \@dtl@setnewvalue{#3}% % \end{macrocode} % There are no entries in this row for the given column. % Add this entry. % \begin{macrocode} \toks@gconcat@middle@cx{dtldb@#1}% {\dtlbeforerow}% {% % \end{macrocode} % Start of this row: % \begin{macrocode} \noexpand\db@row@elt@w% % \end{macrocode} % Row ID: % \begin{macrocode} \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname \noexpand\db@row@id@end@% % \end{macrocode} % Current row so far % \begin{macrocode} \the\dtlcurrentrow % \end{macrocode} % New column: % Column ID % \begin{macrocode} \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@% % \end{macrocode} % Value: % \begin{macrocode} \noexpand\db@col@elt@w \the\@dtl@toks \noexpand\db@col@elt@end@% % \end{macrocode} % Column ID: % \begin{macrocode} \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@% % \end{macrocode} % Row ID: % \begin{macrocode} \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname \noexpand\db@row@id@end@% % \end{macrocode} % End of this row % \begin{macrocode} \noexpand\db@row@elt@end@% }% % \end{macrocode} % Rest (this should be empty) % \begin{macrocode} {\dtlafterrow}% % \end{macrocode} % Print information message if in verbose mode. % \begin{macrocode} \dtl@message{Added #2\space -> #3\space to database `#1'}% \else % \end{macrocode} % There's already an entry for the given column in this row % \begin{macrocode} \PackageError{datatool}{Can't add entry with ID `#2' to current row of database `#1'}{There is already an entry with this ID in the current row}% \fi } % \end{macrocode} %\end{macro} % %\changes{2.0}{2009 February 27}{removed \cs{@dtl@setidtype}} %\changes{2.0}{2009 February 27}{removed \cs{@dtl@setkeys}} %\changes{2.0}{2009 February 27}{removed \cs{@dtl@getidtype}} % %\begin{macro}{\DTLifdbexists} %\begin{definition} %\cs{DTLifdbexists}\marg{db name}\marg{true part}\marg{false part} %\end{definition} % Checks if a data base with the given name exists. % \begin{macrocode} \newcommand{\DTLifdbexists}[3]{% \@ifundefined{dtldb@#1}{#3}{#2}} % \end{macrocode} %\end{macro} % %\changes{2.0}{2009 February 27}{removed \cs{@dtl@ifrowcontains}} %\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryvalue}} %\changes{2.0}{2009 February 27}{removed \cs{dtl@getentryid}} % %\subsection{Accessing Data} % %\begin{macro}{\@dtl@assign} %\begin{definition} %\cs{@dtl@assign}\marg{list}\marg{db} %\end{definition} % Assigns commands according to the given keys. % The current row must be stored in \cs{dtlcurrentrow}. %\changes{2.0}{2009 February 27}{updated to use new database % structure} % \begin{macrocode} \newcommand*{\@dtl@assign}[2]{% \@dtl@assigncmd#1,\@nil\@@{#2}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@assigncmd} %\begin{definition} % \cs{@dtl@assigncmd}\meta{cmd}=\meta{id}\cs{@nil} %\end{definition} %\changes{2.03}{2009 November 15}{modified to ignore spaces after % commas} % \begin{macrocode} \def\@dtl@assigncmd#1#2=#3,#4\@@#5{% % \end{macrocode} % get entry for ID given by \#3 and store in \#2 % \begin{macrocode} \@sDTLifhaskey{#5}{#3}% {% \edef\@dtl@dogetentry{% \noexpand\dtlgetentryfromcurrentrow {\noexpand#1}{\dtlcolumnindex{#5}{#3}}}% \@dtl@dogetentry % \end{macrocode} % Set to null if required % \begin{macrocode} \ifx#1\dtlnovalue \@@dtl@setnull{#1}{#3}% \fi % \end{macrocode} % Make it global % \begin{macrocode} \global\let#1=#1\relax }% {% \PackageError{datatool}{Can't assign \string#1\space: there is no key `#3' in data base `#5'}{}% % \end{macrocode} % Set to null % \begin{macrocode} \global\let#1\DTLstringnull }% % \end{macrocode} % Recurse? % \begin{macrocode} \def\dtl@tmp{#4}% \ifx\@nnil\dtl@tmp \let\@dtl@next\@dtl@assigncmdnoop \else \let\@dtl@next\@dtl@assigncmd \fi \@dtl@next#4\@@{#5}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@assigncmdnoop} % End loop % \begin{macrocode} \def\@dtl@assigncmdnoop#1\@@#2{} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@setnull} %\cs{@dtl@setnull}\marg{cmd}\marg{id} sets \meta{cmd} to either % \cs{DTLstringnull} or \cs{DTLnumbernull} depending on the data % type for \meta{id}. (Database % name should be stored in \cs{@dtl@dbname} prior to use.) %\changes{2.0}{2009 February 27}{modified to use new database % structure} % \begin{macrocode} \newcommand*{\@dtl@setnull}[2]{% % \end{macrocode} % Check if database given by \cs{@dtl@dbname} has the required key. % \begin{macrocode} \@sDTLifhaskey{\@dtl@dbname}{#2}% {% % \end{macrocode} % Set to null % \begin{macrocode} \@@dtl@setnull{#1}{#2}% }% {% % \end{macrocode} % Key not defined in database \cs{@dtl@dbname}. % \begin{macrocode} \global\let#1=\DTLstringnull }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@dtl@setnull} % As above, but doesn't check if key exists % \begin{macrocode} \newcommand*{\@@dtl@setnull}[2]{% % \end{macrocode} % Get the data type associated with this key and store in % \cs{@dtl@type}. % \begin{macrocode} \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}% % \end{macrocode} % Check data type. % \begin{macrocode} \ifnum0\@dtl@type=0\relax % \end{macrocode} % Data type is \meta{empty} or 0, so set to string null. % \begin{macrocode} \global\let#1=\DTLstringnull \else % \end{macrocode} % Data type is numerical, so set to number null. % \begin{macrocode} \global\let#1=\DTLnumbernull \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLstringnull} % String null value: % \begin{macrocode} \newcommand*{\DTLstringnull}{NULL} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLnumbernull} % Number null value: % \begin{macrocode} \newcommand*{\DTLnumbernull}{0} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLifnull} %\begin{definition} %\cs{DTLifnull}\marg{value}\marg{true part}\marg{false part} %\end{definition} % Checks if \meta{value} is null (either \cs{DTLstringnull} or % \cs{DTLnumbernull}) if true, does \meta{true part} otherwise % does \meta{false part}. % \begin{macrocode} \newcommand*{\DTLifnull}[3]{% \ifx\DTLstringnull#1\relax #2% \else \ifx\DTLnumbernull#1\relax #2% \else #3% \fi \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlnovalue} % \begin{macrocode} \def\@dtlnovalue{Undefined Value} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlnovalue} % \begin{macrocode} \def\dtlnovalue{\@dtlnovalue} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetkeydata} %\begin{definition} %\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} and data type is stored in \meta{type cs}. % The unstarred version checks for the existance of the database % and key, the starred version doesn't. % \begin{macrocode} \newcommand*{\DTLgetkeydata}{% \@ifstar\@sdtlgetkeydata\@dtlgetkeydata } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlgetkeydata} % Unstarred version of \cs{DTLgetkeydata} % \begin{macrocode} \newcommand*{\@dtlgetkeydata}[5]{% % \end{macrocode} % Check if the database exists. % \begin{macrocode} \DTLifdbexists{#2}% {% % \end{macrocode} % Check if the given key exists in the database. % \begin{macrocode} \@sDTLifhaskey{#2}{#1}% {% % \end{macrocode} % Get the data. % \begin{macrocode} \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}% }% {% % \end{macrocode} % Key not defined in the given database. % \begin{macrocode} \PackageError{datatool}{Key `#1' not defined in database `#2'}{}% }% }% {% % \end{macrocode} % Database not defined. % \begin{macrocode} \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sdtlgetkeydata} %\cs{@sdtlgetkeydata}\marg{key}\marg{db}\marg{col cs}\marg{type cs}\marg{header cs} % Starred verison of \cs{DTLgetkeydata}. % \begin{macrocode} \newcommand*{\@sdtlgetkeydata}[5]{% \@sdtl@getcolumnindex{#3}{#2}{#1}% \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}% {\noexpand\@dtl@before}{\noexpand\@dtl@after}% {\expandafter\the\csname dtlkeys@#2\endcsname}% {#3}}% \@dtl@dogetkeydata \edef#5{\the\@dtl@toks}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@gathervalues} %\begin{definition} %\cs{dtl@gathervalues}\oarg{label}\marg{db name}\marg{row toks} %\end{definition} % Stores each element of \meta{row} in \meta{db name} into % the command \cs{@dtl@}\meta{label}\texttt{@}\meta{key}, % where \meta{key} is the % key for that element, and \meta{label} defaults to "key". %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand{\dtl@gathervalues}[3][key]{% \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do {% \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}% \ifx\@dtl@tmp\dtlnovalue \@dtl@setnull{\@dtl@tmp}{\@dtl@key}% \fi \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlcurrentrow} % Define token register to store current row. % \begin{macrocode} \newtoks\dtlcurrentrow % \end{macrocode} %\end{macro} %\begin{macro}{\dtlbeforerow} % Define token register to store everything before the current row. % \begin{macrocode} \newtoks\dtlbeforerow % \end{macrocode} %\end{macro} %\begin{macro}{\dtlafterrow} % Define token register to store everything after the current row. % \begin{macrocode} \newtoks\dtlafterrow % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlgetrow} %\begin{definition} %\cs{dtlgetrow}\marg{db}\marg{row idx} %\end{definition} % Gets row with index \meta{row idx} from database named \meta{db} % and stores the row in \cs{dtlcurrentrow}, the preceding rows in % \cs{dtlbeforerow} and the following rows in \cs{dtlafterrow}. % This assumes that the given row exists. % \begin{macrocode} \newcommand*{\dtlgetrow}[2]{% \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}% \@dtl@dogetrow } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlgetrow} %\begin{definition} %\cs{@dtlgetrow}\marg{data specs}\marg{row idx} %\end{definition} % Gets the row specs from \meta{data specs} for row with index % \meta{row idx} which must be fully expanded. % \begin{macrocode} \newcommand*{\@dtlgetrow}[2]{% \def\@dtl@getrow##1% before stuff \db@row@elt@w% start of the row \db@row@id@w #2\db@row@id@end@% row id ##2% \db@row@id@w #2\db@row@id@end@% row id \db@row@elt@end@% end of the row ##3% after stuff \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}% \@dtl@getrow#1\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlgetentryfromcurrentrow} %\begin{definition} %\cs{dtlgetentryfromcurrentrow}\marg{cs}\marg{col num} %\end{definition} % Gets value for column \meta{col num} from \cs{dtlcurrentrow} % and stores in \meta{cs}. If not found, \meta{cs} is set to % \cs{dtlnovalue}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlgetentryfromcurrentrow}[2]{% \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlgetentryfromrow} %\begin{definition} %\cs{dtlgetentryfromrow}\marg{cs}\marg{col num}\marg{row toks} %\end{definition} % \begin{macrocode} \newcommand*{\dtlgetentryfromrow}[3]{% \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow {\noexpand#1}{\number#2}{\the#3}}% \@dtl@do@getentry } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@getentryfromrow} %\begin{definition} %\cs{dtl@getentryfromrow}\marg{cs}\marg{col num}\marg{row specs} %\end{definition} % \begin{macrocode} \newcommand*{\dtl@getentryfromrow}[3]{% \def\dtl@dogetentry##1% before stuff \db@col@id@w #2\db@col@id@end@% Column id \db@col@elt@w ##2\db@col@elt@end@% Value \db@col@id@w #2\db@col@id@end@% Column id ##3% Remaining stuff \q@nil{\def#1{##2}}% \dtl@dogetentry#3% \db@col@id@w #2\db@col@id@end@% \db@col@elt@w \@dtlnovalue\db@col@elt@end@% \db@col@id@w #2\db@col@id@end@% \q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetvalue} %\begin{definition} %\cs{DTLgetvalue}\marg{cs}\marg{db}\marg{r}\marg{c} %\end{definition} % Gets the element in row \meta{r}, column \meta{c} from database % \meta{db} and stores in \meta{cs}. % \begin{macrocode} \newcommand*{\DTLgetvalue}[4]{% \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}% {\number#3}{\number#4}}% \dtl@dogetvalue } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@getvalue} % \begin{macrocode} \newcommand*{\dtl@getvalue}[4]{% \def\@dtl@getvalue ##1% stuff before row \db@row@id@w #3\db@row@id@end@% row id ##2% stuff in row before column \db@col@id@w #4\db@col@id@end@% column id \db@col@elt@w ##3\db@col@elt@end@% value ##4% stuff after value \q@nil{\def#1{##3}}% \toks@=\csname dtldb@#2\endcsname \expandafter\@dtl@getvalue\the\toks@% contents of data base \db@row@id@w #3\db@row@id@end@% \db@col@id@w #4\db@col@id@end@% \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value \q@nil \ifx#1\dtlnovalue \PackageError{datatool}{There is no element at (row=#3, column=#4) in database `#2'}{}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetlocation} %\begin{definition} %\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{macrocode} \newcommand*{\DTLgetlocation}[4]{% \def\@dtl@getlocation##1% stuff before value \db@col@elt@w #4\db@col@elt@end@% value \db@col@id@w ##2\db@col@id@end@% column id ##3% stuff after this column \db@row@id@w ##4\db@row@id@end@% row id ##5% stuff after row \q@nil{\def#1{##4}\def#2{##2}}% \toks@=\csname dtldb@#3\endcsname \expandafter\@dtl@getlocation\the\toks@% contents of data base \db@col@elt@w #4\db@col@elt@end@% value \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id \q@nil \ifx#1\dtlnovalue \PackageError{datatool}{There is no element `#4' in database `#3'}{}% \fi } % \end{macrocode} %\end{macro} %\subsection{Iterating Through Databases} %\label{sec:code:loops} % %\begin{macro}{\dtlbreak} % Break out of loop at the end of current iteration. % \begin{macrocode} \newcommand*{\dtlbreak}{% \PackageError{datatool}{Can't break out of anything}{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlforint} %\begin{definition} %\cs{dtlforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% %\meta{inc}\cs{do}\marg{body} %\end{definition} % \meta{ct} is a count register, \meta{start}, \meta{end} and % \meta{inc} are integers. % Group if nested or use \cs{dtlgforint}. % An infinite loop may result if \meta{inc}$=0$ and % \meta{start} $\le$ \meta{end} and \cs{dtlbreak} isn't used. % \begin{macrocode} \long\def\dtlforint#1=#2\to#3\step#4\do#5{% % \end{macrocode} % Make a copy of old version of break function % \begin{macrocode} \let\@dtl@orgbreak\dtlbreak \def\@dtl@endloophook{}% % \end{macrocode} % Setup break function for the loop (sets \meta{ct} to \meta{end} % at the end of the current iteration). % \begin{macrocode} \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}% % \end{macrocode} % Initialise \meta{ct} % \begin{macrocode} #1=#2\relax % \end{macrocode} % Check if the steps are positive or negative. % \begin{macrocode} \ifnum#4<0\relax % \end{macrocode} % Counting down % \begin{macrocode} \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% {% #5% \@dtl@endloophook \advance#1 by #4\relax }% \else % \end{macrocode} % Counting up % \begin{macrocode} \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% {% #5% \@dtl@endloophook \advance#1 by #4\relax }% \fi % \end{macrocode} % Restore break function. % \begin{macrocode} \let\dtlbreak\@dtl@orgbreak } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@foreach@level} % Count register to keep track of global nested loops. % \begin{macrocode} \newcount\@dtl@foreach@level % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlgforint} %\begin{definition} %\cs{dtlgforint}\meta{ct}=\meta{start}\cs{to}\meta{end}\cs{step}% %\meta{inc}\cs{do}\marg{body} %\end{definition} % \meta{ct} is a count register, \meta{start}, \meta{end} and % \meta{inc} are integers. % An infinite loop may result if \meta{inc}=0 and \meta{start} $\le$ % \meta{end} and \cs{dtlbreak} isn't used. % \begin{macrocode} \long\def\dtlgforint#1=#2\to#3\step#4\do#5{% % \end{macrocode} % Initialise % \begin{macrocode} \global#1=#2\relax % \end{macrocode} % Increment level counter to allow for nested loops % \begin{macrocode} \global\advance\@dtl@foreach@level by 1\relax % \end{macrocode} % Set up end loop hook % \begin{macrocode} \expandafter\global\expandafter \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname \relax % \end{macrocode} % Set up the break function: % Copy current definition % \begin{macrocode} \expandafter\global\expandafter \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname \dtlbreak % \end{macrocode} % Set up definition for this level (sets to at the end % of the current iteration). % \begin{macrocode} \gdef\dtlbreak{\expandafter \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{% #1=#3}}% % \end{macrocode} % check the direction % \begin{macrocode} \ifnum#4<0\relax % \end{macrocode} % Counting down % \begin{macrocode} \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}% {% #5% \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname \global\advance#1 by #4\relax }% \else % \end{macrocode} % Counting up (or 0 increments) % \begin{macrocode} \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}% {% #5% \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname \global\advance#1 by #4\relax }% \fi % \end{macrocode} % Restore break function % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\dtlbreak \csname @dtl@break@\the\@dtl@foreach@level\endcsname % \end{macrocode} % Decrement level counter % \begin{macrocode} \global\advance\@dtl@foreach@level by -1\relax } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlforeachrow} %\begin{definition} %\cs{@dtlforeachrow}(\meta{idx cs},\meta{row cs})\cs{in}\marg{db}% %\cs{do}\marg{body} %\end{definition} % Iterates through each row in database. Assigns the current row % index to \meta{idx cs} and the row specs to \meta{row cs} % \begin{macrocode} \long\def\@dtlforeachrow(#1,#2)\in#3\do#4{% \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}% \expandafter\@dtl@foreachrow\dtl@tmp \db@row@elt@w% \db@row@id@w \@nil\db@row@id@end@% \db@row@id@w \@nil\db@row@id@end@% \db@row@elt@end@% \@@{#1}{#2}{#4}\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@foreachrow} % \begin{macrocode} \long\def\@dtl@foreachrow\db@row@elt@w% \db@row@id@w #1\db@row@id@end@% #2\db@row@id@w #3\db@row@id@end@% \db@row@elt@end@#4\@@#5#6#7\q@nil{% % \end{macrocode} % Define control sequence given by "#5" % \begin{macrocode} \gdef#5{#1}% % \end{macrocode} % Hide the loop body in a macro % \begin{macrocode} \gdef\@dtl@loopbody{#7}% % \end{macrocode} % Increment level counter to allow for nested loops % \begin{macrocode} \global\advance\@dtl@foreach@level by 1\relax % \end{macrocode} % Check if we have reached the end of the loop % \begin{macrocode} \ifx#5\@nnil \expandafter\global\expandafter \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname =\@dtl@foreachnoop \else \gdef#6{#2}% % \end{macrocode} % Set up the break function: % Make a copy of current break function % \begin{macrocode} \expandafter\let \csname @dtl@break@\the\@dtl@foreach@level\endcsname \dtlbreak % \end{macrocode} % Setup break function for this level % \begin{macrocode} \gdef\dtlbreak{\expandafter\global\expandafter \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname =\@dtl@foreachnoop}% % \end{macrocode} % Initialise % \begin{macrocode} \expandafter\global\expandafter \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname =\@dtl@foreachrow % \end{macrocode} % Do body of loop % \begin{macrocode} \@dtl@loopbody % \end{macrocode} % Restore break function % \begin{macrocode} \expandafter\let\expandafter\dtlbreak \csname @dtl@break@\the\@dtl@foreach@level\endcsname \fi % \end{macrocode} % Set up what to do next. % \begin{macrocode} \expandafter\let\expandafter\@dtl@foreachnext \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname % \end{macrocode} % Decrement level counter. % \begin{macrocode} \global\advance\@dtl@foreach@level by -1\relax % \end{macrocode} % Repeat loop if necessary. % \begin{macrocode} \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@foreachnoop} % \begin{macrocode} \long\def\@dtl@foreachnoop#1\@@#2\q@nil{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlforeachkey} %\begin{definition} %\cs{dtlforeachkey}(\meta{key cs},\meta{col cs},\meta{type cs},\meta{header cs})% %\cs{in}\marg{db}\cs{do}\marg{body} %\end{definition} % Iterates through all the keys in database \meta{db}. In each % iteration, \meta{key cs} stores the key, \meta{col cs} stores the % column index and \meta{type cs} stores the data type. % \begin{macrocode} \long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{% \gdef\@dtl@loopbody{#6}% \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}% \expandafter\@dtl@foreachkey\@dtl@keys \db@plist@elt@w% \db@col@id@w -1\db@col@id@end@% \db@key@id@w \db@key@id@end@% \db@type@id@w \db@type@id@end@% \db@header@id@w \db@header@id@end@% \db@col@id@w -1\db@col@id@end@% \db@plist@elt@end@% \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@updatefkcs} % \begin{macrocode} \newcommand*{\@dtl@updatefkcs}[8]{% \gdef#1{#5}% \gdef#2{#6}% \gdef#3{#7}% \gdef#4{#8}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@foreachkey} % Sets everything globally in case it occurs in a tabular environment % Loop body needs to be stored in \cs{@dtl@loopbody}. % "#7" indicates an update macro. % \begin{macrocode} \long\def\@dtl@foreachkey\db@plist@elt@w% \db@col@id@w #1\db@col@id@end@% \db@key@id@w #2\db@key@id@end@% \db@type@id@w #3\db@type@id@end@% \db@header@id@w #4\db@header@id@end@% \db@col@id@w #5\db@col@id@end@% \db@plist@elt@end@#6\@@#7\q@nil{% \ifnum#1=-1\relax % \end{macrocode} % Terminate loop % \begin{macrocode} \let\@dtl@foreachnext\@dtl@foreachnoop \else % \end{macrocode} % Set up loop variables % \begin{macrocode} #7{#2}{#1}{#3}{#4}% % \end{macrocode} % Increment level counter to allow for nested loops % \begin{macrocode} \global\advance\@dtl@foreach@level by 1\relax % \end{macrocode} % Set up the break function % \begin{macrocode} \expandafter\let \csname @dtl@break@\the\@dtl@foreach@level\endcsname \dtlbreak \gdef\dtlbreak{\expandafter\global\expandafter \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname =\@dtl@foreachnoop}% % \end{macrocode} % Initialise % \begin{macrocode} \expandafter\global\expandafter \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname =\@dtl@foreachkey % \end{macrocode} % Do body of loop % \begin{macrocode} \@dtl@loopbody % \end{macrocode} % Set up what to do next % \begin{macrocode} \expandafter\let\expandafter\@dtl@foreachnext \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname % \end{macrocode} % Restore break function % \begin{macrocode} \expandafter\let\expandafter\dtlbreak \csname @dtl@break@\the\@dtl@foreach@level\endcsname % \end{macrocode} % Decrement level counter % \begin{macrocode} \global\advance\@dtl@foreach@level by -1\relax \fi % \end{macrocode} % Recurse if necessary % \begin{macrocode} \@dtl@foreachnext#6\@@{#7}\q@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlforcolumn} %\begin{definition} %\cs{dtlforcolumn}\marg{cs}\marg{db}\marg{key}\marg{body} %\end{definition} % Iterates through column given by \meta{key} in database \meta{db}. % \meta{cs} is assign to the element of the column in the % current iteration. Starred version doesn't check if data base % exists % \begin{macrocode} \newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlforcolumn} % \begin{macrocode} \newcommand{\@dtlforcolumn}[4]{% % \end{macrocode} % Check if data base exists % \begin{macrocode} \DTLifdbexists{#2}% {% \@DTLifhaskey{#2}{#3}% {% \@sdtlforcolumn{#1}{#2}{#3}{#4}% }% % \end{macrocode} % key not in data base % \begin{macrocode} {% \PackageError{datatool}{Database `#2' doesn't contain key `#3'}{}% }% }% % {% \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sdtlforcolumn} % \begin{macrocode} \newcommand{\@sdtlforcolumn}[4]{% \toks@{#4}% \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% {\expandafter\the\csname dtldb@#2\endcsname}% {\dtlcolumnindex{#2}{#3}}{\the\toks@}% }% \@dtl@doforcol% } % end{macrocode} %\end{macro} % %\begin{macro}{\dtlforcolumnidx} %\begin{definition} %\cs{dtlforcolumnidx}\marg{cs}\marg{db}\marg{col num}\marg{body} %\end{definition} % Iterates through the column with index in database . % Starred version doesn't check if database exists. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlforcolumnidx}{% \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlforcolumnidx} % \begin{macrocode} \newcommand{\@dtlforcolumnidx}[4]{% \DTLifdbexists{#2}% {% \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax \PackageError{datatool}{Column index \number#3\space out of bounds for database `#2'}{Database `#2' only has \expandafter\number\csname dtlcols@#2\endcsname\space columns}% \else \ifnum#3<1\relax \PackageError{datatool}{Column index \number#3\space out of bounds for database `#2'}{Indices start from 1}% \else \@sdtlforcolumnidx{#1}{#2}{#3}{#4}% \fi \fi }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sdtlforcolumnidx} % \begin{macrocode} \newcommand{\@sdtlforcolumnidx}[4]{% \toks@{#4}% \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}% {\expandafter\the\csname dtldb@#2\endcsname}% {\number#3}{\the\toks@}% }% \@dtl@doforcol } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@forcolumn} %\begin{definition} %\cs{dtl@forcolumn}\marg{cs}\marg{db specs}\marg{col num}\marg{body} %\end{definition} % \meta{col num} needs to be fully expanded % \begin{macrocode} \newcommand{\dtl@forcolumn}[4]{% % \end{macrocode} % make a copy of break function % \begin{macrocode} \let\@dtl@oldbreak\dtlbreak % \end{macrocode} % set up break function % \begin{macrocode} \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}% % \end{macrocode} % define loop macro for this column % \begin{macrocode} \def\@dtl@forcolumn##1% before stuff \db@col@id@w #3\db@col@id@end@% column index \db@col@elt@w ##2\db@col@elt@end@% entry \db@col@id@w #3\db@col@id@end@% column index ##3% after stuff \q@nil{% \def#1{##2}% assign value to % \end{macrocode} % check if end of loop % \begin{macrocode} \ifx#1\@nnil \let\@dtl@forcolnext=\@dtl@forcolnoop \else % \end{macrocode} % do body of loop % \begin{macrocode} #4% \let\@dtl@forcolnext=\@dtl@forcolumn \fi % \end{macrocode} % repeat if necessary % \begin{macrocode} \@dtl@forcolnext##3\q@nil }% % \end{macrocode} % do loop % \begin{macrocode} \@dtl@forcolumn#2% \db@col@id@w #3\db@col@id@end@% \db@col@elt@w \@nil\db@col@elt@end@% \db@col@id@w #3\db@col@id@end@\q@nil % \end{macrocode} % restore break function % \begin{macrocode} \let\dtlbreak\@dtl@oldbreak } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@forcolnoop} % \begin{macrocode} \def\@dtl@forcolnoop#1\q@nil{} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlforeachlevel} %\cs{DTLforeach} can only be nested up to three levels. % \cs{dtlforeachlevel} keeps track of the current level. % \begin{macrocode} \newcount\dtlforeachlevel % \end{macrocode} %\end{macro} % % The counter DTLrow\meta{n} keeps track of each row of data during % the \meta{n} nested \cs{DTLforeach}. It is only incremented in the % conditions (given by the optional argument) are met. % \begin{macrocode} \newcounter{DTLrowi} \newcounter{DTLrowii} \newcounter{DTLrowiii} % \end{macrocode} % Keep \sty{hyperref} happy % \begin{macrocode} \newcounter{DTLrow} \def\theHDTLrow{\arabic{DTLrow}} \def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}} \def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}} \def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}} % \end{macrocode} % % \begin{macrocode} \newcount\dtl@rowi \newcount\dtl@rowii \newcount\dtl@rowiii % \end{macrocode} % % \begin{macrocode} \newtoks\@dtl@curi \newtoks\@dtl@previ \newtoks\@dtl@nexti \newtoks\@dtl@curii \newtoks\@dtl@previi \newtoks\@dtl@nextii \newtoks\@dtl@curiii \newtoks\@dtl@previii \newtoks\@dtl@nextiii % \end{macrocode} % %\begin{macro}{\DTLsaverowcount} %\begin{definition} %\cs{DTLsavelastrowcount}\marg{cmd} %\end{definition} % Stores the maximum row count for the last \cs{DTLforeach}. % \begin{macrocode} \newcommand*{\DTLsavelastrowcount}[1]{% \ifnum\dtlforeachlevel>2\relax \def#1{0}% \else \ifnum\dtlforeachlevel<0\relax \def#1{0}% \else \@dtl@tmpcount=\dtlforeachlevel \advance\@dtl@tmpcount by 1\relax \edef#1{\expandafter\number \csname c@DTLrow\romannumeral\@dtl@tmpcount\endcsname}% \fi \fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLforeach} %\begin{definition} % \cs{DTLforeach}\oarg{conditions}\marg{db name}\marg{values}\marg{text} %\end{definition} % For each row of data in the database given by \meta{db name}, % do \meta{text}, if the specified conditions are satisfied. % The argument \marg{values} is a comma separated list of % \meta{cmd}\texttt{=}\meta{key} pairs. At the start of each row, % each of the commands in this list are set to the value of the % entry with the corresponding key \meta{key}. % (\cs{gdef} is used to ensure \cs{DTLforeach} works in a tabular % environment.) The database may be edited in the unstarred % version, in the starred version the database is read only. %\changes{1.01}{2007 Aug 17}{added starred version} % \begin{macrocode} \newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach} % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLforeach} % \cs{@DTLforeach} is the unstarred version of \cs{DTLforeach}. % The database is reconstructed to allow for rows to be edited. % Use the starred version for faster access. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand{\@DTLforeach}[4][\boolean{true}]{% % \end{macrocode} % Check database exists % \begin{macrocode} \DTLifdbexists{#2}% {% % \end{macrocode} % Keep \sty{hyperref} happy % \begin{macrocode} \refstepcounter{DTLrow}% % \end{macrocode} % Make it global (so that it works in tabular environment) % \begin{macrocode} \global\c@DTLrow=\c@DTLrow\relax % \end{macrocode} % Store database name % \begin{macrocode} \gdef\@dtl@dbname{#2}% % \end{macrocode} % Increment level and check not exceeded 3 % \begin{macrocode} \global\advance\dtlforeachlevel by 1\relax \ifnum\dtlforeachlevel>3\relax \PackageError{datatool}{\string\DTLforeach\space nested too deeply}{Only 3 levels are allowed}% \else \@DTLifdbempty{#2}% % \end{macrocode} % Do nothing if database is empty % \begin{macrocode} {}% {% % \end{macrocode} % Set level dependent information (needs to be global to ensure % it works in the \env{tabular} environment). Row counter: % \begin{macrocode} \expandafter\global \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax % \end{macrocode} % Store previous value of \cs{DTLiffirstrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname \DTLiffirstrow % \end{macrocode} % Define current \cs{DTLiffirstrow} % \begin{macrocode} \gdef\DTLiffirstrow##1##2{% \expandafter\ifnum \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname =1\relax ##1% \else ##2% \fi}% % \end{macrocode} % Store previous value of \cs{DTLiflastrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname \DTLiflastrow % \end{macrocode} % Define current \cs{DTLiflastrow} % \begin{macrocode} \gdef\DTLiflastrow##1##2{% \expandafter\ifnum \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname =\csname dtlcols@#2\endcsname\relax ##1% \else ##2% \fi}% % \end{macrocode} % Store previous value of \cs{DTLifoddrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname \DTLifoddrow % \end{macrocode} % Define current \cs{DTLifoddrow} % \begin{macrocode} \gdef\DTLifoddrow##1##2{% \expandafter\ifodd \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname ##1% \else ##2% \fi}% % \end{macrocode} % Store data base name for current level % \begin{macrocode} \expandafter\global\expandafter\let \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname =\@dtl@dbname % \end{macrocode} % Mark it as not read only % \begin{macrocode} \expandafter\global\expandafter\let \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname = 0\relax % \end{macrocode} % Loop through each row. % Loop counter given by \cs{dtl@row@}\meta{level} % \begin{macrocode} \dtlgforint \csname dtl@row\romannumeral\dtlforeachlevel\endcsname =1\to\csname dtlrows@#2\endcsname\step1\do {% % \end{macrocode} % Get current row from the data base % \begin{macrocode} \@dtl@tmpcount= \csname dtl@row\romannumeral\dtlforeachlevel\endcsname \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}% {\number\@dtl@tmpcount}}% \dtl@dogetrow % \end{macrocode} % Store the current row for this level % \begin{macrocode} \expandafter\global \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname = \dtlcurrentrow % \end{macrocode} % Store the previous rows for this level % \begin{macrocode} \expandafter\global \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname = \dtlbeforerow % \end{macrocode} % Store the subsequent rows for this level % \begin{macrocode} \expandafter\global \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname = \dtlafterrow % \end{macrocode} % Assign commands to the required entries % \begin{macrocode} \ifx\relax#3\relax \else \@dtl@assign{#3}{#2}% \fi % \end{macrocode} % Do the main body of text if condition is satisfied % \begin{macrocode} \ifthenelse{#1}% {% % \end{macrocode} % Increment user row counter % \begin{macrocode} \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% \expandafter\edef\expandafter\DTLcurrentindex% \expandafter{% \arabic{DTLrow\romannumeral\dtlforeachlevel}}% #4% % \end{macrocode} % Has this row been marked for deletion? % \begin{macrocode} \edef\@dtl@tmp{\expandafter\the \csname @dtl@cur\romannumeral \dtlforeachlevel\endcsname}% \ifx\@dtl@tmp\@nnil % \end{macrocode} % Row needs to be deleted % Decrement row indices for rows with a higher index than this one % \begin{macrocode} \expandafter\dtl@decrementrows\expandafter {\csname @dtl@prev\romannumeral \dtlforeachlevel\endcsname }{\csname dtl@row\romannumeral \dtlforeachlevel\endcsname}% \expandafter\dtl@decrementrows\expandafter {\csname @dtl@next\romannumeral \dtlforeachlevel\endcsname }{\csname dtl@row\romannumeral \dtlforeachlevel\endcsname}% % \end{macrocode} % Reconstruct data base without this row % \begin{macrocode} \edef\@dtl@tmp{% \expandafter\the \csname @dtl@prev\romannumeral \dtlforeachlevel\endcsname \expandafter\the \csname @dtl@next\romannumeral \dtlforeachlevel\endcsname }% \expandafter\global\expandafter \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}% % \end{macrocode} % Decrement the row count for this database: % \begin{macrocode} \expandafter\global\expandafter \advance\csname dtlrows@#2\endcsname by -1\relax % \end{macrocode} % Decrement the counter for this loop % \begin{macrocode} \expandafter\global\expandafter \advance\csname dtl@row\romannumeral \dtlforeachlevel\endcsname by -1\relax \else % \end{macrocode} % Reconstruct data base % \begin{macrocode} \@dtl@before=\csname @dtl@prev\romannumeral \dtlforeachlevel\endcsname \@dtl@after=\csname @dtl@next\romannumeral \dtlforeachlevel\endcsname \toks@gconcat@middle@cx{dtldb@#2}% {\@dtl@before}% {% % \end{macrocode} % This row % \begin{macrocode} \noexpand\db@row@elt@w% \noexpand\db@row@id@w \expandafter\number \csname dtl@row\romannumeral \dtlforeachlevel\endcsname \noexpand\db@row@id@end@% \expandafter\the \csname @dtl@cur\romannumeral \dtlforeachlevel\endcsname \noexpand\db@row@id@w \expandafter\number \csname dtl@row\romannumeral \dtlforeachlevel\endcsname \noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% }% {\@dtl@after}% \fi }% % \end{macrocode} % Condition not met so ignore % \begin{macrocode} {}% }% % \end{macrocode} % Restore previous value of \cs{DTLiffirstrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLiffirstrow \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname % \end{macrocode} % Restore previous value of \cs{DTLiflastrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLiflastrow \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname % \end{macrocode} % Restore previous value of \cs{DTLifoddrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLifoddrow \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname }% \fi % \end{macrocode} % Decrement level % \begin{macrocode} \global\advance\dtlforeachlevel by -1\relax }% % \end{macrocode} % else part (data base doesn't exist): % \begin{macrocode} {% \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sDTLforeach} % \cs{@sDTLforeach} is the starred version of \cs{DTLforeach}. % The database rows can't be edited. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand{\@sDTLforeach}[4][\boolean{true}]{% % \end{macrocode} % Check database exists % \begin{macrocode} \DTLifdbexists{#2}% {% % \end{macrocode} % Keep \sty{hyperref} happy % \begin{macrocode} \refstepcounter{DTLrow}% % \end{macrocode} % Make it global (so that it works in tabular environment) % \begin{macrocode} \global\c@DTLrow=\c@DTLrow % \end{macrocode} % Increment level and check not exceeded 3 % \begin{macrocode} \global\advance\dtlforeachlevel by 1\relax \ifnum\dtlforeachlevel>3\relax \PackageError{datatool}{\string\DTLforeach\space nested too deeply}{Only 3 levels are allowed}% \else \@DTLifdbempty{#2}% % \end{macrocode} % Do nothing if database is empty % \begin{macrocode} {}% {% % \end{macrocode} % Set level dependent information (needs to be global to ensure % it works in the \env{tabular} environment). Row counter: % \begin{macrocode} \expandafter\global \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax % \end{macrocode} % Store previous value of \cs{DTLiffirstrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname \DTLiffirstrow % \end{macrocode} % Define current \cs{DTLiffirstrow} % \begin{macrocode} \gdef\DTLiffirstrow##1##2{% \expandafter\ifnum \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname =1\relax ##1% \else ##2% \fi}% % \end{macrocode} % Store previous value of \cs{DTLiflastrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname \DTLiflastrow % \end{macrocode} % Define current \cs{DTLiflastrow} % \begin{macrocode} \gdef\DTLiflastrow##1##2{% \expandafter\ifnum \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname =\csname dtlcols@#2\endcsname\relax ##1% \else ##2% \fi}% % \end{macrocode} % Store previous value of \cs{DTLifoddrow} % \begin{macrocode} \expandafter\global\expandafter\let% \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname \DTLifoddrow % \end{macrocode} % Define current \cs{DTLifoddrow} % \begin{macrocode} \gdef\DTLifoddrow##1##2{% \expandafter\ifodd \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname ##1% \else ##2% \fi}% % \end{macrocode} % Store data base name for current level % \begin{macrocode} \expandafter\gdef\csname @dtl@dbname@\romannumeral \dtlforeachlevel\endcsname{#2}% % \end{macrocode} % Mark it as read only % \begin{macrocode} \expandafter\global\expandafter\let \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname = 1\relax % \end{macrocode} % Iterate through each row. % \begin{macrocode} \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do% {% % \end{macrocode} % Assign row number (not sure if this is needed here) % \begin{macrocode} \csname dtl@row\romannumeral\dtlforeachlevel\endcsname = \dtl@thisidx\relax % \end{macrocode} % Store the current row specs for this level % \begin{macrocode} \expandafter\global \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname = \expandafter{\dtl@thisrow}% % \end{macrocode} % Assign commands to the required entries % \begin{macrocode} \ifx\relax#3\relax \else % \end{macrocode} % Need to set \cs{dtlcurrentrow} for \cs{@dtl@assign} % \begin{macrocode} \dtlcurrentrow=\expandafter{\dtl@thisrow}% \@dtl@assign{#3}{#2}% \fi % \end{macrocode} % Do the main body of text if condition is satisfied % \begin{macrocode} \ifthenelse{#1}% {% % \end{macrocode} % Increment user row counter % \begin{macrocode} \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}% \expandafter\edef\expandafter\DTLcurrentindex% \expandafter{% \arabic{DTLrow\romannumeral\dtlforeachlevel}}% #4% }% % \end{macrocode} % Condition not met so ignore % \begin{macrocode} {}% }% % \end{macrocode} % Restore previous value of \cs{DTLiffirstrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLiffirstrow \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname % \end{macrocode} % Restore previous value of \cs{DTLiflastrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLiflastrow \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname % \end{macrocode} % Restore previous value of \cs{DTLifoddrow} % \begin{macrocode} \expandafter\global\expandafter\let\expandafter\DTLifoddrow \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname }% \fi % \end{macrocode} % Decrement level % \begin{macrocode} \global\advance\dtlforeachlevel by -1\relax }% % \end{macrocode} % else part (data base doesn't exist): % \begin{macrocode} {% \PackageError{datatool}{Database `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlifreadonly} %\begin{definition} %\cs{@dtlifreadonly}\marg{true part}\marg{false part} %\end{definition} % Checks if current loop level is read only %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@dtlifreadonly}[2]{% \expandafter\ifx \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax % \end{macrocode} % Read only % \begin{macrocode} #1% \else % \end{macrocode} % Not read only % \begin{macrocode} #2% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLappendtorow} %\begin{definition} %\cs{DTLappendtorow}\marg{key}\marg{value} %\end{definition} % Appends entry to current row. (The current row is given by % \cs{@dtl@cur}\meta{n} where \meta{n} is roman % numeral value of \cs{dtlforeachlevel}. % One level expansion is applied to \meta{value}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLappendtorow}[2]{% \ifnum\dtlforeachlevel=0\relax \PackageError{datatool}{\string\DTLappendrow\space can only be used inside \string\DTLforeach}{}% \else % \end{macrocode} % Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} \expandafter\let\expandafter\@dtl@thisdb \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Check this isn't in \cs{DTLforeach*} % \begin{macrocode} \@dtlifreadonly {% \PackageError{datatool}{\string\DTLappendtorow\space can't be used inside \DTLforeach*}{The starred version of \string\DTLforeach\space is read only}% }% {% % \end{macrocode} % Store current row number in \cs{dtlrownum} % \begin{macrocode} \dtlrownum= \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} % Update information about this column (adding new column if % necessary) % \begin{macrocode} \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}% % \end{macrocode} % Get column index and store in \cs{dtlcolumnnum} % \begin{macrocode} \expandafter\dtlcolumnnum\expandafter =\dtlcolumnindex{\@dtl@thisdb}{#1}\relax % \end{macrocode} % Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} \dtlcurrentrow = \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Does this row already have an entry with this key? % \begin{macrocode} \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow {\noexpand\dtl@entry}{\number\dtlcolumnnum}% }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue % \end{macrocode} % There are no entries in this row for the given key. % Expand entry value before storing. %\changes{2.03}{2009 November 15}{value expanded before storing} % \begin{macrocode} \protected@edef\@dtl@tmp{#2}% \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% % \end{macrocode} % Append this entry to the current row. % \begin{macrocode} \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}% {% \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@ \noexpand\db@col@elt@w \the\@dtl@toks \noexpand\db@col@elt@end@ \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@ }% % \end{macrocode} % Print information to terminal and log file if in verbose mode. % \begin{macrocode} \dtl@message{Appended #1\space -> #2\space to database `\@dtl@thisdb'}% \else % \end{macrocode} % There is already an entry in this row for the given key % \begin{macrocode} \PackageError{datatool}{Can't append entry to row: there is already an entry for key `#1' in this row}{}% \fi }% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLremoveentryfromrow} %\begin{definition} %\cs{DTLremoveentryfromrow}\marg{key} %\end{definition} % Removes entry given by \meta{key} from current row. % (The current row is given by % \cs{@dtl@cur}\meta{n} where \meta{n} is roman % numeral value of \cs{dtlforeachlevel}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLremoveentryfromrow}[1]{% \ifnum\dtlforeachlevel=0\relax \PackageError{datatool}{\string\DTLremoventryfromrow\space can only be used inside \string\DTLforeach}{}% \else % \end{macrocode} % Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} \expandafter\let\expandafter\@dtl@thisdb \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Check this isn't in \cs{DTLforeach*} % \begin{macrocode} \@dtlifreadonly {% \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't be used inside \string\DTLforeach*}{The starred version of \string\DTLforeach\space is read only}% }% {% % \end{macrocode} % Store current row number in \cs{dtlrownum} % \begin{macrocode} \dtlrownum= \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} % Is there a column corresponding to this key? % \begin{macrocode} \@DTLifhaskey{\@dtl@thisdb}{#1}% {% % \end{macrocode} % There exists a column for this key, so get the index: % \begin{macrocode} \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax \dtlcolumnnum=\thiscol\relax % \end{macrocode} % Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} \dtlcurrentrow = \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Does this row have an entry with this key? % \begin{macrocode} \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow {\noexpand\dtl@entry}{\number\dtlcolumnnum}% }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue % \end{macrocode} % This row doesn't contain an entry with this key % \begin{macrocode} \PackageError{datatool}{Can't remove entry given by `#1' from current row in database `\@dtl@thisdb': no such entry}{The current row doesn't contain an entry for key `#1'}% \else % \end{macrocode} % Split the current row around the unwanted entry % \begin{macrocode} \edef\@dtl@dosplitrow{% \noexpand\dtlsplitrow{\the\dtlcurrentrow}% {\number\dtlcolumnnum}{\noexpand\dtl@pre}% {\noexpand\dtl@post}% }% \@dtl@dosplitrow % \end{macrocode} % Reconstruct row without unwanted entry % \begin{macrocode} \expandafter\@dtl@toks\expandafter{\dtl@pre}% \expandafter\toks@\expandafter{\dtl@post}% \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}% \dtlcurrentrow=\expandafter{\@dtl@tmp}% \expandafter\global \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname = \dtlcurrentrow \dtl@message{Removed entry given by #1\space from current row of database `\@dtl@thisdb'}% \fi }% {% \PackageError{datatool}{Can't remove entry given by `#1' - no such key exists}{}% }% }% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLreplaceentryforrow} %\begin{definition} %\cs{DTLreplaceentryforrow}\marg{key}\marg{value} %\end{definition} % Replaces entry given by \meta{key} in current row with % \meta{value}. % (The current row is given by the token register % \cs{@dtl@cur}\meta{n} where \meta{n} is roman % numeral value of \cs{dtlforeachlevel}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLreplaceentryforrow}[2]{% \ifnum\dtlforeachlevel=0\relax \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only be used inside \string\DTLforeach}{}% \else % \end{macrocode} % Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} \expandafter\let\expandafter\@dtl@thisdb \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Check this isn't in \cs{DTLforeach*} % \begin{macrocode} \@dtlifreadonly {% \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't be used inside \string\DTLforeach*}{The starred version of \string\DTLforeach\space is read only}% }% {% % \end{macrocode} % Store current row number in \cs{dtlrownum} % \begin{macrocode} \dtlrownum= \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax % \end{macrocode} % Is there a column corresponding to this key? % \begin{macrocode} \@DTLifhaskey{\@dtl@thisdb}{#1}% {% % \end{macrocode} % There exists a column for this key, so get the index: % \begin{macrocode} \@dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax \dtlcolumnnum=\thiscol\relax % \end{macrocode} % Set \cs{dtlcurrentrow} to the current row % \begin{macrocode} \dtlcurrentrow = \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Does this row have an entry with this key? % \begin{macrocode} \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow {\noexpand\dtl@entry}{\number\dtlcolumnnum}% }% \dtl@dogetentry \ifx\dtl@entry\dtlnovalue % \end{macrocode} % This row doesn't contain an entry with this key % \begin{macrocode} \PackageError{datatool}{Can't replace entry given by `#1' from current row in database `\@dtl@thisdb': no such entry}{The current row doesn't contain an entry for key `#1'}% \else % \end{macrocode} % Split the current row around the requested entry % \begin{macrocode} \edef\@dtl@dosplitrow{% \noexpand\dtlsplitrow{\the\dtlcurrentrow}% {\number\dtlcolumnnum}{\noexpand\dtl@pre}% {\noexpand\dtl@post}% }% \@dtl@dosplitrow % \end{macrocode} % Reconstruct row with new value (given by \verb|#2|). %\changes{2.03}{2009 November 15}{expand replacement entry} % \begin{macrocode} \protected@edef\@dtl@tmp{#2}% \expandafter\@dtl@toks\expandafter{\@dtl@tmp}% new value \expandafter\@dtl@before\expandafter{\dtl@pre}% \expandafter\@dtl@after\expandafter{\dtl@post}% \toks@gconcat@middle@cx {@dtl@cur\romannumeral\dtlforeachlevel}% {\@dtl@before}% {% \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@% \noexpand\db@col@elt@w \the\@dtl@toks \noexpand\db@col@elt@end@% \noexpand\db@col@id@w \number\dtlcolumnnum \noexpand\db@col@id@end@% }% {\@dtl@after}% % \end{macrocode} % Print information to terminal and log file if in verbose mode. % \begin{macrocode} \dtl@message{Updated #1\space -> #2\space in database `\@dtl@thisdb'}% \fi }% {% % \end{macrocode} % There doesn't exist a column for this key. % \begin{macrocode} \PackageError{datatool}{Can't replace key `#1' - no such key in database `\@dtl@thisdb'}{}% }% }% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLremovecurrentrow} %\begin{definition} %\cs{DTLremovecurrentrow} %\end{definition} % Removes current row. This just sets the current row to empty %\changes{1.01}{2007 Aug 17}{fix bug caused by missing \cs{fi} % and unrequired argument} %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLremovecurrentrow}{% \ifnum\dtlforeachlevel=0\relax \PackageError{datatool}{\string\DTLremovecurrentrow\space can only be used inside \string\DTLforeach}{}% \else % \end{macrocode} % Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} \expandafter\let\expandafter\@dtl@thisdb \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Check this isn't in \cs{DTLforeach*} % \begin{macrocode} \@dtlifreadonly {% \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't be used inside \string\DTLforeach*}{The starred version of \string\DTLforeach\space is read only}% }% {% % \end{macrocode} % Set the current row to \cs{@nil} (\cs{DTLforeach} needs to check % for this) % \begin{macrocode} \expandafter\global \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname ={\@nil}% }% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLaddentryforrow} %\begin{definition} %\cs{DTLaddentryforrow}\marg{db name}\marg{assign list}\marg{condition}\marg{key}\marg{value} %\end{definition} % Adds the entry with key given by \meta{key} and value given by % \meta{value} to the first row in the database \meta{db name} % which satisfies the condition given by \meta{condition}. The % \meta{assign list} is the same as for \cs{DTLforeach} and may % be used to set the values which are to be tested in \meta{condition}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand{\DTLaddentryforrow}[5]{% % \end{macrocode} % Iterate through the data base until condition is met % \begin{macrocode} \DTLifdbexists{#1}% { \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry given by key `#4': condition not met for any row in database `#1'}{}}% % \end{macrocode} % Iterate through each row % \begin{macrocode} \DTLforeach[#3]{#1}{#2}% {% % \end{macrocode} % add entry to this row % \begin{macrocode} \DTLappendtorow{#4}{#5}% % \end{macrocode} % disable error message % \begin{macrocode} \let\@dtl@notdone\relax % \end{macrocode} % break out of loop % \begin{macrocode} \dtlbreak }% \@dtl@notdone }% {% \PackageError{datatool}{Unable to add entry given by key `#4': database `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLforeachkeyinrow} %\begin{definition} %\cs{DTLforeachkeyinrow}\marg{cmd}\marg{text} %\end{definition} % Iterates through each key in the current row of \cs{DTLforeach}, % and does \meta{text}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLforeachkeyinrow}[2]{% \ifnum\dtlforeachlevel=0\relax \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only be used inside \string\DTLforeach}{}% \else % \end{macrocode} % Set \cs{@dtl@thisdb} to the current database name: % \begin{macrocode} \expandafter\let\expandafter\@dtl@thisdb \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Iterate through key list % \begin{macrocode} \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in \@dtl@thisdb\do{% % \end{macrocode} % store row in \cs{dtlcurrentrow} % (This may get nested so need to do it here instead of % outside this loop in case % \meta{text} changes it.) % \begin{macrocode} \dtlcurrentrow = \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname % \end{macrocode} % Get the value for this key and store in "#1" % \begin{macrocode} \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow {\noexpand#1}{\dtlcol}}% \dtl@dogetentry % \end{macrocode} % Check if null % \begin{macrocode} \ifx#1\dtlnovalue \ifnum0\dtltype=0\relax % \end{macrocode} % Data type is \meta{empty} or 0, so set to string null. % \begin{macrocode} \let#1=\DTLstringnull \else % \end{macrocode} % Data type is numerical, so set to number null. % \begin{macrocode} \let#1=\DTLnumbernull \fi \fi % \end{macrocode} % Make "#1" global in case this is in a tabular environment (or % something similar) % \begin{macrocode} \global\let#1#1% % \end{macrocode} % Store loop body so that any scoping commands (such as "&") don't % cause a problem for \cs{ifx} % \begin{macrocode} \def\@dtl@loop@body{#2}% \@dtl@loop@body }% \fi } % \end{macrocode} %\end{macro} % %\subsection{Displaying Database} % This section defines commands to display the entire database % in a \env{tabular} or \env{longtable} environment. % %\begin{macro}{\dtlbetweencols} % This specifies what to put between the column alignment % specifiers. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlbetweencols}{} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlbeforecols} % This specifies what to put before the first column alignment % specifier. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlbeforecols}{} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlaftercols} % This specifies what to put after the last column alignment % specifier. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlaftercols}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlstringalign} % Alignment character for columns containing strings % \begin{macrocode} \newcommand*{\dtlstringalign}{l} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlintalign} % Alignment character for columns containing integers % \begin{macrocode} \newcommand*{\dtlintalign}{r} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlrealalign} % Alignment character for columns containing real numbers % \begin{macrocode} \newcommand*{\dtlrealalign}{r} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlcurrencyalign} % Alignment character for columns containing currency numbers % \begin{macrocode} \newcommand*{\dtlcurrencyalign}{r} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtladdalign} %\begin{definition} %\cs{dtladdalign}\marg{cs}\marg{type}\marg{col num}\marg{max cols} %\end{definition} % Adds tabular column alignment character to \meta{cs} for column % \meta{col num} which contains data type \meta{type}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtladdalign}[4]{% \ifnum#3=1\relax \protected@edef#1{\dtlbeforecols}% \else \protected@edef#1{#1\dtlbetweencols}% \fi \ifx\@empty#2\@empty \protected@edef#1{#1c}% \else \ifcase#2\relax % \end{macrocode} % string % \begin{macrocode} \protected@edef#1{#1\dtlstringalign}% \or % \end{macrocode} % integer % \begin{macrocode} \protected@edef#1{#1\dtlintalign}% \or % \end{macrocode} % real number % \begin{macrocode} \protected@edef#1{#1\dtlrealalign}% \or % \end{macrocode} % currency % \begin{macrocode} \protected@edef#1{#1\dtlcurrencyalign}% \else % \end{macrocode} % Unknown type % \begin{macrocode} \protected@edef#1{#1c}% \PackageError{datatool}{Unknown data type `#2'}{}% \fi \fi \ifnum#3=#4\relax \protected@edef#1{#1\dtlaftercols}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlheaderformat} %\begin{definition} %\cs{dtlheaderformat}\marg{text} %\end{definition} % Specifies how to format the column title. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlstringformat} %\begin{definition} %\cs{dtlstringformat}\marg{text} %\end{definition} % Specifies how to format entries in columns with string data type. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlstringformat}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlintformat} %\begin{definition} %\cs{dtlintformat}\marg{text} %\end{definition} % Specifies how to format entries in columns with integer data type. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlintformat}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlrealformat} %\begin{definition} %\cs{dtlrealformat}\marg{text} %\end{definition} % Specifies how to format entries in columns with real data type. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlrealformat}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\dtlcurrencyformat} %\begin{definition} %\cs{dtlcurrencyformat}\marg{text} %\end{definition} % Specifies how to format entries in columns with currency data type. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtlcurrencyformat}[1]{#1} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtldisplaystarttab} % Indicates what to do just after "\begin{tabular}"\marg{column specs} % (e.g.\ \cs{hline}). %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtldisplaystarttab}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtldisplayendtab} % Indicates what to do just before "\end{tabular}". %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtldisplayendtab}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtldisplayafterhead} % Indicates what to do after the header row, before the first row % of data. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtldisplayafterhead}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtldisplaystartrow} % Indicates what to do at the start of each row (not including % the header row or the first row of data). %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtldisplaystartrow}{} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdisplaydb} %\begin{definition} %\cs{DTLdisplaydb}\marg{db} %\end{definition} % Displays the database \meta{db} in a tabular environment. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLdisplaydb}[1]{% % \end{macrocode} % Initialise: % only want "&" between columns % \begin{macrocode} \def\@dtl@doamp{\gdef\@dtl@doamp{&}} \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} % \end{macrocode} % Store maximum number of columns % \begin{macrocode} \edef\@dtl@maxcols{\expandafter\number \csname dtlcols@#1\endcsname}% % \end{macrocode} % Argument for tabular environment % \begin{macrocode} \def\@dtl@tabargs{}% \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#1}\do {% \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols }% % \end{macrocode} % Begin tabular environment % \begin{macrocode} \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}% \@dtl@dobegintab % \end{macrocode} % Do start hook % \begin{macrocode} \dtldisplaystarttab % \end{macrocode} % Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the % start of the first column. % \begin{macrocode} \@dtl@resetdoamp % \end{macrocode} % Do the header row. % \begin{macrocode} \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#1}\do {% \@dtl@doamp \dtlheaderformat{\@dtl@head}% }% \\% % \end{macrocode} % Do the after header hook % \begin{macrocode} \dtldisplayafterhead % \end{macrocode} % Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the % start of the first column. % \begin{macrocode} \@dtl@resetdoamp % \end{macrocode} % Iterate through each row of the database % \begin{macrocode} \DTLforeach*{#1}{}{% % \end{macrocode} % Do the start row hook if not the first row % \begin{macrocode} \DTLiffirstrow{}{\\\dtldisplaystartrow}% % \end{macrocode} % Reset \cs{@dtl@doamp} so it doesn't do an ampersand at the % start of the first column. % \begin{macrocode} \@dtl@resetdoamp % \end{macrocode} % Iterate through each column. % \begin{macrocode} \DTLforeachkeyinrow{\@dtl@val}% {% % \end{macrocode} % Need to make value global as it needs to be used after the % ampersand. % \begin{macrocode} \global\let\@dtl@val\@dtl@val \@dtl@doamp % \end{macrocode} % \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type % for the current key. This can be used to determine which % format to use for this entry. % \begin{macrocode} \@dtl@datatype=0\dtltype\relax \ifcase\@dtl@datatype \dtlstringformat\@dtl@val \or \dtlintformat\@dtl@val \or \dtlrealformat\@dtl@val \or \dtlcurrencyformat\@dtl@val \else \@dtl@val \fi }% }% \dtldisplayendtab \end{tabular}% } % \end{macrocode} %\end{macro} % % Define keys to use in the optional argument of % \cs{DTLdisplaylongdb}. % % The caption key sets the caption for the longtable. % \begin{macrocode} \define@key{displaylong}{caption}{\def\@dtl@cap{#1}} % \end{macrocode} % The contcaption key sets the continuation caption for the % longtable. % \begin{macrocode} \define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}} % \end{macrocode} % The shortcaption key sets the lof caption for the longtable. % \begin{macrocode} \define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}} % \end{macrocode} % The label key sets the label for the longtable. % \begin{macrocode} \define@key{displaylong}{label}{\def\@dtl@label{#1}} % \end{macrocode} % The foot key sets the longtable foot % \begin{macrocode} \define@key{displaylong}{foot}{\def\@dtl@foot{#1}} % \end{macrocode} % The lastfoot key sets the longtable last foot % \begin{macrocode} \define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}} % \end{macrocode} % %\begin{macro}{\@dtl@resetdostartrow} % Resets start row hook so that it skips the first row. % \begin{macrocode} \newcommand*{\@dtl@resetdostartrow}{% \gdef\@dtl@dostartrow{% \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdisplaylongdb} %\begin{definition} %\cs{DTLdisplaylongdb}\oarg{options}\marg{db} %\end{definition} % Displays the database \meta{db} in a longtable environment. % (User needs to load \sty{longtable}). %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLdisplaylongdb}[2][]{% % \end{macrocode} % Initialise. % \begin{macrocode} \def\@dtl@cap{\@nil}% \def\@dtl@contcap{\@nil}% \def\@dtl@label{\@nil}% \def\@dtl@shortcap{\@dtl@cap}% \def\@dtl@foot{\@nil}% \def\@dtl@lastfoot{\@nil}% % \end{macrocode} % Set the options % \begin{macrocode} \setkeys{displaylong}{#1}% % \end{macrocode} % Only want "&" between columns % \begin{macrocode} \def\@dtl@doamp{\gdef\@dtl@doamp{&}} \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}} \@dtl@resetdostartrow % \end{macrocode} % Store maximum number of columns % \begin{macrocode} \edef\@dtl@maxcols{\expandafter\number \csname dtlcols@#2\endcsname}% % \end{macrocode} % Argument for \env{longtable} environment % \begin{macrocode} \def\@dtl@tabargs{}% \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#2}\do {% \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols }% % \end{macrocode} % Start the \env{longtable} environment. % \begin{macrocode} \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}% \@dtl@dobegintab % \end{macrocode} % Do start hook. % \begin{macrocode} \dtldisplaystarttab % \end{macrocode} % Is a foot required? % \begin{macrocode} \ifx\@dtl@foot\@nnil \else \@dtl@foot\endfoot \fi % \end{macrocode} % Is a last foot required? % \begin{macrocode} \ifx\@dtl@lastfoot\@nnil \else \@dtl@lastfoot\endlastfoot \fi % \end{macrocode} % Is a caption required? % \begin{macrocode} \ifx\@dtl@cap\@nnil % \end{macrocode} % No caption required, just do header row. % \begin{macrocode} \@dtl@resetdoamp \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#2}\do {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% \@dtl@resetdoamp \@dtl@resetdostartrow \endhead\dtldisplayafterhead \else % \end{macrocode} % Caption is required % \begin{macrocode} \caption[\@dtl@shortcap]{\@dtl@cap}% % \end{macrocode} % Is a label required? % \begin{macrocode} \ifx\@dtl@label\@nnil \else \label{\@dtl@label}% \fi \\% % \end{macrocode} % Do header row. % \begin{macrocode} \@dtl@resetdoamp \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#2}\do {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% \@dtl@resetdoamp \@dtl@resetdostartrow \endfirsthead % \end{macrocode} % Is a continuation caption required? % \begin{macrocode} \ifx\@dtl@contcap\@nnil \caption{\@dtl@cap}% \else \caption{\@dtl@contcap}% \fi \\% % \end{macrocode} % Do header row. % \begin{macrocode} \@dtl@resetdoamp \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)% \in{#2}\do {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}% \@dtl@resetdoamp \@dtl@resetdostartrow \endhead\dtldisplayafterhead \fi % \end{macrocode} % Iterate through each row of the database % \begin{macrocode} \DTLforeach*{#2}{}{% \@dtl@dostartrow \@dtl@resetdoamp % \end{macrocode} % Iterate through each column % \begin{macrocode} \DTLforeachkeyinrow{\@dtl@val}% {% \global\let\@dtl@val\@dtl@val \@dtl@doamp % \end{macrocode} % \cs{DTLforeachkeyinrow} sets \cs{dtltype} to the data type % for the current key. This can be used to determine which % format to use for this entry. % \begin{macrocode} \@dtl@datatype=0\dtltype\relax \ifcase\@dtl@datatype \dtlstringformat\@dtl@val \or \dtlintformat\@dtl@val \or \dtlrealformat\@dtl@val \or \dtlcurrencyformat\@dtl@val \fi }% }% \dtldisplayendtab \end{longtable}% } % \end{macrocode} %\end{macro} % % %\subsection{Editing Databases} % %\begin{macro}{\dtlswaprows} %\begin{definition} %\cs{dtlswaprows}\marg{db}\marg{row1 idx}\marg{row2 idx} %\end{definition} % Swaps the rows with indices \meta{row1 idx} and \meta{row2 idx} % in the database \meta{db}. % (Doesn't check if data base exists of if indices are out of % bounds.) % \begin{macrocode} \newcommand*{\dtlswaprows}[3]{% \ifnum#2=#3\relax % \end{macrocode} % Attempt to swap row with itself: do nothing. % \begin{macrocode} \else % \end{macrocode} % Let row A be the row with the lower index and row B be the % row with ther higher index. % \begin{macrocode} \ifnum#2<#3\relax \edef\@dtl@rowAidx{\number#2}% \edef\@dtl@rowBidx{\number#3}% \else \edef\@dtl@rowAidx{\number#3}% \edef\@dtl@rowBidx{\number#2}% \fi % \end{macrocode} % Split the database around row A. % \begin{macrocode} \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}% \@dtl@dosplit % \end{macrocode} % Store first part of database in \cs{@dtl@firstpart}. % \begin{macrocode} \expandafter\def\expandafter\@dtl@firstpart\expandafter {\the\dtlbeforerow}% % \end{macrocode} % Store row A in \cs{@dtl@toksA}. % \begin{macrocode} \@dtl@toksA=\dtlcurrentrow % \end{macrocode} % Split the second part (everything after row A). % \begin{macrocode} \edef\@dtl@dosplit{\noexpand\@dtlgetrow {\the\dtlafterrow}{\@dtl@rowBidx}}% \@dtl@dosplit % \end{macrocode} % Store the mid part (everything between row A and row B) % \begin{macrocode} \expandafter\def\expandafter\@dtl@secondpart\expandafter {\the\dtlbeforerow}% % \end{macrocode} % Store row B in \cs{@dtl@toksB}. % \begin{macrocode} \@dtl@toksB=\dtlcurrentrow % \end{macrocode} % Store the last part (everything after row B). % \begin{macrocode} \expandafter\def\expandafter\@dtl@thirdpart\expandafter {\the\dtlafterrow}% % \end{macrocode} % Reconstruct database: store first part in \cs{toks@} % \begin{macrocode} \toks@=\expandafter{\@dtl@firstpart}% % \end{macrocode} % Store mid part in \cs{dtl@toks} % \begin{macrocode} \@dtl@toks=\expandafter{\@dtl@secondpart}% % \end{macrocode} % Format data for first part, row B and mid part. % \begin{macrocode} \edef\@dtl@tmp{\the\toks@ \noexpand\db@row@elt@w% \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% \the\@dtl@toksB \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% \the\@dtl@toks}% % \end{macrocode} % Store data so far in \cs{toks@}. % \begin{macrocode} \toks@=\expandafter{\@dtl@tmp}% % \end{macrocode} % Store last part in \cs{dtl@toks}. % \begin{macrocode} \@dtl@toks=\expandafter{\@dtl@thirdpart}% % \end{macrocode} % Format row A and end part. % \begin{macrocode} \edef\@dtl@tmp{\the\toks@ \noexpand\db@row@elt@w% \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% \the\@dtl@toksA \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% \the\@dtl@toks}% % \end{macrocode} % Update the database % \begin{macrocode} \expandafter\global\csname dtldb@#1\endcsname=\expandafter {\@dtl@tmp}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@decrementrows} %\begin{definition} %\cs{dtl@decrementrows}\marg{toks}\marg{n} %\end{definition} % decrement by 1 all rows in \meta{toks} with row index above % \meta{n} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtl@decrementrows}[2]{% \def\@dtl@newlist{}% \edef\@dtl@min{\number#2}% \expandafter\@dtl@decrementrows\the#1% \db@row@elt@w% \db@row@id@w \@nil\db@row@id@end@% \db@row@id@w \@nil\db@row@id@end@% \db@row@elt@end@% \@nil #1=\expandafter{\@dtl@newlist}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@decrementrows} %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@% #2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{% \def\@dtl@thisrow{#1}% \ifx\@dtl@thisrow\@nnil \let\@dtl@donextdec=\@dtl@gobbletonil \else \ifnum\@dtl@thisrow>\@dtl@min \@dtl@tmpcount=\@dtl@thisrow\relax \advance\@dtl@tmpcount by -1\relax \toks@{#2}% \@dtl@toks=\expandafter{\@dtl@newlist}% \edef\@dtl@newlist{\the\@dtl@toks \noexpand\db@row@elt@w% row header \noexpand\db@row@id@w \number\@dtl@tmpcount \noexpand\db@row@id@end@% row id \the\toks@ % row contents \noexpand\db@row@id@w \number\@dtl@tmpcount \noexpand\db@row@id@end@% row id \noexpand\db@row@elt@end@% row end }% \else \toks@{#2}% \@dtl@toks=\expandafter{\@dtl@newlist}% \edef\@dtl@newlist{\the\@dtl@toks \noexpand\db@row@elt@w% row header \noexpand\db@row@id@w #1% \noexpand\db@row@id@end@% row id \the\toks@ % row contents \noexpand\db@row@id@w #3% \noexpand\db@row@id@end@% row id \noexpand\db@row@elt@end@% row end }% \fi \let\@dtl@donextdec=\@dtl@decrementrows \fi \@dtl@donextdec#4\@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLremoverow} %\begin{definition} %\cs{DTLremoverow}\marg{db}\marg{row index} %\end{definition} % Remove row with given index from database named \meta{db}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLremoverow}[2]{% % \end{macrocode} % Check database exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check index if index is out of bounds % \begin{macrocode} \ifnum#2>0\relax % \end{macrocode} % Check if data base has at least \meta{row index} rows % \begin{macrocode} \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax \PackageError{datatool}{Can't remove row `\number#2' from database `#1': no such row}{Database `#1' only has 1 row}% \else \PackageError{datatool}{Can't remove row `\number#2' from database `#1': no such row}{Database `#1' only has \expandafter\number\csname dtlrows@#1\endcsname\space rows}% \fi \else \@DTLremoverow{#1}{#2}% \fi \else \PackageError{datatool}{Can't remove row \number#2: index out of bounds}{Row indices start at 1}% \fi }% {% \PackageError{datatool}{Can't remove row: database `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLremoverow} %\begin{definition} %\cs{@DTLremoverow}\marg{db}\marg{row index} %\end{definition} % Doesn't perform any checks for the existance of the database % or if the index is in range. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\@DTLremoverow}[2]{% % \end{macrocode} % Get row from data base % \begin{macrocode} \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}% \dtl@dogetrow % \end{macrocode} % Update the row indices % \begin{macrocode} \expandafter\dtl@decrementrows\expandafter {\dtlbeforerow}{#2}% \expandafter\dtl@decrementrows\expandafter {\dtlafterrow}{#2}% % \end{macrocode} % Reconstruct database % \begin{macrocode} \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}% \expandafter\global\csname dtldb@#1\endcsname =\expandafter{\dtl@tmp}% % \end{macrocode} % decrement row counter % \begin{macrocode} \expandafter\global\expandafter\advance \csname dtlrows@#1\endcsname by -1\relax } % \end{macrocode} %\end{macro} % %\subsection{Database Functions} % %\begin{macro}{\DTLsumforkeys} %\begin{definition} %\cs{DTLsumforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Sums all entries for key \meta{key} over all databases listed % in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument provides % an assignment list to pass to \cs{DTLforeach} in case extra % information is need by \meta{condition}. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLsumforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlsumforkeys } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlsumforkeys} % \begin{macrocode} \newcommand*{\@dtlsumforkeys}[4][]{% \def#4{0}% % \end{macrocode} % Iterate over all the listed data bases % \begin{macrocode} \@for\@dtl@dbname:=#2\do{% % \end{macrocode} % Iterate through this database (using read only version) % \begin{macrocode} \@sDTLforeach{\@dtl@dbname}% {#1}% assignment list {% % \end{macrocode} % Iterate through key list. % \begin{macrocode} \@for\@dtl@key:=#3\do{% \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% \dtlcurrentrow=\expandafter{\dtl@thisrow}% \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% \expandafter\ifthenelse\expandafter{\@dtl@cond}% {\DTLadd{#4}{#4}{\DTLthisval}}{}% }% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsumcolumn} %\begin{definition} %\cs{DTLsumcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLsumforkeys} that just sums over % one column (specified by \meta{key}) for a single database % (specified by \meta{db}) and stores the result in \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLsumcolumn}[3]{% \def#3{0}% % \end{macrocode} % Check data base exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check column exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sdtlforcolumn{\DTLthisval}{#1}{#2}% {% \DTLadd{#3}{#3}{\DTLthisval}% }% }% % \end{macrocode} % key not defined for this data base % \begin{macrocode} {% \PackageError{datatool}{Key `#2' doesn't exist in database `#1'}{}% }% }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Data base `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmeanforkeys} %\begin{definition} %\cs{DTLmeanforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Computes the arithmetic mean of all entries for each key in % \meta{key list} over all databases in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument allows an % assignment list to be passed to \cs{DTLforeach}. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlmeanforkeys } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@elements} % Count register to keep track of number of elements % \begin{macrocode} \newcount\@dtl@elements % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlmeanforkeys} % \begin{macrocode} \newcommand*{\@dtlmeanforkeys}[4][]{% \def#4{0}% \@dtl@elements=0\relax % \end{macrocode} % Iterate over all the listed data bases % \begin{macrocode} \@for\@dtl@dbname:=#2\do{% % \end{macrocode} % Iterate through this database (using read only version) % \begin{macrocode} \@sDTLforeach{\@dtl@dbname}% {#1}% assignment list {% % \end{macrocode} % Iterate through key list. % \begin{macrocode} \@for\@dtl@key:=#3\do{% \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% \dtlcurrentrow=\expandafter{\dtl@thisrow}% \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% \expandafter\ifthenelse\expandafter{\@dtl@cond}% {% \DTLadd{#4}{#4}{\DTLthisval}% \advance\@dtl@elements by 1\relax }{}% }% }% }% % \end{macrocode} % Divide total by number of elements summed. % \begin{macrocode} \ifnum\@dtl@elements=0\relax \PackageError{datatool}{Unable to evaluate mean: no data}{}% \else \edef\@dtl@n{\number\@dtl@elements}% \DTLdiv{#4}{#4}{\@dtl@n}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmeanforcolumn} %\begin{definition} %\cs{DTLmeanforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLmeanforkeys} that just computes the % mean over one column (specified by \meta{key}) for a single % database (specified by \meta{db}) and stores the result in % \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLmeanforcolumn}[3]{% \def#3{0}% \@dtl@elements=0\relax % \end{macrocode} % Check data base exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check column exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sdtlforcolumn{\DTLthisval}{#1}{#2}% {% \DTLadd{#3}{#3}{\DTLthisval}% \advance\@dtl@elements by 1\relax }% \ifnum\@dtl@elements=0\relax \PackageError{datatool}{Can't compute mean for column `#2' in database `#1': no data}{}% \else \edef\@dtl@n{\number\@dtl@elements}% \DTLdiv{#3}{#3}{\@dtl@n}% \fi }% % \end{macrocode} % key not defined for this data base % \begin{macrocode} {% \PackageError{datatool}{Key `#2' doesn't exist in database `#1'}{}% }% }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Data base `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLvarianceforkeys} %\begin{definition} %\cs{DTLvarianceforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Computes the variance of all entries for each key in % \meta{key list} over all databases in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first optional argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument is an assignment % list to pass to \cs{DTLforeach} in case it is required for the % condition. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlvarianceforkeys } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlmeanforkeys} % \begin{macrocode} \newcommand*{\@dtlvarianceforkeys}[4][]{% \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}% \def#4{0}% \@dtl@elements=0\relax % \end{macrocode} % Iterate over all the listed data bases % \begin{macrocode} \@for\@dtl@dbname:=#2\do{% % \end{macrocode} % Iterate through this database (using read only version) % \begin{macrocode} \@sDTLforeach{\@dtl@dbname}% {#1}% assignment list {% % \end{macrocode} % Iterate through key list. % \begin{macrocode} \@for\@dtl@key:=#3\do{% \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% \dtlcurrentrow=\expandafter{\dtl@thisrow}% \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% \expandafter\ifthenelse\expandafter{\@dtl@cond}% {% % \end{macrocode} % compute $(x_i - \mu)^2$ % \begin{macrocode} \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% \DTLadd{#4}{#4}{\dtl@diff}% \advance\@dtl@elements by 1\relax }{}% }% }% }% % \end{macrocode} % Divide by number of elements. % \begin{macrocode} \ifnum\@dtl@elements=0\relax \PackageError{datatool}{Unable to evaluate variance: no data}{}% \else \edef\@dtl@n{\number\@dtl@elements}% \DTLdiv{#4}{#4}{\@dtl@n}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLvarianceforcolumn} %\begin{definition} %\cs{DTLvarianceforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLvarianceforkeys} that just computes the % variance over one column (specified by \meta{key}) for a single % database (specified by \meta{db}) and stores the result in % \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLvarianceforcolumn}[3]{% \DTLmeanforcolumn{#1}{#2}{\dtl@mean}% \def#3{0}% \@dtl@elements=0\relax % \end{macrocode} % Check data base exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check column exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sdtlforcolumn{\DTLthisval}{#1}{#2}% {% % \end{macrocode} % compute $(x_i - \mu)^2$ % \begin{macrocode} \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}% \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}% \DTLadd{#3}{#3}{\dtl@diff}% \advance\@dtl@elements by 1\relax }% \ifnum\@dtl@elements=0\relax \PackageError{datatool}{Can't compute variance for column `#2' in database `#1': no data}{}% \else \edef\@dtl@n{\number\@dtl@elements}% \DTLdiv{#3}{#3}{\@dtl@n}% \fi }% % \end{macrocode} % key not defined for this data base % \begin{macrocode} {% \PackageError{datatool}{Key `#2' doesn't exist in database `#1'}{}% }% }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Data base `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % % %\begin{macro}{\DTLsdforkeys} %\begin{definition} %\cs{DTLsdforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Computes the standard deviation of all entries for each key in % \meta{key list} over all databases in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first optional argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument is an % assignment list for \cs{DTLforeach} in case it is needed for % the condition. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLsdforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlsdforkeys } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtlsdforkeys} % \begin{macrocode} \newcommand*{\@dtlsdforkeys}[4][]{% \@dtlvarianceforkeys[#1]{#2}{#3}{#4}% \DTLsqrt{#4}{#4}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsdforcolumn} %\begin{definition} %\cs{DTLsdforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLsdforkeys} that just computes the % standard deviation over one column (specified by \meta{key}) for % a single database (specified by \meta{db}) and stores the result % in \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLsdforcolumn}[3]{% \DTLvarianceforcolumn{#1}{#2}{#3}% \DTLsqrt{#3}{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLminforkeys} %\begin{definition} %\cs{DTLminforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Determines the minimum over all entries for each key in % \meta{key list} over all databases in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first optional argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument is an % assignment list for \cs{DTLforeach} in the event that extra % information is need for the condition. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLminforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlminforkeys } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlminforkeys} % \begin{macrocode} \newcommand*{\@dtlminforkeys}[4][]{% \def#4{}% % \end{macrocode} % Iterate over all the listed data bases % \begin{macrocode} \@for\@dtl@dbname:=#2\do{% % \end{macrocode} % Iterate through this database (using read only version) % \begin{macrocode} \@sDTLforeach{\@dtl@dbname}% {#1}% assignment list {% % \end{macrocode} % Iterate through key list. % \begin{macrocode} \@for\@dtl@key:=#3\do{% \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% \dtlcurrentrow=\expandafter{\dtl@thisrow}% \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% \expandafter\ifthenelse\expandafter{\@dtl@cond}% {% \ifx#4\@empty \let#4\DTLthisval \else \DTLmin{#4}{#4}{\DTLthisval}% \fi }{}% }% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLminforcolumn} %\begin{definition} %\cs{DTLminforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLminforkeys} that just finds the % minimum value in one column (specified by \meta{key}) for a % single database (specified by \meta{db}) and stores the result % in \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLminforcolumn}[3]{% \def#3{}% % \end{macrocode} % Check data base exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check column exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sdtlforcolumn{\DTLthisval}{#1}{#2}% {% \ifx#3\@empty \let#3\DTLthisval \else \DTLmin{#3}{#3}{\DTLthisval}% \fi }% }% % \end{macrocode} % key not defined for this data base % \begin{macrocode} {% \PackageError{datatool}{Key `#2' doesn't exist in database `#1'}{}% }% }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Data base `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % % %\begin{macro}{\DTLmaxforkeys} %\begin{definition} %\cs{DTLmaxforkeys}\oarg{condition}\oarg{assign list}\marg{db list}\marg{key list}\marg{cmd} %\end{definition} % Determines the maximum over all entries for each key in % \meta{key list} over all databases in \meta{db list}, % and stores in \meta{cmd}, which must be a control sequence. % The first optional argument \meta{condition} is the same as that % for \cs{DTLforeach}. The second optional argument is an % assignment list to pass to \cs{DTLforeach} in the event that % extra information is required in the condition. %\changes{2.0}{2009 February 27}{added second optional argument} % \begin{macrocode} \newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and \DTLisnumerical{\DTLthisval}]{% \def\@dtl@cond{#1}% \@dtlmaxforkeys } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlmaxforkeys} % \begin{macrocode} \newcommand*{\@dtlmaxforkeys}[4][]{% \def#4{}% % \end{macrocode} % Iterate over all the listed data bases % \begin{macrocode} \@for\@dtl@dbname:=#2\do{% % \end{macrocode} % Iterate through this database (using read only version) % \begin{macrocode} \@sDTLforeach{\@dtl@dbname}% {#1}% assignment list {% % \end{macrocode} % Iterate through key list. % \begin{macrocode} \@for\@dtl@key:=#3\do{% \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% \dtlcurrentrow=\expandafter{\dtl@thisrow}% \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}% \expandafter\ifthenelse\expandafter{\@dtl@cond}% {% \ifx#4\@empty \let#4\DTLthisval \else \DTLmax{#4}{#4}{\DTLthisval}% \fi }{}% }% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmaxforcolumn} %\begin{definition} %\cs{DTLmaxforcolumn}\marg{db}\marg{key}\marg{cmd} %\end{definition} % Quicker version of \cs{DTLmaxforkeys} that just finds the % maximum value in one column (specified by \meta{key}) for a % single database (specified by \meta{db}) and stores the result % in \meta{cmd}. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\DTLmaxforcolumn}[3]{% \def#3{}% % \end{macrocode} % Check data base exists % \begin{macrocode} \DTLifdbexists{#1}% {% % \end{macrocode} % Check column exists % \begin{macrocode} \@sDTLifhaskey{#1}{#2}% {% \@sdtlforcolumn{\DTLthisval}{#1}{#2}% {% \ifx#3\@empty \let#3\DTLthisval \else \DTLmax{#3}{#3}{\DTLthisval}% \fi }% }% % \end{macrocode} % key not defined for this data base % \begin{macrocode} {% \PackageError{datatool}{Key `#2' doesn't exist in database `#1'}{}% }% }% % \end{macrocode} % data base doesn't exist % \begin{macrocode} {% \PackageError{datatool}{Data base `#1' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLcomputebounds} %\begin{definition} %\cs{DTLcomputebounds}\oarg{condition}\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} in % standard decimal format. % \begin{macrocode} \newcommand*{\DTLcomputebounds}[8][\boolean{true}]{% \let#5=\relax \let#6=\relax \let#7=\relax \let#8=\relax \@for\dtl@thisdb:=#2\do{% \@sDTLforeach[#1]{\dtl@thisdb}{\DTLthisX=#3,\DTLthisY=#4}{% \DTLconverttodecimal{\DTLthisX}{\dtl@decx}% \DTLconverttodecimal{\DTLthisY}{\dtl@decy}% \ifx#5\relax \let#5=\dtl@decx \let#6=\dtl@decy \let#7=\dtl@decx \let#8=\dtl@decy \else \FPmin{#5}{#5}{\dtl@decx}% \FPmin{#6}{#6}{\dtl@decy}% \FPmax{#7}{#7}{\dtl@decx}% \FPmax{#8}{#8}{\dtl@decy}% \fi }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetvalueforkey} %\begin{definition} %\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}. %\changes{1.01}{2007 Aug 17}{new} %\changes{2.0}{2009 February 27}{updated to use new database % structure} % \begin{macrocode} \newcommand*{\DTLgetvalueforkey}[5]{% % \end{macrocode} % Get row containing referenced (key,value) pair % \begin{macrocode} \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}% % \end{macrocode} % Get column number for \meta{key} % \begin{macrocode} \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}% % \end{macrocode} % Get value for given column % \begin{macrocode} {% \dtlcurrentrow=\expandafter{\@dtl@row}% \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow {\noexpand\@dtl@val}{\@dtl@col}}% \@dtl@dogetval \global\let#1=\@dtl@val }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetrowforkey} %\begin{definition} %\cs{DTLgetrowforkey}\marg{cmd}\marg{db name}\marg{ref % key}\marg{ref value} %\end{definition} % This (globally) sets \meta{cmd} (a control sequence) to the % first row % of the database called \meta{db name} which contains the key % \meta{ref key} that has the value \meta{value}. %\changes{1.01}{2007 Aug 17}{new} %\changes{2.0}{2009 February 27}{update to use new database % structure} % \begin{macrocode} \newcommand*{\DTLgetrowforkey}[4]{% \global\let#1=\@empty \@sDTLforeach{#2}{\dtl@refvalue=#3}{% \DTLifnull{\dtl@refvalue}% {}% {% \ifthenelse{\equal{\dtl@refvalue}{#4}}% {% \xdef#1{\the\dtlcurrentrow}% \dtlbreak }% {}% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlsplitrow} %\begin{definition} %\cs{dtlsplitrow}\marg{row specs}\marg{col num}\marg{before % cs}\marg{after cs} %\end{definition} % Splits the row around the entry given by \meta{col num}. The % entries before the split are stored in \meta{before cs} and the % entries after the split are stored in \meta{after cs}. % \meta{row specs} and \meta{col num} need to be expanded before use. % \begin{macrocode} \newcommand*{\dtlsplitrow}[4]{% \def\@dtlsplitrow##1%before stuff \db@col@id@w #2\db@col@id@end@% column id ##2% unwanted stuff \db@col@id@w #2\db@col@id@end@% column id ##3% after stuff \q@nil{\def#3{##1}\def#4{##3}}% \@dtlsplitrow#1\q@nil } % \end{macrocode} %\end{macro} % %\subsection{Sorting Databases} % %\begin{macro}{\@dtl@list} % Token register to store data when sorting. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newtoks\@dtl@list % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsort} %\begin{definition} % \cs{DTLsort}\oarg{replacement keys}\marg{sort criteria}\marg{db name} %\end{definition} % Sorts database \meta{db name} according to \marg{sort criteria}, % which must be a comma separated list of keys, and optionally % \texttt{=}\meta{order}, where \meta{order} is either % "ascending" or "descending". The optional argument is a list of % keys to uses if the given key has a null value. The starred % version uses a case insensitive string comparison. %\changes{1.01}{2007 Aug 17}{added optional argument} %\changes{1.01}{2007 Aug 17}{added starred version} %\changes{2.0}{2009 February 27}{updated to use new data structure} % \begin{macrocode} \newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort} % \end{macrocode} %\end{macro} % %\begin{macro}{\@DTLsort} % Unstarred (case sensitive) version. % \begin{macrocode} \newcommand{\@DTLsort}[3][]{% % \end{macrocode} % Check the database exists % \begin{macrocode} \DTLifdbexists{#3}% {% % \end{macrocode} % Store replacement keys in \cs{@dtl@replacementkeys}. % \begin{macrocode} \edef\@dtl@replacementkeys{#1}% % \end{macrocode} % Store sort order in \cs{@dtl@sortorder}. % \begin{macrocode} \edef\@dtl@sortorder{#2}% % \end{macrocode} % Set \cs{@dtl@comparecs} to the required string comparison % function. (Using case sensitive comparison macro \cs{dtlcompare}.) % \begin{macrocode} \let\@dtl@comparecs=\dtlcompare % \end{macrocode} % Sort the database. % \begin{macrocode} \dtl@sortdata{#3}% }% {% \PackageError{datatool}{Database `#3' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@sDTLsort} % Starred (case insensitive) version. % \begin{macrocode} \newcommand{\@sDTLsort}[3][]{% % \end{macrocode} % Check the database exists % \begin{macrocode} \DTLifdbexists{#3}% {% % \end{macrocode} % Store replacement keys in \cs{@dtl@replacementkeys}. % \begin{macrocode} \edef\@dtl@replacementkeys{#1}% % \end{macrocode} % Store sort order in \cs{@dtl@sortorder}. % \begin{macrocode} \edef\@dtl@sortorder{#2}% % \end{macrocode} % Set \cs{@dtl@comparecs} to the required string comparison % function. (Using case insensitive comparison macro % \cs{dtlicompare}.) % \begin{macrocode} \let\@dtl@comparecs=\dtlicompare % \end{macrocode} % Sort the database. % \begin{macrocode} \dtl@sortdata{#3}% }% {% \PackageError{datatool}{Database `#3' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@rowa} % Token register to store first row when sorting. % \begin{macrocode} \newtoks\@dtl@rowa % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@rowb} % Token register to store comparison row when sorting. % \begin{macrocode} \newtoks\@dtl@rowb % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@sortdata} %\begin{definition} %\cs{dtl@sortdata}\marg{db} %\end{definition} % Sorts the data in named database using an insertion sort % algorithm. % \cs{@dtl@replacementkeys}, \cs{@dtl@sortorder} and % \cs{@dtl@comparecs} must be set prior to use. %\changes{2.0}{2009 February 27}{new} % \begin{macrocode} \newcommand*{\dtl@sortdata}[1]{% % \end{macrocode} % Initialise macro containing sorted data. % \begin{macrocode} \def\@dtl@sortedlist{}% % \end{macrocode} % Store database name. % \begin{macrocode} \edef\@dtl@dbname{#1}% % \end{macrocode} % Iterate through each row and insert into sorted list. % \begin{macrocode} \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{% \@dtl@rowa=\expandafter{\@dtl@rowAcontents}% % \end{macrocode} % Create a temporary list % \begin{macrocode} \def\@dtl@newlist{}% % \end{macrocode} % Initialise the insertion for this iteration. Insertion hasn't % been done yet. % \begin{macrocode} \@dtl@insertdonefalse % \end{macrocode} % Initialise row index to 0 % \begin{macrocode} \dtlrownum=0\relax % \end{macrocode} % Iterate through sorted list. % \begin{macrocode} \expandafter\@dtl@foreachrow\@dtl@sortedlist \db@row@elt@w% \db@row@id@w \@nil\db@row@id@end@% \db@row@id@w \@nil\db@row@id@end@% \db@row@elt@end@% \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{% % \end{macrocode} % Store row B in a token register % \begin{macrocode} \@dtl@rowb=\expandafter{\@dtl@rowBcontents}% % \end{macrocode} % Get current row number of sorted list % \begin{macrocode} \dtlrownum=\@dtl@rowBnum % \end{macrocode} % Has the insertion been done? % \begin{macrocode} \if@dtl@insertdone % \end{macrocode} % New element has already been inserted, so just increment the row % number to compensate for the inserted row. % \begin{macrocode} \advance\dtlrownum by 1\relax \else % \end{macrocode} % Insertion hasn't been done yet. % Compare row A and row B. % \begin{macrocode} \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}% % \end{macrocode} % If \cs{dtl@sortresult} is negative insert A before B. % \begin{macrocode} \ifnum\dtl@sortresult<0\relax % \end{macrocode} % Insert row A into new list. First store \cs{@dtl@newlist} in % \cs{toks@}. % \begin{macrocode} \toks@=\expandafter{\@dtl@newlist}% % \end{macrocode} % Update \cs{@dtl@newlist} to be the old value followed by % row A. % \begin{macrocode} \edef\@dtl@newlist{% % \end{macrocode} % Old value: % \begin{macrocode} \the\toks@ % \end{macrocode} % Format row A % \begin{macrocode} \noexpand\db@row@elt@w% \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \the\@dtl@rowa \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% }% % \end{macrocode} % Increment row number to compensate for inserted row. % \begin{macrocode} \advance\dtlrownum by 1\relax % \end{macrocode} % Mark insertion done. % \begin{macrocode} \@dtl@insertdonetrue \fi \fi % \end{macrocode} % Insert row B % \begin{macrocode} \toks@=\expandafter{\@dtl@newlist}% \edef\@dtl@newlist{\the\toks@ % \end{macrocode} % row B % \begin{macrocode} \noexpand\db@row@elt@w% \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \the\@dtl@rowb \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% }% % \end{macrocode} % Repeat loop. % \begin{macrocode} }\q@nil % \end{macrocode} % If row A hasn't been inserted, do so now. % \begin{macrocode} \if@dtl@insertdone \else % \end{macrocode} % \cs{dtlrownum} contains the index of the last row in new list, % So increment it to get the new index for row A. % \begin{macrocode} \advance\dtlrownum by 1\relax % \end{macrocode} % Insert row A. % \begin{macrocode} \toks@=\expandafter{\@dtl@newlist}% \edef\@dtl@newlist{\the\toks@ % \end{macrocode} % row A % \begin{macrocode} \noexpand\db@row@elt@w% \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \the\@dtl@rowa \noexpand\db@row@id@w \number\dtlrownum \noexpand\db@row@id@end@% \noexpand\db@row@elt@end@% }% \fi % \end{macrocode} % Set sorted list to new list. % \begin{macrocode} \let\@dtl@sortedlist=\@dtl@newlist }% % \end{macrocode} % Update database. % \begin{macrocode} \expandafter\global\csname dtldb@#1\endcsname=\expandafter {\@dtl@sortedlist}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@sortcriteria} %\begin{definition} % \cs{@dtl@sortcriteria}\marg{row a toks}\marg{row b toks} %\end{definition} % \cs{@dtl@dbname} and \cs{@dtl@sortorder} must be set before use % \cs{@dtl@sortorder} is a comma separated list of either just keys % or \meta{key}=\meta{direction}. % (Check keys are valid before use.) %\changes{2.0}{2009 February 27}{updated to take account of new % database structure} % \begin{macrocode} \newcommand{\@dtl@sortcriteria}[2]{% % \end{macrocode} % Iterate through the sort order. % \begin{macrocode} \@for\@dtl@level:=\@dtl@sortorder\do{% % \end{macrocode} % Set \cs{@dtl@sortdirection} to $-1$ (ascending) or $+1$ % (descending). Key is stored in \cs{@dtl@key}. % \begin{macrocode} \expandafter\@dtl@getsortdirection\@dtl@level=\relax % \end{macrocode} % Initially comparing on the same key % \begin{macrocode} \let\@dtl@keya=\@dtl@key \let\@dtl@keyb=\@dtl@key % \end{macrocode} % Get values corresponding to key from both rows. % First get column index corresponding to key. % \begin{macrocode} \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}% % \end{macrocode} % Get entry for this column from row A and store in \cs{@dtl@a}. % \begin{macrocode} \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% % \end{macrocode} % Get entry for this column from row B and store in \cs{@dtl@b}. % \begin{macrocode} \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% % \end{macrocode} % Has value from row A been defined? % \begin{macrocode} \ifx\@dtl@a\dtlnovalue % \end{macrocode} % Value hasn't been defined so set to null % \begin{macrocode} \@dtl@setnull{\@dtl@a}{\@dtl@key}% \fi % \end{macrocode} % Has value from row B been defined? % \begin{macrocode} \ifx\@dtl@b\dtlnovalue % \end{macrocode} % Value hasn't been defined so set to null % \begin{macrocode} \@dtl@setnull{\@dtl@b}{\@dtl@key}% \fi % \end{macrocode} % Check if value for row A is null. % \begin{macrocode} \DTLifnull{\@dtl@a}% {% % \end{macrocode} % Value for row A is null, so find the first non null key in list of % replacement keys. % \begin{macrocode} \@for\@dtl@keya:=\@dtl@replacementkeys\do{% % \end{macrocode} % Get column corresponding to this key. % \begin{macrocode} \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}% \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}% % \end{macrocode} % Has value for row A been defined? % \begin{macrocode} \ifx\@dtl@a\dtlnovalue % \end{macrocode} % Value for row A hasn't been defined so set to null % \begin{macrocode} \@dtl@setnull{\@dtl@a}{\@dtl@key}% \fi % \end{macrocode} % Is value for row A null? If not null end the loop. % \begin{macrocode} \DTLifnull{\@dtl@a}{}{\@endfortrue}% }% % \end{macrocode} % No non-null value found. % \begin{macrocode} \ifx\@dtl@keya\@nnil \let\@dtl@keya\@dtl@key \@dtl@setnull{\@dtl@a}{\@dtl@key}% \fi }% {}% % \end{macrocode} % Check if value for row B is null. % \begin{macrocode} \DTLifnull{\@dtl@b}% {% % \end{macrocode} % Value for row B is null, so find the first non null key in list of % replacement keys. % \begin{macrocode} \@for\@dtl@keyb:=\@dtl@replacementkeys\do{% % \end{macrocode} % Get column corresponding to this key. % \begin{macrocode} \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}% \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}% % \end{macrocode} % Has value for row B been defined? % \begin{macrocode} \ifx\@dtl@b\dtlnovalue % \end{macrocode} % Value for row B hasn't been defined so set to null. % \begin{macrocode} \@dtl@setnull{\@dtl@b}{\@dtl@key}% \fi % \end{macrocode} % Is value for row B null? If not null end the loop. % \begin{macrocode} \DTLifnull{\@dtl@b}{}{\@endfortrue}% }% % \end{macrocode} % No non-null value found. % \begin{macrocode} \ifx\@dtl@keyb\@nnil \let\@dtl@keyb\@dtl@key \@dtl@setnull{\@dtl@b}{\@dtl@key}% \fi }% {}% % \end{macrocode} % Compare rows A and B. First store the values for row A and B % in token registers so that they can be passed to % \cs{dtl@compare@}. % \begin{macrocode} \@dtl@toksA=\expandafter{\@dtl@a}% \@dtl@toksB=\expandafter{\@dtl@b}% % \end{macrocode} % Do comparison. % \begin{macrocode} \edef\@dtl@docompare{\noexpand\dtl@compare@ {\@dtl@keya}{\@dtl@keyb}% {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}% \@dtl@docompare % \end{macrocode} % Repeat if the two values are considered identical and there % are further sorting options. % \begin{macrocode} \ifnum\dtl@sortresult=0\relax % \end{macrocode} % Reset switch to prevent breaking out of outer loop. % \begin{macrocode} \@endforfalse \else % \end{macrocode} % Break out of loop. % \begin{macrocode} \@endfortrue \fi }% % \end{macrocode} % Apply sort direction %\changes{2.01}{2009 March 27}{fixed sort direction} % \begin{macrocode} \multiply\dtl@sortresult by -\@dtl@sortdirection\relax } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@getsortdirection} % Get the direction from either \meta{key} or % \meta{key}=\meta{direction}. Sets \cs{@dtl@sortdirection} to % either -1 (ascending) or 1 (descending). % \begin{macrocode} \def\@dtl@getsortdirection#1=#2\relax{% % \end{macrocode} % Store key in \cs{@dtl@key}. % \begin{macrocode} \def\@dtl@key{#1}% % \end{macrocode} % Store sort direction. This will be empty if no direction was % specified. % \begin{macrocode} \def\@dtl@sortdirection{#2}% % \end{macrocode} % Check if a direction was specified. % \begin{macrocode} \ifx\@dtl@sortdirection\@empty % \end{macrocode} % No direction specified so assume ascending. % \begin{macrocode} \def\@dtl@sortdirection{-1}% \else % \end{macrocode} % Get the sort direction from the second argument (needs terminating % equal sign removed) and store in \cs{@dtl@sortdirection}. % \begin{macrocode} \@dtl@get@sortdirection#2% % \end{macrocode} % Determine the direction. % \changes{2.0}{2009 February 27}{modified to use \cs{ifx} instead % of \cs{ifthenelse}} % \begin{macrocode} \def\@dtl@dir{ascending}% \ifx\@dtl@sortdirection\@dtl@dir % \end{macrocode} % Ascending % \begin{macrocode} \def\@dtl@sortdirection{-1}% \else % \end{macrocode} % Check if descending. % \begin{macrocode} \def\@dtl@dir{descending}% \ifx\@dtl@sortdirection\@dtl@dir % \end{macrocode} % Descending % \begin{macrocode} \def\@dtl@sortdirection{1}% \else % \end{macrocode} % Direction not valid. Generate error message. % \begin{macrocode} \PackageError{datatool}{Invalid sort direction `\@dtl@sortdirection'}{The sort direction can only be one of `ascending' or `descending'}% % \end{macrocode} % Assume ascending. % \begin{macrocode} \def\@dtl@sortdirection{-1} \fi \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@get@sortdirection} % Get direction (trims trailing = sign) % \begin{macrocode} \def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@toksA} % \begin{macrocode} \newtoks\@dtl@toksA % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@toksB} % \begin{macrocode} \newtoks\@dtl@toksB % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@toks} % \begin{macrocode} \newtoks\@dtl@toks % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@compare} %\begin{definition} %\cs{dtl@compare}\marg{key}\marg{a toks}\marg{b toks} %\end{definition} % Compares two values according to \meta{key} of database given by % \cs{@dtl@dbname}. Sets \cs{dtl@sortresult}. \cs{@dtl@comparecs} % must be set to the required comparison macro. %\changes{2.0}{2009 February 27}{no longer used} % \begin{macrocode} \newcommand{\dtl@compare}[3]{% \dtl@compare@{#1}{#1}{#2}{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@compare@} %\begin{definition} % \cs{dtl@compare@}\marg{keyA}\marg{keyB}\marg{A toks}\marg{B toks} %\end{definition} % Compare \meta{A} and \meta{B} according \meta{keyA} and % \meta{keyB} for database given by \cs{@dtl@dbname}. Sets % \cs{dtl@sortresult}. % \cs{@dtl@comparecs} must be set before use. %\changes{2.0}{2009 February 27}{updated to use new database % structure} % \begin{macrocode} \newcommand{\dtl@compare@}[4]{% % \end{macrocode} % Get the data type for first key and store in \cs{@dtl@typeA}. % \begin{macrocode} \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}% % \end{macrocode} % Is it unset? If so, assume string % \begin{macrocode} \ifx\@dtl@typeA\DTLunsettype \let\@dtl@typeA\DTLstringtype \fi % \end{macrocode} % Get the data type for the second key and store in \cs{@dtl@typeB} % \begin{macrocode} \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}% % \end{macrocode} % Is it unset? If so, assume string % \begin{macrocode} \ifx\@dtl@typeB\DTLunsettype \let\@dtl@typeB\DTLstringtype \fi % \end{macrocode} % Multiply the two values together % \begin{macrocode} \@dtl@tmpcount=\@dtl@typeA\relax \multiply\@dtl@tmpcount by \@dtl@typeB\relax % \end{macrocode} % If either type is 0 (a string) then the product will also be % 0 (string) otherwise it will be one of the numerical types. % \begin{macrocode} \ifnum\@dtl@tmpcount=0\relax % \end{macrocode} % A string, so use comparison function % \begin{macrocode} \edef\@dtl@tmpcmp{% \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}% {\the#3}{\the#4}% }% \@dtl@tmpcmp \ifdtlverbose \edef\@dtl@a{\the#3}% \edef\@dtl@b{\the#4}% \fi \else % \end{macrocode} % Store the first value % \begin{macrocode} \edef\@dtl@a{\the#3}% % \end{macrocode} % Store the second value % \begin{macrocode} \edef\@dtl@b{\the#4}% % \end{macrocode} % Compare % \begin{macrocode} \DTLifnumlt{\@dtl@a}{\@dtl@b}% {% % \end{macrocode} % $A < B$ % \begin{macrocode} \dtl@sortresult=-1\relax }% {% \DTLifnumgt{\@dtl@a}{\@dtl@b}% {% % \end{macrocode} % $A > B$ % \begin{macrocode} \dtl@sortresult=1\relax }% {% % \end{macrocode} % $A = B$ % \begin{macrocode} \dtl@sortresult=0\relax }% }% \fi % \end{macrocode} % Write comparison result to terminal/log if verbose mode. % \begin{macrocode} \ifdtlverbose \@onelevel@sanitize\@dtl@a \@onelevel@sanitize\@dtl@b \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}% \fi } % \end{macrocode} %\end{macro} % %\subsection{Saving a database to an external file} % %\begin{macro}{\@dtl@write} % \begin{macrocode} \newwrite\@dtl@write % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsavedb} %\begin{definition} % \cs{DTLsavedb}\marg{db name}\marg{filename} %\end{definition} % Save a database as an ASCII data file using the separator % and delimiter given by \cs{@dtl@separator} and \cs{@dtl@delimiter}. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLsavedb}[2]{% \DTLifdbexists{#1}% {% % \end{macrocode} % Open output file %\changes{2.02}{2009 July 13}{Fixed bug that didn't set the filename} % \begin{macrocode} \openout\@dtl@write=#2\relax % \end{macrocode} % Initialise header row % \begin{macrocode} \def\@dtl@header{}% % \end{macrocode} % Construct the header row % \begin{macrocode} \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)% \in{#1}\do {% \IfSubStringInString{\@dtl@separator}{\@dtl@key}% {% \ifx\@dtl@header\@empty \protected@edef\@dtl@header{% \@dtl@delimiter\@dtl@key\@dtl@delimiter}% \else \toks@=\expandafter{\@dtl@header}% \protected@edef\@dtl@header{% \the\toks@\@dtl@separator \@dtl@delimiter\@dtl@key\@dtl@delimiter}% \fi }% {% \ifx\@dtl@header\@empty \protected@edef\@dtl@header{\@dtl@key}% \else \toks@=\expandafter{\@dtl@header}% \protected@edef\@dtl@header{\the\toks@ \@dtl@separator\@dtl@key}% \fi }% }% % \end{macrocode} % Print header % \begin{macrocode} \protected@write\@dtl@write{}{\@dtl@header}% % \end{macrocode} % Iterate through each row % \begin{macrocode} \@sDTLforeach{#1}{}% {% % \end{macrocode} % Initialise row % \begin{macrocode} \def\@dtl@row{}% % \end{macrocode} % Iterate through each key % \begin{macrocode} \DTLforeachkeyinrow{\@dtl@val}% {% \IfSubStringInString{\@dtl@separator}{\@dtl@val}% {% \ifx\@dtl@row\@empty \protected@edef\@dtl@row{% \@dtl@delimiter\@dtl@val\@dtl@delimiter}% \else \toks@=\expandafter{\@dtl@row}% \protected@edef\@dtl@row{\the\toks@\@dtl@separator \@dtl@delimiter\@dtl@val\@dtl@delimiter}% \fi }% {% \ifx\@dtl@row\@empty \protected@edef\@dtl@row{\@dtl@val}% \else \toks@=\expandafter{\@dtl@row}% \protected@edef\@dtl@row{\the\toks@\@dtl@separator \@dtl@val}% \fi }% }% % \end{macrocode} % Print row\changes{2.03}{2009 November 15}{Moved outside loop} % \begin{macrocode} \protected@write\@dtl@write{}{\@dtl@row}% }% % \end{macrocode} % Close output file % \begin{macrocode} \closeout\@dtl@write }% {% \PackageError{datatool}{Can't save database `#1': no such database}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsavetexdb} %\begin{definition} % \cs{DTLsavetexdb}\marg{db name}\marg{filename} %\end{definition} % Save a database as a \LaTeX\ file. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\DTLsavetexdb}[2]{% \DTLifdbexists{#1}% {% % \end{macrocode} % Open output file % \begin{macrocode} \openout\@dtl@write=#2\relax % \end{macrocode} % Write new data base definition % \begin{macrocode} \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}% % \end{macrocode} % Iterate through each row % \begin{macrocode} \@sDTLforeach{#1}{}% {% % \end{macrocode} % Start new row % \begin{macrocode} \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}% % \end{macrocode} % Iterate through each column % \begin{macrocode} \DTLforeachkeyinrow{\@dtl@val}% {% % \end{macrocode} % Is this entry null? % \begin{macrocode} \DTLifnull{\@dtl@val}% {\def\@dtl@val{}}% {}% % \end{macrocode} % Add entry % \begin{macrocode} \protected@write\@dtl@write{}{% \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}% }% }% % \end{macrocode} % Save the column headers. % \begin{macrocode} \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do {% \@onelevel@sanitize\@dtl@h \protected@write\@dtl@write{}{% \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}% }% % \end{macrocode} % Close output file % \begin{macrocode} \closeout\@dtl@write }% {% \PackageError{datatool}{Can't save database `#1': no such database}{}% }% } % \end{macrocode} %\end{macro} % %\subsection{Loading a database from an external file} % % \begin{macrocode} \newcommand{\@longempty}{} % \end{macrocode} %\begin{macro}{\@dtl@read} % \begin{macrocode} \newread\@dtl@read % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@entrycr} % Keep track of current column in data file % \begin{macrocode} \newcount\dtl@entrycr % \end{macrocode} %\end{macro} % %\begin{macro}{\ifdtlnoheader} % The "noheader" option indicates that the file doesn't have a % header row. % \begin{macrocode} \define@boolkey{loaddb}[dtl]{noheader}[true]{} % \end{macrocode} %\end{macro} % The "keys" option specifies the list of keys in the same order % as the columns in the data file. % Each key is stored in \cs{@dtl@inky@}\meta{n} where \meta{n} is the % roman numeral representation of the current column. % \begin{macrocode} \define@key{loaddb}{keys}{% \dtl@entrycr=0\relax \@for\@dtl@key:=#1\do {% \advance\dtl@entrycr by 1\relax \expandafter \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{% \@dtl@key}% }% } % \end{macrocode} % The "headers" option specifies the list of headers in the % same order as the columns in the data file. % \begin{macrocode} \define@key{loaddb}{headers}{% \dtl@entrycr=0\relax \@for\@dtl@head:=#1\do {% \advance\dtl@entrycr by 1\relax \toks@=\expandafter{\@dtl@head}% \expandafter \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{% \the\toks@}% }% } % \end{macrocode} % %\begin{macro}{\dtldefaultkey} % Default key to use if none specified (column index will be % appended). % \begin{macrocode} \newcommand*{\dtldefaultkey}{Column} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@readline} %\begin{definition} %\cs{@dtl@readline}\marg{file reg}\marg{cs} %\end{definition} % Reads line from \meta{file reg}, trims end of line character % and stores in \meta{cs}. % \begin{macrocode} \newcommand*{\@dtl@readline}[2]{% % Read a line from "#1" and store in "#2" % \begin{macrocode} \read#1 to #2% % \end{macrocode} % Trim the end of line character % \begin{macrocode} \dtl@trim#2% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@readrawline} %\begin{definition} %\cs{@dtl@readrawline}\marg{file register}\marg{cs} %\end{definition} % Reads line from \meta{file register}, trims end of line character, % applies mappings and stores in \meta{cs}. % \begin{macrocode} \newcommand*{\@dtl@readrawline}[2]{% % Read a line from "#1" and store in "#2" % \begin{macrocode} \@dtl@rawread#1 to #2% % \end{macrocode} % Trim the end of line character % \begin{macrocode} \dtl@trim#2% % \end{macrocode} % Apply mappings % \begin{macrocode} \dtl@domappings\@dtl@line } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLloaddb} %\begin{definition} % \cs{DTLloaddb}\oarg{options}\marg{db name}\marg{filename} %\end{definition} % Creates a new database called \meta{db name}, and loads the data % in \meta{filename} into it. The separator and delimiter used in % the file must match \cs{@dtl@separator} and \cs{@dtl@delimiter}. % The optional argument is a comma-separated list. %\changes{2.0}{2009 February 27}{removed checks to see if the % database exists when adding to it} %\changes{2.0}{2009 February 27}{added optional argument} % \begin{macrocode} \newcommand*{\DTLloaddb}{% \let\@dtl@doreadline\@dtl@readline \@dtlloaddb } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtlloaddb} % Loads database using \cs{@dtl@doreadline} to read and trim % line from file. (\cs{@dtl@doreadline} must be set before use.) % \begin{macrocode} \newcommand*{\@dtlloaddb}[3][]{% % \end{macrocode} % Check if file exists % \begin{macrocode} \IfFileExists{#3}{% % \end{macrocode} % File exists. Locally change catcode of double quote character in % case it has been made active. % \begin{macrocode} \begingroup \catcode`\"12\relax % \end{macrocode} % Initialise default options % \begin{macrocode} \dtlnoheaderfalse % \end{macrocode} % Get the options % \begin{macrocode} \setkeys{loaddb}{#1}% % \end{macrocode} % Open the file for reading. % \begin{macrocode} \openin\@dtl@read=#3% \dtl@message{Reading `#3'}% % \end{macrocode} % Create the new database. % \begin{macrocode} \DTLnewdb{#2}% % \end{macrocode} % Check if the file is empty. % \begin{macrocode} \ifeof\@dtl@read % \end{macrocode} % File is empty, so just issue a warning. % \begin{macrocode} \PackageWarning{datatool}{File `#3' has no data}% \else % \end{macrocode} % Does the file have a header row? % \begin{macrocode} \ifdtlnoheader \else % \end{macrocode} % Remove initial blank rows % \begin{macrocode} \loop % \end{macrocode} % Set repeat condition to false % \begin{macrocode} \@dtl@conditionfalse % \end{macrocode} % Do nothing if reached the end of file % \begin{macrocode} \ifeof\@dtl@read \else % \end{macrocode} % Read a line from the file and store in \cs{@dtl@line} % \begin{macrocode} \@dtl@doreadline\@dtl@read\@dtl@line % \end{macrocode} % If this is a blank row, set repeat condition to true % \begin{macrocode} \ifx\@dtl@line\@longempty \@dtl@conditiontrue \fi \fi % \end{macrocode} % Repeat loop if necessary % \begin{macrocode} \if@dtl@condition \repeat % \end{macrocode} % Parse the header row. Store the row as % \meta{sep}\meta{row}\meta{sep} in \cs{@dtl@lin@}. % \begin{macrocode} \protected@edef\@dtl@lin@{% \@dtl@separator\@dtl@line\@dtl@separator}% % \end{macrocode} % Keep track of columns: % \begin{macrocode} \dtl@entrycr=0\relax % \end{macrocode} % Keep lopping off elements until the end of the row is reached. % (That is, until \cs{@dtl@lin@} is \cs{@dtl@separator}.) %\changes{2.0}{2009 February 27}{changed \cs{whiledo} to % \cs{loop} to improve efficiency}% % \begin{macrocode} \loop % \end{macrocode} % Lopoff the first element and store in \cs{@dtl@key} % \begin{macrocode} \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key % \end{macrocode} % Increment column count. % \begin{macrocode} \advance\dtl@entrycr by 1\relax % \end{macrocode} % Store key in \cs{@dtl@toks} % \begin{macrocode} \expandafter\@dtl@toks\expandafter{\@dtl@key}% % \end{macrocode} % Store the key in \cs{@dtl@inky@}\meta{n} where \meta{n} is the % roman numeral representation of the current column, unless % already defined. % \begin{macrocode} \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% {% \expandafter \edef\csname @dtl@inky@\romannumeral \dtl@entrycr\endcsname{\the\@dtl@toks}% }% {% % \end{macrocode} % If key has been specified in "#1", then use the header found in the % file, unless a header has also been specified in "#1" % \begin{macrocode} \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% {% \expandafter \edef\csname @dtl@inhd@\romannumeral \dtl@entrycr\endcsname{\the\@dtl@toks}% }% {}% }% % \end{macrocode} % Check if the loop should be repeated % \begin{macrocode} \ifx\@dtl@lin@\@dtl@separator \@dtl@conditionfalse \else \@dtl@conditiontrue \fi % \end{macrocode} % Repeat loop if necessary. % \begin{macrocode} \if@dtl@condition \repeat % \end{macrocode} % End if no header % \begin{macrocode} \fi % \end{macrocode} % Now for the rest of the data. If the end of file has been % reached, then only the header row is available or file is empty. % \begin{macrocode} \ifeof\@dtl@read \ifdtlnoheader \PackageWarning{datatool}{No data in `#3'}% \else \PackageWarning{datatool}{Only header row found in `#3'}% \fi \else % \end{macrocode} % Iterate through the rest of the file. First set the repeat % condition to true: % \begin{macrocode} \@dtl@conditiontrue \loop % \end{macrocode} % Read in a line % \begin{macrocode} \@dtl@doreadline\@dtl@read\@dtl@line % \end{macrocode} % Check if the line is empty. %\changes{2.0}{2009 February 27}{changed \cs{ifthenelse} to %\cs{ifx} to improve efficiency} % \begin{macrocode} \ifx\@dtl@line\@longempty % \end{macrocode} % Do nothing if the row is empty. % \begin{macrocode} \else % \end{macrocode} % Add a new row to the database. (Don't need to check if the % database exists, since it's just been created.) % \begin{macrocode} \@sDTLnewrow{#2}% % \end{macrocode} % Store the row as \meta{sep}\meta{row}\meta{sep} to make the % lopping off easier % \begin{macrocode} \expandafter\@dtl@toks\expandafter{\@dtl@line}% \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks \@dtl@separator}% % \end{macrocode} % Reset the column counter. % \begin{macrocode} \dtl@entrycr=0\relax % \end{macrocode} %\changes{2.0}{2009 February 27}{changed \cs{whiledo} to \cs{loop} % to improve efficiency} % Iterate through each element in the row. Needs to be grouped % since we're already inside a loop. % \begin{macrocode} {% % \end{macrocode} % Initialise repeat condition % \begin{macrocode} \@dtl@conditiontrue % \end{macrocode} % Iterate through the list % \begin{macrocode} \loop % \end{macrocode} % lop off first element and store in \cs{@dtl@thisentry} % \begin{macrocode} \expandafter\@dtl@lopoff\@dtl@lin@\to \@dtl@lin@\@dtl@thisentry % \end{macrocode} % Increment the column count. % \begin{macrocode} \advance\dtl@entrycr by 1\relax % \end{macrocode} % Get the key for this column and store in \cs{@dtl@thiskey}. % Use default value if not defined. % \begin{macrocode} \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}% {% \edef\@dtl@thiskey{\dtldefaultkey \number\dtl@entrycr}% \expandafter\let \csname @dtl@inky@\romannumeral \dtl@entrycr\endcsname\@dtl@thiskey }% {% \edef\@dtl@thiskey{% \csname @dtl@inky@\romannumeral \dtl@entrycr\endcsname}% }% % \end{macrocode} % Store this entry in \cs{@dtl@toks} % \begin{macrocode} \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}% % \end{macrocode} % Add this entry to the database % \begin{macrocode} \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry {#2}{\@dtl@thiskey}{\the\@dtl@toks}}% \@do@dtlnewentry % \end{macrocode} % Check if loop should be terminated % \begin{macrocode} \ifx\@dtl@lin@\@dtl@separator \@dtl@conditionfalse \fi % \end{macrocode} % Repeat loop if necessary % \begin{macrocode} \if@dtl@condition \repeat }% % \end{macrocode} % End of parsing this row % \begin{macrocode} \fi % \end{macrocode} % If the end of file has been reached, set the repeat condition % to false. % \begin{macrocode} \ifeof\@dtl@read \@dtl@conditionfalse\fi % \end{macrocode} % Repeat if necessary % \begin{macrocode} \if@dtl@condition \repeat \fi % \end{macrocode} % End of first \cs{ifeof} % \begin{macrocode} \fi % \end{macrocode} % Close the input file % \begin{macrocode} \closein\@dtl@read % \end{macrocode} % Set the headers if required % \begin{macrocode} \edef\@dtl@maxcols{\expandafter \number\csname dtlcols@#2\endcsname}% \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do {% \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}% {}% {% \expandafter\let\expandafter\@dtl@head \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname \@dtl@toks=\expandafter{\@dtl@head}% \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}% \@dtl@dosetheader }% }% % \end{macrocode} % End current scope % \begin{macrocode} \endgroup % \end{macrocode} % End true part of if file exists % \begin{macrocode} }{% % \end{macrocode} % Requested file not found on TeX's path % \begin{macrocode} \PackageError{datatool}{Can't load database `#2' (file `#3' doesn't exist)}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@trim} %\begin{definition} %\cs{dtl@trim}\marg{line} %\end{definition} % Trims the trailing space from \meta{line}. % \begin{macrocode} \newcommand{\dtl@trim}[1]{% \def\@dtl@trmstr{}% \expandafter\@dtl@starttrim#1\@nil% \let#1=\@dtl@trmstr } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@starttrim} % Start trimming % \begin{macrocode} \long\def\@dtl@starttrim#1#2{% \ifx\par#1% \def\@dtl@dotrim{\@dtl@trim{} #2}% \else \def\@dtl@dotrim{\@dtl@trim#1#2}% \fi \@dtl@dotrim% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@trim} % \begin{macrocode} \long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLloadrawdb} %\begin{definition} %\cs{DTLloadrawdb}\marg{db name}\marg{filename} %\end{definition} % Loads a raw database (substitutes "%" $\to$ "\%", % "$" $\to$ "\$", "&" $\to$ "\&", "#" $\to$ "\#", % "~" $\to$ "\textasciitilde", "_" $\to$ "\_" % and "^" $\to$ "\textasciicircum".) The user can add additional % mappings. % \begin{macrocode} \newcommand*\DTLloadrawdb{% \let\@dtl@doreadline\@dtl@readrawline \@dtlloaddb } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@rawread} %\begin{definition} % \cs{@dtl@rawread}\meta{number}to\meta{cmd} %\end{definition} % Reads in a raw line from file given by \meta{number} % converts special characters and stores in \meta{cmd} % \begin{macrocode} \begingroup \catcode`\%=\active \catcode`$=\active \catcode`&=\active \catcode`~=\active \catcode`_=\active \catcode`^=\active \catcode`#=\active \catcode`?=6\relax \catcode`<=1\relax \catcode`>=2\relax \catcode`\{=\active \catcode`\}=\active \gdef\@dtl@rawread?1to?2<\relax <<\catcode`\%=\active \catcode`$=\active \catcode`&=\active \catcode`~=\active \catcode`_=\active \catcode`^=\active \catcode`#=\active \catcode`\{=\active \catcode`\}=\active \def%<\noexpand\%>\relax \def$<\noexpand\$>\relax \def&<\&>\relax \def#<\#>\relax \def~<\noexpand\textasciitilde>\relax \def_<\noexpand\_>\relax \def^<\noexpand\textasciicircum>\relax \@dtl@activatebraces \@dtl@doreadraw?1?2>>> \gdef\@dtl@doreadraw?1?2<\relax \read?1 to \tmp \xdef?2<\tmp>\relax > \endgroup % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@activatebraces} % \cs{@dtl@activatebraces} resets braces for \cs{@dtl@rawread} % \begin{macrocode} \begingroup \catcode`\{=\active \catcode`\}=\active \catcode`<=1\relax \catcode`>=2\relax \gdef\@dtl@activatebraces<% \catcode`\{=\active \catcode`\}=\active \def{<\noexpand\{>% \def}<\noexpand\}>% >% \endgroup % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLrawmap} %\begin{definition} %\cs{DTLrawmap}\marg{string}\marg{replacement} %\end{definition} % Additional mappings to perform when reading a raw data file % \begin{macrocode} \newcommand*{\DTLrawmap}[2]{% \expandafter\@dtl@toks\expandafter{\@dtl@rawmappings}% \ifx\@dtl@rawmappings\@empty \def\@dtl@rawmappings{{#1}{#2}}% \else \def\@dtl@tmp{{#1}{#2}} \protected@edef\@dtl@rawmappings{\the\@dtl@toks,\@dtl@tmp} \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@rawmappings} % List of mappings. % \begin{macrocode} \newcommand*{\@dtl@rawmappings}{} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@domappings} %\begin{definition} % \cs{dtl@domappings}\marg{cmd} %\end{definition} % Do all mappings in string given by \meta{cmd}. % \begin{macrocode} \newcommand*{\dtl@domappings}[1]{% \@for\@dtl@map:=\@dtl@rawmappings\do{% \expandafter\DTLsubstitute\expandafter#1\@dtl@map }} % \end{macrocode} %\end{macro} % %\subsection{General List Utilities} % %\begin{macro}{\DTLifinlist} %\begin{definition} %\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 do \meta{true part} otherwise do false % part. (Does a one level expansion on \meta{list}, but no % expansion on \meta{element}.) % \begin{macrocode} \newcommand*{\DTLifinlist}[4]{% \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% \def\@before{##1}% \def\@after{##2}% }% \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil \end@dtl@doifinlist \ifx\@after\@nnil % not found #4% \else % found #3% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@choplast} %\begin{definition} % \cs{dtl@choplast}\marg{list}\marg{rest}\marg{last} %\end{definition} % Chops the last element off a comma separated list, putting the % last element in the control sequence \meta{last} and putting % the rest in the control sequence \meta{rest}. The control % sequence \meta{list} is unchanged. If the list is empty, both % \meta{last} and \meta{rest} will be empty. % \begin{macrocode} \newcommand*{\dtl@choplast}[3]{% % \end{macrocode} % Set \meta{rest} to empty: % \begin{macrocode} \let#2\@empty % \end{macrocode} % Set \meta{last} to empty: % \begin{macrocode} \let#3\@empty % \end{macrocode} % Iterate through \meta{list}: % \begin{macrocode} \@for\@dtl@element:=#1\do{% \ifx#3\@empty % \end{macrocode} % First iteration, don't set \meta{rest}. % \begin{macrocode} \else \ifx#2\@empty % \end{macrocode} % Second iteration, set \meta{rest} to \meta{last} (which is % currently set to the previous value: % \begin{macrocode} \expandafter\toks@\expandafter{#3}% \edef#2{{\the\toks@}}% \else % \end{macrocode} % Subsequent iterations, set \meta{rest} to \meta{rest},\meta{last} % (\meta{last} is currently set to the previous value): % \begin{macrocode} \expandafter\toks@\expandafter{#3}% \expandafter\@dtl@toks\expandafter{#2}% \edef#2{\the\@dtl@toks,{\the\toks@}}% \fi \fi % \end{macrocode} % Now set \meta{last} to current element. % \begin{macrocode} \let#3=\@dtl@element% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@chopfirst} %\begin{definition} % \cs{dtl@chopfirst}\marg{list}\marg{first}\marg{rest} %\end{definition} % Chops first element off \meta{list} and store in \meta{first}. % The remainder of the list is stored in \meta{rest}. (\meta{list} % remains unchanged.) % \begin{macrocode} \newcommand*{\dtl@chopfirst}[3]{% \let#2=\@empty \let#3=\@empty \@for\@dtl@element:=#1\do{% \let#2=\@dtl@element \@endfortrue }% \if@endfor \let#3=\@forremainder \fi \@endforfalse } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@sortlist} %\begin{definition} % \cs{dtl@sortlist}\marg{list}\marg{criteria cmd} %\end{definition} % Performs an insertion sort on \meta{list}, where \meta{criteria cmd} % is a macro which takes two arguments \meta{a} and \meta{b}. % \meta{criteria cmd} must set the count register \cs{dtl@sortresult} % to either -1 (\meta{a} less than \meta{b}), 0 (\meta{a} is % equal to \meta{b}) or 1 (\meta{a} is greater than \meta{b}.) % \begin{macrocode} \newcommand{\dtl@sortlist}[2]{% \def\@dtl@sortedlist{}% \@for\@dtl@currentrow:=#1\do{% \expandafter\dtl@insertinto\expandafter {\@dtl@currentrow}{\@dtl@sortedlist}{#2}% \@endforfalse}% \let#1=\@dtl@sortedlist } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@insertinto} %\begin{definition} % \cs{dtl@insertinto}\marg{element}\marg{sorted-list}\marg{criteria cmd} %\end{definition} % Inserts \meta{element} into the sorted list \meta{sorted-list} % according to the criteria given by \meta{criteria cmd} (see above.) % \begin{macrocode} \newcommand{\dtl@insertinto}[3]{% \def\@dtl@newsortedlist{}% \@dtl@insertdonefalse \@for\dtl@srtelement:=#2\do{% \if@dtl@insertdone \expandafter\toks@\expandafter{\dtl@srtelement}% \edef\@dtl@newstuff{{\the\toks@}}% \else \expandafter#3\expandafter{\dtl@srtelement}{#1}% \ifnum\dtl@sortresult<0\relax \expandafter\toks@\expandafter{\dtl@srtelement}% \@dtl@toks{#1}% \edef\@dtl@newstuff{{\the\@dtl@toks},{\the\toks@}}% \@dtl@insertdonetrue \else \expandafter\toks@\expandafter{\dtl@srtelement}% \edef\@dtl@newstuff{{\the\toks@}}% \fi \fi \ifx\@dtl@newsortedlist\@empty \expandafter\toks@\expandafter{\@dtl@newstuff}% \edef\@dtl@newsortedlist{\the\toks@}% \else \expandafter\toks@\expandafter{\@dtl@newsortedlist}% \expandafter\@dtl@toks\expandafter{\@dtl@newstuff}% \edef\@dtl@newsortedlist{\the\toks@,\the\@dtl@toks}% \fi \@endforfalse }% \ifx\@dtl@newsortedlist\@empty \@dtl@toks{#1}% \edef\@dtl@newsortedlist{{\the\@dtl@toks}}% \else \if@dtl@insertdone \else \expandafter\toks@\expandafter{\@dtl@newsortedlist}% \@dtl@toks{#1}% \edef\@dtl@newsortedlist{\the\toks@,{\the\@dtl@toks}}% \fi \fi \global\let#2=\@dtl@newsortedlist } % \end{macrocode} %\end{macro} %\begin{macro}{\if@dtl@insertdone} % Define conditional to indicate whether the new entry has % been inserted into the sorted list. % \begin{macrocode} \newif\if@dtl@insertdone % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@sortresult} % Define \cs{dtl@sortresult} to be set by comparision macro. % \begin{macrocode} \newcount\dtl@sortresult % \end{macrocode} %\end{macro} % % \subsection{General Token Utilities} %\begin{macro}{\toks@gput@right@cx} %\begin{definition} %\cs{toks@gput@right@cx}\marg{toks name}\marg{stuff} %\end{definition} % Globally appends stuff to token register \cs{}\meta{toks name} % \begin{macrocode} \newcommand{\toks@gput@right@cx}[2]{% \def\@toks@name{#1}% \edef\@dtl@stuff{#2}% \global\csname\@toks@name\endcsname\expandafter \expandafter\expandafter{\expandafter\the \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}% } % \end{macrocode} %\end{macro} %\begin{macro}{\toks@gconcat@middle@cx} %\begin{definition} %\cs{toks@gconcat@middle@cx}\marg{toks name}\marg{before toks}\marg{stuff}\marg{after toks} %\end{definition} % Globally sets token register \cs{}\meta{toks name} to % the contents of \meta{before toks} concatenated with % \meta{stuff} (expanded) and the contents of \meta{after toks} % \begin{macrocode} \newcommand{\toks@gconcat@middle@cx}[4]{% \def\@toks@name{#1}% \edef\@dtl@stuff{#3}% \global\csname\@toks@name\endcsname\expandafter\expandafter \expandafter\expandafter\expandafter \expandafter\expandafter{\expandafter\expandafter\expandafter \the\expandafter\expandafter\expandafter#2% \expandafter\@dtl@stuff\the#4}% } % \end{macrocode} %\end{macro} % % \subsection{Floating Point Arithmetic} % The commands defined in this section all use the equivalent % commands provided by the \sty{fp} package, but first convert % the decimal number into the required format. % %\begin{macro}{\DTLadd} %\begin{definition} % \cs{DTLadd}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = \meta{num1} + \meta{num2} % \begin{macrocode} \newcommand*{\DTLadd}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \DTLconverttodecimal{#3}{\@dtl@numii}% \FPadd{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgadd} % Global version % \begin{macrocode} \newcommand*{\DTLgadd}[3]{% \DTLadd{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLaddall} %\begin{definition} %\cs{DTLaddall}\marg{cmd}\marg{num list} %\end{definition} % Sums all the values in \meta{num list} and stores in % \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLaddall}[2]{% \def\@dtl@sum{0}% \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \FPadd{\@dtl@sum}{\@dtl@sum}{\@dtl@num}% }% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@sum}{#1}% \else \DTLdecimaltocurrency{\@dtl@sum}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgaddall} %\begin{definition} %\cs{DTLgaddall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgaddall}[2]{% \DTLaddall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsub} %\begin{definition} % \cs{DTLsub}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = \meta{num1} - \meta{num2} % \begin{macrocode} \newcommand*{\DTLsub}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \DTLconverttodecimal{#3}{\@dtl@numii}% \FPsub{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgsub} % Global version % \begin{macrocode} \newcommand*{\DTLgsub}[3]{% \DTLsub{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmul} %\begin{definition} % \cs{DTLmul}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = \meta{num1} $\times$ \meta{num2} % \begin{macrocode} \newcommand*{\DTLmul}[3]{% \let\@dtl@thisreplaced=\@empty \DTLconverttodecimal{#2}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \else \let\@dtl@thisreplaced=\@dtl@replaced \fi \DTLconverttodecimal{#3}{\@dtl@numii}% \ifx\@dtl@replaced\@empty \else \let\@dtl@thisreplaced=\@dtl@replaced \fi \FPmul{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% \ifx\@dtl@thisreplaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgmul} % Global version % \begin{macrocode} \newcommand*{\DTLgmul}[3]{% \DTLmul{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdiv} %\begin{definition} % \cs{DTLdiv}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = \meta{num1} / \meta{num2} % \begin{macrocode} \newcommand*{\DTLdiv}[3]{% \let\@dtl@thisreplaced=\@empty \DTLconverttodecimal{#2}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \else \let\@dtl@thisreplaced=\@dtl@replaced \fi \DTLconverttodecimal{#3}{\@dtl@numii}% \FPdiv{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% \ifx\@dtl@thisreplaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \ifx\@dtl@thisreplaced\@dtl@replaced \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgdiv} % Global version % \begin{macrocode} \newcommand*{\DTLgdiv}[3]{% \DTLdiv{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLabs} %\begin{definition} % \cs{DTLabs}\marg{cmd}\marg{num} %\end{definition} % Sets \meta{cmd} = abs(\meta{num}) % \begin{macrocode} \newcommand*{\DTLabs}[2]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FPabs{\@dtl@tmp}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgabs} % Global version % \begin{macrocode} \newcommand*{\DTLgabs}[2]{% \DTLabs{\@dtl@tmpii}{#2}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLneg} %\begin{definition} % \cs{DTLneg}\marg{cmd}\marg{num} %\end{definition} % Sets \meta{cmd} = -\meta{num} % \begin{macrocode} \newcommand*{\DTLneg}[2]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FPneg{\@dtl@tmp}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgneg} % Global version % \begin{macrocode} \newcommand*{\DTLgneg}[2]{% \DTLneg{\@dtl@tmpii}{#2}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsqrt} %\begin{definition} % \cs{DTLsqrt}\marg{cmd}\marg{num} %\end{definition} % Sets \meta{cmd} = sqrt(\meta{num}) % \begin{macrocode} \newcommand*{\DTLsqrt}[2]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FProot{\@dtl@tmpi}{\@dtl@numi}{2}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmpi}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmpi}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgsqrt} % Global version % \begin{macrocode} \newcommand*{\DTLgsqrt}[2]{% \DTLsqrt{\@dtl@tmpii}{#2}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmin} %\begin{definition} % \cs{DTLmin}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = min(\meta{num1}, \meta{num2}) % \begin{macrocode} \newcommand*{\DTLmin}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \DTLconverttodecimal{#3}{\@dtl@numii}% \FPiflt{\@dtl@numi}{\@dtl@numii}% \dtl@ifsingle{#2}{% \let#1=#2}{% \def#1{#2}}% \else \dtl@ifsingle{#3}{% \let#1=#3}{% \def#1{#3}}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgmin} % Global version % \begin{macrocode} \newcommand*{\DTLgmin}[3]{% \DTLmin{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLminall} %\begin{definition} %\cs{DTLminall}\marg{cmd}\marg{num list} %\end{definition} % Finds the minimum value in \meta{num list} and stores in % \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLminall}[2]{% \let\@dtl@min=\@empty \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \ifx\@dtl@min\@empty \let\@dtl@min=\@dtl@num \else \FPmin{\@dtl@min}{\@dtl@min}{\@dtl@num}% \fi }% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@min}{#1}% \else \DTLdecimaltocurrency{\@dtl@min}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgminall} %\begin{definition} %\cs{DTLgminall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgminall}[2]{% \DTLminall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmax} %\begin{definition} % \cs{DTLmax}\marg{cmd}\marg{num1}\marg{num2} %\end{definition} % Sets \meta{cmd} = max(\meta{num1}, \meta{num2}) % \begin{macrocode} \newcommand*{\DTLmax}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \DTLconverttodecimal{#3}{\@dtl@numii}% \FPmax{\@dtl@tmp}{\@dtl@numi}{\@dtl@numii}% \FPifgt{\@dtl@numi}{\@dtl@numii}% \dtl@ifsingle{#2}{% \let#1=#2}{% \def#1{#2}}% \else \dtl@ifsingle{#3}{% \let#1=#3}{% \def#1{#3}}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgmax} % Global version % \begin{macrocode} \newcommand*{\DTLgmax}[3]{% \DTLmax{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmaxall} %\begin{definition} %\cs{DTLmaxall}\marg{cmd}\marg{num list} %\end{definition} % Finds the maximum value in \meta{num list} and stores in % \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLmaxall}[2]{% \let\@dtl@max=\@empty \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \ifx\@dtl@max\@empty \let\@dtl@max\@dtl@num \else \FPmax{\@dtl@max}{\@dtl@max}{\@dtl@num}% \fi }% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@max}{#1}% \else \DTLdecimaltocurrency{\@dtl@max}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgmaxall} %\begin{definition} %\cs{DTLgmaxall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgmaxall}[2]{% \DTLmaxall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmeanforall} %\begin{definition} %\cs{DTLmeanforall}\marg{cmd}\marg{num list} %\end{definition} % Computes the arithmetic mean of all the values in \meta{num list} % and stores in \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLmeanforall}[2]{% \def\@dtl@mean{0}% \def\@dtl@n{0}% \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% \FPadd{\@dtl@n}{\@dtl@n}{1}% }% \FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@mean}{#1}% \else \DTLdecimaltocurrency{\@dtl@mean}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgmeanforall} %\begin{definition} %\cs{DTLgmeanforall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgmeanforall}[2]{% \DTLmeanforall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLvarianceforall} %\begin{definition} %\cs{DTLvarianceforall}\marg{cmd}\marg{num list} %\end{definition} % Computes the variance of all the values in \meta{num list} % and stores in \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{fixed bug} %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLvarianceforall}[2]{% \def\@dtl@mean{0}% \def\@dtl@n{0}% \let\@dtl@decvals=\@empty \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \ifx\@dtl@decvals\@empty \let\@dtl@decvals=\@dtl@num \else \expandafter\toks@\expandafter{\@dtl@decvals}% \edef\@dtl@decvals{\the\toks@,\@dtl@num}% \fi \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% \FPadd{\@dtl@n}{\@dtl@n}{1}% }% \FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% \def\@dtl@var{0}% \@for\@dtl@num:=\@dtl@decvals\do{% \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% \FPadd{\@dtl@var}{\@dtl@var}{\@dtl@diff}% }% \FPdiv{\@dtl@var}{\@dtl@var}{\@dtl@n}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@var}{#1}% \else \DTLdecimaltocurrency{\@dtl@var}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgvarianceforall} %\begin{definition} %\cs{DTLgvarianceforall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgvarianceforall}[2]{% \DTLvarianceforall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsdforall} %\begin{definition} %\cs{DTLsdforall}\marg{cmd}\marg{num list} %\end{definition} % Computes the standard deviation of all the values in \meta{num list} % and stores in \meta{cmd} which must be a control sequence. %\changes{1.01}{2007 Aug 17}{fixed bug} %\changes{1.01}{2007 Aug 17}{removed extraneous space} % \begin{macrocode} \newcommand*{\DTLsdforall}[2]{% \def\@dtl@mean{0}% \def\@dtl@n{0}% \let\@dtl@decvals=\@empty \@for\dtl@thisval:=#2\do{% \DTLconverttodecimal{\dtl@thisval}{\@dtl@num}% \ifx\@dtl@decvals\@empty \let\@dtl@decvals=\@dtl@num \else \expandafter\toks@\expandafter{\@dtl@decvals}% \edef\@dtl@decvals{\the\toks@,\@dtl@num}% \fi \FPadd{\@dtl@mean}{\@dtl@mean}{\@dtl@num}% \FPadd{\@dtl@n}{\@dtl@n}{1}% }% \FPdiv{\@dtl@mean}{\@dtl@mean}{\@dtl@n}% \def\@dtl@sd{0}% \@for\@dtl@num:=\@dtl@decvals\do{% \FPsub{\@dtl@diff}{\@dtl@num}{\@dtl@mean}% \FPmul{\@dtl@diff}{\@dtl@diff}{\@dtl@diff}% \FPadd{\@dtl@sd}{\@dtl@sd}{\@dtl@diff}% }% \FPdiv{\@dtl@sd}{\@dtl@sd}{\@dtl@n}% \FProot{\@dtl@sd}{\@dtl@sd}{2}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@sd}{#1}% \else \DTLdecimaltocurrency{\@dtl@sd}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgsdforall} %\begin{definition} %\cs{DTLgsdforall}\marg{cmd}\marg{num list} %\end{definition} % Global version % \begin{macrocode} \newcommand*{\DTLgsdforall}[2]{% \DTLsdforall{\@dtl@tmpi}{#2}% \global\let#1=\@dtl@tmpi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLround} %\begin{definition} % \cs{DTLround}\marg{cmd}\marg{num}\marg{num digits} %\end{definition} % Sets \meta{cmd} to \meta{num} rounded to \meta{num digits} % digits after the decimal character. % \begin{macrocode} \newcommand*{\DTLround}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FPround{\@dtl@tmp}{\@dtl@numi}{#3}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLground} % Global version % \begin{macrocode} \newcommand*{\DTLground}[3]{% \DTLround{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtrunc} %\begin{definition} % \cs{DTLtrunc}\marg{cmd}\marg{num}\marg{num digits} %\end{definition} % Sets \meta{cmd} to \meta{num} truncated to \meta{num digits} % digits after the decimal character. % \begin{macrocode} \newcommand*{\DTLtrunc}[3]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FPtrunc{\@dtl@tmp}{\@dtl@numi}{#3}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgtrunc} % Global version % \begin{macrocode} \newcommand*{\DTLgtrunc}[3]{% \DTLtrunc{\@dtl@tmpii}{#2}{#3}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLclip} %\begin{definition} % \cs{DTLclip}\marg{cmd}\marg{num} %\end{definition} % Sets \meta{cmd} to \meta{num} with all unnecessary 0's removed. % \begin{macrocode} \newcommand*{\DTLclip}[2]{% \DTLconverttodecimal{#2}{\@dtl@numi}% \FPclip{\@dtl@tmp}{\@dtl@numi}% \ifx\@dtl@replaced\@empty \DTLdecimaltolocale{\@dtl@tmp}{#1}% \else \DTLdecimaltocurrency{\@dtl@tmp}{#1}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLgclip} % Global version % \begin{macrocode} \newcommand*{\DTLgclip}[3]{% \DTLclip{\@dtl@tmpii}{#2}% \global\let#1=\@dtl@tmpii } % \end{macrocode} %\end{macro} % %\subsection{String Macros} %\begin{macro}{\DTLinitials} %\begin{definition} %\cs{DTLinitials}\marg{string} %\end{definition} % Convert a string into initials. % (Any "~" character found is first converted into a space.) %\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} %\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} % \begin{macrocode} \newcommand*\DTLinitials[1]{% \def\dtl@initialscmd{}% \dtl@subnobrsp{#1}{\dtl@string}% \DTLsubstituteall{\dtl@string}{~}{ }% \DTLsubstituteall{\dtl@string}{\ }{ }% \DTLsubstituteall{\dtl@string}{\space}{ }% \expandafter\dtl@initials\dtl@string{} \@nil% \dtl@initialscmd}% % \end{macrocode} %\end{macro} % The following substitutes "\protect \nobreakspace {}" with % a space. (Note that in this case the space following % "\nobreakspace" forms part of the command.) % \begin{macrocode} \edef\dtl@construct@subnobrsp{% \noexpand\def\noexpand\@dtl@subnobrsp##1\noexpand\protect \expandafter\noexpand\csname nobreakspace \endcsname ##2{% \noexpand\toks@{##1}% \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% \noexpand\@dtl@string}% \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks \noexpand\the\noexpand\toks@}% \noexpand\def\noexpand\@dtl@tmp{##2}% \noexpand\ifx\noexpand\@dtl@tmp\noexpand\@nnil \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\relax \noexpand\else \noexpand\toks@{ }% \noexpand\expandafter\noexpand\@dtl@toks\noexpand\expandafter{% \noexpand\@dtl@string}% \noexpand\edef\noexpand\@dtl@string{\noexpand\the\noexpand\@dtl@toks \noexpand\the\noexpand\toks@}% \noexpand\let\noexpand\@dtl@subnobrspnext=\noexpand\@dtl@subnobrsp \noexpand\fi \noexpand\@dtl@subnobrspnext }% \noexpand\def\noexpand\dtl@subnobrsp##1##2{% \noexpand\def\noexpand\@dtl@string{}% \noexpand\@dtl@subnobrsp ##1\noexpand\protect\expandafter\noexpand \csname nobreakspace \endcsname \noexpand\@nil \noexpand\let##2=\noexpand\@dtl@string }} \dtl@construct@subnobrsp % \end{macrocode} % %\begin{macro}{\DTLstoreinitials} %\begin{definition} %\cs{DTLstoreinitials}\marg{string}\marg{cmd} %\end{definition} % Convert a string into initials and store in \meta{cmd}. % (Any "~" character found is first converted into a space.) %\changes{1.01}{2007 Aug 17}{now works with unbreakable space symbol} %\changes{1.01}{2007 Aug 17}{now uses \cs{DTLinitialhyphen}} % \begin{macrocode} \newcommand*{\DTLstoreinitials}[2]{% \def\dtl@initialscmd{}% \dtl@subnobrsp{#1}{\dtl@string}% \DTLsubstituteall{\dtl@string}{~}{ }% \DTLsubstituteall{\dtl@string}{\ }{ }% \DTLsubstituteall{\dtl@string}{\space}{ }% \expandafter\dtl@initials\dtl@string{} \@nil \let#2=\dtl@initialscmd } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@initials} % \begin{macrocode} \def\dtl@initials#1#2 #3{% \dtl@ifsingle{#1}{% \ifcat\noexpand#1\relax\relax \def\@dtl@donextinitials{\@dtl@initials#2 {#3}}% \else \def\@dtl@donextinitials{\@dtl@initials#1#2 {#3}}% \fi }{% \def\@dtl@donextinitials{\@dtl@initials{#1}#2 {#3}}% }% \@dtl@donextinitials } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@initials} % \begin{macrocode} \def\@dtl@initials#1#2 #3{% \dtl@initialshyphen#2-{}\dtl@endhyp \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% \toks@{#1}% \ifx\dtl@inithyphen\@empty \else \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@}% \expandafter\@dtl@toks\expandafter{\dtl@initialscmd}% \expandafter\toks@\expandafter{\dtl@inithyphen}% \fi \def\dtl@tmp{#3}% \ifx\@nnil\dtl@tmp \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLafterinitials}% \let\dtl@initialsnext=\@gobble \else \edef\dtl@initialscmd{\the\@dtl@toks\the\toks@\DTLbetweeninitials}% \let\dtl@initialsnext=\dtl@initials \fi \dtl@initialsnext{#3}} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@initialshyphen} % \begin{macrocode} \def\dtl@initialshyphen#1-#2#3\dtl@endhyp{% \def\dtl@inithyphen{#2}% \ifx\dtl@inithyphen\@empty \else \edef\dtl@inithyphen{% \DTLafterinitialbeforehyphen\DTLinitialhyphen#2}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLafterinitials} % Defines what to do after the final initial. % \begin{macrocode} \newcommand*{\DTLafterinitials}{.} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLbetweeninitials} % Defines what to do between initials. % \begin{macrocode} \newcommand*{\DTLbetweeninitials}{.} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLafterinitialbeforehyphen} % Defines what to do before a hyphen. % \begin{macrocode} \newcommand*{\DTLafterinitialbeforehyphen}{.} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLinitialhyphen} %Defines what to do at the hyphen %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLinitialhyphen}{-} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifAllUpperCase} %\begin{definition} %\cs{DTLifAllUpperCase}\marg{string}\marg{true part}\marg{false part} %\end{definition} % If \meta{string} only contains uppercase characters do \meta{true %part}, otherwise do \meta{false part}. % \begin{macrocode} \newcommand*{\DTLifAllUpperCase}[3]{% \protected@edef\dtl@tuc{#1}% \expandafter\dtl@testifuppercase\dtl@tuc\@nil\relax \if@dtl@condition#2\else#3\fi } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testifalluppercase} % \begin{macrocode} \def\dtl@testifuppercase#1#2{% \def\dtl@argi{#1}% \def\dtl@argii{#2}% \def\dtl@tc@rest{}% \ifx\dtl@argi\@nnil \let\dtl@testifuppernext=\@nnil \else \ifx#1\protect \let\dtl@testifuppernext=\dtl@testifuppercase \else \ifx\uppercase#1\relax \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testifuppernext=\relax \else \edef\dtl@tc@arg{\string#1}% \expandafter\dtl@test@ifuppercase\dtl@tc@arg\end \ifx\dtl@argii\@nnil \let\dtl@testifuppernext=\@dtl@gobbletonil \fi \fi \fi \fi \ifx\dtl@testifuppernext\relax \edef\dtl@dotestifuppernext{% \noexpand\dtl@testifuppercase}% \else \ifx\dtl@testifuppernext\@nnil \edef\dtl@dotestifuppernext{#2}% \else \expandafter\toks@\expandafter{\dtl@tc@rest}% \@dtl@toks{#2}% \edef\dtl@dotestifuppernext{% \noexpand\dtl@testifuppernext\the\toks@\the\@dtl@toks}% \fi \fi \dtl@dotestifuppernext } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@test@ifalluppercase} % \begin{macrocode} \def\dtl@test@ifuppercase#1#2\end{% \def\dtl@tc@rest{#2}% \IfSubStringInString{\string\MakeUppercase}{#1#2}{% \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testifuppernext=\relax }{% \IfSubStringInString{\string\MakeTextUppercase}{#1#2}{% \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testifuppernext=\relax }{% \edef\dtl@uccode{\the\uccode`#1}% \edef\dtl@code{\number`#1}% \ifnum\dtl@code=\dtl@uccode\relax \@dtl@conditiontrue \let\dtl@testifuppernext=\dtl@testifuppercase \else \ifnum\dtl@uccode=0\relax \@dtl@conditiontrue \let\dtl@testifuppernext=\dtl@testifuppercase \else \@dtl@conditionfalse \let\dtl@testifuppernext=\@dtl@gobbletonil \fi \fi }}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLifAllLowerCase} %\begin{definition} %\cs{DTLifAllLowerCase}\marg{string}\marg{true part}\marg{false part} %\end{definition} % If \meta{string} only contains lowercase characters do \meta{true %part}, otherwise do \meta{false part}. % \begin{macrocode} \newcommand*{\DTLifAllLowerCase}[3]{% \protected@edef\dtl@tlc{#1}% \expandafter\dtl@testiflowercase\dtl@tlc\@nil\relax \if@dtl@condition#2\else#3\fi } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testifalllowercase} % \begin{macrocode} \def\dtl@testiflowercase#1#2{% \def\dtl@argi{#1}% \def\dtl@argii{#2}% \ifx\dtl@argi\@nnil \let\dtl@testiflowernext=\@nnil \else \ifx#1\protect \let\dtl@testiflowernext=\dtl@testiflowercase \else \ifx\lowercase#1\relax \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testiflowernext=\relax \else \edef\dtl@tc@arg{\string#1}% \expandafter\dtl@test@iflowercase\dtl@tc@arg\end \ifx\dtl@argii\@nnil \let\dtl@testiflowernext=\@dtl@gobbletonil \fi \fi \fi \fi \ifx\dtl@testiflowernext\relax \edef\dtl@dotestiflowernext{% \noexpand\dtl@testiflowercase}% \else \ifx\dtl@testiflowernext\@nnil \edef\dtl@dotestiflowernext{#2}% \else \expandafter\toks@\expandafter{\dtl@tc@rest}% \@dtl@toks{#2}% \edef\dtl@dotestiflowernext{% \noexpand\dtl@testiflowernext\the\toks@\the\@dtl@toks}% \fi \fi \dtl@dotestiflowernext } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@test@ifalllowercase} % \begin{macrocode} \def\dtl@test@iflowercase#1#2\end{% \def\dtl@tc@rest{#2}% \IfSubStringInString{\string\MakeLowercase}{#1#2}{% \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testiflowernext=\relax }{% \IfSubStringInString{\string\MakeTextLowercase}{#1#2}{% \@dtl@conditiontrue \def\dtl@tc@rest{}% \let\dtl@testiflowernext=\relax }{% \edef\dtl@lccode{\the\lccode`#1}% \edef\dtl@code{\number`#1}% \ifnum\dtl@code=\dtl@lccode\relax \@dtl@conditiontrue \let\dtl@testiflowernext=\dtl@testiflowercase \else \ifnum\dtl@lccode=0\relax \@dtl@conditiontrue \let\dtl@testiflowernext=\dtl@testiflowercase \else \@dtl@conditionfalse \let\dtl@testiflowernext=\@dtl@gobbletonil \fi \fi }}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsubstitute} %\begin{definition} %\cs{DTLsubstitute}\marg{cmd}\marg{original}\marg{replacement} %\end{definition} % Substitutes first occurence of \meta{original} with % \marg{replacement} within the string given by \meta{cmd} % \begin{macrocode} \newcommand{\DTLsubstitute}[3]{% \expandafter\DTLsplitstring\expandafter {#1}{#2}{\@dtl@beforepart}{\@dtl@afterpart}% \ifx\@dtl@replaced\@empty \else \def#1{}% \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% \expandafter\toks@\expandafter{#1}% \protected@edef#1{\the\toks@\the\@dtl@toks#3}% \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% \expandafter\toks@\expandafter{#1}% \edef#1{\the\toks@\the\@dtl@toks}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsplitstring} %\begin{definition} %\cs{DTLsplitstring}\marg{string}\marg{split text}\marg{before %cmd}\marg{after cmd} %\end{definition} % Splits string at \meta{split text} stores the pre split text % in \meta{before cmd} and the post split text in \meta{after cmd}. %\changes{1.01}{2007 Aug 17}{new} % \begin{macrocode} \newcommand*{\DTLsplitstring}[4]{% \def\dtl@splitstr##1#2##2\@nil{% \def#3{##1}% \def#4{##2}% \ifx#4\@empty \let\@dtl@replaced=\@empty \else \def\@dtl@replaced{#2}% \dtl@split@str##2\@nil \fi }% \def\dtl@split@str##1#2\@nil{% \def#4{##1}}% \dtl@splitstr#1#2\@nil } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsubstituteall} %\begin{definition} %\cs{DTLsubstituteall}\marg{cmd}\marg{original}\marg{replacement} %\end{definition} % Substitutes all occurences of \meta{original} with % \marg{replacement} within the string given by \meta{cmd} %\changes{1.01}{2007 Aug 17}{fixed bug caused when certain commands % occur in the string} % \begin{macrocode} \newcommand{\DTLsubstituteall}[3]{% \def\@dtl@splitsubstr{}% \let\@dtl@afterpart=#1\relax \@dtl@dosubstitute{#2}{#3}% \expandafter\toks@\expandafter{\@dtl@splitsubstr}% \expandafter\@dtl@toks\expandafter{\@dtl@afterpart}% \edef#1{\the\toks@\the\@dtl@toks}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@dosubstitute} % Recursive substitution macro. % \begin{macrocode} \def\@dtl@dosubstitute#1#2{% \expandafter\DTLsplitstring\expandafter {\@dtl@afterpart}{#1}{\@dtl@beforepart}{\@dtl@afterpart}% \expandafter\toks@\expandafter{\@dtl@splitsubstr}% \expandafter\@dtl@toks\expandafter{\@dtl@beforepart}% \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% \ifx\@dtl@replaced\@empty \let\@dtl@dosubstnext=\@dtl@dosubstitutenoop \else \expandafter\toks@\expandafter{\@dtl@splitsubstr}% \@dtl@toks{#2}% \edef\@dtl@splitsubstr{\the\toks@\the\@dtl@toks}% \let\@dtl@dosubstnext=\@dtl@dosubstitute \fi \@dtl@dosubstnext{#1}{#2}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@dosubstitutenoop} % Terminates recursive substitution macro. % \begin{macrocode} \def\@dtl@dosubstitutenoop#1#2{} % \end{macrocode} %\end{macro} % %\subsection{Currencies} %\begin{macro}{\@dtl@currencies} % \cs{@dtl@currencies} stores all known currencies. % \begin{macrocode} \newcommand*{\@dtl@currencies}{\$,\pounds} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLnewcurrencysymbol} %\begin{definition} % \cs{DTLaddcurrency}\marg{symbol} %\end{definition} % Adds \meta{symbol} to the list of known currencies % \begin{macrocode} \newcommand*{\DTLnewcurrencysymbol}[1]{% \expandafter\toks@\expandafter{\@dtl@currencies}% \@dtl@toks{#1}% \edef\@dtl@currencies{\the\@dtl@toks,\the\toks@}% } % \end{macrocode} %\end{macro} % If any of the following currency commands have been defined, % add them to the list: % \begin{macrocode} \AtBeginDocument{% \@ifundefined{texteuro}{}{\DTLnewcurrencysymbol{\texteuro}}% \@ifundefined{textdollar}{}{\DTLnewcurrencysymbol{\textdollar}}% \@ifundefined{textstirling}{}{\DTLnewcurrencysymbol{\textstirling}}% \@ifundefined{textyen}{}{\DTLnewcurrencysymbol{\textyen}}% \@ifundefined{textwon}{}{\DTLnewcurrencysymbol{\textwon}}% \@ifundefined{textcurrency}{}{\DTLnewcurrencysymbol{\textcurrency}}% \@ifundefined{euro}{}{\DTLnewcurrencysymbol{\euro}}% \@ifundefined{yen}{}{\DTLnewcurrencysymbol{\yen}}% } % \end{macrocode} %\begin{macro}{\@dtl@standardize@currency} %\begin{definition} %\cs{@dtl@standardize@currency}\marg{cmd} %\end{definition} % Substitutes the first currency symbol found in \meta{cmd} % with "\$". This is used when testing text to determine % if it is currency. The original currency symbol is stored % in \cs{@dtl@org@currency}, so that it can be replaced later. % If no currency symbol is found, \cs{@dtl@org@currency} will % be empty. % \begin{macrocode} \newcommand{\@dtl@standardize@currency}[1]{% \def\@dtl@org@currency{}% \@for\@dtl@thiscurrency:=\@dtl@currencies\do{% \expandafter\toks@\expandafter{\@dtl@thiscurrency}% \edef\@dtl@dosubs{\noexpand\DTLsubstitute{\noexpand#1}% {\the\toks@}{\noexpand\$}}% \@dtl@dosubs \ifx\@dtl@replaced\@empty \else \let\@dtl@org@currency=\@dtl@replaced \@endfortrue \fi }% \@endforfalse} % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@currency} %\cs{@dtl@currency} is set by \cs{DTLlocaltodecimal} and %\cs{@dtl@checknumerical}. It is used by \cs{DTLdecimaltocurrency}. % Set to "\$" by default. % \begin{macrocode} \newcommand*{\@dtl@currency}{\$} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLsetdefaultcurrency} %\cs{DTLsetdefaultcurrency}\marg{symbol} sets the default currency. % \begin{macrocode} \newcommand*{\DTLsetdefaultcurrency}[1]{% \renewcommand*{\@dtl@currency}{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@ifsingle} %\begin{definition} %\cs{dtl@ifsingle}\marg{arg}\marg{true part}\marg{false part} %\end{definition} % If there is only one object in \meta{arg} (without expansion) % do \meta{true part}, otherwise do false part. % \begin{macrocode} \newcommand{\dtl@ifsingle}[3]{% \def\@dtl@arg{#1}% \ifx\@dtl@arg\@empty #3% \else \@dtl@ifsingle#1\@nil{#2}{#3}% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\@dtl@ifsingle} % \begin{macrocode} \def\@dtl@ifsingle#1#2\@nil#3#4{% \def\dtl@sg@arg{#2}% \ifx\dtl@sg@arg\@empty #3% \else #4% \fi } % \end{macrocode} %\end{macro} % %\subsection{Debugging commands} % These commands are provided to assist debugging %\begin{macro}{\dtlshowdb} %\begin{definition} %\cs{dtlshowdb}\marg{db name} %\end{definition} % Shows the database. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\dtlshowdb}[1]{% \expandafter\showthe\csname dtldb@#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlshowdbkeys} %\begin{definition} %\cs{dtlshowdbkeys}\marg{db name} %\end{definition} % Shows the key list for the named database. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\dtlshowdbkeys}[1]{% \expandafter\showthe\csname dtlkeys@#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlshowtype} %\begin{definition} %\cs{dtlshowtype}\marg{db name}\marg{key} %\end{definition} % Show the data type for given key in the named database. % This should be an integer from 0 to 3. %\changes{2.0}{2009 February 27}{updated to use new database structure} % \begin{macrocode} \newcommand*{\dtlshowtype}[2]{% \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type } % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*datapie.sty> % \end{macrocode} %\fi %\section{datapie.sty} % Declare package: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{datapie}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} % Require \sty{xkeyval} package % \begin{macrocode} \RequirePackage{xkeyval} % \end{macrocode} %\begin{macro}{\ifDTLcolorpiechart} % The conditional \cs{ifDTLcolorpiechart} is to determine % whether to use colour or grey scale. % \begin{macrocode} \newif\ifDTLcolorpiechart \DTLcolorpiecharttrue % \end{macrocode} %\end{macro} % Package options to change the conditional: % \begin{macrocode} \DeclareOption{color}{\DTLcolorpiecharttrue} \DeclareOption{gray}{\DTLcolorpiechartfalse} % \end{macrocode} %\begin{macro}{\ifDTLrotateinner} % Define boolean keys to govern label rotations. % \begin{macrocode} \define@boolkey{datapie}[DTL]{rotateinner}[true]{} % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLrotateouter} % \begin{macrocode} \define@boolkey{datapie}[DTL]{rotateouter}[true]{} % \end{macrocode} %\end{macro} % Set defaults: % \begin{macrocode} \DTLrotateinnerfalse \DTLrotateouterfalse % \end{macrocode} % Package options to change \cs{DTLrotateinner} % \begin{macrocode} \DeclareOption{rotateinner}{\DTLrotateinnertrue} \DeclareOption{norotateinner}{\DTLrotateinnerfalse} % \end{macrocode} % Package options to change \cs{DTLrotateouter} % \begin{macrocode} \DeclareOption{rotateouter}{\DTLrotateoutertrue} \DeclareOption{norotateouter}{\DTLrotateouterfalse} % \end{macrocode} % Process options: % \begin{macrocode} \ProcessOptions % \end{macrocode} % Required packages: % \begin{macrocode} \RequirePackage{datatool} \RequirePackage{tikz} % \end{macrocode} % Define some variables that govern the appearance of the pie % chart. % %\begin{macro}{\DTLradius} % The radius of the pie chart is given by \cs{DTLradius}. % \begin{macrocode} \newlength\DTLradius \DTLradius=2cm % \end{macrocode} %\end{macro} %\begin{macro}{\DTLinnerratio} % The inner label offset ratio is given by \cs{DTLinnerratio} % \begin{macrocode} \newcommand*{\DTLinnerratio}{0.5} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLouterratio} % The outer label offset ratio is given by \cs{DTLouterratio}. % \begin{macrocode} \newcommand*{\DTLouterratio}{1.25} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLcutawayratio} % The cutaway offset ratio is given by \cs{DTLcutawayratio}. % \begin{macrocode} \newcommand*\DTLcutawayratio{0.2} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLstartangle} % The angle of the first segment is given by \cs{DTLstartangle}. % \begin{macrocode} \newcommand*{\DTLstartangle}{0} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@inneroffset} % \begin{macrocode} \newlength\dtl@inneroffset \dtl@inneroffset=\DTLinnerratio\DTLradius % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@outeroffset} % \begin{macrocode} \newlength\dtl@outeroffset \dtl@outeroffset=\DTLouterratio\DTLradius % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@cutawayoffset} % \begin{macrocode} \newlength\dtl@cutawayoffset \dtl@cutawayoffset=\DTLcutawayratio\DTLradius % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@piecutaways} % \cs{dtl@piecutaways} is a comma separated list of segments that % need to be cut away from the pie chart. % \begin{macrocode} \newcommand*{\dtl@piecutaways}{} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@innerlabel} % \cs{dtl@innerlabel} specifies the label to appear inside % the segment. By default this is the variable used to create % the pie chart. % \begin{macrocode} \def\dtl@innerlabel{\DTLpievariable}% % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@outerlabel} % \begin{macrocode} \def\dtl@outerlabel{}% % \end{macrocode} %\end{macro} %\begin{counter}{DTLpieroundvar} % \ctrfmt{DTLpieroundvar} is a counter governing the number of digits % to round to when using \cs{FPround}. % \begin{macrocode} \newcounter{DTLpieroundvar} \setcounter{DTLpieroundvar}{1} % \end{macrocode} %\end{counter} % %\begin{macro}{\DTLdisplayinnerlabel} %\begin{definition} %\cs{DTLdisplayinnerlabel}\marg{label} %\end{definition} % This is used to format the inner label. This just does the % label by default. % \begin{macrocode} \newcommand*{\DTLdisplayinnerlabel}[1]{#1} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdisplayouterlabel} %\begin{definition} %\cs{DTLdisplayouterlabel}\marg{label} %\end{definition} % This is used to format the outer label. This just does the % label by default. % \begin{macrocode} \newcommand*{\DTLdisplayouterlabel}[1]{#1} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLpiepercent} %\cs{DTLpiepercent} % returns the percentage value of the current segment. % \begin{macrocode} \newcommand*{\DTLpiepercent}{% \ifnum\dtlforeachlevel=0\relax \PackageError{datapie}{Can't use \string\DTLpiepercent\space outside \string\DTLpiechart}{}% \else \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname \fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLpieatbegintikz} % \cs{DTLpieatbegintikz} specifies any commands % to apply at the start of the \env{tikzpicture} environment. % By default it does nothing. % \begin{macrocode} \newcommand*{\DTLpieatbegintikz}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLpieatendtikz} % \cs{DTLpieatendtikz} specifies any commands % to apply at the end of the \env{tikzpicture} environment. % By default it does nothing. % \begin{macrocode} \newcommand*{\DTLpieatendtikz}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsetpiesegmentcolor} %\begin{definition} % \cs{DTLsetpiesegmentcolor}\marg{n}\marg{color} %\end{definition} % Assign colour name \meta{color} to the \meta{n}th segment. % \begin{macrocode} \newcommand*{\DTLsetpiesegmentcolor}[2]{% \expandafter\def\csname dtlpie@segcol\romannumeral#1\endcsname{#2}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetpiesegmentcolor} %\begin{definition} %\cs{DTLgetpiesegmentcolor}\marg{n} %\end{definition} % Get the colour specification for segment \meta{n} % \begin{macrocode} \newcommand*{\DTLgetpiesegmentcolor}[1]{% \csname dtlpie@segcol\romannumeral#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdopiesegmentcolor} %\begin{definition} %\cs{DTLdopiesegmentcolor}\marg{n} %\end{definition} % Set the colour to that for segment \meta{n} % \begin{macrocode} \newcommand*{\DTLdopiesegmentcolor}[1]{% \expandafter\color\expandafter {\csname dtlpie@segcol\romannumeral#1\endcsname}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdocurrentpiesegmentcolor} %\cs{DTLdocurrentpiesegmentcolor} % sets the colour to that of the current segment. % \begin{macrocode} \newcommand*{\DTLdocurrentpiesegmentcolor}{% \ifnum\dtlforeachlevel=0\relax \PackageError{datapie}{Can't use \string\DTLdocurrentpiesegmentcolor\space outside \string\DTLpiechart}{}% \else \expandafter\DTLdopiesegmentcolor\expandafter{% \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}% \fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLpieoutlinecolor} %\cs{DTLpieoutlinecolor} specifies what colour to draw the % outline. % \begin{macrocode} \newcommand*{\DTLpieoutlinecolor}{black} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLpieoutlinewidth} %\cs{DTLpieoutlinewidth} specifies the line width of the outline: % Outline is only drawn if the linewidth is greater than 0pt. % \begin{macrocode} \newlength\DTLpieoutlinewidth \DTLpieoutlinewidth=0pt % \end{macrocode} %\end{macro} % % Set the default colours. If there are more than eight segments, % more colours will need to be defined. % \begin{macrocode} \ifDTLcolorpiechart \DTLsetpiesegmentcolor{1}{red} \DTLsetpiesegmentcolor{2}{green} \DTLsetpiesegmentcolor{3}{blue} \DTLsetpiesegmentcolor{4}{yellow} \DTLsetpiesegmentcolor{5}{magenta} \DTLsetpiesegmentcolor{6}{cyan} \DTLsetpiesegmentcolor{7}{orange} \DTLsetpiesegmentcolor{8}{white} \else \DTLsetpiesegmentcolor{1}{black!15} \DTLsetpiesegmentcolor{2}{black!25} \DTLsetpiesegmentcolor{3}{black!35} \DTLsetpiesegmentcolor{4}{black!45} \DTLsetpiesegmentcolor{5}{black!55} \DTLsetpiesegmentcolor{6}{black!65} \DTLsetpiesegmentcolor{7}{black!75} \DTLsetpiesegmentcolor{8}{black!85} \fi % \end{macrocode} % Define keys for \cs{DTLpiechart} optional argument. % Set the starting angle of the first segment. % \begin{macrocode} \define@key{datapie}{start}{\def\DTLstartangle{#1}} % \end{macrocode} % Set the radius of the pie chart (must be set prior to % inneroffset and outeroffset keys.) % \begin{macrocode} \define@key{datapie}{radius}{\DTLradius=#1\relax \dtl@inneroffset=\DTLinnerratio\DTLradius \dtl@outeroffset=\DTLouterratio\DTLradius \dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} % Set the inner ratio. % \begin{macrocode} \define@key{datapie}{innerratio}{% \def\DTLinnerratio{#1}% \dtl@inneroffset=\DTLinnerratio\DTLradius} % \end{macrocode} % Set the outer ratio % \begin{macrocode} \define@key{datapie}{outerratio}{% \def\DTLouterratio{#1}% \dtl@outeroffset=\DTLouterratio\DTLradius} % \end{macrocode} % The cutaway offset ratio % \begin{macrocode} \define@key{datapie}{cutawayratio}{% \def\DTLcutawayratio{#1}% \dtl@cutawayoffset=\DTLcutawayratio\DTLradius} % \end{macrocode} % Set the inner offset as an absolute value (not dependent % on the radius.) % \begin{macrocode} \define@key{datapie}{inneroffset}{% \dtl@inneroffset=#1} % \end{macrocode} % Set the outer offset as an absolute value (not dependent % on the radius.) % \begin{macrocode} \define@key{datapie}{outeroffset}{% \dtl@outeroffset=#1} % \end{macrocode} % Set the cutaway offset as an absolute value (not dependent % on the radius.) % \begin{macrocode} \define@key{datapie}{cutawayoffset}{% \dtl@cutawayoffset=#1} % \end{macrocode} % List of cut away segments. % \begin{macrocode} \define@key{datapie}{cutaway}{% \renewcommand*{\dtl@piecutaways}{#1}} % \end{macrocode} % Variable used to create the pie chart. (Must be a control % sequence.) % \begin{macrocode} \define@key{datapie}{variable}{% \def\DTLpievariable{#1}} % \end{macrocode} % Inner label % \begin{macrocode} \define@key{datapie}{innerlabel}{% \def\dtl@innerlabel{#1}} % \end{macrocode} % Outer label % \begin{macrocode} \define@key{datapie}{outerlabel}{% \def\dtl@outerlabel{#1}} % \end{macrocode} % %\begin{macro}{\DTLpiechart} %\begin{definition} % \cs{DTLpiechart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} %\end{definition} % Make a pie chart from data given in data base \meta{db name}, % where \meta{assign list} is a comma-separated list of % \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must % include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} % is included in \meta{assign list}. The optional argument % \meta{conditions} is the same as that for \cs{DTLforeach}. % \begin{macrocode} \newcommand*{\DTLpiechart}[4][\boolean{true}]{% {\let\DTLpievariable=\relax \setkeys{datapie}{#2}% \ifx\DTLpievariable\relax \PackageError{datapie}{\string\DTLpiechart\space missing variable}{}% \else % \end{macrocode} % Compute the total. %\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of %\cs{DTLforeach}} % \begin{macrocode} \def\dtl@total{0}% \@sDTLforeach[#1]{#3}{#4}{% \let\dtl@oldtotal=\dtl@total \expandafter\DTLconverttodecimal\expandafter {\DTLpievariable}{\dtl@variable}% \FPadd{\dtl@total}{\dtl@variable}{\dtl@total}% }% % \end{macrocode} % Compute the angles % \begin{macrocode} \expandafter\DTLconverttodecimal\expandafter {\DTLstartangle}{\@dtl@start}% \@sDTLforeach[#1]{#3}{#4}{% \expandafter\DTLconverttodecimal\expandafter {\DTLpievariable}{\dtl@variable}% \dtl@computeangles{% \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}{% \dtl@variable}% \expandafter\@dtl@seg\expandafter= \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% \FPmul{\dtl@tmp}{\dtl@variable}{100}% \let\dtl@old=\dtl@tmp \FPdiv{\dtl@tmp}{\dtl@old}{\dtl@total}% \expandafter\FPround \csname dtl@piepercent@\romannumeral\@dtl@seg\endcsname\dtl@tmp \c@DTLpieroundvar }% % \end{macrocode} % Compute the offsets for each cut away segment % \begin{macrocode} \@for\dtl@row:=\dtl@piecutaways\do{% \expandafter\@dtl@set@off\dtl@row-\relax }% % \end{macrocode} % Set the starting angle % \begin{macrocode} \let\dtl@start=\DTLstartangle % \end{macrocode} % Do the pie chart % \begin{macrocode} \begin{tikzpicture} \DTLpieatbegintikz \@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} % Store the segment number in \cs{@dtl@seg} % \begin{macrocode} \expandafter\@dtl@seg\expandafter= \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \end{macrocode} % Set the start angle. % \begin{macrocode} \edef\dtl@start{\csname dtl@sang@\romannumeral\@dtl@seg\endcsname}% % \end{macrocode} % Set the extent % \begin{macrocode} \edef\dtl@extent{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% % \end{macrocode} % Compute the end angle % \begin{macrocode} \FPadd{\dtl@endangle}{\dtl@start}{\dtl@extent}% % \end{macrocode} % Compute the shift. % \begin{macrocode} \edef\dtl@angle{\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname}% \let\dtl@old=\dtl@angle \dtl@truncatedecimal\dtl@angle \ifnum\dtl@angle>180 \FPsub{\dtl@angle}{\dtl@old}{360}% \dtl@truncatedecimal\dtl@angle \fi \edef\dtl@cutlen{% \csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname} \edef\@dtl@shift{(\dtl@angle:\dtl@cutlen)}% % \end{macrocode} % Compute the mid way angle. % \begin{macrocode} \FPmul{\dtl@angle}{\dtl@extent}{0.5}% \FPadd{\dtl@midangle}{\dtl@angle}{\dtl@start}% % \end{macrocode} % Draw the segment. % \begin{macrocode} \begin{scope}[shift={\@dtl@shift}]% \dtl@truncatedecimal\dtl@start \dtl@truncatedecimal\dtl@endangle \fill[color=\DTLgetpiesegmentcolor\@dtl@seg] (0,0) -- (\dtl@start:\DTLradius) arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle; % \end{macrocode} % Draw the outline if required: % \begin{macrocode} \ifdim\DTLpieoutlinewidth>0pt\relax \draw[color=\DTLpieoutlinecolor,line width=\DTLpieoutlinewidth] (0,0) -- (\dtl@start:\DTLradius) arc (\dtl@start:\dtl@endangle:\DTLradius) -- cycle; \fi % \end{macrocode} % Convert decimal to an integer % \begin{macrocode} \dtl@truncatedecimal\dtl@midangle % \end{macrocode} % Determine whether to rotate inner labels % \begin{macrocode} \ifDTLrotateinner % \end{macrocode} % If the mid way angle is between 90 and 270, the text will look % upside-down, so adjust accordingly. % \begin{macrocode} \ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\) \TE@or \dtl@midangle < -90}{% \FPsub{\dtl@labelangle}{\dtl@midangle}{180}% \dtl@truncatedecimal\dtl@labelangle \edef\dtl@innernodeopt{anchor=east,rotate=\dtl@labelangle}% }{% \edef\dtl@innernodeopt{anchor=west,rotate=\dtl@midangle}% }% % \end{macrocode} % Don't rotate inner labels % \begin{macrocode} \else \edef\dtl@innernodeopt{anchor=center}% \fi % \end{macrocode} % Determine whether to rotate outer labels % \begin{macrocode} \ifDTLrotateouter % \end{macrocode} % If the mid way angle is between 90 and 270, the text will look % upside-down, so adjust accordingly. % \begin{macrocode} \ifthenelse{\(\dtl@midangle > 90 \and \dtl@midangle < 270\) \TE@or \dtl@midangle < -90}{% \FPsub{\dtl@labelangle}{\dtl@midangle}{180}% \dtl@truncatedecimal\dtl@labelangle \edef\dtl@outernodeopt{anchor=east,rotate=\dtl@labelangle}% }{% \edef\dtl@outernodeopt{anchor=west,rotate=\dtl@midangle}% }% % \end{macrocode} % Don't rotate outer labels % \begin{macrocode} \else \ifthenelse{\(\dtl@midangle<45\and\dtl@midangle>-45\) \TE@or \dtl@midangle=45 \TE@or \dtl@midangle>315}{% % east quadrant \edef\dtl@outernodeopt{anchor=west}% }{% \ifthenelse{\(\dtl@midangle<135\and\dtl@midangle>45\) \TE@or \dtl@midangle=135}{% % north quadrant \edef\dtl@outernodeopt{anchor=south}% }{% \ifthenelse{\(\dtl@midangle<225\and\dtl@midangle>135\) \TE@or \dtl@midangle=225 \TE@or \dtl@midangle=-135 \TE@or \dtl@midangle<-135}{% % west quadrant \edef\dtl@outernodeopt{anchor=east}% }{% \edef\dtl@outernodeopt{anchor=north}% }% } } \fi % \end{macrocode} % Draw inner and outer labels % \begin{macrocode} \edef\@dtl@dolabel{% \noexpand\draw (\dtl@midangle:\the\dtl@inneroffset) node[\dtl@innernodeopt]{% \noexpand\DTLdisplayinnerlabel{\noexpand\dtl@innerlabel}};}% \@dtl@dolabel \edef\@dtl@dolabel{% \noexpand\draw (\dtl@midangle:\the\dtl@outeroffset) node[\dtl@outernodeopt]{% \noexpand\DTLdisplayouterlabel{\noexpand\dtl@outerlabel}};}% \@dtl@dolabel \end{scope} }% \DTLpieatendtikz \end{tikzpicture} \fi }} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@computeangles} %\begin{definition} %\cs{dtl@computeangles}\marg{n}\marg{variable} %\end{definition} % Compute the angles for segment \meta{n}. This sets % \cs{dtl@sang@}\meta{n} (start angle), % \cs{dtl@angle@}\meta{n} (extent angle), % \cs{dtl@cut@angle@}\meta{n} (cut away angle) and % \cs{dtl@cut@len@}\meta{n} (cut away length). % \begin{macrocode} \newcommand*{\dtl@computeangles}[2]{% \FPifgt{\@dtl@start}{180}% % if startangle > 180 \let\dtl@old=\@dtl@start % startangle = startangle - 360 \FPsub{\@dtl@start}{\dtl@old}{360}% \fi \FPiflt{\@dtl@start}{-180}% % if startangle < -180 \let\dtl@old=\@dtl@start % startangle = startangle + 360 \FPadd{\@dtl@start}{\dtl@old}{360}% \fi \expandafter\edef\csname dtl@sang@\romannumeral#1\endcsname{% \@dtl@start}% \FPmul{\dtl@angle}{360}{#2}% \let\dtl@old=\dtl@angle \FPdiv{\dtl@angle}{\dtl@old}{\dtl@total}% \expandafter\let\csname dtl@angle@\romannumeral#1\endcsname=\dtl@angle \let\dtl@old=\@dtl@start \FPadd{\@dtl@start}{\dtl@old}{\dtl@angle}% \expandafter\def\csname dtl@cut@angle@\romannumeral#1\endcsname{0}% \expandafter\def\csname dtl@cut@len@\romannumeral#1\endcsname{0cm}% } % \end{macrocode} %\end{macro} % % Set the offset angles. %\begin{macro}{\@dtl@set@off} % \begin{macrocode} \def\@dtl@set@off#1-#2\relax{% \ifthenelse{\equal{#2}{}}{% \@@dtl@set@off{#1}}{% \@@dtl@set@offr#1-#2\relax}% } % \end{macrocode} %\end{macro} % Set offset for individual segment: %\begin{macro}{\@@dtl@set@off} % \begin{macrocode} \newcommand*{\@@dtl@set@off}[1]{% \edef\dtl@old{\csname dtl@angle@\romannumeral#1\endcsname}% \FPmul{\dtl@angle}{\dtl@old}{0.5}% \let\dtl@old=\dtl@angle \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}% \FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}% \expandafter\edef\csname dtl@cut@angle@\romannumeral#1\endcsname{% \dtl@angle}% \expandafter\edef\csname dtl@cut@len@\romannumeral#1\endcsname{% \the\dtl@cutawayoffset} } % \end{macrocode} %\end{macro} % Define count register to keep track of segments %\begin{macro}{\@dtl@seg} % \begin{macrocode} \newcount\@dtl@seg % \end{macrocode} %\end{macro} %\begin{macro}{\@@dtl@setoffr} % Set offset for a range of segments % \begin{macrocode} \def\@@dtl@set@offr#1-#2-\relax{% \ifnum#1>#2\relax \PackageError{datapie}{Segment ranges must go in ascending order}{% Try #2-#1 instead of #1-#2}% \else \def\dtl@angle{0}% \@dtl@seg=#1\relax \whiledo{\not\(\@dtl@seg > #2\)}{% \let\dtl@old=\dtl@angle \edef\dtl@segang{\csname dtl@angle@\romannumeral\@dtl@seg\endcsname}% \FPadd{\dtl@angle}{\dtl@old}{\dtl@segang}% \advance\@dtl@seg by 1\relax }% \let\dtl@old=\dtl@angle \FPmul{\dtl@angle}{\dtl@old}{0.5}% \edef\dtl@sang{\csname dtl@sang@\romannumeral#1\endcsname}% \let\dtl@old=\dtl@angle \FPadd{\dtl@angle}{\dtl@old}{\dtl@sang}% \@dtl@seg=#1\relax \whiledo{\not\(\@dtl@seg > #2\)}{% \expandafter \let\csname dtl@cut@angle@\romannumeral\@dtl@seg\endcsname =\dtl@angle \expandafter \edef\csname dtl@cut@len@\romannumeral\@dtl@seg\endcsname{% \the\dtl@cutawayoffset} \advance\@dtl@seg by 1\relax }% \fi } % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*dataplot.sty> % \end{macrocode} %\fi %\section{dataplot.sty} % Declare package: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{dataplot}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} % Required packages % \begin{macrocode} \RequirePackage{xkeyval} \RequirePackage{tikz} \RequirePackage{datatool} % \end{macrocode} % Load TikZ plot libraries % \begin{macrocode} \usetikzlibrary{plotmarks} \usetikzlibrary{plothandlers} % \end{macrocode} % %\begin{macro}{\DTLplotstream} %\begin{definition} %\cs{DTLplotstream}\oarg{condition}\marg{db name}\marg{x key}\marg{y key} %\end{definition} % Add 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}. % The optional argument \meta{condition} is the same as that % for \cs{DTLforeach} %\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of %\cs{DTLforeach}} % \begin{macrocode} \newcommand*{\DTLplotstream}[4][\boolean{true}]{% \@sDTLforeach[#1]{#2}{\dtl@x=#3,\dtl@y=#4}{% \DTLconverttodecimal{\dtl@x}{\dtl@decx}% \DTLconverttodecimal{\dtl@y}{\dtl@decy}% \pgfplotstreampoint{\pgfpointxy{\dtl@decx}{\dtl@decy}}}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLplotmarks} %\cs{DTLplotmarks} contains a list of plot marks used by %\cs{DTLplot}. % \begin{macrocode} \newcommand*{\DTLplotmarks}{% \pgfuseplotmark{o},% \pgfuseplotmark{x},% \pgfuseplotmark{+},% \pgfuseplotmark{square},% \pgfuseplotmark{triangle},% \pgfuseplotmark{diamond},% \pgfuseplotmark{pentagon},% \pgfuseplotmark{asterisk},% \pgfuseplotmark{star}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLplotmarkcolors} %\cs{DTLplotmarkcolors} contains a list of the plot mark colours. % \begin{macrocode} \newcommand*{\DTLplotmarkcolors}{% red,% green,% blue,% yellow,% magenta,% cyan,% orange,% black,% gray} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLplotlines} %\cs{DTLplotlines} contains a list of dash patterns used by %\cs{DLTplot}. %\changes{1.03}{2009 January 27}{fixed error in solid line setting} % \begin{macrocode} \newcommand*{\DTLplotlines}{% \pgfsetdash{}{0pt},% solid line \pgfsetdash{{10pt}{5pt}}{0pt},% \pgfsetdash{{5pt}{5pt}}{0pt},% \pgfsetdash{{1pt}{5pt}}{0pt},% \pgfsetdash{{5pt}{5pt}{1pt}{5pt}}{0pt},% \pgfsetdash{{1pt}{3pt}}{0pt},% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLplotlinecolors} %\cs{DTLplotlinecolors} contains a list of the plot line colours. % \begin{macrocode} \newcommand*{\DTLplotlinecolors}{% red,% green,% blue,% yellow,% magenta,% cyan,% orange,% black,% gray} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLplotwidth} % The default total plot width is stored in the length % \cs{dtlplotwidth} % \begin{macrocode} \newlength\DTLplotwidth \setlength\DTLplotwidth{4in} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLplotheight} % The default total plot height is stored in the length % \cs{dtlplotheight} % \begin{macrocode} \newlength\DTLplotheight \setlength\DTLplotheight{4in} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLticklength} % The length of the tick marks is given by \cs{DTLticklength} % \begin{macrocode} \newlength\DTLticklength \setlength\DTLticklength{5pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLminorticklength} % The length of the minor tick marks is given by % \cs{DTLminorticklength}. % \begin{macrocode} \newlength\DTLminorticklength \setlength\DTLminorticklength{2pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLticklabeloffset} % The offset from the axis to the tick label is given by % \cs{DTLticklabeloffset}. % \begin{macrocode} \newlength\DTLticklabeloffset \setlength\DTLticklabeloffset{8pt} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@xticlabelheight} % \cs{dtl@xticlabelheight} is used to store the height of % the $x$ tick labels. % \begin{macrocode} \newlength\dtl@xticlabelheight % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@yticlabelwidth} % \cs{dtl@yticlabelwidth} is used to store the width of % the $y$ tick labels. % \begin{macrocode} \newlength\dtl@yticlabelwidth % \end{macrocode} %\end{macro} %\begin{macro}{\DTLmintickgap} % \cs{DTLmintickgap} stores the suggested minimum distance between % tick marks where the gap is not specified. % \begin{macrocode} \newlength\DTLmintickgap \setlength\DTLmintickgap{20pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLminminortickgap} % The suggested minimum distance between minor tick marks where the % gap is not specified is given by \cs{DTLminminortickgap}. % \begin{macrocode} \newlength\DTLminminortickgap \setlength\DTLminminortickgap{5pt} % \end{macrocode} %\end{macro} %\begin{counter}{DTLplotroundvar} % Round $x$ tick labels to the number of digits given by % the counter \ctrfmt{DTLplotroundXvar}. % \begin{macrocode} \newcounter{DTLplotroundXvar} \setcounter{DTLplotroundXvar}{2} % \end{macrocode} %\end{counter} %\begin{counter}{DTLplotroundYvar} % Round $y$ tick labels to the number of digits given by % the counter \ctrfmt{DTLplotroundYvar}. % \begin{macrocode} \newcounter{DTLplotroundYvar} \setcounter{DTLplotroundYvar}{2} % \end{macrocode} %\end{counter} %\begin{macro}{\ifDTLxaxis} % The conditional \cs {ifDTLxaxis} is used to determine whether or % not to display the $x$ axis. % \begin{macrocode} \newif\ifDTLxaxis \DTLxaxistrue % \end{macrocode} %\end{macro} %\begin{macro}{\DTLXAxisStyle} % The style of the $x$ axis is given by \cs{DTLXAxisStyle}. This % is just a solid line by default. % \begin{macrocode} \newcommand*{\DTLXAxisStyle}{-} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifDTLyaxis} % The conditional \cs{ifDTLyaxis} is used to determine whether or % not to display the $y$ axis % \begin{macrocode} \newif\ifDTLyaxis \DTLyaxistrue % \end{macrocode} %\end{macro} %\begin{macro}{\DTLYAxisStyle} % The style of the $y$ axis is given by \cs{DTLYAxisStyle}. This % is just a solid line by default. % \begin{macrocode} \newcommand*{\DTLYAxisStyle}{-} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLmajorgridstyle} % The style of the major grid lines is given by % \cs{DTLmajorgridstyle}. % \begin{macrocode} \newcommand*{\DTLmajorgridstyle}{color=gray,-} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLminorgridstyle} % The style of the minor grid lines is given by % \cs{DTLminorgridstyle}. % \begin{macrocode} \newcommand*{\DTLminorgridstyle}{color=gray,loosely dotted} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifDTLxticsin} % The conditional \cs{ifDTLxticsin} is used to determine whether % the $x$ tics should point in or out. % \begin{macrocode} \newif\ifDTLxticsin \DTLxticsintrue % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLyticsin} % The conditional \cs{ifDTLyticsin} is used to determine whether % the $y$ tics should point in or out. % \begin{macrocode} \newif\ifDTLyticsin \DTLyticsintrue % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@legendsetting} % The legend setting is stored in the count register % \cs{dtl@legendsetting}. % \begin{macrocode} \newcount\dtl@legendsetting % \end{macrocode} %\end{macro} %\begin{macro}{\DTLlegendxoffset} % The gap between the border of plot and legend is given by the % lengths \cs{DTLlegendxoffset} and \cs{DTLlegendyoffset} % \begin{macrocode} \newlength\DTLlegendxoffset \setlength\DTLlegendxoffset{10pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLlegendyoffset} % \begin{macrocode} \newlength\DTLlegendyoffset \setlength\DTLlegendyoffset{10pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLformatlegend} %\begin{definition} %\cs{DTLformatlegend}\marg{legend} %\end{definition} % This formats the legend. % \begin{macrocode} \newcommand*{\DTLformatlegend}[1]{% \setlength{\fboxrule}{1.1pt}% \fcolorbox{black}{white}{#1}} % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLshowmarkers} % The conditional \cs{ifDTLshowmarkers} is used to specify % whether or not to use markers. % \begin{macrocode} \newif\ifDTLshowmarkers \DTLshowmarkerstrue % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLshowlines} % The conditional \cs{ifDTLshowlines} is used to specify % whether or not to use lines. % \begin{macrocode} \newif\ifDTLshowlines \DTLshowlinesfalse % \end{macrocode} %\end{macro} %\begin{macro}{\DTLplotatbegintikz} % \cs{DTLplotatbegintikz} is a hook to insert stuff at the % start of the \env{tikzpicture} % environment (after the unit vectors have been set). % \begin{macrocode} \newcommand*{\DTLplotatbegintikz}{} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLplotatendtikz} % \cs{DTLplotatendtikz} is a hook to insert stuff at the end % of the \env{tikzpicture} environment. % \begin{macrocode} \newcommand*{\DTLplotatendtikz}{} % \end{macrocode} %\end{macro} % % Plot settings. The database key for the $x$ value is % given by the "x" setting: % \begin{macrocode} \define@key{dataplot}{x}{% \def\dtl@xkey{#1}} % \end{macrocode} % The database key for the $y$ value is given by the "y" setting: % \begin{macrocode} \define@key{dataplot}{y}{% \def\dtl@ykey{#1}} % \end{macrocode} % The list of plot mark colours is given by the "markcolors" setting. % (This should be a comma separated list of colour names.) % \begin{macrocode} \define@key{dataplot}{markcolors}{% \def\DTLplotmarkcolors{#1}} % \end{macrocode} % The list of plot line colours is given by the "linecolors" setting. % (This should be a comma separated list of colour names.) % \begin{macrocode} \define@key{dataplot}{linecolors}{% \def\DTLplotlinecolors{#1}} % \end{macrocode} % The list of plot mark and line colours is given by the "colors" % setting. (This should be a comma separated list of colour names.) % \begin{macrocode} \define@key{dataplot}{colors}{% \def\DTLplotmarkcolors{#1}% \def\DTLplotlinecolors{#1}} % \end{macrocode} % The list of plot marks is given by the "marks" setting. (This % should be a comma separated list of code that generates % pgf plot marks.) % \begin{macrocode} \define@key{dataplot}{marks}{% \def\DTLplotmarks{#1}} % \end{macrocode} % The list of plot line styles is given by the "lines" setting. (This % should be a comma separated list of code that sets the line % style.) An empty set will create solid lines. % \begin{macrocode} \define@key{dataplot}{lines}{% \def\DTLplotlines{#1}} % \end{macrocode} % The total width of the plot is given by the "width" setting. % \begin{macrocode} \define@key{dataplot}{width}{% \setlength\DTLplotwidth{#1}} % \end{macrocode} % The total height of the plot is given by the "height" setting. % \begin{macrocode} \define@key{dataplot}{height}{% \setlength\DTLplotheight{#1}} % \end{macrocode} % Determine whether to show lines, markers or both % \begin{macrocode} \define@choicekey{dataplot}{style}[\val\nr]{both,lines,markers}{% \ifcase\nr\relax \DTLshowlinestrue \DTLshowmarkerstrue \or \DTLshowlinestrue \DTLshowmarkersfalse \or \DTLshowmarkerstrue \DTLshowlinesfalse \fi} % \end{macrocode} % Determine whether or not to display the axes % \begin{macrocode} \define@choicekey{dataplot}{axes}[\val\nr]{both,x,y,none}[both]{% \ifcase\nr\relax % both \DTLxaxistrue \DTLxticstrue \DTLyaxistrue \DTLyticstrue \or % x \DTLxaxistrue \DTLxticstrue \DTLyaxisfalse \DTLyticsfalse \or % y \DTLxaxisfalse \DTLxticsfalse \DTLyaxistrue \DTLyticstrue \or % none \DTLxaxisfalse \DTLxticsfalse \DTLyaxisfalse \DTLyticsfalse \fi } % \end{macrocode} %\begin{macro}{\ifDTLbox} % Enclose plot in a box % \begin{macrocode} \define@boolkey{dataplot}[DTL]{box}[true]{} \DTLboxfalse % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLxticstrue} % Condition to determine whether to show the $x$ tick marks % \begin{macrocode} \define@boolkey{dataplot}[DTL]{xtics}[true]{} \DTLxticstrue % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLyticstrue} % Condition to determine whether to show the $y$ tick marks % \begin{macrocode} \define@boolkey{dataplot}[DTL]{ytics}[true]{} \DTLyticstrue % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLxminortics} % Condition to determine whether to show the $x$ minor tick marks % \begin{macrocode} \define@boolkey{dataplot}[DTL]{xminortics}[true]{% \ifDTLxminortics \DTLxticstrue\fi} \DTLxminorticsfalse % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLyminortics} % Condition to determine whether to show the $y$ minor tick marks % \begin{macrocode} \define@boolkey{dataplot}[DTL]{yminortics}[true]{% \ifDTLyminortics \DTLyticstrue\fi} \DTLyminorticsfalse % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLgrid} % Determine whether to draw the grid % \begin{macrocode} \define@boolkey{dataplot}[DTL]{grid}[true]{} % \end{macrocode} %\end{macro} % Determine whether the $x$ tick marks should point % in or out: % \begin{macrocode} \define@choicekey{dataplot}{xticdir}[\val\nr]{in,out}{% \ifcase\nr\relax \DTLxticsintrue \or \DTLxticsinfalse \fi } % \end{macrocode} % Determine whether the $y$ tick marks should point % in or out: % \begin{macrocode} \define@choicekey{dataplot}{yticdir}[\val\nr]{in,out}{% \ifcase\nr\relax \DTLyticsintrue \or \DTLyticsinfalse \fi } % \end{macrocode} % Determine whether the $x$ and $y$ tick marks should point % in or out; % \begin{macrocode} \define@choicekey{dataplot}{ticdir}[\val\nr]{in,out}{% \ifcase\nr\relax \DTLxticsintrue \DTLyticsintrue \or \DTLxticsinfalse \DTLyticsinfalse \fi } % \end{macrocode} % Set the bounds of the graph (value must be in the form % \meta{min x}","\meta{min y}","\meta{max x}","\meta{max y} % (bounds overrides minx, miny, maxx and maxy settings.) % \begin{macrocode} \define@key{dataplot}{bounds}{% \def\dtl@bounds{#1}} \let\dtl@bounds=\relax % \end{macrocode} % Set only the lower $x$ bound % \begin{macrocode} \define@key{dataplot}{minx}{% \def\dtl@minx{#1}} \let\dtl@minx=\relax % \end{macrocode} % Set only the upper $x$ bound: % \begin{macrocode} \define@key{dataplot}{maxx}{% \def\dtl@maxx{#1}} \let\dtl@maxx=\relax % \end{macrocode} % Set only the lower $y$ bound: % \begin{macrocode} \define@key{dataplot}{miny}{% \def\dtl@miny{#1}} \let\dtl@miny=\relax % \end{macrocode} % Set only the upper $y$ bound: % \begin{macrocode} \define@key{dataplot}{maxy}{% \def\dtl@maxy{#1}} \let\dtl@maxy=\relax % \end{macrocode} % Define list of points for $x$ ticks. (Must be a comma separated % list of decimal numbers.) % \begin{macrocode} \define@key{dataplot}{xticpoints}{% \def\dtl@xticlist{#1}\DTLxticstrue\DTLxaxistrue} \let\dtl@xticlist=\relax % \end{macrocode} % Define list of points for $y$ ticks. (Must be a comma separated % list of decimal numbers.) % \begin{macrocode} \define@key{dataplot}{yticpoints}{% \def\dtl@yticlist{#1}\DTLyticstrue\DTLyaxistrue} \let\dtl@yticlist=\relax % \end{macrocode} % Define a the gap between $x$ tick marks (xticpoints overrides % xticgap) % \begin{macrocode} \define@key{dataplot}{xticgap}{\def\dtl@xticgap{#1}% \DTLxticstrue\DTLxaxistrue} \let\dtl@xticgap=\relax % \end{macrocode} % Define a the gap between $y$ tick marks (yticpoints overrides % yticgap) % \begin{macrocode} \define@key{dataplot}{yticgap}{\def\dtl@yticgap{#1}% \DTLyticstrue\DTLyaxistrue} \let\dtl@yticgap=\relax % \end{macrocode} % Define comma separated list of labels for $x$ ticks. % \begin{macrocode} \define@key{dataplot}{xticlabels}{% \def\dtl@xticlabels{#1}\DTLxticstrue\DTLxaxistrue} \let\dtl@xticlabels=\relax % \end{macrocode} % Define comma separated list of labels for $y$ ticks. % \begin{macrocode} \define@key{dataplot}{yticlabels}{% \def\dtl@yticlabels{#1}\DTLyticstrue\DTLyaxistrue} \let\dtl@yticlabels=\relax % \end{macrocode} % Define $x$ axis label % \begin{macrocode} \define@key{dataplot}{xlabel}{% \def\dtl@xlabel{#1}} \let\dtl@xlabel=\relax % \end{macrocode} % Define $y$ axis label % \begin{macrocode} \define@key{dataplot}{ylabel}{% \def\dtl@ylabel{#1}} \let\dtl@ylabel=\relax % \end{macrocode} % The legend setting may be one of: "none" (don't show it), % "north", "northeast", "east", "southeast", "south", "southwest", % "west", or "northwest". These set the count register % \cs{dtl@legendsetting}. % \begin{macrocode} \define@choicekey{dataplot}{legend}[\val\nr]{none,north,northeast,% east,southeast,south,southwest,west,northwest}[northeast]{% \dtl@legendsetting=\nr\relax } % \end{macrocode} % Legend labels (comma separated list). If omitted, the database % name is used. % \begin{macrocode} \define@key{dataplot}{legendlabels}{\def\dtl@legendlabels{#1}} % \end{macrocode} % %\begin{macro}{\DTLplot} %\begin{definition} %\cs{DTLplot}\oarg{condition}\marg{db list}\marg{settings} %\end{definition} % Creates a plot (inside a \env{tikzpicture} environment) of all % the data given in the databases listed in \meta{db list}. % \begin{macrocode} \newcommand*{\DTLplot}[3][\boolean{true}]{{% \let\dtl@xkey=\relax \let\dtl@ykey=\relax \let\dtl@legendlabels=\relax \setkeys{dataplot}{#3}% \let\dtl@plotmarklist=\DTLplotmarks \let\dtl@plotlinelist=\DTLplotlines \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors \let\dtl@plotlinecolorlist=\DTLplotlinecolors \def\dtl@legend{}% \ifx\dtl@legendlabels\relax \edef\dtl@legendlabels{#2}% \fi \ifx\dtl@xkey\relax \PackageError{dataplot}{Missing x setting for \string\DTLplot}{}% \else \ifx\dtl@ykey\relax \PackageError{dataplot}{Missing y setting for \string\DTLplot}{}% \else % \end{macrocode} % If user didn't specified bounds, % compute the maximum and minimum $x$ and $y$ values over % all the databases listed. % \begin{macrocode} \ifx\dtl@bounds\relax \DTLcomputebounds[#1]{#2}{\dtl@xkey}{\dtl@ykey} {\DTLminX}{\DTLminY}{\DTLmaxX}{\DTLmaxY}% \ifx\dtl@minx\relax \else \let\DTLminX=\dtl@minx \fi \ifx\dtl@maxx\relax \else \let\DTLmaxX=\dtl@maxx \fi \ifx\dtl@miny\relax \else \let\DTLminY=\dtl@miny \fi \ifx\dtl@maxy\relax \else \let\DTLmaxY=\dtl@maxy \fi % \end{macrocode} % Otherwise extract information from \cs{dtl@bounds} % \begin{macrocode} \else \expandafter\dtl@getbounds\dtl@bounds\@nil \fi % \end{macrocode} % Determine scaling factors. % \begin{macrocode} \@dtl@tmpcount=\DTLplotwidth \FPsub{\dtl@dx}{\DTLmaxX}{\DTLminX}% \FPdiv{\dtl@unit@x}{\number\@dtl@tmpcount}{\dtl@dx}% \@dtl@tmpcount=\DTLplotheight \FPsub{\dtl@dy}{\DTLmaxY}{\DTLminY}% \FPdiv{\dtl@unit@y}{\number\@dtl@tmpcount}{\dtl@dy}% % \end{macrocode} % If x tics specified, construct a list of x tic points if not % already specified. % \begin{macrocode} \ifDTLxtics \ifx\dtl@xticlist\relax \ifx\dtl@xticgap\relax \dtl@constructticklist\DTLminX\DTLmaxX \dtl@unit@x\dtl@xticlist \else \DTLifFPopenbetween{0}{\DTLminX}{\DTLmaxX}{% \dtl@constructticklistwithgapz \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}{% \dtl@constructticklistwithgap \DTLminX\DTLmaxX\dtl@xticlist\dtl@xticgap}% \fi \fi % \end{macrocode} % Construct a list of $x$ minor tick points if required % \begin{macrocode} \let\dtl@xminorticlist\@empty \ifDTLxminortics \let\dtl@prevtick=\relax \@for\dtl@nexttick:=\dtl@xticlist\do{% \ifx\dtl@prevtick\relax \else \dtl@constructminorticklist \dtl@prevtick\dtl@nexttick\dtl@unit@x\dtl@xminorticlist \fi \let\dtl@prevtick=\dtl@nexttick }% \fi % \end{macrocode} % Determine the height of the $x$ tick labels. % \begin{macrocode} \ifx\dtl@xticlabels\relax \settoheight{\dtl@xticlabelheight}{\dtl@xticlist}% \else \settoheight{\dtl@xticlabelheight}{\dtl@xticlabels}% \fi \else \setlength{\dtl@xticlabelheight}{0pt}% \fi % \end{macrocode} % If y tics specified, construct a list of y tic points if not % already specified. % \begin{macrocode} \setlength{\dtl@yticlabelwidth}{0pt}% \ifDTLytics \ifx\dtl@yticlist\relax \ifx\dtl@yticgap\relax \dtl@constructticklist\DTLminY\DTLmaxY \dtl@unit@y\dtl@yticlist \else \DTLifFPopenbetween{0}{\DTLminY}{\DTLmaxY}{% \dtl@constructticklistwithgapz \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}{% \dtl@constructticklistwithgap \DTLminY\DTLmaxY\dtl@yticlist\dtl@yticgap}% \fi \fi % \end{macrocode} % Construct a list of $y$ minor tick points if required % \begin{macrocode} \let\dtl@yminorticlist\@empty \ifDTLyminortics \let\dtl@prevtick=\relax \@for\dtl@nexttick:=\dtl@yticlist\do{% \ifx\dtl@prevtick\relax \else \dtl@constructminorticklist \dtl@prevtick\dtl@nexttick\dtl@unit@y\dtl@yminorticlist \fi \let\dtl@prevtick=\dtl@nexttick }% \fi % \end{macrocode} % Determine the width of the $y$ tick labels. % \begin{macrocode} \ifx\dtl@ylabel\relax \else \ifx\dtl@yticlabels\relax \@for\dtl@thislabel:=\dtl@yticlist\do{% \FPround{\dtl@thislabel}{\dtl@thislabel} {\c@DTLplotroundYvar}% \settowidth{\dtl@tmplength}{\dtl@thislabel}% \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \else \@for\dtl@thislabel:=\dtl@yticlabels\do{% \settowidth{\dtl@tmplength}{\dtl@thislabel}% \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \fi \fi % \end{macrocode} % Start the picture. % \begin{macrocode} \begin{tikzpicture} % \end{macrocode} % Set the $x$ and $y$ unit vectors. % \begin{macrocode} \pgfsetxvec{\pgfpoint{\dtl@unit@x sp}{0pt}}% \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit@y sp}}% % \end{macrocode} % Add any extra information the user requires % \begin{macrocode} \DTLplotatbegintikz % \end{macrocode} % Determine whether to put a box around the plot % \begin{macrocode} \ifDTLbox \draw (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY) -- (\DTLmaxX,\DTLmaxY) -- (\DTLminX,\DTLmaxY) -- cycle; \else % \end{macrocode} % Plot $x$ axis if required. % \begin{macrocode} \ifDTLxaxis \expandafter\draw\expandafter[\DTLXAxisStyle] (\DTLminX,\DTLminY) -- (\DTLmaxX,\DTLminY); \fi % \end{macrocode} % Plot $y$ axis if required. % \begin{macrocode} \ifDTLyaxis \expandafter\draw\expandafter[\DTLYAxisStyle] (\DTLminX,\DTLminY) -- (\DTLminX,\DTLmaxY); \fi \fi % \end{macrocode} % Plot grid if required % \begin{macrocode} \ifDTLgrid \ifDTLxminortics \@for\dtl@thistick:=\dtl@xminorticlist\do{% \expandafter\draw\expandafter[\DTLminorgridstyle] (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY); }% \fi \ifDTLyminortics \@for\dtl@thistick:=\dtl@yminorticlist\do{% \expandafter\draw\expandafter[\DTLminorgridstyle] (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick); }% \fi \@for\dtl@thistick:=\dtl@xticlist\do{% \expandafter\draw\expandafter[\DTLmajorgridstyle] (\dtl@thistick,\DTLminY) -- (\dtl@thistick,\DTLmaxY); }% \@for\dtl@thistick:=\dtl@yticlist\do{% \expandafter\draw\expandafter[\DTLmajorgridstyle] (\DTLminX,\dtl@thistick) -- (\DTLmaxX,\dtl@thistick); }% \fi % \end{macrocode} % Plot $x$ tics if required. % \begin{macrocode} \ifDTLxtics \addtolength\dtl@xticlabelheight{\DTLticklabeloffset}% \@for\dtl@thistick:=\dtl@xticlist\do{% \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}} \ifDTLxticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} {\pgfpoint{0pt}{\DTLticklength}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} {\pgfpoint{0pt}{-\DTLticklength}}} \fi \ifDTLbox \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} \ifDTLxticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} {\pgfpoint{0pt}{-\DTLticklength}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} {\pgfpoint{0pt}{\DTLticklength}}} \fi \fi \pgfusepath{stroke}% % \end{macrocode} % Plot the tick labels % \begin{macrocode} \ifx\dtl@xticlabels\relax \FPround{\dtl@thislabel}{\dtl@thistick} {\c@DTLplotroundXvar}% \else \dtl@chopfirst\dtl@xticlabels\dtl@thislabel\dtl@rest \let\dtl@xticlabels=\dtl@rest \fi \pgftext[base,center,at={\pgfpointadd {\pgfpointxy{\dtl@thistick}{\DTLminY}} {\pgfpoint{0pt}{-\dtl@xticlabelheight}}}] {\dtl@thislabel} }% \fi % \end{macrocode} % Plot $x$ label if required. % \begin{macrocode} \ifx\dtl@xlabel\relax \else \addtolength{\dtl@xticlabelheight}{\baselineskip}% \setlength{\dtl@tmplength}{0.5\DTLplotwidth} \pgftext[base,center,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLminY}}% {\pgfpoint{\dtl@tmplength}{-\dtl@xticlabelheight}}}]{% \dtl@xlabel} \fi % \end{macrocode} % Plot the $x$ minor ticks if required % \begin{macrocode} \ifDTLxminortics \@for\dtl@thistick:=\dtl@xminorticlist\do{% \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLminY}} \ifDTLxticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} {\pgfpoint{0pt}{\DTLminorticklength}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLminY}} {\pgfpoint{0pt}{-\DTLminorticklength}}} \fi \ifDTLbox \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} \ifDTLxticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} {\pgfpoint{0pt}{-\DTLminorticklength}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{\DTLmaxY}} {\pgfpoint{0pt}{\DTLminorticklength}}} \fi \fi }% \fi % \end{macrocode} % Plot $y$ tics if required. % \begin{macrocode} \ifDTLytics \@for\dtl@thistick:=\dtl@yticlist\do{% \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}} \ifDTLyticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} {\pgfpoint{\DTLticklength}{0pt}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} {\pgfpoint{-\DTLticklength}{0pt}}} \fi \ifDTLbox \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} \ifDTLyticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} {\pgfpoint{-\DTLticklength}{0pt}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} {\pgfpoint{\DTLticklength}{0pt}}} \fi \fi \pgfusepath{stroke} % \end{macrocode} % Plot the $y$ tick labels if required % \begin{macrocode} \ifx\dtl@yticlabels\relax \FPround{\dtl@thislabel}{\dtl@thistick} {\c@DTLplotroundYvar}% \else \dtl@chopfirst\dtl@yticlabels\dtl@thislabel\dtl@rest \let\dtl@yticlabels=\dtl@rest \fi \pgftext[right,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\dtl@thistick}} {\pgfpoint{-\DTLticklabeloffset}{0pt}}}] {\dtl@thislabel} }% \fi % \end{macrocode} % Plot $y$ label if required. % \begin{macrocode} \ifx\dtl@ylabel\relax \else \addtolength{\dtl@yticlabelwidth}{\baselineskip}% \setlength{\dtl@tmplength}{0.5\DTLplotheight} \pgftext[bottom,center,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLminY}}% {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, rotate=90]{% \dtl@ylabel} \fi % \end{macrocode} % Plot the $y$ minor ticks if required % \begin{macrocode} \ifDTLyminortics \@for\dtl@thistick:=\dtl@yminorticlist\do{% \pgfpathmoveto{\pgfpointxy{\DTLminX}{\dtl@thistick}} \ifDTLyticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} {\pgfpoint{\DTLminorticklength}{0pt}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLminX}{\dtl@thistick}} {\pgfpoint{-\DTLminorticklength}{0pt}}} \fi \ifDTLbox \pgfpathmoveto{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} \ifDTLyticsin \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} {\pgfpoint{-\DTLminorticklength}{0pt}}} \else \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\DTLmaxX}{\dtl@thistick}} {\pgfpoint{\DTLminorticklength}{0pt}}} \fi \fi \pgfusepath{stroke} }% \fi % \end{macrocode} % Iterate through each database % \begin{macrocode} \@for\dtl@thisdb:=#2\do{% % \end{macrocode} % Get the current plot mark colour. % \begin{macrocode} \ifx\dtl@plotmarkcolorlist\@empty \let\dtl@plotmarkcolorlist=\DTLplotmarkcolors \fi \dtl@chopfirst\dtl@plotmarkcolorlist\dtl@thisplotmarkcolor \dtl@remainder \let\dtl@plotmarkcolorlist=\dtl@remainder % \end{macrocode} % Get the current plot mark, and store in \cs{dtl@mark} % \begin{macrocode} \ifDTLshowmarkers \ifx\dtl@plotmarklist\@empty \let\dtl@plotmarklist=\DTLplotmarks \fi \dtl@chopfirst\dtl@plotmarklist\dtl@thisplotmark \dtl@remainder \let\dtl@plotmarklist=\dtl@remainder \ifx\dtl@thisplotmark\relax \let\dtl@mark=\relax \else \expandafter\toks@\expandafter{\dtl@thisplotmark}% \ifx\dtl@thisplotmarkcolor\@empty \edef\dtl@mark{\the\toks@}% \else \edef\dtl@mark{% \noexpand\color{\dtl@thisplotmarkcolor}% \the\toks@}% \fi \fi \else \let\dtl@mark=\relax \fi % \end{macrocode} % Get the current plot line colour. % \begin{macrocode} \ifx\dtl@plotlinecolorlist\@empty \let\dtl@plotlinecolorlist=\DTLplotlinecolors \fi \dtl@chopfirst\dtl@plotlinecolorlist\dtl@thisplotlinecolor \dtl@remainder \let\dtl@plotlinecolorlist=\dtl@remainder % \end{macrocode} % Get the current line style, and store in \cs{dtl@linestyle} % \begin{macrocode} \ifDTLshowlines \ifx\dtl@plotlinelist\@empty \let\dtl@plotlinelist=\DTLplotlines \fi \dtl@chopfirst\dtl@plotlinelist\dtl@thisplotline \dtl@remainder \let\dtl@plotlinelist=\dtl@remainder \expandafter\ifx\dtl@thisplotline\relax \let\dtl@linestyle=\relax \else \expandafter\toks@\expandafter{\dtl@thisplotline}% \ifx\dtl@thisplotlinecolor\@empty \edef\dtl@linestyle{\the\toks@}% \else \edef\dtl@linestyle{% \noexpand\color{\dtl@thisplotlinecolor}% \the\toks@}% \fi \fi \else \let\dtl@linestyle=\relax \fi % \end{macrocode} % Append this plot setting to the legend. % \begin{macrocode} \ifnum\dtl@legendsetting>0\relax \dtl@chopfirst\dtl@legendlabels\dtl@thislabel\dtl@rest \let\dtl@legendlabels=\dtl@rest \expandafter\toks@\expandafter{\dtl@mark}% \expandafter\@dtl@toks\expandafter{\dtl@linestyle}% \edef\dtl@addtolegend{\noexpand\DTLaddtoplotlegend {\the\toks@}{\the\@dtl@toks}{\dtl@thislabel}}% \dtl@addtolegend \fi % \end{macrocode} % Store stream in \cs{dtl@stream} % \begin{macrocode} \def\dtl@stream{\pgfplotstreamstart}% % \end{macrocode} % Only plot points that lie inside bounds. %\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of %\cs{DTLforeach}} % \begin{macrocode} \@sDTLforeach[#1]{\dtl@thisdb}{\dtl@x=\dtl@xkey,% \dtl@y=\dtl@ykey}{% \DTLconverttodecimal{\dtl@x}{\dtl@decx}% \DTLconverttodecimal{\dtl@y}{\dtl@decy}% \ifthenelse{% \DTLisclosedbetween{\dtl@x}{\DTLminX}{\DTLmaxX}% \and \DTLisclosedbetween{\dtl@y}{\DTLminY}{\DTLmaxY}% }{% \expandafter\toks@\expandafter{\dtl@stream}% \edef\dtl@stream{\the\toks@ \noexpand\pgfplotstreampoint {\noexpand\pgfpointxy{\dtl@decx}{\dtl@decy}}}% }{}% }% \expandafter\toks@\expandafter{\dtl@stream}% \edef\dtl@stream{\the\toks@\noexpand\pgfplotstreamend}% % \end{macrocode} % End plot stream and draw path. % \begin{macrocode} \ifx\dtl@linestyle\relax \else \begin{scope} \dtl@linestyle \pgfplothandlerlineto \dtl@stream \pgfusepath{stroke} \end{scope} \fi \ifx\dtl@mark\relax \else \begin{scope} \pgfplothandlermark{\dtl@mark}% \dtl@stream \pgfusepath{stroke} \end{scope} \fi }% % \end{macrocode} % Plot legend if required. % \begin{macrocode} \ifcase\dtl@legendsetting % none \or % north \pgftext[top,center,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLmaxY}} {\pgfpoint{0.5\DTLplotwidth}{-\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % north east \pgftext[top,right,at={\pgfpointadd {\pgfpointxy{\DTLmaxX}{\DTLmaxY}} {\pgfpoint{-\DTLlegendxoffset}{-\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % east \pgftext[center,right,at={\pgfpointadd {\pgfpointxy{\DTLmaxX}{\DTLminY}} {\pgfpoint{-\DTLlegendxoffset}{0.5\DTLplotheight}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % south east \pgftext[bottom,right,at={\pgfpointadd {\pgfpointxy{\DTLmaxX}{\DTLminY}} {\pgfpoint{-\DTLlegendxoffset}{\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % south \pgftext[center,bottom,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLminY}} {\pgfpoint{0.5\DTLplotwidth}{\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % south west \pgftext[bottom,left,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLminY}} {\pgfpoint{\DTLlegendxoffset}{\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % west \pgftext[center,left,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLminY}} {\pgfpoint{\DTLlegendxoffset}{0.5\DTLplotheight}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \or % north west \pgftext[top,left,at={\pgfpointadd {\pgfpointxy{\DTLminX}{\DTLmaxY}} {\pgfpoint{\DTLlegendxoffset}{-\DTLlegendyoffset}}}] {\DTLformatlegend {\begin{tabular}{cl}\dtl@legend\end{tabular}}} \fi \DTLplotatendtikz \end{tikzpicture} \fi \fi \fi }} % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@getbounds} % Extract bounds: % \begin{macrocode} \def\dtl@getbounds#1,#2,#3,#4\@nil{% \def\DTLminX{#1}% \def\DTLminY{#2}% \def\DTLmaxX{#3}% \def\DTLmaxY{#4}% \FPifgt{\DTLminX}{\DTLmaxX} \PackageError{dataplot}{Min X > Max X in bounds #1,#2,#3,#4}{% The bounds must be specified as minX,minY,maxX,maxY}% \fi \FPifgt{\DTLminY}{\DTLmaxY} \PackageError{dataplot}{Min Y > Max Y in bounds #1,#2,#3,#4}{% The bounds must be specified as minX,minY,maxX,maxY}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@constructticklist} %\begin{definition} %\cs{dtl@constructticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} %\end{definition} % Constructs a list of tick points between \meta{min} and \meta{max} % and store in \meta{list} (a control sequence.) % \begin{macrocode} \newcommand*{\dtl@constructticklist}[4]{% \DTLifFPopenbetween{0}{#1}{#2}{% \FPsub{\@dtl@width}{0}{#1}% \FPmul{\@dtl@width}{\@dtl@width}{#3}% \FPdiv{\@dtl@neggap}{\@dtl@width}{10}% \setlength\dtl@tmplength{\@dtl@neggap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@neggap}{\@dtl@width}{4}% \setlength\dtl@tmplength{\@dtl@neggap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@neggap}{\@dtl@width}{2}% \setlength\dtl@tmplength{\@dtl@neggap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \let\@dtl@neggap=\@dtl@width \fi \fi \fi \FPmul{\@dtl@width}{#2}{#3}% \FPdiv{\@dtl@posgap}{\@dtl@width}{10}% \setlength\dtl@tmplength{\@dtl@posgap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@posgap}{\@dtl@width}{4}% \setlength\dtl@tmplength{\@dtl@posgap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@posgap}{\@dtl@width}{2}% \setlength\dtl@tmplength{\@dtl@posgap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \let\@dtl@posgap=\@dtl@width \fi \fi \fi \FPmax{\@dtl@gap}{\@dtl@neggap}{\@dtl@posgap}% \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% \dtl@constructticklistwithgapz{#1}{#2}{#4}{\@dtl@gap}% }{% \FPsub{\@dtl@width}{#2}{#1}% \FPmul{\@dtl@width}{\@dtl@width}{#3}% \FPdiv{\@dtl@gap}{\@dtl@width}{10}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@gap}{\@dtl@width}{4}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \FPdiv{\@dtl@gap}{\@dtl@width}{2}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLmintickgap \let\@dtl@gap=\@dtl@width \fi \fi \fi \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% \dtl@constructticklistwithgap{#1}{#2}{#4}{\@dtl@gap}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@constructticklistwithgap} %\begin{definition} %\cs{dtl@constructticklistwithgap}\marg{min}\marg{max}\marg{list}\marg{gap} %\end{definition} % Constructs a list of tick points between \meta{min} and \meta{max} % and store in \meta{list} (a control sequence) using the gap given % by \meta{gap} where the gap is given in user co-ordinates. % \begin{macrocode} \newcommand*{\dtl@constructticklistwithgap}[4]{% \edef\@dtl@thistick{#1}% \edef#3{#1}% \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{% \expandafter\toks@\expandafter{\@dtl@thistick}% \edef#3{#3,\the\toks@}% \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% }% \expandafter\toks@\expandafter{#2}% \edef#3{#3,\the\toks@}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@constructticklistwithgapz} %\begin{definition} %\cs{dtl@constructticklistwithgapz}\marg{min}\marg{max}\marg{list}\marg{gap} %\end{definition} % Constructs a list of tick points between \meta{min} and \meta{max} % and store in \meta{list} (a control sequence) using the gap given % by \meta{gap} where the tick list straddles zero. % \begin{macrocode} \newcommand*{\dtl@constructticklistwithgapz}[4]{% \edef\@dtl@thistick{0}% \edef#3{0}% \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{0}{#2}}{% \expandafter\toks@\expandafter{\@dtl@thistick}% \edef#3{#3,\the\toks@}% \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% }% \expandafter\toks@\expandafter{#2}% \edef#3{#3,\the\toks@}% \FPifeq{#1}{0}% \else \edef\@dtl@thistick{0}% \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{0}}{% \expandafter\toks@\expandafter{\@dtl@thistick}% \edef#3{\the\toks@,#3}% \FPsub{\@dtl@thistick}{\@dtl@thistick}{#4}% }% \expandafter\toks@\expandafter{#1}% \edef#3{\the\toks@,#3}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@constructminorticklist} %\begin{definition} %\cs{dtl@constructminorticklist}\marg{min}\marg{max}\marg{scale factor}\marg{list} %\end{definition} % Constructs a list of minor tick points between \meta{min} and \meta{max} % and append to \meta{list} (a control sequence.) % \begin{macrocode} \newcommand*{\dtl@constructminorticklist}[4]{% \FPsub{\@dtl@width}{#2}{#1}% \FPmul{\@dtl@width}{\@dtl@width}{#3}% \FPdiv{\@dtl@gap}{\@dtl@width}{10}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLminminortickgap \FPdiv{\@dtl@gap}{\@dtl@width}{4}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLminminortickgap \FPdiv{\@dtl@gap}{\@dtl@width}{2}% \setlength\dtl@tmplength{\@dtl@gap sp}% \ifdim\dtl@tmplength<\DTLminminortickgap \let\@dtl@gap=\@dtl@width \fi \fi \fi \FPdiv{\@dtl@gap}{\@dtl@gap}{#3}% \dtl@constructticklistwithgapex{#1}{#2}{\dtl@tmp}{\@dtl@gap}% \ifx#4\@empty \let#4=\dtl@tmp \else \expandafter\toks@\expandafter{#4}% \edef#4{#4,\dtl@tmp}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@constructticklistwithgapex} %\begin{definition} %\cs{dtl@constructticklistwithgapex}\marg{min}\marg{max}\marg{list}\marg{gap} %\end{definition} % Constructs a list of tick points between \meta{min} and \meta{max} % and store in \meta{list} (a control sequence) using the gap given % by \meta{gap} where the gap is given in user co-ordinates. % The end points are excluded from the list. % \begin{macrocode} \newcommand*{\dtl@constructticklistwithgapex}[4]{% \edef\@dtl@thistick{#1}% \let#3=\@empty \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% \whiledo{\DTLisFPopenbetween{\@dtl@thistick}{#1}{#2}}{% \expandafter\toks@\expandafter{\@dtl@thistick}% \ifx#3\@empty \edef#3{\the\toks@}% \else \edef#3{#3,\the\toks@}% \fi \FPadd{\@dtl@thistick}{\@dtl@thistick}{#4}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLaddtoplotlegend} %\begin{definition} %\cs{DTLaddtoplotlegend}\marg{marker}\marg{line style}\marg{label} %\end{definition} % Adds entry to legend. % \begin{macrocode} \newcommand*{\DTLaddtoplotlegend}[3]{% \def\dtl@legendline{}% \ifx\relax#2\relax \else \toks@{#2% \pgfpathmoveto{\pgfpoint{-10pt}{0pt}}% \pgfpathlineto{\pgfpoint{10pt}{0pt}}% \pgfusepath{stroke}}% \edef\dtl@legendline{\the\toks@}% \fi \ifx\relax#1\relax \else \toks@{#1}% \expandafter\@dtl@toks\expandafter{\dtl@legendline}% \edef\dtl@legendline{\the\@dtl@toks\the\toks@}% \fi \expandafter\toks@\expandafter{\dtl@legendline}% \ifx\dtl@legend\@empty \edef\dtl@legend{\noexpand\tikz\the\toks@; \noexpand& #3}% \else \expandafter\@dtl@toks\expandafter{\dtl@legend}% \edef\dtl@legend{\the\@dtl@toks\noexpand\\% \noexpand\tikz\the\toks@; \noexpand& #3}% \fi } % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*databar.sty> % \end{macrocode} %\fi %\section{databar.sty} % Declare package: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{databar}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} % Require \sty{xkeyval} package % \begin{macrocode} \RequirePackage{xkeyval} % \end{macrocode} % Require \sty{dataplot} package % \begin{macrocode} \RequirePackage{dataplot} % \end{macrocode} %\begin{macro}{\ifDTLcolorbarchart} % The conditional \cs{ifDTLcolorbarchart} is used to determine % whether to use colour or grey scale. % \begin{macrocode} \newif\ifDTLcolorbarchart \DTLcolorbarcharttrue % \end{macrocode} %\end{macro} % Package options to change the conditional: % \begin{macrocode} \DeclareOption{color}{\DTLcolorbarcharttrue} \DeclareOption{gray}{\DTLcolorbarchartfalse} % \end{macrocode} %\cs{DTLbarXlabelalign} specifies the alignment % for the $x$ axis labels. % \begin{macrocode} \newcommand*{\DTLbarXlabelalign}{left,rotate=-90} % \end{macrocode} %\cs{DTLbarYticklabelalign} specifies the alignment % for the $x$ axis labels. % \begin{macrocode} \newcommand*{\DTLbarYticklabelalign}{right} % \end{macrocode} %\begin{macro}{\ifDTLverticalbars} % Define boolean keys to govern bar chart orientation. % \begin{macrocode} \define@boolkey{databar}[DTL]{verticalbars}[true]{% \ifDTLverticalbars \def\DTLbarXlabelalign{left,rotate=-90}% \def\DTLbarYticklabelalign{right} \else \def\DTLbarXlabelalign{right}% \def\DTLbarYticklabelalign{center} \fi} % \end{macrocode} %\end{macro} % Set defaults: % \begin{macrocode} \DTLverticalbarstrue % \end{macrocode} % Package options to change \cs{ifDTLverticalbars} % \begin{macrocode} \DeclareOption{vertical}{\DTLverticalbarstrue \def\DTLbarXlabelalign{left,rotate=-90}% \def\DTLbarYticklabelalign{right} } \DeclareOption{horizontal}{\DTLverticalbarsfalse \def\DTLbarXlabelalign{right}% \def\DTLbarYticklabelalign{center} } % \end{macrocode} % Process options: % \begin{macrocode} \ProcessOptions % \end{macrocode} % Required packages: % \begin{macrocode} \RequirePackage{datatool} \RequirePackage{tikz} % \end{macrocode} % Define some variables that govern the appearance of the bar % chart. % %\begin{macro}{\DTLbarchartlength} % The total height of the bar chart is given by \cs{DTLbarchartheight} % \begin{macrocode} \newlength\DTLbarchartlength \DTLbarchartlength=3in % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbarwidth} % The width of each bar is given by \cs{DTLbarwidth}. % \begin{macrocode} \newlength\DTLbarwidth \DTLbarwidth=1cm % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbarlabeloffset} % The offset from the $x$ axis to the bar label if given by % \cs{DTLbarlabeloffset}. % \begin{macrocode} \newlength\DTLbarlabeloffset \setlength\DTLbarlabeloffset{10pt} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLBarXAxisStyle} % The style of the $x$ axis is given by \cs{DTLBarXAxisStyle} % \begin{macrocode} \newcommand*{\DTLBarXAxisStyle}{-} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLBarYAxisStyle} % The style of the $y$ axis is given by \cs{DTLBarYAxisStyle}. % \begin{macrocode} \newcommand*{\DTLBarYAxisStyle}{-} % \end{macrocode} %\end{macro} % %\begin{counter}{DTLbarroundvar} % \ctrfmt{DTLbarroundvar} is a counter governing the number of digits % to round to when using \cs{FPround}. % \begin{macrocode} \newcounter{DTLbarroundvar} \setcounter{DTLbarroundvar}{1} % \end{macrocode} %\end{counter} % %\begin{macro}{\DTLbardisplayYticklabel} %\cs{DTLbardisplayYticklabel} governs how the $y$ tick labels appear. % \begin{macrocode} \newcommand*{\DTLbardisplayYticklabel}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdisplaylowerbarlabel} %\cs{DTLdisplaylowerbarlabel} governs how the lower bar labels appear. % \begin{macrocode} \newcommand*{\DTLdisplaylowerbarlabel}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdisplaylowermultibarlabel} %\cs{DTLdisplaylowermultibarlabel} governs how the lower multi bar labels appear. % \begin{macrocode} \newcommand*{\DTLdisplaylowermultibarlabel}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdisplayupperbarlabel} %\cs{DTLdisplayupperbarlabel} governs how the upper bar labels % appear. % \begin{macrocode} \newcommand*{\DTLdisplayupperbarlabel}[1]{#1} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLdisplayuppermultibarlabel} %\cs{DTLdisplayuppermultibarlabel} governs how the upper multi bar % labels appear. % \begin{macrocode} \newcommand*{\DTLdisplayuppermultibarlabel}[1]{#1} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbaratbegintikz} % \cs{DTLbaratbegintikz} specifies any commands % to apply at the start of the \env{tikzpicture} environment. % By default it does nothing. % \begin{macrocode} \newcommand*{\DTLbaratbegintikz}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbaratendtikz} % \cs{DTLbaratendtikz} specifies any commands % to apply at the end of the \env{tikzpicture} environment. % By default it does nothing. % \begin{macrocode} \newcommand*{\DTLbaratendtikz}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifDTLbarxaxis} % The conditional \cs{ifDTLbarxaxis} is used to determine % whether or not to display the $x$ axis % \begin{macrocode} \newif\ifDTLbarxaxis % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLbaryaxis} % The conditional \cs{ifDTLbaryaxis} is used to determine % whether or not to display the $y$ axis. % \begin{macrocode} \newif\ifDTLbaryaxis % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLbarytics} % The conditional \cs{ifDTLbarytics} to determine whether % or not to display the $y$ tick marks. % \begin{macrocode} \newif\ifDTLbarytics % \end{macrocode} %\end{macro} % %\begin{macro}{\@dtl@barcount} % The count register \cs{@dtl@barcount} is used to store % the current bar index. % \begin{macrocode} \newcount\@dtl@barcount % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsetbarcolor} %\begin{definition} % \cs{DTLsetbarcolor}\marg{n}\marg{color} %\end{definition} % Assigns colour name \meta{color} to the \meta{n}th bar. % \begin{macrocode} \newcommand*{\DTLsetbarcolor}[2]{% \expandafter\def\csname dtlbar@segcol\romannumeral#1\endcsname{#2}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLgetbarcolor} %\begin{definition} %\cs{DTLgetbarcolor}\marg{n} %\end{definition} % Gets the colour specification for the \meta{n}th bar. % \begin{macrocode} \newcommand*{\DTLgetbarcolor}[1]{% \csname dtlbar@segcol\romannumeral#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdobarcolor} %\begin{definition} %\cs{DTLdobarcolor}\marg{n} %\end{definition} % Sets the colour to that for the \meta{n}th bar. % \begin{macrocode} \newcommand*{\DTLdobarcolor}[1]{% \expandafter\color\expandafter {\csname dtlbar@segcol\romannumeral#1\endcsname}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLdocurrentbarcolor} %\cs{DTLdocurrentbarcolor} % sets the colour to that of the current bar. % \begin{macrocode} \newcommand*{\DTLdocurrentbarcolor}{% \ifnum\dtlforeachlevel=0\relax \PackageError{databar}{Can't use \string\DTLdocurrentbarcolor\space outside \string\DTLbarchart}{}% \else \expandafter\DTLdobarcolor\expandafter{% \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname}% \fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbaroutlinecolor} %\cs{DTLbaroutlinecolor} specifies what colour to draw the % outline. % \begin{macrocode} \newcommand*{\DTLbaroutlinecolor}{black} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbaroutlinewidth} %\cs{DTLbaroutlinewidth} specifies the line width of the outline: % Outline is only drawn if the linewidth is greater than 0pt. % \begin{macrocode} \newlength\DTLbaroutlinewidth \DTLbaroutlinewidth=0pt % \end{macrocode} %\end{macro} % % Set the default colours. If there are more than eight bars, % more colours will need to be defined. % \begin{macrocode} \ifDTLcolorbarchart \DTLsetbarcolor{1}{red} \DTLsetbarcolor{2}{green} \DTLsetbarcolor{3}{blue} \DTLsetbarcolor{4}{yellow} \DTLsetbarcolor{5}{magenta} \DTLsetbarcolor{6}{cyan} \DTLsetbarcolor{7}{orange} \DTLsetbarcolor{8}{white} \else \DTLsetbarcolor{1}{black!15} \DTLsetbarcolor{2}{black!25} \DTLsetbarcolor{3}{black!35} \DTLsetbarcolor{4}{black!45} \DTLsetbarcolor{5}{black!55} \DTLsetbarcolor{6}{black!65} \DTLsetbarcolor{7}{black!75} \DTLsetbarcolor{8}{black!85} \fi % \end{macrocode} %\begin{macro}{\DTLeverybarhook} % Code to apply at every bar. The start point of the bar % can be accessed via \cs{DTLstartpt}, the mid point of the bar % can be accessed via \cs{DTLmidpt} and the end point of the % bar can be accessed via \cs{DTLendpt} %\changes{2.0}{2009 February 27}{new}% % \begin{macrocode} \newcommand*{\DTLeverybarhook}{} % \end{macrocode} %\end{macro} % % Define keys for \cs{DTLbarchart} optional argument. % Set the maximum value of the $y$ axis. % \begin{macrocode} \define@key{databar}{max}{\def\DTLbarmax{#1}} % \end{macrocode} % Set the total length of the bar chart % \begin{macrocode} \define@key{databar}{length}{\DTLbarchartlength=#1\relax } % \end{macrocode} % Set the maximum depth (negative extent) % \begin{macrocode} \define@key{databar}{maxdepth}{% \ifnum#1>0\relax \PackageError{databar}{depth must be zero or negative}{}% \else \def\DTLnegextent{#1}% \fi} % \end{macrocode} % Determine which axes should be shown % \begin{macrocode} \define@choicekey{databar}{axes}[\var\nr]{both,x,y,none}{% \ifcase\nr\relax % both \DTLbarxaxistrue \DTLbaryaxistrue \DTLbaryticstrue \or % x only \DTLbarxaxistrue \DTLbaryaxisfalse \DTLbaryticsfalse \or % y only \DTLbarxaxisfalse \DTLbaryaxistrue \DTLbaryticstrue \or % neither \DTLbarxaxisfalse \DTLbaryaxisfalse \DTLbaryticsfalse \fi } % \end{macrocode} % Variable used to create the bar chart. (Must be a control % sequence.) % \begin{macrocode} \define@key{databar}{variable}{% \def\DTLbarvariable{#1}} % \end{macrocode} % Variables used to create the multi bar chart. (Must be a % comma separated list of control sequences.) % \begin{macrocode} \define@key{databar}{variables}{% \def\dtlbar@variables{#1}} % \end{macrocode} % Bar width % \begin{macrocode} \define@key{databar}{barwidth}{\setlength{\DTLbarwidth}{#1}} % \end{macrocode} % Lower bar labels % \begin{macrocode} \define@key{databar}{barlabel}{% \def\dtl@barlabel{#1}} \def\dtl@barlabel{} % \end{macrocode} % Lower bar labels for multi-bar charts % \begin{macrocode} \define@key{databar}{multibarlabels}{% \def\dtl@multibarlabels{#1}} \def\dtl@multibarlabels{} % \end{macrocode} % Gap between groups in multi-bar charts (This should be in $x$ units % where 1 $x$ unit is the width of a bar.) % \begin{macrocode} \define@key{databar}{groupgap}{\def\dtlbar@groupgap{#1}} \def\dtlbar@groupgap{1} % \end{macrocode} % Upper bar labels % \begin{macrocode} \define@key{databar}{upperbarlabel}{% \def\dtl@upperbarlabel{#1}} \def\dtl@upperbarlabel{} % \end{macrocode} % Upper bar labels for multi-bar charts % \begin{macrocode} \define@key{databar}{uppermultibarlabels}{% \def\dtl@uppermultibarlabels{#1}} \def\dtl@uppermultibarlabels{} % \end{macrocode} % Define list of points for $y$ tics. (Must be a comma separated list % of decimal numbers.) % \begin{macrocode} \define@key{databar}{yticpoints}{% \def\dtlbar@yticlist{#1}\DTLbaryticstrue\DTLbaryaxistrue} \let\dtlbar@yticlist=\relax % \end{macrocode} % Set the $y$ tick gap: % \begin{macrocode} \define@key{databar}{yticgap}{% \def\dtlbar@yticgap{#1}\DTLbaryticstrue\DTLbaryaxistrue} \let\dtlbar@yticgap=\relax % \end{macrocode} % Define list of labels for $y$ tics. % \begin{macrocode} \define@key{databar}{yticlabels}{% \def\dtlbar@yticlabels{#1}\DTLbaryticstrue\DTLbaryaxistrue} \let\dtlbar@yticlabels=\relax % \end{macrocode} % Define $y$ axis label. % \begin{macrocode} \define@key{databar}{ylabel}{% \def\dtlbar@ylabel{#1}} \let\dtlbar@ylabel=\relax % \end{macrocode} % %\begin{macro}{\DTLbarchart} %\begin{definition} % \cs{DTLbarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} %\end{definition} % Make a bar chart from data given in data base \meta{db name}, % where \meta{assign list} is a comma-separated list of % \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must % include \texttt{variable}\texttt{=}\meta{cmd}, where \meta{cmd} % is included in \meta{assign list}. The optional argument % \meta{conditions} is the same as that for \cs{DTLforeach}. % \begin{macrocode} \newcommand*{\DTLbarchart}[4][\boolean{true}]{% {\let\DTLbarvariable=\relax \let\DTLbarmax=\relax \let\DTLnegextent=\relax \disable@keys{databar}{variables,multibarlabels,% uppermultibarlabels,groupgap}% \setkeys{databar}{#2}% \ifx\DTLbarvariable\relax \PackageError{databar}{\string\DTLbarchart\space missing variable}{You haven't use the "variable" key}% \else % \end{macrocode} % Compute the maximum bar height, unless \cs{DTLbarmax} has been % set. %\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of %\cs{DTLforeach}} % \begin{macrocode} \ifx\DTLbarmax\relax \@sDTLforeach[#1]{#3}{#4}{% \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@barvar}% \ifx\DTLbarmax\relax \let\DTLbarmax=\dtl@barvar \else \let\dtl@old=\DTLbarmax \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% \fi }% \ifx\dtlbar@yticgap\relax \else \let\dtl@thistick=\dtlbar@yticgap% \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% }% \let\DTLbarmax=\dtl@thistick \fi \fi % \end{macrocode} % Compute the bar depth, unless \cs{DTLnegextent} has been % set. % \begin{macrocode} \ifx\DTLnegextent\relax \def\DTLnegextent{0}% \@sDTLforeach[#1]{#3}{#4}{% \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@barvar}% \let\dtl@old=\DTLnegextent \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% }% \ifx\dtlbar@yticgap\relax \else \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% \edef\dtl@thistick{0}% \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% }% \let\DTLnegextent=\dtl@thistick }{}% \fi \fi % \end{macrocode} % Determine scaling factor % \begin{macrocode} \@dtl@tmpcount=\DTLbarchartlength \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% % \end{macrocode} % Construct $y$ tick list if required % \begin{macrocode} \setlength{\dtl@yticlabelwidth}{0pt}% \ifDTLbarytics \ifx\dtlbar@yticlist\relax \ifx\dtlbar@yticgap\relax \dtl@constructticklist\DTLnegextent\DTLbarmax \dtl@unit\dtlbar@yticlist \else \dtl@constructticklistwithgapz \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap \fi \fi \ifx\dtlbar@ylabel\relax \else \ifx\dtlbar@yticlabels\relax \@for\dtl@thislabel:=\dtlbar@yticlist\do{% \FPround{\dtl@thislabel}{\dtl@thislabel} {\c@DTLbarroundvar}% \ifDTLverticalbars \settowidth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \else \settoheight{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \edef\@dtl@h{\the\dtl@tmplength}% \settodepth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \addtolength{\dtl@tmplength}{\@dtl@h}% \addtolength{\dtl@tmplength}{\baselineskip}% \fi \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \else \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% \ifDTLverticalbars \settowidth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \else \settoheight{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \edef\@dtl@h{\the\dtl@tmplength}% \settodepth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \addtolength{\dtl@tmplength}{\@dtl@h}% \addtolength{\dtl@tmplength}{\baselineskip}% \fi \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \fi \fi \fi % \end{macrocode} % Store the width of the bar chart in \cs{DTLbarchartwidth} % \begin{macrocode} \edef\DTLbarchartwidth{\expandafter\number\csname dtlrows@#3\endcsname} % \end{macrocode} % Do the bar chart % \begin{macrocode} \begin{tikzpicture} % \end{macrocode} % Set unit vectors % \begin{macrocode} \ifDTLverticalbars \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% \else \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% \fi % \end{macrocode} % Begin hook % \begin{macrocode} \DTLbaratbegintikz % \end{macrocode} % Initialise % \begin{macrocode} \def\@dtl@start{0}% % \end{macrocode} % Iterate through data % \begin{macrocode} \@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} % Store the bar number in \cs{@dtl@bar} % \begin{macrocode} \expandafter\let\expandafter\@dtl@bar \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname% % \end{macrocode} % Convert variable to decimal % \begin{macrocode} \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@variable}% % \end{macrocode} % Draw bars % \begin{macrocode} \begin{scope} \DTLdocurrentbarcolor \ifDTLverticalbars \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; \else \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; \fi \end{scope} % \end{macrocode} % Draw outline % \begin{macrocode} \begin{scope} \ifdim\DTLbaroutlinewidth>0pt \expandafter\color\expandafter{\DTLbaroutlinecolor} \ifDTLverticalbars \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) -- (\@dtl@bar,\dtl@variable) -- (\@dtl@bar,0) -- cycle; \else \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) -- (\dtl@variable,\@dtl@bar) -- (0,\@dtl@bar) -- cycle; \fi \fi \end{scope} % \end{macrocode} % Draw lower $x$ labels % \begin{macrocode} \ifDTLverticalbars \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@start.5}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, \DTLbarXlabelalign }% % \end{macrocode} % Set \cs{DTLstartpt} to the starting point. % \begin{macrocode} \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@start.5}{0}}% \else \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{0}{\@dtl@start.5}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, \DTLbarXlabelalign }% % \end{macrocode} % Set \cs{DTLstartpt} to the starting point. % \begin{macrocode} \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@start.5}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLdisplaylowerbarlabel{\dtl@barlabel}} % \end{macrocode} % Draw upper $x$ labels % \begin{macrocode} \ifDTLverticalbars % \end{macrocode} % Vertical bars % \begin{macrocode} \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} }% }{% \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} }% } % \end{macrocode} % Set \cs{DTLendpt} to the end point. % \begin{macrocode} \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@start.5}{\dtl@variable}}% \else % \end{macrocode} % Horizontal bars % \begin{macrocode} \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{right, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} }% }{% \edef\dtl@textopt{left, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}} {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} }% } % \end{macrocode} % Set \cs{DTLendpt} to the end point. % \begin{macrocode} \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@start.5}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLdisplayupperbarlabel{\dtl@upperbarlabel}} % \end{macrocode} % Set the mid point % \begin{macrocode} \def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% % \end{macrocode} % Do every bar hook %\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \begin{macrocode} \DTLeverybarhook % \end{macrocode} % End of loop % \begin{macrocode} \edef\@dtl@start{\number\@dtl@bar}% } % \end{macrocode} % Draw $x$ axis % \begin{macrocode} \ifDTLbarxaxis \ifDTLverticalbars \expandafter\draw\expandafter[\DTLBarXAxisStyle] (0,0) -- (\DTLbarchartwidth,0); \else \expandafter\draw\expandafter[\DTLBarXAxisStyle] (0,0) -- (0,\DTLbarchartwidth); \fi \fi % \end{macrocode} % Draw $y$ axis % \begin{macrocode} \ifDTLbaryaxis \ifDTLverticalbars \expandafter\draw\expandafter[\DTLBarYAxisStyle] (0,\DTLnegextent) -- (0,\DTLbarmax); \else \expandafter\draw\expandafter[\DTLBarYAxisStyle] (\DTLnegextent,0) -- (\DTLbarmax,0); \fi \fi % \end{macrocode} % Plot $y$ tick marks if required % \begin{macrocode} \ifx\dtlbar@yticlist\relax \else \@for\dtl@thistick:=\dtlbar@yticlist\do{% \ifDTLverticalbars \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} \pgfpathlineto{ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} {\pgfpoint{-\DTLticklength}{0pt}}} \else \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} {\pgfpoint{0pt}{-\DTLticklength}}} \fi \pgfusepath{stroke} \ifx\dtlbar@yticlabels\relax \FPround{\dtl@thislabel}{\dtl@thistick} {\c@DTLbarroundvar}% \else \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest \let\dtlbar@yticlabels=\dtl@rest \fi \ifDTLverticalbars \edef\dtl@textopt{\DTLbarYticklabelalign,% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{0}{\dtl@thistick}} {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, }}% \else \edef\dtl@textopt{\DTLbarYticklabelalign, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@thistick}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} }}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLbardisplayYticklabel{\dtl@thislabel}} }% \fi % \end{macrocode} % Plot the $y$ label if required % \begin{macrocode} \ifx\dtlbar@ylabel\relax \else \addtolength{\dtl@yticlabelwidth}{\baselineskip}% \setlength{\dtl@tmplength}{0.5\DTLbarchartlength} \ifDTLverticalbars \pgftext[bottom,center,at={\pgfpointadd {\pgfpointxy{0}{\DTLnegextent}}% {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, rotate=90]{% \dtlbar@ylabel} \else \pgftext[bottom,center,at={\pgfpointadd {\pgfpointxy{\DTLnegextent}{0}}% {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{% \dtlbar@ylabel} \fi \fi % \end{macrocode} % Finish bar chart % \begin{macrocode} \DTLbaratendtikz \end{tikzpicture} \fi }} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmultibarchart} %\begin{definition} % \cs{DTLmultibarchart}\oarg{conditions}\marg{option list}\marg{db name}\marg{assign list} %\end{definition} % Make a multi-bar chart from data given in data base \meta{db name}, % where \meta{assign list} is a comma-separated list of % \meta{cmd}\texttt{=}\meta{key} pairs. \meta{option list} must % include the \texttt{variables} key which must be a comma separated % list of commands, where each command % is included in \meta{assign list}. The optional argument % \meta{conditions} is the same as that for \cs{DTLforeach}. % \begin{macrocode} \newcommand*{\DTLmultibarchart}[4][\boolean{true}]{% {\let\dtlbar@variables=\relax \let\DTLbarmax=\relax \let\DTLnegextent=\relax \disable@keys{databar}{variable,upperbarlabel}% \setkeys{databar}{#2}% \ifx\dtlbar@variables\relax \PackageError{databar}{\string\DTLmultibarchart\space missing variables setting}{}% \else % \end{macrocode} % Compute the maximum bar height, unless \cs{DTLbarmax} has been % set. %\changes{1.01}{2007 Aug 17}{uses \cs{@sDTLforeach} instead of %\cs{DTLforeach}} % \begin{macrocode} \ifx\DTLbarmax\relax \@sDTLforeach[#1]{#3}{#4}{% \@for\DTLbarvariable:=\dtlbar@variables\do{% \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@barvar}% \ifx\DTLbarmax\relax \let\DTLbarmax=\dtl@barvar \else \let\dtl@old=\DTLbarmax \FPmax{\DTLbarmax}{\dtl@old}{\dtl@barvar}% \fi }% }% \ifx\dtlbar@yticgap\relax \else \let\dtl@thistick=\dtlbar@yticgap% \whiledo{\DTLisFPopenbetween{\dtl@thistick}{0}{\DTLbarmax}}{% \FPadd{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% }% \let\DTLbarmax=\dtl@thistick \fi \fi % \end{macrocode} % Compute the bar depth, unless \cs{DTLnegextent} has been % set. % \begin{macrocode} \ifx\DTLnegextent\relax \def\DTLnegextent{0}% \@sDTLforeach[#1]{#3}{#4}{% \@for\DTLbarvariable:=\dtlbar@variables\do{% \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@barvar}% \let\dtl@old=\DTLnegextent \DTLmin{\DTLnegextent}{\dtl@old}{\dtl@barvar}% }% }% \ifx\dtlbar@yticgap\relax \else \ifthenelse{\DTLisFPlt{\DTLnegextent}{0}}{% \edef\dtl@thistick{0}% \whiledo{\DTLisFPclosedbetween{\dtl@thistick}{\DTLnegextent}{0}}{% \FPsub{\dtl@thistick}{\dtl@thistick}{\dtlbar@yticgap}% }% \let\DTLnegextent=\dtl@thistick }{}% \fi \fi % \end{macrocode} % Determine scaling factor % \begin{macrocode} \@dtl@tmpcount=\DTLbarchartlength \FPsub{\dtl@extent}{\DTLbarmax}{\DTLnegextent}% \FPdiv{\dtl@unit}{\number\@dtl@tmpcount}{\dtl@extent}% % \end{macrocode} % Construct $y$ tick list if required % \begin{macrocode} \setlength{\dtl@yticlabelwidth}{0pt}% \ifDTLbarytics \ifx\dtlbar@yticlist\relax \ifx\dtlbar@yticgap\relax \dtl@constructticklist\DTLnegextent\DTLbarmax \dtl@unit\dtlbar@yticlist \else \dtl@constructticklistwithgapz \DTLnegextent\DTLbarmax\dtlbar@yticlist\dtlbar@yticgap \fi \fi \ifx\dtlbar@ylabel\relax \else \ifx\dtlbar@yticlabels\relax \@for\dtl@thislabel:=\dtlbar@yticlist\do{% \FPround{\dtl@thislabel}{\dtl@thislabel} {\c@DTLbarroundvar}% \ifDTLverticalbars \settowidth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \else \settoheight{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \edef\@dtl@h{\the\dtl@tmplength}% \settodepth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \addtolength{\dtl@tmplength}{\@dtl@h}% \addtolength{\dtl@tmplength}{\baselineskip}% \fi \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \else \@for\dtl@thislabel:=\dtlbar@yticlabels\do{% \ifDTLverticalbars \settowidth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \else \settoheight{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \edef\@dtl@h{\the\dtl@tmplength}% \settodepth{\dtl@tmplength}{% \DTLbardisplayYticklabel{\dtl@thislabel}}% \addtolength{\dtl@tmplength}{\@dtl@h}% \addtolength{\dtl@tmplength}{\baselineskip}% \fi \ifdim\dtl@tmplength>\dtl@yticlabelwidth \setlength{\dtl@yticlabelwidth}{\dtl@tmplength}% \fi }% \fi \fi \fi % \end{macrocode} % Calculate the offset for the lower label and number of labels % \begin{macrocode} \dtl@xticlabelheight=0pt\relax \@dtl@tmpcount=0\relax \@for\dtl@thislabel:=\dtl@multibarlabels\do{% \advance\@dtl@tmpcount by 1\relax \settoheight{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% \edef\@dtl@h{\the\dtl@tmplength}% \settodepth{\dtl@tmplength}{\tikz\expandafter\pgftext\expandafter [\DTLbarXlabelalign]{\DTLdisplaylowerbarlabel{\dtl@thislabel}};}% \addtolength{\dtl@tmplength}{\@dtl@h}% \addtolength{\dtl@tmplength}{\baselineskip}% \ifdim\dtl@tmplength>\dtl@xticlabelheight \setlength{\dtl@xticlabelheight}{\dtl@tmplength}% \fi } % \end{macrocode} % Calculate number of bars per group % \begin{macrocode} \@dtl@tmpcount=0\relax \@for\dtl@this:=\dtlbar@variables\do{% \advance\@dtl@tmpcount by 1\relax }% \edef\DTLbargroupwidth{\number\@dtl@tmpcount}% % \end{macrocode} % Compute the total width of the bar chart (in terms of % the $x$ unit vector.) % \begin{macrocode} \edef\dtl@n{\expandafter\number\csname dtlrows@#3\endcsname} \FPmul{\dtl@tmpi}{\dtl@n}{\DTLbargroupwidth} \FPsub{\dtl@tmpii}{\dtl@n}{1}% \FPmul{\dtl@tmpii}{\dtl@tmpii}{\dtlbar@groupgap}% \FPadd{\DTLbarchartwidth}{\dtl@tmpi}{\dtl@tmpii} % \end{macrocode} % Do the bar chart % \begin{macrocode} \begin{tikzpicture} % \end{macrocode} % Set unit vectors % \begin{macrocode} \ifDTLverticalbars \pgfsetyvec{\pgfpoint{0pt}{\dtl@unit sp}}% \pgfsetxvec{\pgfpoint{\DTLbarwidth}{0pt}}% \else \pgfsetxvec{\pgfpoint{\dtl@unit sp}{0pt}}% \pgfsetyvec{\pgfpoint{0pt}{\DTLbarwidth}}% \fi % \end{macrocode} % Begin hook % \begin{macrocode} \DTLbaratbegintikz % \end{macrocode} % Initialise % \begin{macrocode} \def\@dtl@start{0}% % \end{macrocode} % Iterate through data % \begin{macrocode} \@sDTLforeach[#1]{#3}{#4}{% % \end{macrocode} % Store the bar number in \cs{@dtl@bar} % \begin{macrocode} \@dtl@barcount = 1\relax % \end{macrocode} % Set the multibar label lists % \begin{macrocode} \let\dtl@multibar@labels=\dtl@multibarlabels \let\dtl@uppermultibar@labels=\dtl@uppermultibarlabels % \end{macrocode} % Compute mid point over group % \begin{macrocode} \FPmul{\dtl@multimidpt}{\DTLbargroupwidth}{0.5}% \FPadd{\dtl@multimidpt}{\dtl@multimidpt}{\@dtl@start}% % \end{macrocode} % Iterate through each variable % \begin{macrocode} \@for\DTLbarvariable:=\dtlbar@variables\do{% % \end{macrocode} % Set end point % \begin{macrocode} \FPadd{\@dtl@endpt}{\@dtl@start}{1}% % \end{macrocode} % Convert variable to decimal % \begin{macrocode} \expandafter\DTLconverttodecimal\expandafter {\DTLbarvariable}{\dtl@variable}% % \end{macrocode} % Get the current lower label: % \begin{macrocode} \dtl@chopfirst\dtl@multibar@labels\dtl@thisbarlabel\dtl@rest \let\dtl@multibar@labels=\dtl@rest % \end{macrocode} % Get the current upper label: % \begin{macrocode} \dtl@chopfirst\dtl@uppermultibar@labels\dtl@thisupperbarlabel\dtl@rest \let\dtl@uppermultibar@labels=\dtl@rest % \end{macrocode} % Draw bars % \begin{macrocode} \begin{scope} \expandafter\color\expandafter{\DTLgetbarcolor{\@dtl@barcount}}% \ifDTLverticalbars \fill (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; \else \fill (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; \fi \end{scope} % \end{macrocode} % Draw outline % \begin{macrocode} \begin{scope} \ifdim\DTLbaroutlinewidth>0pt \expandafter\color\expandafter{\DTLbaroutlinecolor} \ifDTLverticalbars \draw (\@dtl@start,0) -- (\@dtl@start,\dtl@variable) -- (\@dtl@endpt,\dtl@variable) -- (\@dtl@endpt,0) -- cycle; \else \draw (0,\@dtl@start) -- (\dtl@variable,\@dtl@start) -- (\dtl@variable,\@dtl@endpt) -- (0,\@dtl@endpt) -- cycle; \fi \fi \end{scope} % \end{macrocode} % Calculate mid point % \begin{macrocode} \FPadd{\@dtl@midpt}{\@dtl@start}{0.5}% % \end{macrocode} % Draw lower $x$ labels % \begin{macrocode} \ifDTLverticalbars \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@midpt}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}}, \DTLbarXlabelalign }% \edef\DTLstartpt{\noexpand\pgfpointxy{\@dtl@midpt}{0}}% \else \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{0}{\@dtl@midpt}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}}, \DTLbarXlabelalign }% \edef\DTLstartpt{\noexpand\pgfpointxy{0}{\@dtl@midpt}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLdisplaylowermultibarlabel{\dtl@thisbarlabel}} % \end{macrocode} % Draw upper $x$ labels % \begin{macrocode} \ifDTLverticalbars \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLbarlabeloffset}}} }% }{% \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}} {\noexpand\pgfpoint{0pt}{\noexpand\DTLbarlabeloffset}}} }% } \edef\DTLendpt{\noexpand\pgfpointxy{\@dtl@midpt}{\dtl@variable}}% \else \expandafter\DTLifnumlt\expandafter{\DTLbarvariable}{0} { \edef\dtl@textopt{right, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} {\noexpand\pgfpoint{-\noexpand\DTLbarlabeloffset}{0pt}}} }% }{% \edef\dtl@textopt{left, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}} {\noexpand\pgfpoint{\noexpand\DTLbarlabeloffset}{0pt}}} }% } \edef\DTLendpt{\noexpand\pgfpointxy{\dtl@variable}{\@dtl@midpt}}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLdisplayuppermultibarlabel{\dtl@thisupperbarlabel}} % \end{macrocode} % Set the mid point % \begin{macrocode} \def\DTLmidpt{\pgfpointlineattime{0.5}{\DTLstartpt}{\DTLendpt}}% % \end{macrocode} % Do every bar hook %\changes{2.0}{2009 February 27}{added \cs{DTLeverybarhook}}% % \begin{macrocode} \DTLeverybarhook % \end{macrocode} % End of loop increment loop variables % \begin{macrocode} \FPadd{\@dtl@start}{\@dtl@start}{1}% \advance\@dtl@barcount by 1\relax }% % Draw lower group $x$ labels % \begin{macrocode} \setlength{\dtl@tmplength}{\DTLbarlabeloffset}% \addtolength{\dtl@tmplength}{\dtl@xticlabelheight}% \ifDTLverticalbars \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@multimidpt}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\dtl@tmplength}}}, \DTLbarXlabelalign }% \else \edef\dtl@textopt{% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{0}{\dtl@multimidpt}} {\noexpand\pgfpoint{-\noexpand\dtl@tmplength}{0pt}}}, \DTLbarXlabelalign }% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLdisplaylowerbarlabel{\dtl@barlabel}} % \end{macrocode} % Increment starting position by \cs{dtlbar@groupgap} % \begin{macrocode} \FPadd{\@dtl@start}{\@dtl@start}{\dtlbar@groupgap}% } % \end{macrocode} % Draw $x$ axis % \begin{macrocode} \ifDTLbarxaxis \ifDTLverticalbars \expandafter\draw\expandafter[\DTLBarXAxisStyle] (0,0) -- (\DTLbarchartwidth,0); \else \expandafter\draw\expandafter[\DTLBarXAxisStyle] (0,0) -- (0,\DTLbarchartwidth); \fi \fi % \end{macrocode} % Draw $y$ axis % \begin{macrocode} \ifDTLbaryaxis \ifDTLverticalbars \expandafter\draw\expandafter[\DTLBarYAxisStyle] (0,\DTLnegextent) -- (0,\DTLbarmax); \else \expandafter\draw\expandafter[\DTLBarYAxisStyle] (\DTLnegextent,0) -- (\DTLbarmax,0); \fi \fi % \end{macrocode} % Plot $y$ tick marks if required % \begin{macrocode} \ifx\dtlbar@yticlist\relax \else \@for\dtl@thistick:=\dtlbar@yticlist\do{% \ifDTLverticalbars \pgfpathmoveto{\pgfpointxy{0}{\dtl@thistick}} \pgfpathlineto{ \pgfpointadd{\pgfpointxy{0}{\dtl@thistick}} {\pgfpoint{-\DTLticklength}{0pt}}} \else \pgfpathmoveto{\pgfpointxy{\dtl@thistick}{0}} \pgfpathlineto{ \pgfpointadd{\pgfpointxy{\dtl@thistick}{0}} {\pgfpoint{0pt}{-\DTLticklength}}} \fi \pgfusepath{stroke} \ifx\dtlbar@yticlabels\relax \FPround{\dtl@thislabel}{\dtl@thistick} {\c@DTLbarroundvar}% \else \dtl@chopfirst\dtlbar@yticlabels\dtl@thislabel\dtl@rest \let\dtlbar@yticlabels=\dtl@rest \fi \ifDTLverticalbars \edef\dtl@textopt{\DTLbarYticklabelalign,% at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{0}{\dtl@thistick}} {\noexpand\pgfpoint{-\noexpand\DTLticklabeloffset}{0pt}}, }}% \else \edef\dtl@textopt{\DTLbarYticklabelalign, at={\noexpand\pgfpointadd {\noexpand\pgfpointxy{\dtl@thistick}{0}} {\noexpand\pgfpoint{0pt}{-\noexpand\DTLticklabeloffset}} }}% \fi \expandafter\pgftext\expandafter[\dtl@textopt]{% \DTLbardisplayYticklabel{\dtl@thislabel}} }% \fi % \end{macrocode} % Plot the $y$ label if required % \begin{macrocode} \ifx\dtlbar@ylabel\relax \else \addtolength{\dtl@yticlabelwidth}{\baselineskip}% \setlength{\dtl@tmplength}{0.5\DTLbarchartlength} \ifDTLverticalbars \pgftext[bottom,center,at={\pgfpointadd {\pgfpointxy{0}{\DTLnegextent}}% {\pgfpoint{-\dtl@yticlabelwidth}{\dtl@tmplength}}}, rotate=90]{% \dtlbar@ylabel} \else \pgftext[bottom,center,at={\pgfpointadd {\pgfpointxy{\DTLnegextent}{0}}% {\pgfpoint{\dtl@tmplength}{-\dtl@yticlabelwidth}}}]{% \dtlbar@ylabel} \fi \fi % \end{macrocode} % Finish bar chart % \begin{macrocode} \DTLbaratendtikz \end{tikzpicture} \fi }} % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*databib.sty> % \end{macrocode} %\fi %\section{databib.sty} %\label{sec:src:databib} %\subsection{Package Declaration} % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{databib}[2009/10/22 v2.01 (NLCT)] % \end{macrocode} % Load required packages: % \begin{macrocode} \RequirePackage{datatool} % \end{macrocode} %\subsection{Package Options} %\begin{macro}{\dtlbib@style} %The default bib style is stored in \cs{dtlbib@style}. % \begin{macrocode} \newcommand*{\dtlbib@style}{plain} % \end{macrocode} %\end{macro} % The \pkgopt[databib]{style} package option sets \cs{dtlbib@style}. % \begin{macrocode} \define@choicekey{databib.sty}{style}{plain,abbrv,alpha}{% \def\dtlbib@style{#1}} % \end{macrocode} % Process package options: % \begin{macrocode} \ProcessOptionsX % \end{macrocode} %\subsection{Loading BBL file} %\begin{macro}{\DTLloadbbl} %\begin{definition} %\cs{DTLloadbib}\oarg{bbl file}\marg{db name}\marg{bib list} %\end{definition} % \begin{macrocode} \newcommand*{\DTLloadbbl}[3][\jobname.bbl]{% \bibliographystyle{databib}% \if@filesw \immediate\write\@auxout{\string\bibdata{#3}}% \fi \DTLnewdb{#2}% \edef\DTLBIBdbname{#2}% \@input@{#1}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLnewbibrow} % \cs{DTLnewbibrow} adds a new row to the bibliography database. % (\cs{DTLBIBdbname} must be set prior to use to the name % of the \sty{datatool} database which must exist. Any check % to determine its existence should be performed when % \cs{DTLBIBdbname} is set.) %\changes{1.03}{2009 January 27}{removed check if database exists} % \begin{macrocode} \newcommand*{\DTLnewbibrow}{\@DTLnewrow{\DTLBIBdbname}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLnewbibitem} %\begin{definition} %\cs{DTLnewbibitem}\marg{key}\marg{value} %\end{definition} % Adds a new database entry with the given key and value. %\changes{1.03}{2009 January 27}{removed check if database exists} % \begin{macrocode} \newcommand*{\DTLnewbibitem}[2]{% \@DTLnewdbentry{\DTLBIBdbname}{#1}{#2}} % \end{macrocode} %\end{macro} %\subsection{Predefined text} %\label{sec:src:bibnames} %\begin{macro}{\andname} % \begin{macrocode} \providecommand*{\andname}{and} % \end{macrocode} %\end{macro} %\begin{macro}{\ofname} % \begin{macrocode} \providecommand*{\ofname}{of} % \end{macrocode} %\end{macro} %\begin{macro}{\inname} % \begin{macrocode} \providecommand*{\inname}{in} % \end{macrocode} %\end{macro} %\begin{macro}{\etalname} % \begin{macrocode} \providecommand*{\etalname}{et al.} % \end{macrocode} %\end{macro} %\begin{macro}{\editorname} % \begin{macrocode} \providecommand*{\editorname}{editor} % \end{macrocode} %\end{macro} %\begin{macro}{\editorsname} % \begin{macrocode} \providecommand*{\editorsname}{editors} % \end{macrocode} %\end{macro} %\begin{macro}{\volumename} % \begin{macrocode} \providecommand*{\volumename}{volume} % \end{macrocode} %\end{macro} %\begin{macro}{\numbername} % \begin{macrocode} \providecommand*{\numbername}{number} % \end{macrocode} %\end{macro} %\begin{macro}{\pagesname} % \begin{macrocode} \providecommand*{\pagesname}{pages} % \end{macrocode} %\end{macro} %\begin{macro}{\pagename} % \begin{macrocode} \providecommand*{\pagename}{page} % \end{macrocode} %\end{macro} %\begin{macro}{\editionname} % \begin{macrocode} \providecommand*{\editionname}{edition} % \end{macrocode} %\end{macro} %\begin{macro}{\techreportname} % \begin{macrocode} \providecommand*{\techreportname}{Technical report} % \end{macrocode} %\end{macro} %\begin{macro}{\mscthesisname} % \begin{macrocode} \providecommand*{\mscthesisname}{Master's thesis} % \end{macrocode} %\end{macro} %\begin{macro}{\phdthesisname} % \begin{macrocode} \providecommand*{\phdthesisname}{PhD thesis} % \end{macrocode} %\end{macro} % % %\subsection{Displaying the bibliography} %\label{sec:src:displaybib} %\begin{definition} %\cs{DTLbibliography}\marg{bib dbname} %\end{definition} % Displays the bibliography for the database \meta{bib dbname} % which must have previously been loaded using % \cs{DTLloadbbl}. %\begin{macro}{\DTLbibliography} % \begin{macrocode} \newcommand*{\DTLbibliography}[2][\boolean{true}]{% \begin{DTLthebibliography}[#1]{#2}% \DTLforeachbibentry[#1]{#2}{% \DTLbibitem \DTLformatbibentry \DTLendbibitem }% \end{DTLthebibliography}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatbibentry} %\begin{definition} %\cs{DTLformatbibentry} %\end{definition} % Formats the current bib entry. % \begin{macrocode} \newcommand*{\DTLformatbibentry}{% % \end{macrocode} % Check format for this type is defined. % \begin{macrocode} \@ifundefined{DTLformat\DBIBentrytype}% {% \PackageError{databib}{Don't know how to format bibliography entries of type `\DBIBentrytype'}{}% }% {% % \end{macrocode} % Print information to terminal and log file if in verbose mode. % \begin{macrocode} \dtl@message{[\DBIBcitekey]}% % \end{macrocode} % Initialise % \begin{macrocode} \DTLstartsentencefalse\DTLmidsentencefalse\DTLperiodfalse % \end{macrocode} % Format this entry % \begin{macrocode} \csname DTLformat\DBIBentrytype\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLendbibitem} % Hook to add extra information at the end of a bibliography item. % This does nothing by default. % \begin{macrocode} \newcommand*{\DTLendbibitem}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLwidest} %Define a length to store the widest bib entry label % \begin{macrocode} \newlength\dtl@widest % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLcomputewidestbibentry} %\begin{definition} %\cs{DTLcomputewidestbibentry}\marg{conditions}\marg{db %name}\marg{bib label}\marg{cmd} %\end{definition} %Computes the widest bibliography entry over all entries satisfying %\meta{condition} for the database called \meta{db name}, where % the bibliography label is formated according to \meta{bib label} and % stores the result in \meta{cmd} which must be a command name. % \begin{macrocode} \newcommand*{\DTLcomputewidestbibentry}[4]{% \dtl@widest=0pt\relax \let#4=\@empty \DTLforeachbibentry[#1]{#2}{% \settowidth{\dtl@tmplength}{#3}% \ifdim\dtl@tmplength>\dtl@widest\relax \dtl@widest=\dtl@tmplength \protected@edef#4{#3}% \fi }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLforeachbibentry} %\begin{definition} %\cs{DTLforeachbibentry}\oarg{condition}\marg{db name}\marg{text} %\end{definition} %\begin{definition} %\cs{DTLforeachbibentry*}\oarg{condition}\marg{db name}\marg{text} %\end{definition} % Iterates through the database called \meta{db name} and does % \meta{text} if \meta{condition} is met. As with % \cs{DTLforeach}, the starred version is read only. % \begin{macrocode} \newcommand*{\DTLforeachbibentry}{% \@ifstar\@DTLforeachbibentry\@DTLforeachbibentry} % \end{macrocode} %\end{macro} %\begin{macro}{\@DTLforeachbibentry} % Unstarred version % \begin{macrocode} \newcommand*{\@DTLforeachbibentry}[3][\boolean{true}]{% % \end{macrocode} % Store database name. % \begin{macrocode} \edef\DBIBname{#2}% % \end{macrocode} % Reset row counter. % \begin{macrocode} \setcounter{DTLbibrow}{0}% % \end{macrocode} % Iterate through the database. % \begin{macrocode} \@DTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% {% \dtl@gathervalues{#2}{\dtlcurrentrow}% \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\@sDTLforeachbibentry} % Starred version % \begin{macrocode} \newcommand*{\@sDTLforeachbibentry}[3][\boolean{true}]{% % \end{macrocode} % Store database name. % \begin{macrocode} \edef\DBIBname{#2}% % \end{macrocode} % Reset row counter. % \begin{macrocode} \setcounter{DTLbibrow}{0}% % \end{macrocode} % Iterate through the database (read only). % \begin{macrocode} \@sDTLforeach{#2}{\DBIBcitekey=CiteKey,\DBIBentrytype=EntryType}% {% \dtl@gathervalues{#2}{\dtlcurrentrow}% \ifthenelse{#1}{\refstepcounter{DTLbibrow}#3}{}% }% } % \end{macrocode} %\end{macro} % %\begin{counter}{DTLbibrow} %The counter \ctrfmt{DTLbibrow} keeps track of the current %row in the body of \cs{DTLforeachbibentry}. (You can't rely on %\ctr{DTLrowi}, \ctr{DTLrowii} and % \ctr{DTLrowiii}, as \cs{DTLforeachbibentry} pass the % conditions to the optional argument of \cs{DTLforeach}, but % instead uses \cs{ifthenelse}, which means that \ctr{DTLrowi} % etc will be incremented, even when the given condition is not met.) % \begin{macrocode} \newcounter{DTLbibrow} % \end{macrocode} %\end{counter} %\begin{macro}{\theHDTLbibrow} % Keep \sty{hyperref} happy: % \begin{macrocode} \def\theHDTLbibrow{\theHDTLrow.bib.\arabic{DTLbibrow}}% % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfield} %\begin{definition} %\cs{DTLbibfield}\marg{field name} %\end{definition} % Gets the value assigned to the field \meta{field name} for % the current row of \cs{DTLforeachbibentry}. (Doesn't check if % the field exists, or if it is being used within % \cs{DTLforeachbibentry}.) % \begin{macrocode} \newcommand*{\DTLbibfield}[1]{\csname @dtl@key@#1\endcsname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifbibfieldexists} %\begin{definition} %\cs{DTLifbibfieldexists}\marg{field name}\marg{true part}\marg{false %part} %\end{definition} %Determines whether the given field name exists for the current % row of \cs{DTLforeachbibentry}. % \begin{macrocode} \newcommand*{\DTLifbibfieldexists}[3]{% \@ifundefined{@dtl@key@#1}{#3}{% \expandafter\DTLifnull\csname @dtl@key@#1\endcsname {#3}{#2}}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifanybibfieldexists} %\begin{definition} %\cs{DTLifanybibfieldexists}\marg{list of field name}\marg{true part}\marg{false %part} %\end{definition} % Determines whether any of the listed fields exist for the current % row of \cs{DTLforeachbibentry}. % \begin{macrocode} \newcommand*{\DTLifanybibfieldexists}[3]{% \@for\dtl@thisfield:=#1\do{% \@ifundefined{@dtl@key@\dtl@thisfield}{}{% \expandafter\DTLifnull\csname @dtl@key@\dtl@thisfield\endcsname {}{% \@endfortrue}}}% \if@endfor #2% \else #3% \fi \@endforfalse } % \end{macrocode} %\end{macro} % %\begin{macro}{\ifDTLperiod} % The conditional \cs{ifDTLperiod} is used to keep track of any % abbreviations ending with a period, this is to ensure that % abbreviations aren't followed by a full stop if they already % have a full stop terminating the abbreviation. % \begin{macrocode} \newif\ifDTLperiod % \end{macrocode} %\end{macro} %\begin{macro}{\DTLcheckendsperiod} %\begin{definition} %\cs{DTLcheckendperiod}\marg{string} %\end{definition} % Checks if \meta{string} ends with a full stop. This sets % \cs{ifDTLperiod}. % \begin{macrocode} \newcommand*{\DTLcheckendsperiod}[1]{% \dtl@checkendsperiod#1\@nil\relax} % \end{macrocode} % \begin{macrocode} \def\dtl@checkendsperiod#1#2{% \def\@dtl@argi{#1}\def\@dtl@argii{#2}% \def\@dtl@period{.}% \ifx\@dtl@argi\@nnil \global\DTLperiodfalse \let\@dtl@donext=\relax \else \ifx\@dtl@argii\@nnil \ifx\@dtl@argi\@dtl@period \global\DTLperiodtrue \else \global\DTLperiodfalse \fi \let\@dtl@donext=\@gobble \else \let\@dtl@donext=\dtl@checkendsperiod \fi \fi \@dtl@donext{#2}% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLcheckbibfieldendsperiod} %\begin{definition} %\cs{DTLcheckbibfieldendperiod}\marg{label} %\end{definition} % Checks if the bib field \meta{label} ends with a full stop. % This sets \cs{ifDTLperiod}. % \begin{macrocode} \newcommand*{\DTLcheckbibfieldendsperiod}[1]{% \protected@edef\@dtl@tmp{\DTLbibfield{#1}}% \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifDTLmidsentence} %\begin{definition} %\cs{ifDTLmidsentence} %\end{definition} % Determine whether we are in the middle % of a sentence. % \begin{macrocode} \newif\ifDTLmidsentence % \end{macrocode} %\end{macro} %\begin{macro}{\ifDTLstartsentence} %\begin{definition} %\cs{ifDTLstartsentence} %\end{definition} % Determine whether we are at the start % of a sentence. % \begin{macrocode} \newif\ifDTLstartsentence % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLaddperiod} %\begin{definition} %\cs{DTLaddperiod} %\end{definition} %Adds a full stop and sets \cs{DTLmidsentencefalse}, %\cs{DTLstartsentencetrue} and %\cs{DTLperiodfalse}. % \begin{macrocode} \newcommand*{\DTLaddperiod}{\DTLmidsentencefalse\DTLperiodfalse \DTLstartsentencetrue \ifDTLperiod\else.\fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLaddcomma} %\begin{definition} %\cs{DTLaddcomma} %\end{definition} %Adds a comma and sets \cs{DTLmidsentencetrue}, \cs{DTLperiodfalse} %and \cs{DTLstartsentencefalse} % \begin{macrocode} \newcommand*{\DTLaddcomma}{, \DTLmidsentencetrue \DTLperiodfalse\DTLstartsentencefalse} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLstartsentencespace} %Adds a space if at the start of the sentence, otherwise does % nothing. (The space between sentences is added this way, rather % than in \cs{DTLaddperiod} otherwise spurious extra space can % occur at the end of the bib item. The spacefactor needs to be % set manually, because there's stuff in the way of the previous % sentence's full stop and this space which confuses the inter % sentence spacing (and, of course, the previous sentence could % have ended with a capital letter.) % \begin{macrocode} \newcommand*{\DTLstartsentencespace}{% \ifDTLstartsentence\spacefactor=\sfcode`\.\relax\space \fi\DTLstartsentencefalse} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtwoand} % In a list of only two author (or editor) names, the text between the % two names is given by \cs{DTLtwoand}: % \begin{macrocode} \newcommand*{\DTLtwoand}{\ \andname\ } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLandlast} % In a list of author (or editor) names, the text between the % penultimate and last name is given by \cs{DTLandlast}: % \begin{macrocode} \newcommand*{\DTLandlast}{, \andname\ } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLandnotlast} % In a list of author (or editor) names, the text between the % names (except the penultimate and last name) is given by % \cs{DTLandnotlast}: % \begin{macrocode} \newcommand*{\DTLandnotlast}{, } % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@authorcount} % Define a count register to keep track of the number of authors: % \begin{macrocode} \newcount\@dtl@authorcount % \end{macrocode} %\end{macro} %\begin{counter}{DTLmaxauthors} % The counter \ctrfmt{DTLmaxauthors} indicates the maximum number of % author names to display, if there are more than that number, % \cs{etalname} is used. % \begin{macrocode} \newcounter{DTLmaxauthors} \setcounter{DTLmaxauthors}{10} % \end{macrocode} %\end{counter} %\begin{macro}{\DTLformatauthorlist} % Format a list of author names (the list is stored in % \cs{@dtl@key@Author}): % \begin{macrocode} \newcommand*{\DTLformatauthorlist}{% \DTLifbibfieldexists{Author}{% \DTLstartsentencespace \@dtl@authorcount=0\relax \@for\@dtl@author:=\@dtl@key@Author\do{% \advance\@dtl@authorcount by 1\relax}% \@dtl@tmpcount=0\relax \ifnum\@dtl@authorcount>\c@DTLmaxauthors {% \@for\@dtl@author:=\@dtl@key@Author\do{% \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount=1\relax \expandafter\DTLformatauthor\@dtl@author \else \ifnum\@dtl@tmpcount>\c@DTLmaxauthors \DTLandnotlast \etalname \expandafter\DTLcheckendsperiod\expandafter{\etalname}% \@endfortrue \else \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author \fi \fi }% }% \else \@for\@dtl@author:=\@dtl@key@Author\do{% \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount=1\relax \expandafter\DTLformatauthor\@dtl@author \else \ifnum\@dtl@tmpcount=\@dtl@authorcount \ifnum\@dtl@authorcount=2\relax \DTLtwoand \else \DTLandlast \fi \expandafter\DTLformatauthor\@dtl@author \else \DTLandnotlast \expandafter\DTLformatauthor\@dtl@author \fi \fi }% \fi }{}% } % \end{macrocode} %\end{macro} %\begin{counter}{DTLmaxeditors} % The counter \ctrfmt{DTLmaxeditors} indicates the maximum number of % editor names to display, if there are more than that number, % \cs{etalname} is used. % \begin{macrocode} \newcounter{DTLmaxeditors} \setcounter{DTLmaxeditors}{10} % \end{macrocode} %\end{counter} % %\begin{macro}{\DTLformateditorlist} % Format a list of editor names (the list is stored in % \cs{@dtl@key@Editor}): % \begin{macrocode} \newcommand*{\DTLformateditorlist}{% \DTLifbibfieldexists{Editor}{% \DTLstartsentencespace \@dtl@authorcount=0\relax \@for\@dtl@author:=\@dtl@key@Editor\do{% \advance\@dtl@authorcount by 1\relax}% \@dtl@tmpcount=0\relax \ifnum\@dtl@authorcount>\c@DTLmaxeditors {% \@for\@dtl@author:=\@dtl@key@Editor\do{% \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount=1\relax \expandafter\DTLformateditor\@dtl@author \else \ifnum\@dtl@tmpcount>\c@DTLmaxeditors \DTLandnotlast \etalname \expandafter\DTLcheckendsperiod\expandafter{\etalname}% \@endfortrue \else \DTLandnotlast \expandafter\DTLformateditor\@dtl@author \fi \fi }% }% \else \@for\@dtl@author:=\@dtl@key@Editor\do{% \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount=1\relax \expandafter\DTLformateditor\@dtl@author \else \ifnum\@dtl@tmpcount=\@dtl@authorcount \ifnum\@dtl@authorcount=2\relax \DTLtwoand \else \DTLandlast \fi \expandafter\DTLformateditor\@dtl@author \else \DTLandnotlast \expandafter\DTLformateditor\@dtl@author \fi \fi }% \fi , \ifnum\@dtl@authorcount=1\relax \editorname \expandafter\DTLcheckendsperiod\expandafter{\editorname}% \else \editorsname \expandafter\DTLcheckendsperiod\expandafter{\editorsname}% \fi }{}% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLformatsurnameonly} %\begin{definition} %\cs{DTLformatsurnameonly}\marg{von part}\marg{surname}\marg{jr %part}\marg{forenames} %\end{definition} % This is used when only the surname should be displayed. (The % final argument, \meta{forenames}, is ignored.) % \begin{macrocode} \newcommand*{\DTLformatsurnameonly}[4]{% \DTLstartsentencespace \def\@dtl@tmp{#1}% \ifx\@dtl@tmp\@empty\else#1~\fi #2% \def\@dtl@tmp{#3}% \ifx\@dtl@tmp\@empty \DTLcheckendsperiod{#2}% \else , #3% \DTLcheckendsperiod{#3}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatforenames} %\begin{definition} %\cs{DTLformatforenames}\marg{forenames} %\end{definition} % The format of an author/editor's forenames. If the forenames % occur at the start of sentence, a new sentence space is added. % The argument is checked to determine whether it ends with a % full stop (sometimes the forenames may include initials.) % \begin{macrocode} \newcommand*{\DTLformatforenames}[1]{% \DTLstartsentencespace #1% \DTLcheckendsperiod{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatabbrvforenames} %\begin{definition} %\cs{DTLformatabbrvforenames}\marg{forenames} %\end{definition} % The format of an author/editor's abbreviated forenames. The initials % may or may not end in a full stop depending on the commands % governing the format of \cs{DTLstoreinitials}, so the initials % need to be check using \cs{DTLcheckendsperiod}. % \begin{macrocode} \newcommand*{\DTLformatabbrvforenames}[1]{% \DTLstartsentencespace \DTLstoreinitials{#1}{\@dtl@tmp}\@dtl@tmp \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatvon} %\begin{definition} %\cs{DTLformatvon}\marg{von part} %\end{definition} % The format of the ``von'' part. This does nothing if the argument % is empty, otherwise it does the argument followed by a % non-breakable space. % \begin{macrocode} \newcommand*{\DTLformatvon}[1]{% \DTLstartsentencespace \def\@dtl@tmp{#1}% \ifx\@dtl@tmp\@empty \else #1~% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatsurname} %\begin{definition} %\cs{DTLformatsurname}\marg{surname} %\end{definition} % The format of an author/editor's surname. % \begin{macrocode} \newcommand*{\DTLformatsurname}[1]{% \DTLstartsentencespace #1\DTLcheckendsperiod{#1}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatjr} %\begin{definition} %\cs{DTLformatjr}\marg{jr part} %\end{definition} % The format of the ``jr'' part. This does nothing if the % argument is empty. % \begin{macrocode} \newcommand*{\DTLformatjr}[1]{% \DTLstartsentencespace \def\@dtl@tmp{#1}% \ifx\@dtl@tmp\@empty \else , #1\DTLcheckendsperiod{#1}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatcrossrefeditor} % Format cross reference editors: % \begin{macrocode} \newcommand*{\DTLformatcrossrefeditor}{% \DTLifbibfieldexists{Editor}{% \DTLstartsentencespace \@dtl@authorcount=0\relax \@for\@dtl@author:=\@dtl@key@Editor\do{% \advance\@dtl@authorcount by 1\relax}% {\@dtl@tmpcount=0\relax \@for\@dtl@author:=\@dtl@key@Editor\do{% \ifnum\@dtl@authorcount=1\relax \expandafter\DTLformatsurnameonly\@dtl@author \else \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount=1\relax \expandafter\DTLformatsurnameonly\@dtl@author \else \ifnum\@dtl@authorcount=2\relax \ \andname\ \expandafter\DTLformatsurnameonly\@dtl@author \else \ \etalname \expandafter\DTLcheckendsperiod\expandafter{\etalname} \fi \@endfortrue \fi \fi }}% }{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatvolnumpages} % Format volume, number and pages (of an article). % \begin{macrocode} \newcommand*{\DTLformatvolnumpages}{% \DTLifbibfieldexists{Volume}{% \DTLstartsentencespace \DTLbibfield{Volume}\DTLperiodfalse}{}% \DTLifbibfieldexists{Number}{% \DTLstartsentencespace (\DTLbibfield{Number})\DTLperiodfalse}{}% \DTLifbibfieldexists{Pages}{% \DTLifanybibfieldexists{Volume,Number}{:}{% \DTLstartsentencespace \protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% \DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~}% \DTLbibfield{Pages}\DTLperiodfalse}{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatbvolume} % Format book volume. % \begin{macrocode} \newcommand*{\DTLformatbvolume}{% \DTLifbibfieldexists{Volume}{% \ifDTLmidsentence \volumename \else \DTLstartsentencespace \expandafter\MakeUppercase\volumename \fi ~\DTLbibfield{Volume}% \DTLifbibfieldexists{Series}{\ \ofname\ {\em\DTLbibfield{Series}}\DTLcheckbibfieldendsperiod{Series}}{% \DTLcheckbibfieldendsperiod{Volume}}% }{}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatchapterpages} % Format chapter and pages: % \begin{macrocode} \newcommand*{\DTLformatchapterpages}{% \DTLifbibfieldexists{Chapter}{% \DTLifbibfieldexists{Type}{% \DTLstartsentencespace \DTLbibfield{Type}}{% \DTLstartsentencespace \chaptername}~\DTLbibfield{Chapter}% \DTLifbibfieldexists{Pages}{\DTLaddcomma}{% \DTLcheckbibfieldendsperiod{Chapter}}}{}% \DTLstartsentencespace \DTLformatpages} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatpages} % Format pages: % \begin{macrocode} \newcommand*{\DTLformatpages}{% \DTLifbibfieldexists{Pages}{% \DTLstartsentencespace \protected@edef\@dtl@pages{0\DTLbibfield{Pages}}% \DTLifnumerical{\@dtl@pages}{\pagename}{\pagesname}~% \DTLbibfield{Pages}\DTLcheckbibfieldendsperiod{Pages}}{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatnumberseries} % Format number and series (of book) % \begin{macrocode} \newcommand*{\DTLformatnumberseries}{% \DTLifbibfieldexists{Volume}{}{% \DTLifbibfieldexists{Number}{% \ifDTLmidsentence \numbername \else \DTLstartsentencespace \expandafter\MakeUppercase\numbername \fi~\DTLbibfield{Number}% \DTLifbibfieldexists{Series}{\ \inname\ \DTLbibfield{Series}% \DTLcheckbibfieldendsperiod{Series}}{% \DTLcheckbibfieldendsperiod{Number}}% }{% \DTLifbibfieldexists{Series}{% \DTLstartsentencespace \DTLbibfield{Series}% \DTLcheckbibfieldendsperiod{Series}}{}}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLformatbookcrossref} % Format a book cross reference. % \begin{macrocode} \newcommand*{\DTLformatbookcrossref}{% \DTLifbibfieldexists{Volume}{% \ifDTLmidsentence \volumename \else \DTLstartsentencespace \expandafter\MakeUppercase\volumename \fi ~\DTLbibfield{Volume}\ \ofname\ }{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi\ }% \DTLifbibfieldexists{Editor}{\DTLformatcrossrefeditor}{% \DTLifbibfieldexists{Key}{% \DTLbibfield{Key}}{% \DTLifbibfieldexists{Series}{% {\em\DTLbibfield{Series}}}{}% }% }% \edef\@dtl@tmp{\DTLbibfield{CrossRef}}% ~\cite{\@dtl@tmp}% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLformatincollproccrossref} % Format `incollections' cross reference. % \begin{macrocode} \newcommand*{\DTLformatincollproccrossref}{% \DTLifbibfieldexists{Editor}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi\ \DTLformatcrossrefeditor }{% \DTLifbibfieldexists{Key}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi\ \DTLbibfield{Key}% }{% \DTLifbibfieldexists{BookTitle}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi\ {\em\DTLbibfield{BookTitle}}}{}% }}% \edef\@dtl@tmp{\DTLbibfield{CrossRef}}% ~\cite{\@dtl@tmp}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatinedbooktitle} %Format editor and booktitle: % \begin{macrocode} \newcommand*{\DTLformatinedbooktitle}{% \DTLifbibfieldexists{BookTitle}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi\ \DTLifbibfieldexists{Editor}{% \DTLformateditorlist\DTLaddcomma {\em\DTLbibfield{BookTitle}}% \DTLcheckbibfieldendsperiod{BookTitle}% }{{\em\DTLbibfield{BookTitle}}% \DTLcheckbibfieldendsperiod{BookTitle}% }}{}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatdate} %Format date. % \begin{macrocode} \newcommand*{\DTLformatdate}{% \DTLifbibfieldexists{Year}{% \DTLifbibfieldexists{Month}{% \protected@edef\@dtl@tmp{\DTLbibfield{Month}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace \expandafter\MakeUppercase\@dtl@tmp \fi\ \DTLmidsentencefalse}{}% \DTLstartsentencespace \DTLbibfield{Year}}{% \DTLifbibfieldexists{Month}{% \protected@edef\@dtl@tmp{\DTLbibfield{Month}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace \expandafter\MakeUppercase\@dtl@tmp \fi \DTLcheckbibfieldendsperiod{Month}% }{}}} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLformatarticlecrossref} % Format article cross reference. % \begin{macrocode} \newcommand*{\DTLformatarticlecrossref}{% \DTLifbibfieldexists{Key}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi \ {\em\DTLbibfield{Key}}}{% \DTLifbibfieldexists{Journal}{% \ifDTLmidsentence \inname \else \DTLstartsentencespace \expandafter\MakeUppercase\inname \fi \ {\em\DTLbibfield{Journal}}}{}}% \edef\@dtl@tmp{\DTLbibfield{CrossRef}}% ~\cite{\@dtl@tmp}% } % \end{macrocode} %\end{macro} % %\subsubsection{ifthen conditionals} % The conditionals defined in this section may be used in the % optional argument of \cs{DTLforeachbib}. They may also be % used in the first argument of \cs{ifthenelse}, but only if the % command occurs within the body of \cs{DTLforeachbib}. % %\begin{macro}{\DTLbibfieldexists} %\begin{definition} %\cs{DTLbibfieldexists}\marg{field label} %\end{definition} % Checks if named bib field exists for current entry % \begin{macrocode} \newcommand*{\DTLbibfieldexists}[1]{% \TE@throw\noexpand\dtl@testbibfieldexists{#1}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldexists} % \begin{macrocode} \newcommand*{\dtl@testbibfieldexists}[1]{% \DTLifbibfieldexists{#1}{\@dtl@conditiontrue}{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldiseq} %\begin{definition} %\cs{DTLbibfieldiseq}\marg{field label}\marg{value} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % is equal to \meta{value}. (Uses \cs{dtlcompare} to determine if % the values are equal. If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldiseq}[2]{% \TE@throw\noexpand\dtl@testbibfieldiseq{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldiseq} % \begin{macrocode} \newcommand*{\dtl@testbibfieldiseq}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\toks@\expandafter{\@dtl@tmp}% \@dtl@toks{#2}% \edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% {\the\toks@}{\the\@dtl@toks}}% \@dtl@docompare \ifnum\@dtl@tmpcount=0\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi }{% \@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldislt} %\begin{definition} %\cs{DTLbibfieldislt}\marg{field label}\marg{value} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % is less than \meta{value}. (If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldislt}[2]{% \TE@throw\noexpand\dtl@testbibfieldislt{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldislt} % \begin{macrocode} \newcommand*{\dtl@testbibfieldislt}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\toks@\expandafter{\@dtl@tmp}% \@dtl@toks{#2}% \edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% {\the\toks@}{\the\@dtl@toks}}% \@dtl@docompare \ifnum\@dtl@tmpcount=-1\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi }{% \@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldisle} %\begin{definition} %\cs{DTLbibfieldisle}\marg{field label}\marg{value} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % is less than or equal to \meta{value}. % (If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldisle}[2]{% \TE@throw\noexpand\dtl@testbibfieldisle{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldisle} % \begin{macrocode} \newcommand*{\dtl@testbibfieldisle}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\toks@\expandafter{\@dtl@tmp}% \@dtl@toks{#2}% \edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% {\the\toks@}{\the\@dtl@toks}}% \@dtl@docompare \ifnum\@dtl@tmpcount<1\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi }{% \@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldisgt} %\begin{definition} %\cs{DTLbibfieldisgt}\marg{field label}\marg{value} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % is greater than \meta{value}. (If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldisgt}[2]{% \TE@throw\noexpand\dtl@testbibfieldisgt{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldisgt} % \begin{macrocode} \newcommand*{\dtl@testbibfieldisgt}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\toks@\expandafter{\@dtl@tmp}% \@dtl@toks{#2}% \edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% {\the\toks@}{\the\@dtl@toks}}% \@dtl@docompare \ifnum\@dtl@tmpcount=1\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi }{% \@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldisge} %\begin{definition} %\cs{DTLbibfieldisge}\marg{field label}\marg{value} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % is less than or equal to \meta{value}. % (If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldisge}[2]{% \TE@throw\noexpand\dtl@testbibfieldisge{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldisge} % \begin{macrocode} \newcommand*{\dtl@testbibfieldisge}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\toks@\expandafter{\@dtl@tmp}% \@dtl@toks{#2}% \edef\@dtl@docompare{\noexpand\dtlcompare{\noexpand\@dtl@tmpcount}% {\the\toks@}{\the\@dtl@toks}}% \@dtl@docompare \ifnum\@dtl@tmpcount>-1\relax \@dtl@conditiontrue \else \@dtl@conditionfalse \fi }{% \@dtl@conditionfalse}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibfieldcontains} %\begin{definition} %\cs{DTLbibfieldcontains}\marg{field label}\marg{sub string} %\end{definition} % Checks if the value of the bib field given by \meta{field label} % contains \meta{sub string}. % (If the bib field doesn't exist, the % condition is false.) % \begin{macrocode} \newcommand*{\DTLbibfieldcontains}[2]{% \TE@throw\noexpand\dtl@testbibfieldcontains{#1}{#2}% \noexpand\if@dtl@condition} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@testbibfieldcontains} % \begin{macrocode} \newcommand*{\dtl@testbibfieldcontains}[2]{% \DTLifbibfieldexists{#1}{% \expandafter\let\expandafter\@dtl@tmp\expandafter =\csname @dtl@key@#1\endcsname \expandafter\dtl@testifsubstring\expandafter{\@dtl@tmp}{#2}% }{\@dtl@conditionfalse}} % \end{macrocode} %\end{macro} % %\subsection{Bibliography Style Macros} %\label{sec:src:bibstyle} % The macros defined in this section should be redefined by % bibliography styles. % %\begin{environment}{DTLthebibliography} % How to format the entire bibliography: % \begin{macrocode} \newenvironment{DTLthebibliography}[2][\boolean{true}]{% \@dtl@tmpcount=0\relax \@sDTLforeach[#1]{#2}{}{\advance\@dtl@tmpcount by 1\relax}% \begin{thebibliography}{\number\@dtl@tmpcount} }{\end{thebibliography}} % \end{macrocode} %\end{environment} %\begin{macro}{\DTLmonthname} % The monthname style. The argument must be a number from~1 % to~12. By default, uses \cs{dtl@monthname}. % \begin{macrocode} \newcommand*{\DTLmonthname}[1]{% \dtl@monthname{#1}} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@monthname} % Full month names: % \begin{macrocode} \newcommand*{\dtl@monthname}[1]{% \ifcase#1% \or January% \or February% \or March% \or April% \or May% \or June% \or July% \or August% \or September% \or October% \or November% \or December% \fi} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@abbrvmonthname} % Abbreviated months: % \begin{macrocode} \newcommand*{\dtl@abbrvmonthname}[1]{% \ifcase#1% \or Jan.% \or Feb.% \or Mar.% \or Apr.% \or May% \or June% \or July% \or Aug.% \or Sept.% \or Oct.% \or Nov.% \or Dec.% \fi} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLbibitem} % Define how to start a new bibitem: % \begin{macrocode} \newcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLmbibitem} % As \cs{DTLbibitem} but for \cs{DTLmbibliography} % \begin{macrocode} \newcommand*{\DTLmbibitem}[1]{\bibitem{#1@\DBIBcitekey}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatauthor} %\begin{definition} %\cs{DTLformatauthor}\marg{von part}\marg{surname}\marg{junior %part}\marg{forenames} %\end{definition} % The format of an author's name. % \begin{macrocode} \newcommand*{\DTLformatauthor}[4]{% \DTLformatforenames{#4} \DTLformatvon{#1}% \DTLformatsurname{#2}% \DTLformatjr{#3}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformateditor} % The format of an editor's name. % \begin{macrocode} \newcommand*{\DTLformateditor}[4]{% \DTLformatforenames{#4} \DTLformatvon{#1}% \DTLformatsurname{#2}% \DTLformatjr{#3}} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatedition} % The format of an edition: % \begin{macrocode} \newcommand*{\DTLformatedition}[1]{#1 \editionname} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatarticle} % The format of an article: % \begin{macrocode} \newcommand{\DTLformatarticle}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatbook} % The format of a book: % \begin{macrocode} \newcommand{\DTLformatbook}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatbooklet} % The format of a booklet: % \begin{macrocode} \newcommand{\DTLformatbooklet}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatinbook} % The format of an ``inbook'' type: % \begin{macrocode} \newcommand{\DTLformatinbook}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatincollection} % The format of an ``incollection'' type: % \begin{macrocode} \newcommand{\DTLformatincollection}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatinproceedings} % The format of an ``inproceedings'' type: % \begin{macrocode} \newcommand{\DTLformatinproceedings}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatmanual} % The format of a manual: % \begin{macrocode} \newcommand{\DTLformatmanual}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatmastersthesis} % The format of a master's thesis: % \begin{macrocode} \newcommand{\DTLformatmastersthesis}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatmisc} % The format of a miscellaneous entry: % \begin{macrocode} \newcommand{\DTLformatmisc}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatphdthesis} % The format of a Ph.D. thesis: % \begin{macrocode} \newcommand{\DTLformatphdthesis}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatproceedings} % The format of a proceedings: % \begin{macrocode} \newcommand{\DTLformatproceedings}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformattechreport} % The format of a technical report: % \begin{macrocode} \newcommand{\DTLformattechreport}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLformatunpublished} % The format of an unpublished work: % \begin{macrocode} \newcommand{\DTLformatunpublished}{} % \end{macrocode} %\end{macro} % % Predefined names (these correspond to the standard \BibTeX\ % predefined strings of the same name without the leading % \cs{DTL}): %\begin{macro}{\DTLacmcs} % \begin{macrocode} \newcommand*{\DTLacmcs}{ACM Computing Surveys} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLacta} % \begin{macrocode} \newcommand*{\DTLacta}{Acta Informatica} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLcacm} % \begin{macrocode} \newcommand*{\DTLcacm}{Communications of the ACM} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLibmjrd} % \begin{macrocode} \newcommand*{\DTLibmjrd}{IBM Journal of Research and Development} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLibmsj} % \begin{macrocode} \newcommand*{\DTLibmsj}{IBM Systems Journal} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLieeese} % \begin{macrocode} \newcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLieeetc} % \begin{macrocode} \newcommand*{\DTLieeetc}{IEEE Transactions on Computers} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLieeetcad} % \begin{macrocode} \newcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design of Integrated Circuits} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLipl} % \begin{macrocode} \newcommand*{\DTLipl}{Information Processing Letters} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLjacm} % \begin{macrocode} \newcommand*{\DTLjacm}{Journal of the ACM} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLjcss} % \begin{macrocode} \newcommand*{\DTLjcss}{Journal of Computer and System Sciences} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLscp} % \begin{macrocode} \newcommand*{\DTLscp}{Science of Computer Programming} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLsicomp} % \begin{macrocode} \newcommand*{\DTLsicomp}{SIAM Journal on Computing} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtocs} % \begin{macrocode} \newcommand*{\DTLtocs}{ACM Transactions on Computer Systems} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtods} % \begin{macrocode} \newcommand*{\DTLtods}{ACM Transactions on Database Systems} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtog} % \begin{macrocode} \newcommand*{\DTLtog}{ACM Transactions on Graphics} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtoms} % \begin{macrocode} \newcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtoois} % \begin{macrocode} \newcommand*{\DTLtoois}{ACM Transactions on Office Information Systems} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtoplas} % \begin{macrocode} \newcommand*{\DTLtoplas}{ACM Transactions on Programming Languages and Systems} % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLtcs} % \begin{macrocode} \newcommand*{\DTLtcs}{Theoretical Computer Science} % \end{macrocode} %\end{macro} % %\subsection{Bibliography Styles} % Each bibliography style is set by the command % \cs{dtlbst@}\meta{style}, where \meta{style} is the name % of the bibliography style. % %\begin{macro}{\dtlbst@plain} % The `plain' style: % \begin{macrocode} \newcommand{\dtlbst@plain}{% % \end{macrocode} % Set how to format the entire bibliography: % \begin{macrocode} \renewenvironment{DTLthebibliography}[2][\boolean{true}]{% \@dtl@tmpcount=0\relax \@sDTLforeach[##1]{##2}{}{\advance\@dtl@tmpcount by 1\relax}% \begin{thebibliography}{\number\@dtl@tmpcount}% }{\end{thebibliography}}% % \end{macrocode} % Set how to start the bibliography entry: % \begin{macrocode} \renewcommand*{\DTLbibitem}{\bibitem{\DBIBcitekey}}% \renewcommand*{\DTLmbibitem}[1]{\bibitem{##1@\DBIBcitekey}}% % \end{macrocode} % Sets the author name format. % \begin{macrocode} \renewcommand*{\DTLformatauthor}[4]{% \DTLformatforenames{##4} \DTLformatvon{##1}% \DTLformatsurname{##2}% \DTLformatjr{##3}} % \end{macrocode} % Sets the editor name format. % \begin{macrocode} \renewcommand*{\DTLformateditor}[4]{% \DTLformatforenames{##4} \DTLformatvon{##1}% \DTLformatsurname{##2}% \DTLformatjr{##3}} % \end{macrocode} % Sets the edition format. % \begin{macrocode} \renewcommand*{\DTLformatedition}[1]{##1 \editionname}% % \end{macrocode} % Sets the monthname format. % \begin{macrocode} \let\DTLmonthname\dtl@monthname % \end{macrocode} % Sets other predefined names: % \begin{macrocode} \renewcommand*{\DTLacmcs}{ACM Computing Surveys} \renewcommand*{\DTLacta}{Acta Informatica} \renewcommand*{\DTLcacm}{Communications of the ACM} \renewcommand*{\DTLibmjrd}{IBM Journal of Research and Development} \renewcommand*{\DTLibmsj}{IBM Systems Journal} \renewcommand*{\DTLieeese}{IEEE Transactions on Software Engineering} \renewcommand*{\DTLieeetc}{IEEE Transactions on Computers} \renewcommand*{\DTLieeetcad}{IEEE Transactions on Computer-Aided Design of Integrated Circuits} \renewcommand*{\DTLipl}{Information Processing Letters} \renewcommand*{\DTLjacm}{Journal of the ACM} \renewcommand*{\DTLjcss}{Journal of Computer and System Sciences} \renewcommand*{\DTLscp}{Science of Computer Programming} \renewcommand*{\DTLsicomp}{SIAM Journal on Computing} \renewcommand*{\DTLtocs}{ACM Transactions on Computer Systems} \renewcommand*{\DTLtods}{ACM Transactions on Database Systems} \renewcommand*{\DTLtog}{ACM Transactions on Graphics} \renewcommand*{\DTLtoms}{ACM Transactions on Mathematical Software} \renewcommand*{\DTLtoois}{ACM Transactions on Office Information Systems} \renewcommand*{\DTLtoplas}{ACM Transactions on Programming Languages and Systems} \renewcommand*{\DTLtcs}{Theoretical Computer Science} % \end{macrocode} % The format of an article. % \begin{macrocode} \renewcommand*{\DTLformatarticle}{% \DTLformatauthorlist \DTLifbibfieldexists{Author}{\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace\DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{CrossRef}{% % cross ref field \DTLformatarticlecrossref \DTLifbibfieldexists{Pages}{\DTLaddcomma}{}% \DTLformatpages \DTLaddperiod }{% no cross ref field \DTLifbibfieldexists{Journal}{\DTLstartsentencespace {\em\DTLbibfield{Journal}}% \DTLcheckbibfieldendsperiod{Journal}% \DTLifanybibfieldexists{Number,Volume,Pages,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatvolnumpages \DTLifanybibfieldexists{Volume,Number,Pages}{% \DTLifanybibfieldexists{Year,Month}{\DTLaddcomma}{% \DTLaddperiod}% \DTLmidsentencefalse}{}% \DTLformatdate \DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% }% \DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% } % \end{macrocode} % The format of a book. % \begin{macrocode} \renewcommand*{\DTLformatbook}{% \DTLifbibfieldexists{Author}{% \DTLformatauthorlist\DTLaddperiod }{\DTLformateditorlist\DTLifbibfieldexists{Editor}{% \DTLaddperiod}{}}% \DTLifbibfieldexists{Title}{\DTLstartsentencespace {\em\DTLbibfield{Title}}% \DTLcheckbibfieldendsperiod{Title}}{}% \DTLifbibfieldexists{CrossRef}{% % cross ref field \DTLifbibfieldexists{Title}{\DTLaddperiod}{}% \DTLformatbookcrossref \DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma }{\DTLaddperiod}% }{% no cross ref field \DTLifbibfieldexists{Title}{% \DTLifbibfieldexists{Volume}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatbvolume \DTLformatnumberseries \DTLifanybibfieldexists{Number,Series,Volume}{\DTLaddperiod}{}% \DTLifbibfieldexists{Publisher}{\DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLifbibfieldexists{Address}{\DTLaddcomma}{% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma }{\DTLaddperiod}% }}{}% \DTLifbibfieldexists{Address}{\DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% }% \DTLifbibfieldexists{Edition}{% \protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace\expandafter\MakeUppercase\@dtl@tmp \fi \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}% }{}% \DTLformatdate \DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{\DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a booklet. % \begin{macrocode} \renewcommand*{\DTLformatbooklet}{% \DTLifbibfieldexists{Author}{% \DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{\DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{HowPublished}{% \DTLstartsentencespace\DTLbibfield{HowPublished}% \DTLcheckbibfieldendsperiod{HowPublished}% \DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{\DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Year,Month}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{\DTLstartsentencespace\DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of an `inbook' entry. % \begin{macrocode} \renewcommand*{\DTLformatinbook}{% \DTLifbibfieldexists{Author}{% \DTLformatauthorlist\DTLaddperiod}{% \DTLifbibfieldexists{Editor}{\DTLformateditorlist\DTLaddperiod}{}}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace {\em\DTLbibfield{Title}}% \DTLcheckbibfieldendsperiod{Title}% }{}% \DTLifbibfieldexists{CrossRef}{% % Cross ref entry \DTLifbibfieldexists{Title}{% \DTLifbibfieldexists{Chapter}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatchapterpages \DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% \DTLformatbookcrossref }{% no cross ref \DTLifbibfieldexists{Title}{% \DTLifanybibfieldexists{Chapter,Volume}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLformatbvolume \DTLifanybibfieldexists{Volume,Series}{% \DTLifanybibfieldexists{Chapter,Pages}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatchapterpages \DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLifbibfieldexists{Address}{\DTLaddcomma}{}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}}{}% }% \DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma }{\DTLaddperiod}% \DTLifbibfieldexists{Edition}{% \protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace \expandafter\MakeUppercase\@dtl@tmp \fi \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma }{\DTLaddperiod}% }{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of an `incollection' entry. % \begin{macrocode} \renewcommand*{\DTLformatincollection}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{CrossRef}{% % cross ref entry \DTLformatincollproccrossref \DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma}{}% \DTLformatchapterpages\DTLaddperiod }{% no cross ref entry \DTLformatinedbooktitle \DTLifbibfieldexists{BookTitle}{% \DTLifanybibfieldexists{Volume,Series,Chapter,Pages,Number}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatbvolume \DTLifbibfieldexists{Volume}{% \DTLifanybibfieldexists{Number,Series,Chapter,Pages}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatnumberseries \DTLifanybibfieldexists{Number,Series}{% \DTLifanybibfieldexists{Chapter,Pages}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLformatchapterpages \DTLifanybibfieldexists{Chapter,Pages}{\DTLaddperiod}{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLifanybibfieldexists{Address,Edition,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Edition,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Edition}{% \protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace \expandafter\MakeUppercase\@dtl@tmp \fi \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma }{\DTLaddperiod}% }{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% }% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of an `inproceedings' entry. % \begin{macrocode} \renewcommand*{\DTLformatinproceedings}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist \DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{CrossRef}{% % cross ref entry \DTLformatincollproccrossref \DTLifbibfieldexists{Pages}{\DTLaddcomma}{% \DTLaddperiod}% \DTLformatpages \DTLifbibfieldexists{Pages}{\DTLaddperiod}{}% }{% no cross ref \DTLformatinedbooktitle \DTLifbibfieldexists{BookTitle}{% \DTLifanybibfieldexists{Volume,Series,Pages,Number,Address,% Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatbvolume \DTLifbibfieldexists{Volume}{% \DTLifanybibfieldexists{Number,Series,Pages,Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatnumberseries \DTLifanybibfieldexists{Number,Series}{% \DTLifanybibfieldexists{Pages,Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatpages \DTLifbibfieldexists{Pages}{% \DTLifanybibfieldexists{Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% \DTLaddperiod}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifbibfieldexists{Publisher}{\DTLaddcomma}{% \DTLaddperiod}}{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLaddperiod}{}% }{% \DTLifanybibfieldexists{Publisher,Organization}{% \DTLaddperiod}{}% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifanybibfieldexists{Publisher,Month,Year}{% \DTLaddcomma}{}}{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% \DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% }% }% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a manual. % \begin{macrocode} \renewcommand*{\DTLformatmanual}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist \DTLaddperiod}{% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifbibfieldexists{Address}{\DTLaddcomma \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% }{}% \DTLaddperiod}{}% }% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace {\em\DTLbibfield{Title}}% \DTLcheckbibfieldendsperiod{Title}% \DTLifbibfieldexists{Author}{% \DTLifanybibfieldexists{Organization,Address}{% \DTLaddperiod}{\DTLaddcomma}}{% \DTLifanybibfieldexists{Organization,Address,Edition,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}}{}% \DTLifbibfieldexists{Author}{% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifanybibfieldexists{Address,Edition,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Edition,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% }{% \DTLifbibfieldexists{Organization}{}{% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Edition,Month,Year}{\DTLaddcomma}{% \DTLaddperiod}}{}}% }% \DTLifbibfieldexists{Edition}{% \protected@edef\@dtl@tmp{\DTLformatedition{\DTLbibfield{Edition}}}% \ifDTLmidsentence \@dtl@tmp \else \DTLstartsentencespace \expandafter\MakeUppercase\@dtl@tmp \fi \expandafter\DTLcheckendsperiod\expandafter{\@dtl@tmp}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% \DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a master's thesis. % \begin{macrocode} \renewcommand*{\DTLformatmastersthesis}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{Type}{% \DTLstartsentencespace \DTLbibfield{Type}% \DTLcheckbibfieldendsperiod{Type}% \DTLifanybibfieldexists{School,Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{School}{% \DTLstartsentencespace \DTLbibfield{School}% \DTLcheckbibfieldendsperiod{School}% \DTLifanybibfieldexists{Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a miscellaneous entry. % \begin{macrocode} \renewcommand*{\DTLformatmisc}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLifbibfieldexists{HowPublished}{\DTLaddperiod}{% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% \DTLaddperiod}% }% \DTLmidsentencefalse}{}% \DTLifbibfieldexists{HowPublished}{% \DTLstartsentencespace \DTLbibfield{HowPublished}% \DTLcheckbibfieldendsperiod{HowPublished}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{% \DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a PhD thesis. % \begin{macrocode} \renewcommand*{\DTLformatphdthesis}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace {\em\DTLbibfield{Title}}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{Type}{% \DTLstartsentencespace \DTLbibfield{Type}% \DTLcheckbibfieldendsperiod{Type}% \DTLifanybibfieldexists{School,Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{School}{% \DTLstartsentencespace \DTLbibfield{School}% \DTLcheckbibfieldendsperiod{School}% \DTLifanybibfieldexists{Address,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a proceedings. % \begin{macrocode} \renewcommand*{\DTLformatproceedings}{% \DTLifbibfieldexists{Editor}{% \DTLformateditorlist\DTLaddperiod}{% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLaddperiod}{}}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace {\em\DTLbibfield{Title}}% \DTLcheckbibfieldendsperiod{Title}% \DTLifanybibfieldexists{Volume,Number,Address,Editor,Publisher,% Month,Year}{\DTLaddcomma}{\DTLaddperiod}% }{}% \DTLformatbvolume \DTLifbibfieldexists{Volume}{% \DTLifanybibfieldexists{Number,Address,Editor,Publisher,% Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatnumberseries \DTLifbibfieldexists{Number}{% \DTLifanybibfieldexists{Address,Editor,Publisher,% Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Editor}{\DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifbibfieldexists{Publisher}{% \DTLaddcomma}{\DTLaddperiod}}{}}{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLaddperiod }{}% }{% no address \DTLifbibfieldexists{Editor}{% \DTLifbibfieldexists{Organization}{% \DTLstartsentencespace \DTLbibfield{Organization}% \DTLcheckbibfieldendsperiod{Organization}% \DTLifanybibfieldexists{Publisher,Month,Year}{% \DTLaddcomma}{\DTLaddperiod}}{}% }{}% \DTLifbibfieldexists{Publisher}{% \DTLstartsentencespace \DTLbibfield{Publisher}% \DTLcheckbibfieldendsperiod{Publisher}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% }% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of a technical report. % \begin{macrocode} \renewcommand*{\DTLformattechreport}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{Type}{% \DTLstartsentencespace \DTLbibfield{Type}% \DTLcheckbibfieldendsperiod{Type}% \DTLifbibfieldexists{Number}{~}{}}{}% \DTLifbibfieldexists{Number}{% \DTLstartsentencespace \DTLbibfield{Number}% \DTLcheckbibfieldendsperiod{Number}% }{}% \DTLifanybibfieldexists{Type,Number}{% \DTLifanybibfieldexists{Institution,Address,Month,Year}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLifbibfieldexists{Institution}{% \DTLstartsentencespace \DTLbibfield{Institution}% \DTLcheckbibfieldendsperiod{Institution}% \DTLifanybibfieldexists{Address,Month,Year}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLifbibfieldexists{Address}{% \DTLstartsentencespace \DTLbibfield{Address}% \DTLcheckbibfieldendsperiod{Address}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma }{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLaddperiod}{}% }% % \end{macrocode} % The format of an unpublished work. % \begin{macrocode} \renewcommand*{\DTLformatunpublished}{% \DTLifbibfieldexists{Author}{\DTLformatauthorlist\DTLaddperiod}{}% \DTLifbibfieldexists{Title}{% \DTLstartsentencespace \DTLbibfield{Title}% \DTLcheckbibfieldendsperiod{Title}% \DTLaddperiod}{}% \DTLifbibfieldexists{Note}{% \DTLstartsentencespace \DTLbibfield{Note}% \DTLcheckbibfieldendsperiod{Note}% \DTLifanybibfieldexists{Month,Year}{\DTLaddcomma}{\DTLaddperiod}}{}% \DTLformatdate \DTLifanybibfieldexists{Month,Year}{\DTLaddperiod}{}% }% % \end{macrocode} % End of `plain' style. % \begin{macrocode} } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlbst@abbrv} % Define `abbrv' style. This is similar to `plain' except that % some of the values are abbreviated % \begin{macrocode} \newcommand{\dtlbst@abbrv}{% % \end{macrocode} % Base this style on `plain': % \begin{macrocode} \dtlbst@plain % \end{macrocode} % Sets the author name format. % \begin{macrocode} \renewcommand*{\DTLformatauthor}[4]{% \DTLformatabbrvforenames{##4} \DTLformatvon{##1}% \DTLformatsurname{##2}% \DTLformatjr{##3}} % \end{macrocode} % Sets the editor name format. % \begin{macrocode} \renewcommand*{\DTLformateditor}[4]{% \DTLformatabbrvforenames{##4} \DTLformatvon{##1}% \DTLformatsurname{##2}% \DTLformatjr{##3}} % \end{macrocode} % Sets the monthname format. % \begin{macrocode} \let\DTLmonthname\dtl@abbrvmonthname % \end{macrocode} % Sets other predefined names: % \begin{macrocode} \renewcommand*{\DTLacmcs}{ACM Comput.\ Surv.} \renewcommand*{\DTLacta}{Acta Inf.} \renewcommand*{\DTLcacm}{Commun.\ ACM} \renewcommand*{\DTLibmjrd}{IBM J.\ Res.\ Dev.} \renewcommand*{\DTLibmsj}{IBM Syst.~J.} \renewcommand*{\DTLieeese}{IEEE Trans. Softw.\ Eng.} \renewcommand*{\DTLieeetc}{IEEE Trans.\ Comput.} \renewcommand*{\DTLieeetcad}{IEEE Trans.\ Comput.-Aided Design Integrated Circuits} \renewcommand*{\DTLipl}{Inf.\ Process.\ Lett.} \renewcommand*{\DTLjacm}{J.~ACM} \renewcommand*{\DTLjcss}{J.~Comput.\ Syst.\ Sci.} \renewcommand*{\DTLscp}{Sci.\ Comput.\ Programming} \renewcommand*{\DTLsicomp}{SIAM J.~Comput.} \renewcommand*{\DTLtocs}{ACM Trans.\ Comput.\ Syst.} \renewcommand*{\DTLtods}{ACM Trans.\ Database Syst.} \renewcommand*{\DTLtog}{ACM Trans.\ Gr.} \renewcommand*{\DTLtoms}{ACM Trans.\ Math. Softw.} \renewcommand*{\DTLtoois}{ACM Trans. Office Inf.\ Syst.} \renewcommand*{\DTLtoplas}{ACM Trans.\ Prog. Lang.\ Syst.} \renewcommand*{\DTLtcs}{Theoretical Comput.\ Sci.} % \end{macrocode} % End of `abbrv' style. % \begin{macrocode} } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtlbst@alpha} % Define `alpha' style. This is similar to `plain' except that % the labels are strings rather than numerical. % \begin{macrocode} \newcommand{\dtlbst@alpha}{% % \end{macrocode} % Base this style on `plain': % \begin{macrocode} \dtlbst@plain % \end{macrocode} % Set how to format the entire bibliography: % \begin{macrocode} \renewenvironment{DTLthebibliography}[2][\boolean{true}]{% \dtl@createalphabiblabels{##1}{##2}% \begin{thebibliography}{\@dtl@widestlabel}% }{\end{thebibliography}}% % \end{macrocode} % Set how to start the bibliography entry: % \begin{macrocode} \renewcommand*{\DTLbibitem}{% \expandafter\bibitem\expandafter [\csname dtl@biblabel@\DBIBcitekey\endcsname]{\DBIBcitekey}}% \renewcommand*{\DTLmbibitem}[1]{% \expandafter\bibitem\expandafter [\csname dtl@biblabel@\DBIBcitekey\endcsname]{##1@\DBIBcitekey}}% % \end{macrocode} % \begin{macrocode} % \end{macrocode} % End of `alpha' style. % \begin{macrocode} } % \end{macrocode} %\end{macro} % %\begin{macro}{dtl@createalphabiblabels} %\begin{definition} %\cs{dtl@createalphabiblabels}\marg{condition}\marg{db name} %\end{definition} % Constructs the alpha style bib labels for the given database. % (Labels are stored in the control sequence %\cs{dtl@biblabel@}\meta{citekey}.) This also sets % \cs{@dtl@widestlabel} to the widest label. % \begin{macrocode} \newcommand*{\dtl@createalphabiblabels}[2]{% \dtl@message{Creating bib labels}% \begingroup \gdef\@dtl@widestlabel{}% \dtl@widest=0pt\relax \DTLforeachbibentry[#1]{#2}{% \dtl@message{\DBIBcitekey}% \DTLifbibfieldexists{Author}{% \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Author}% }{% \DTLifbibfieldexists{Editor}{% \dtl@listgetalphalabel{\@dtl@thislabel}{\@dtl@key@Editor}% }{% \DTLifbibfieldexists{Key}{% \expandafter\dtl@get@firstthree\expandafter {\@dtl@key@Key}{\@dtl@thislabel}% }{% \DTLifbibfieldexists{Organization}{% \expandafter\dtl@get@firstthree\expandafter {\@dtl@key@Organization}{\@dtl@thislabel}% }{% \expandafter\dtl@get@firstthree\expandafter {\DBIBentrytype}{\@dtl@thislabel}% }% }}}% \DTLifbibfieldexists{Year}{}{\DTLifbibfieldexists{CrossRef}{% \DTLgetvalueforkey{\@dtl@key@Year}{Year}{#2}{CiteKey}{% \@dtl@key@CrossRef}}{}}% \DTLifbibfieldexists{Year}{% \expandafter\dtl@get@yearsuffix\expandafter{\@dtl@key@Year}% \expandafter\toks@\expandafter{\@dtl@thislabel}% \expandafter\@dtl@toks\expandafter{\@dtl@year}% \edef\@dtl@thislabel{\the\toks@\the\@dtl@toks}% }{}% \let\@dtl@s@thislabel=\@dtl@thislabel \@onelevel@sanitize\@dtl@s@thislabel \@ifundefined{c@biblabel@\@dtl@s@thislabel}{% \newcounter{biblabel@\@dtl@s@thislabel}% \setcounter{biblabel@\@dtl@s@thislabel}{1}% \expandafter\edef\csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname{% \DBIBcitekey}% \expandafter\global \expandafter\let\csname dtl@biblabel@\DBIBcitekey\endcsname= \@dtl@thislabel }{% \expandafter\ifnum\csname c@biblabel@\@dtl@s@thislabel\endcsname=1\relax \expandafter\let\expandafter\@dtl@tmp \csname @dtl@bibfirst@\@dtl@s@thislabel\endcsname \expandafter\protected@xdef\csname dtl@biblabel@\@dtl@tmp\endcsname{% \@dtl@thislabel a}% \fi \stepcounter{biblabel@\@dtl@s@thislabel}% \expandafter\protected@xdef\csname dtl@biblabel@\DBIBcitekey\endcsname{% \@dtl@thislabel\alph{biblabel@\@dtl@s@thislabel}}% }% \settowidth{\dtl@tmplength}{% \csname dtl@biblabel@\DBIBcitekey\endcsname}% \ifdim\dtl@tmplength>\dtl@widest \dtl@widest=\dtl@tmplength \expandafter\global\expandafter\let\expandafter\@dtl@widestlabel \expandafter=\csname dtl@biblabel@\DBIBcitekey\endcsname \fi }% \endgroup } % \end{macrocode} %\end{macro} % %\begin{macro}{\dtl@listgetalphalabel} % Determine the alpha style label from a list of authors/editors % (the first argument must be a control sequence (in which the % label is stored), the second argument must be the list of names.) % \begin{macrocode} \newcommand*{\dtl@listgetalphalabel}[2]{% \@dtl@authorcount=0\relax \@for\@dtl@author:=#2\do{% \advance\@dtl@authorcount by 1\relax}% \ifnum\@dtl@authorcount=1\relax \expandafter\dtl@getsinglealphalabel#2{#1}\relax \else {% \xdef#1{}% \@dtl@tmpcount=0\relax \def\DTLafterinitials{}\def\DTLbetweeninitials{}% \def\DTLafterinitialbeforehyphen{}\def\DTLinitialhyphen{}% \@for\@dtl@author:=#2\do{% \expandafter\dtl@getauthorinitial\@dtl@author \expandafter\toks@\expandafter{\@dtl@tmp}% \expandafter\@dtl@toks\expandafter{#1}% \xdef#1{\the\@dtl@toks\the\toks@}% \advance\@dtl@tmpcount by 1\relax \ifnum\@dtl@tmpcount>2\relax\@endfortrue\fi }}% \fi } % \end{macrocode} %\end{macro} % Get author's initial (stores in \cs{@dtl@tmp}): % \begin{macrocode} \newcommand*{\dtl@getauthorinitial}[4]{% \def\@dtl@vonpart{#1}% \ifx\@dtl@vonpart\@empty \DTLstoreinitials{#2}{\@dtl@tmp}% \else \DTLstoreinitials{#1 #2}{\@dtl@tmp}% \fi} % \end{macrocode} % Get label for single author (last argument is control sequence % in which to store the label): % \begin{macrocode} \newcommand*{\dtl@getsinglealphalabel}[5]{% \def\@dtl@vonpart{#1}% \ifx\@dtl@vonpart\@empty \DTLifSubString{#2}{-}{% {\def\DTLafterinitials{}\def\DTLbetweeninitials{}% \def\DTLafterinitialbeforehyphen{}% \def\DTLinitialhyphen{}% \DTLstoreinitials{#2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}% }{% \dtl@getfirstthree{#5}#2{}{}{}{}\@nil } \else {\def\DTLafterinitials{}\def\DTLbetweeninitials{}% \def\DTLafterinitialbeforehyphen{}% \def\DTLinitialhyphen{}% \DTLstoreinitials{#1 #2}{\@dtl@tmp}\global\let#5=\@dtl@tmp}% \fi } % \end{macrocode} %Get first three letters from the given string: % \begin{macrocode} \def\dtl@getfirstthree#1#2#3#4#5\@nil{% \def#1{#2#3#4}% } \newcommand*{\dtl@get@firstthree}[2]{% \dtl@getfirstthree#2#1{}{}{}{}{}\@nil} % \end{macrocode} %Get year suffix: % \begin{macrocode} \newcommand*{\dtl@get@yearsuffix}[1]{% \dtl@getyearsuffix#1\@nil\relax\relax} \def\dtl@getyearsuffix#1#2#3{% \def\@dtl@argi{#1}\def\@dtl@argii{#2}% \def\@dtl@argiii{#3}% \ifx\@dtl@argi\@nnil \def\@dtl@year{}% \let\@dtl@donext=\relax \else \ifx\@dtl@argii\@nnil \dtl@ifsingle{#1}{% \def\@dtl@year{#1}% \let\@dtl@donext=\relax }{% \def\@dtl@donext{\dtl@getyearsuffix#1#2#3}% }% \else \ifx\@dtl@argiii\@nnil \dtl@ifsingle{#1}{% \dtl@ifsingle{#2}{% \def\@dtl@year{#1#2}% \let\@dtl@donext=\relax }{% \def\@dtl@donext{\dtl@getyearsuffix#2#3}% }% }{% \def\@dtl@donext{\dtl@getyearsuffix#2#3}% }% \else \def\@dtl@donext{\dtl@getyearsuffix{#2}{#3}}% \fi \fi \fi \@dtl@donext } % \end{macrocode} % %\begin{macro}{\DTLbibliographystyle} %\begin{definition} %\cs{DTLbibliographystyle}\marg{style} %\end{definition} % Sets the bibliography style. % \begin{macrocode} \newcommand*{\DTLbibliographystyle}[1]{% \@ifundefined{dtlbst@#1}{\PackageError{databib}{Unknown bibliography style `#1'}{}}{\csname dtlbst@#1\endcsname}} % \end{macrocode} %\end{macro} %Set the default bibliography style: % \begin{macrocode} \DTLbibliographystyle{\dtlbib@style} % \end{macrocode} % %\subsection{Multiple Bibliographies} % In order to have multiple bibliographies, there needs to be % an aux file for each bibliography. The main bibliography is in % \cs{jobname}.aux, but need to provide a means of creating % additional aux files. %\begin{macro}{\DTLmultibibs} %\begin{definition} %\cs{DTLmultibibs}\marg{list} %\end{definition} %\changes{1.01}{2007/08/22}{new} % This creates an auxiliary file for each name in \meta{list}. % For example, "\DTLmultibibs{foo,bar}" will create the files % "foo.aux" and "bar.aux". % \begin{macrocode} \newcommand*{\DTLmultibibs}[1]{% \@for\@dtl@af:=#1\do{% \@ifundefined{dtl@aux@\@dtl@af}{% \expandafter\newwrite\csname dtl@aux@\@dtl@af\endcsname \expandafter\immediate \expandafter\openout\csname dtl@aux@\@dtl@af\endcsname=\@dtl@af.aux \expandafter\def\csname b@\@dtl@af @*\endcsname{}% }{% \PackageError{databib}{Can't create auxiliary file `\@dtl@af.aux', \expandafter\string\csname dtl@aux@\@dtl@af\endcsname\space already exists}{}}}} % \end{macrocode} % Can only be used in the preamble: % \begin{macrocode} \@onlypreamble{\DTLmultibibs} % \end{macrocode} %\end{macro} %\begin{macro}{\DTLcite} %\begin{definition} %\cs{DTLcite}\oarg{text}\marg{mbib}\marg{labels} %\end{definition} % This is similar to \cs{cite}\oarg{text}\marg{labels}, except % 1) the cite information is written to the auxiliary file % associated with the multi-bib \meta{mbib} (which must be named % in \cs{DTLmultibibs}) and 2) the cross referencing label is % constructed from \meta{mbib} and \meta{label} to allow for % the same citation to appear in multiple bibliographies. % \begin{macrocode} \newcommand*{\DTLcite}{\@ifnextchar[{\@tempswatrue \dtl@citex }{\@tempswafalse \dtl@citex[]}} % \end{macrocode} %\end{macro} %\begin{macro}{\dtl@citex} % \begin{macrocode} \def\dtl@citex[#1]#2#3{% \leavevmode\let\@citea\@empty \@cite{\@for\@citeb:=#3\do{\@citea \def\@citea{,\penalty \@m \ }% \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}% \if@filesw \@ifundefined{dtl@aux@#2}{% \PackageError{databib}{multibib `#2' not defined}{% You need to define `#2' in \string\DTLmutlibibs}% }{% \expandafter\immediate \expandafter\write\csname dtl@aux@#2\endcsname{% \string\citation{\@citeb}}% }% \fi \@ifundefined{b@#2@\@citeb}{% \hbox{\reset@font\bfseries ?}% \G@refundefinedtrue \@latex@warning{Citation `\@citeb ' on page \thepage \space undefined}% }{% \@cite@ofmt{\csname b@#2@\@citeb \endcsname }% }% }}{#1}% } % \end{macrocode} %\end{macro} %\begin{macro}{\DTLnocite} %\begin{definition} %\cs{DTLnocite}\marg{mbib}\marg{key list} %\end{definition} % As \cs{nocite} but uses the aux file associated with \meta{mbib} % which must have been defined using \cs{DTLmultibibs}. % \begin{macrocode} \newcommand*{\DTLnocite}[2]{% \@ifundefined{dtl@aux@#1}{% \PackageError{databib}{multibib `#1' not defined}{% You need to define `#1' in \string\DTLmutlibibs}% }{% \@bsphack \ifx\@onlypreamble\document \@for\@citeb:=#2\do{% \edef\@citeb{\expandafter\@firstofone\@citeb}% \if@filesw \expandafter\immediate \expandafter\write\csname dtl@aux@#1\endcsname{% \string\citation{\@citeb}}% \fi \@ifundefined{b@#1@\@citeb}{% \G@refundefinedtrue \@latex@warning{Citation `\@citeb ' undefined}}{}% }% \else \@latex@error{Cannot be used in preamble}\@eha \fi \@esphack }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLloadmbbl} %\begin{definition} %\cs{DTLloadmbib}\marg{mbib}\marg{db name}\marg{bib list} %\end{definition} % \begin{macrocode} \newcommand*{\DTLloadmbbl}[3]{% \@ifundefined{dtl@aux@#1}{% \PackageError{databib}{multibib `#1' not defined}{% You need to define `#1' in \string\DTLmutlibibs}% }{% \if@filesw \expandafter\immediate\expandafter \write\csname dtl@aux@#1\endcsname{\string\bibstyle{databib}}% \expandafter\immediate\expandafter \write\csname dtl@aux@#1\endcsname{\string\bibdata{#3}}% \fi \DTLnewdb{#2}% \edef\DTLBIBdbname{#2}% \@input@{#1.bbl}% }% } % \end{macrocode} %\end{macro} %\begin{definition} %\cs{DTLmbibliography}\oarg{condition}\marg{mbib name}\marg{bib dbname} %\end{definition} % Displays the bibliography for the database \meta{bib dbname} % which must have previously been loaded using % \cs{DTLloadmbbl}, where \meta{mbib name} must be listed % in \cs{DTLmultibibs}. %\begin{macro}{\DTLmbibliography} % \begin{macrocode} \newcommand*{\DTLmbibliography}[3][\boolean{true}]{% \begin{DTLthebibliography}[#1]{#3}% \DTLforeachbibentry[#1]{#3}{% \DTLmbibitem{#2} \DTLformatbibentry \DTLendbibitem }% \end{DTLthebibliography}% } % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*databib.bst> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % \begin{macrocode} % Bibliography style `databib' % This style is provided for use with the databib package. % v1.01 (2007/08/22) - added "file" field ENTRY { 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 url abstract file } {} { label } INTEGERS { output.state before.all mid.sentence after.sentence after.block } FUNCTION {init.state.consts} { #0 'before.all := #1 'mid.sentence := #2 'after.sentence := #3 'after.block := } STRINGS { s t } FUNCTION {output.nonnull} { 's := % output.state mid.sentence = % { "%" * write$ % newline$ % } % { output.state after.block = % { add.period$ write$ % newline$ % } %{ output.state before.all = { "%" * write$ newline$ } { newline$ %add.period$ " " * write$ } if$ % } % if$ % mid.sentence 'output.state := % } %if$ s } FUNCTION {output} { duplicate$ empty$ 'pop$ 'output.nonnull if$ } FUNCTION {output.check} { 't := duplicate$ empty$ { pop$ "empty " t * " in " * cite$ * warning$ } { output.nonnull } if$ } FUNCTION {output.bibitem} { "\DTLnewbibrow" write$ newline$ "\DTLnewbibitem {CiteKey}{" write$ cite$ write$ "}%" write$ newline$ "" before.all 'output.state := } FUNCTION {fin.entry} { "%" * write$ newline$ } FUNCTION {new.block} { output.state before.all = 'skip$ { after.block 'output.state := } if$ } FUNCTION {new.sentence} { output.state after.block = 'skip$ { output.state before.all = 'skip$ { after.sentence 'output.state := } if$ } if$ } FUNCTION {not} { { #0 } { #1 } if$ } FUNCTION {and} { 'skip$ { pop$ #0 } if$ } FUNCTION {or} { { pop$ #1 } 'skip$ if$ } FUNCTION {new.block.checka} { empty$ 'skip$ 'new.block if$ } FUNCTION {new.block.checkb} { empty$ swap$ empty$ and 'skip$ 'new.block if$ } FUNCTION {new.sentence.checka} { empty$ 'skip$ 'new.sentence if$ } FUNCTION {new.sentence.checkb} { empty$ swap$ empty$ and 'skip$ 'new.sentence if$ } FUNCTION {field.or.null} { duplicate$ empty$ { pop$ "" } 'skip$ if$ } FUNCTION {emphasize} { duplicate$ empty$ { pop$ "" } { "{\em " swap$ * "}" * } if$ } FUNCTION {group} { duplicate$ empty$ { pop$ "" } { "{" swap$ * "}" * } if$ } INTEGERS { nameptr namesleft numnames } FUNCTION {format.names} { 's := #1 'nameptr := s num.names$ 'numnames := numnames 'namesleft := { namesleft #0 > } { %s nameptr "{vv,}{ll,}{jj,}{ff}" format.name$ 't := "{" * s nameptr "{vv}" format.name$ 't := t * "}" * "{" * s nameptr "{ll}" format.name$ 't := t * "}{" * s nameptr "{jj}" format.name$ 't := t * "}" * "{" * s nameptr "{ff}" format.name$ 't := t * "}" * s nameptr "" format.name$ 't := namesleft #1 > { "," * } { } if$ nameptr #1 > { t * } 't if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ "}" * } FUNCTION {format.authors} { author empty$ { "" } { author "\DTLnewbibitem {Author}{" write$ format.names } if$ } FUNCTION {format.editors} { editor empty$ { "" } { editor "\DTLnewbibitem {Editor}{" write$ format.names } if$ } FUNCTION {format.title} { title empty$ { "" } { "\DTLnewbibitem {Title}" title "t" change.case$ group * } if$ } FUNCTION {format.howpublished} { howpublished empty$ { "" } { howpublished "\DTLnewbibitem {HowPublished}" swap$ group * } if$ } FUNCTION {format.organization} { organization empty$ { "" } { organization "\DTLnewbibitem {Organization}" swap$ group * } if$ } FUNCTION {format.institution} { institution empty$ { "" } { institution "\DTLnewbibitem {Institution}" swap$ group * } if$ } FUNCTION {format.key} { key empty$ { "" } { key "\DTLnewbibitem {Key}" swap$ group * } if$ } FUNCTION {format.note} { note empty$ { "" } { note "\DTLnewbibitem {Note}" swap$ group * } if$ } FUNCTION {format.isbn} { isbn empty$ { "" } { isbn "\DTLnewbibitem {ISBN}" swap$ group * } if$ } FUNCTION {format.doi} { doi empty$ { "" } { doi "\DTLnewbibitem {DOI}" swap$ group * } if$ } FUNCTION {format.pubmed} { pubmed empty$ { "" } { pubmed "\DTLnewbibitem {PubMed}" swap$ group * } if$ } FUNCTION {format.abstract} { abstract empty$ { "" } { abstract "\DTLnewbibitem {Abstract}" swap$ group * } if$ } FUNCTION {format.url} { url empty$ { "" } { url "\DTLnewbibitem {Url}" swap$ group * } if$ } FUNCTION {format.file} { file empty$ { "" } { file "\DTLnewbibitem {File}" swap$ group * } if$ } FUNCTION {format.address} { address empty$ { "" } { address "\DTLnewbibitem {Address}" swap$ group * } if$ } FUNCTION {format.school} { school empty$ { "" } { school "\DTLnewbibitem {School}" swap$ group * } if$ } FUNCTION {format.publisher} { publisher empty$ { "" } { publisher "\DTLnewbibitem {Publisher}" swap$ group * } if$ } FUNCTION {n.dashify} { 't := "" { t empty$ not } { t #1 #1 substring$ "-" = { t #1 #2 substring$ "--" = not { "--" * t #2 global.max$ substring$ 't := } { { t #1 #1 substring$ "-" = } { "-" * t #2 global.max$ substring$ 't := } while$ } if$ } { t #1 #1 substring$ * t #2 global.max$ substring$ 't := } if$ } while$ } FUNCTION {format.date} { year empty$ { month empty$ { "" } { "there's a month but no year in " cite$ * warning$ "\DTLnewbibitem {Month}" * month group } if$ } { month empty$ { } { "\DTLnewbibitem {Month}{" * month * "}" * } if$ "\DTLnewbibitem {Year}{" * year * "}" } if$ } FUNCTION {format.btitle} { title "\DTLnewbibitem {Title}{" swap$ * "}" * } FUNCTION {tie.or.space.connect} { duplicate$ text.length$ #3 < { "~" } { " " } if$ swap$ * * } FUNCTION {either.or.check} { empty$ 'pop$ { "can't use both " swap$ * " fields in " * cite$ * warning$ } if$ } FUNCTION {format.bvolume} { volume empty$ { "" } { "\DTLnewbibitem {Volume}{" volume * "}" * series empty$ 'skip$ { "\DTLnewbibitem {Series}" * series group * } if$ "volume and number" number either.or.check } if$ } FUNCTION {format.number.series} { volume empty$ { number empty$ { %series field.or.null group series empty$ { "" } { "\DTLnewbibitem {Series}" * series group } if$ } { "\DTLnewbibitem {Number}" number group * series empty$ { "there's a number but no series in " cite$ * warning$ } { "\DTLnewbibitem {Series}{" * series * "}" * } if$ } if$ } { "" } if$ } FUNCTION {format.edition} { edition empty$ { "" } { "\DTLnewbibitem {Edition}" edition "l" change.case$ group * } if$ } INTEGERS { multiresult } FUNCTION {multi.page.check} { 't := #0 'multiresult := { multiresult not t empty$ not and } { t #1 #1 substring$ duplicate$ "-" = swap$ duplicate$ "," = swap$ "+" = or or { #1 'multiresult := } { t #2 global.max$ substring$ 't := } if$ } while$ multiresult } FUNCTION {format.pages} { pages empty$ { "" } { pages multi.page.check { "\DTLnewbibitem {Pages}" pages n.dashify group * } { "\DTLnewbibitem {Pages}" pages group *} if$ } if$ } FUNCTION {format.vol.num.pages} { volume empty$ { "" } { "\DTLnewbibitem {Volume}{" volume * "}" * } if$ number empty$ 'skip$ { "\DTLnewbibitem {Number}{" number * "}\relax " * * volume empty$ { "there's a number but no volume in " cite$ * warning$ } 'skip$ if$ } if$ pages empty$ 'skip$ { duplicate$ empty$ { pop$ format.pages } { "\DTLnewbibitem {Pages}" * pages n.dashify group * } if$ } if$ } FUNCTION {format.chapter.pages} { chapter empty$ 'format.pages { type empty$ { "\DTLnewbibitem {Type}{chapter}" } { "\DTLnewbibitem {Type}" type "l" change.case$ group *} if$ "\DTLnewbibitem {Chapter}{" * chapter * "}" * pages empty$ 'skip$ { format.pages * } if$ } if$ } FUNCTION {format.in.ed.booktitle} { booktitle empty$ { "" } { "\DTLnewbibitem {BookTitle}" booktitle group * editor empty$ {} { "\DTLnewbibitem {Editor}{" * editor format.names * } if$ } if$ } FUNCTION {empty.misc.check} { author empty$ title empty$ howpublished empty$ month empty$ year empty$ note empty$ and and and and and { "all relevant fields are empty in " cite$ * warning$ } 'skip$ if$ } FUNCTION {format.thesis.type} { type empty$ 'skip$ { pop$ type "t" change.case$ "\DTLnewbibitem {Type}" swap$ group * } if$ } FUNCTION {format.tr.number} { type empty$ { "\techreportname " } 'type if$ number empty$ { "t" change.case$ "\DTLnewbibitem {Type}" swap$ group *} { "\DTLnewbibitem {Type}" swap$ group * "\DTLnewbibitem {Number}" * number group * } if$ } FUNCTION {format.article.crossref} { key empty$ { journal empty$ { "need key or journal for " cite$ * " to crossref " * crossref * warning$ "" } { "\DTLnewbibitem {Journal}" journal group * } if$ } { "" } if$ "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } FUNCTION {format.crossref.editor} { format.editors % editor #1 "{vv~}{ll}" format.name$ % editor num.names$ duplicate$ % #2 > % { pop$ " et~al." * } % { #2 < % 'skip$ % { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = % { " et~al." * } % { " and " * editor #2 "{vv~}{ll}" format.name$ * } % if$ % } % if$ % } % if$ } FUNCTION {format.book.crossref} { volume empty$ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ } { "\DTLnewbibitem {Volume}" volume group * } if$ editor empty$ editor field.or.null author field.or.null = or { key empty$ { series empty$ { "need editor, key, or series for " cite$ * " to crossref " * crossref * warning$ "" * } { "\DTLnewbibitem {Series}{" * series * "}" * } if$ } { "" } if$ } { format.crossref.editor * } if$ "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } FUNCTION {format.incoll.inproc.crossref} { editor empty$ editor field.or.null author field.or.null = or { key empty$ { booktitle empty$ { "need editor, key, or booktitle for " cite$ * " to crossref " * crossref * warning$ "" } { "\DTLnewbibitem {BookTitle}{" booktitle * "}" * } if$ } { "" } if$ } { "\DTLnewbibitem {Editor}{" * editor format.names } if$ "\DTLnewbibitem {CrossRef}{" * crossref * "}" * } FUNCTION {article} { output.bibitem "\DTLnewbibitem {EntryType}{article}%" write$ newline$ format.authors "author" output.check format.title "title" output.check new.block crossref missing$ { "\DTLnewbibitem {Journal}" * journal group "journal" output.check format.vol.num.pages output format.date "year" output.check } { format.article.crossref output.nonnull format.pages output } if$ new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {book} { output.bibitem "\DTLnewbibitem {EntryType}{book}%" write$ newline$ author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ new.block format.btitle "title" output.check crossref missing$ { format.bvolume output new.block format.number.series output %new.sentence format.publisher "publisher" output.check format.address output } { new.block format.book.crossref output.nonnull } if$ format.edition output format.date "year" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {booklet} { output.bibitem "\DTLnewbibitem {EntryType}{booklet}%" write$ newline$ format.authors output new.block format.title "title" output.check howpublished address new.block.checkb format.howpublished output format.address output format.date output new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {inbook} { output.bibitem "\DTLnewbibitem {EntryType}{inbook}%" write$ newline$ author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ new.block format.btitle "title" output.check crossref missing$ { format.bvolume output format.chapter.pages "chapter and pages" output.check new.block format.number.series output new.sentence format.publisher "publisher" output.check format.address output } { format.chapter.pages "chapter and pages" output.check new.block format.book.crossref output.nonnull } if$ format.edition output format.date "year" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {incollection} { output.bibitem "\DTLnewbibitem {EntryType}{incollection}%" write$ newline$ format.authors "author" output.check format.title "title" output.check crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.chapter.pages output new.sentence format.publisher "publisher" output.check format.address output format.edition output format.date "year" output.check } { format.incoll.inproc.crossref output.nonnull format.chapter.pages output } if$ format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {inproceedings} { output.bibitem "\DTLnewbibitem {EntryType}{inproceedings}%" write$ newline$ format.authors "author" output.check format.title "title" output.check crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.pages output address empty$ { %organization publisher new.sentence.checkb format.organization write$ format.publisher output } { format.address write$ new.sentence format.organization output format.publisher output } if$ format.date "year" output.check } { format.incoll.inproc.crossref output.nonnull format.pages output } if$ format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {conference} { inproceedings } FUNCTION {manual} { output.bibitem "\DTLnewbibitem {EntryType}{manual}%" write$ newline$ author empty$ { organization empty$ 'skip$ { format.organization output format.address output } if$ } { format.authors output } if$ new.block format.btitle "title" output.check author empty$ { organization empty$ { address new.block.checka address output } 'skip$ if$ } { %organization address new.block.checkb format.organization output format.address output } if$ format.edition output format.date output new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {mastersthesis} { output.bibitem "\DTLnewbibitem {EntryType}{mastersthesis}%" write$ newline$ format.authors "author" output.check new.block format.title "title" output.check new.block "\DTLnewbibitem {Type}{\mscthesisname }" format.thesis.type output.nonnull format.school "school" output.check format.address output format.date "year" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {misc} { output.bibitem "\DTLnewbibitem {EntryType}{misc}%" write$ newline$ format.authors output title howpublished new.block.checkb format.title output %howpublished new.block.checka format.howpublished output format.date output new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry empty.misc.check } FUNCTION {phdthesis} { output.bibitem "\DTLnewbibitem {EntryType}{phdthesis}%" write$ newline$ format.authors "author" output.check new.block format.btitle "title" output.check new.block "\DTLnewbibitem {Type}{\phdthesisname }" format.thesis.type output.nonnull format.school "school" output.check format.address output format.date "year" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {proceedings} { output.bibitem "\DTLnewbibitem {EntryType}{proceedings}%" write$ newline$ editor empty$ { format.organization output } { format.editors output.nonnull } if$ new.block format.btitle "title" output.check format.bvolume output format.number.series output address empty$ { editor empty$ { publisher new.sentence.checka } { organization publisher new.sentence.checkb format.organization output } if$ format.publisher output format.date "year" output.check } { format.address output format.date "year" output.check new.sentence editor empty$ 'skip$ { format.organization output } if$ format.publisher output } if$ new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {techreport} { output.bibitem "\DTLnewbibitem {EntryType}{techreport}%" write$ newline$ format.authors "author" output.check new.block format.title "title" output.check new.block format.tr.number output.nonnull format.institution "institution" output.check format.address output format.date "year" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output fin.entry } FUNCTION {unpublished} { output.bibitem "\DTLnewbibitem {EntryType}{unpublished}%" write$ newline$ format.authors "author" output.check new.block format.title "title" output.check new.block format.key output format.note output format.isbn output format.doi output format.pubmed output format.url output format.abstract output format.file output format.date output fin.entry } FUNCTION {default.type} { misc } MACRO {jan} {"\DTLmonthname{01}"} MACRO {feb} {"\DTLmonthname{02}"} MACRO {mar} {"\DTLmonthname{03}"} MACRO {apr} {"\DTLmonthname{04}"} MACRO {may} {"\DTLmonthname{05}"} MACRO {jun} {"\DTLmonthname{06}"} MACRO {jul} {"\DTLmonthname{07}"} MACRO {aug} {"\DTLmonthname{08}"} MACRO {sep} {"\DTLmonthname{09}"} MACRO {oct} {"\DTLmonthname{10}"} MACRO {nov} {"\DTLmonthname{11}"} MACRO {dec} {"\DTLmonthname{12}"} MACRO {acmcs} {"\DTLacmcs "} MACRO {acta} {"\DTLacta "} MACRO {cacm} {"\DTLcacm "} MACRO {ibmjrd} {"\DTLibmjrd "} MACRO {ibmsj} {"\DTLibmsj "} MACRO {ieeese} {"\DTLieeese "} MACRO {ieeetc} {"\DTLieeetc "} MACRO {ieeetcad} {"\DTLieeetcad "} MACRO {ipl} {"\DTLipl "} MACRO {jacm} {"\DTLjacm "} MACRO {jcss} {"\DTLjcss "} MACRO {scp} {"\DTLscp "} MACRO {sicomp} {"\DTLsicomp "} MACRO {tocs} {"\DTLtocs "} MACRO {tods} {"\DTLtods "} MACRO {tog} {"\DTLtog "} MACRO {toms} {"\DTLtoms "} MACRO {toois} {"\DTLtoois "} MACRO {toplas} {"\DTLtoplas "} MACRO {tcs} {"\DTLtcs "} READ STRINGS { longest.label } INTEGERS { number.label longest.label.width } FUNCTION {initialize.longest.label} { "" 'longest.label := #1 'number.label := #0 'longest.label.width := } FUNCTION {longest.label.pass} { number.label int.to.str$ 'label := number.label #1 + 'number.label := label width$ longest.label.width > { label 'longest.label := label width$ 'longest.label.width := } 'skip$ if$ } EXECUTE {initialize.longest.label} ITERATE {longest.label.pass} FUNCTION {begin.bib} { preamble$ empty$ 'skip$ { preamble$ write$ newline$ } if$ } EXECUTE {begin.bib} EXECUTE {init.state.consts} ITERATE {call.type$} FUNCTION {end.bib} { } EXECUTE {end.bib} % \end{macrocode} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*person.sty> % \end{macrocode} %\fi %\section{person.sty}\label{sec:code:person} %\subsection{Package Declaration} % Package identification: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{person}[2009/11/15 v1.01 (NLCT)] % \end{macrocode} % Requires the \sty{ifthen} package. % \begin{macrocode} \RequirePackage{ifthen} \RequirePackage{datatool} % \end{macrocode} %\subsection{Defining People} %\begin{counter}{people} % Keep count of the number of people who have been defined: % \begin{macrocode} \newcounter{people} % \end{macrocode} %\end{counter} %\begin{counter}{person} % Temporary counter % \begin{macrocode} \newcounter{person} % \end{macrocode} %\end{counter} %\begin{macro}{\@people@list} % Keep a list of labels for each person who has been defined: % \begin{macrocode} \newcommand*{\@people@list}{,} % \end{macrocode} %\end{macro} %\begin{macro}{\@get@firstperson} % Get the first person's name in \cs{@people@list}, and store in % the argument (which must be a control sequence.) % \begin{macrocode} \newcommand*{\@get@firstperson}[1]{% \expandafter\@@get@firstperson\@people@list,\@nil{#1}} \def\@@get@firstperson,#1,#2\@nil#3{% \def#3{#1}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\malelabels} % List of labels that can be used to indicate that a person is % male (when defining a person using \cs{newperson}). % \begin{macrocode} \newcommand*{\malelabels}{male,Male,MALE,M,m} % \end{macrocode} %\end{macro} %\begin{macro}{\addmalelabel} % Adds a label to the list of male labels. % \begin{macrocode} \newcommand*{\addmalelabel}[1]{% \expandafter\@dtl@toksA\expandafter{\malelabels}% \expandafter\@dtl@toksB\expandafter{#1}% \edef\malelabels{\the\@dtl@toksA,\the\@dtl@toksB}% } % \end{macrocode} %\end{macro} %\begin{macro}{\addfemalelabel} % Adds a label to the list of female labels. % \begin{macrocode} \newcommand*{\addfemalelabel}[1]{% \expandafter\@dtl@toksA\expandafter{\femalelabels}% \expandafter\@dtl@toksB\expandafter{#1}% \edef\femalelabels{\the\@dtl@toksA,\the\@dtl@toksB}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\femalelabels} % List of labels that can be used to indicate that a person is % female (when defining a person using \cs{newperson}). % \begin{macrocode} \newcommand*{\femalelabels}{female,Female,FEMALE,F,f} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifmalelabel} % Determines if first argument is contained in the list of male % labels. (One level expansion is performed on the first object % in first argument.) % If true does second argument, otherwise does third argument. % \begin{macrocode} \newcommand{\ifmalelabel}[3]{% \expandafter\DTLifinlist\expandafter{#1}{\malelabels}{#2}{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\iffemalelabel} % Determines if first argument is contained in the list of female % labels. (One level expansion is performed on the first object % in first argument.) % If true does second argument, otherwise does third argument. % \begin{macrocode} \newcommand{\iffemalelabel}[3]{% \expandafter\DTLifinlist\expandafter{#1}{\femalelabels}{#2}{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\newperson} % Define a new person. The optional argument specifies a label % with which to refer to that person. If omitted, \texttt{anon} % is used. If more than one person is defined, the optional % argument will be required to specify a unique label. The % compulsory arguments are the person's full name, their % familiar name and their gender. % \begin{macrocode} \newcommand*{\newperson}[4][anon]{% \@ifundefined{person@#1@name}% {% \ifmalelabel{#4}% {% \expandafter\gdef\csname person@#1@gender\endcsname{male}% }% {% \iffemalelabel{#4}% {% \expandafter\gdef\csname person@#1@gender\endcsname{female}% }% {% \PackageError{person}{Unknown gender `#4' for person `#1'}{Allowed gender labels are: \malelabels\space or \femalelabels}% \@namedef{person@#1@gender}{other}% }% }% \expandafter \protected@xdef\csname person@#1@fullname\endcsname{#2}% \expandafter \protected@xdef\csname person@#1@name\endcsname{#3}% \protected@xdef\@people@list{\@people@list#1,}% \stepcounter{people}% }% {% \PackageError{person}{Person `#1' has already been defined}{}% }% } % \end{macrocode} %\end{macro} % %\subsection{Remove People} % %\begin{macro}{\removeperson} % Removes person identified by their label from the list. % \begin{macrocode} \newcommand*{\removeperson}[1][anon]{% \edef\@person@label{#1}% \expandafter\@removeperson\expandafter{\@person@label}% } % \end{macrocode} % The label has to be full expanded for the internal command. % \begin{macrocode} \newcommand*{\@removeperson}[1]{% \ifpersonexists{#1}% {% % \end{macrocode} % Remove label from list of people. % \begin{macrocode} \def\@remove@person##1,#1,##2\@nil{% \def\@prsn@pre{##1}\def\@prsn@post{##2}}% \expandafter\@remove@person\@people@list\@nil \xdef\@people@list{\@prsn@pre,\@prsn@post}% % \end{macrocode} % Decrement number of people: % \begin{macrocode} \addtocounter{people}{-1}% % \end{macrocode} % Undefine associated control sequences: % \begin{macrocode} \expandafter\global\expandafter \let\csname person@#1@name\endcsname\undefined \expandafter\global\expandafter \let\csname person@#1@fullname\endcsname\undefined \expandafter\global\expandafter \let\csname person@#1@gender\endcsname\undefined }% {% \PackageError{person}{Can't remove person `#1': no such person}{}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\removepeople} % Removes the people listed. % \begin{macrocode} \newcommand*{\removepeople}[1]{% \@for\@thisperson:=#1\do{% \ifx\@thisperson\@empty \else \expandafter\removeperson\expandafter[\@thisperson]% \fi }% } % \end{macrocode} %\end{macro} %\begin{macro}{\removeallpeople} % Removes everyone. % \begin{macrocode} \newcommand*{\removeallpeople}{% \@for\@thisperson:=\@people@list\do{% \expandafter\global\expandafter \let\csname person@\@thisperson @name\endcsname\undefined \expandafter\global\expandafter \let\csname person@\@thisperson @fullname\endcsname\undefined \expandafter\global\expandafter \let\csname person@\@thisperson @gender\endcsname\undefined }% \setcounter{people}{0}% \gdef\@people@list{,}% } % \end{macrocode} %\end{macro} % %\subsection{Conditionals and Loops} %\begin{macro}{\ifpersonexists} % If person whose label is given by the first argument exists, then % do the second argument otherwise do third argument. % \begin{macrocode} \newcommand{\ifpersonexists}[3]{% \@ifundefined{person@#1@name}{#3}{#2}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\ifmale} % If the person given by the label in the first argument is male, % do the second argument, otherwise do the third argument. % \begin{macrocode} \newcommand{\ifmale}[3]{% \ifpersonexists{#1}% {% \edef\@gender{\csname person@\@thisperson @gender\endcsname}% \ifx\@gender\@male@label #2% \else #3% \fi }% {% \PackageError{person}{Person `#1' doesn't exist.}{}% }% } \def\@male@label{male} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifallmale} % If all people listed in first argument are male, do the second % argument otherwise do the third argument. If the first argument % is omitted, all defined people are checked. % \begin{macrocode} \newcommand{\ifallmale}[3][\@people@list]{% \@for\@thisperson:=#1\do{% \ifpersonexists{\@thisperson}% {% \edef\@gender{\csname person@\@thisperson @gender\endcsname}% \ifx\@gender\@male@label \else \@endfortrue \fi }% {% \PackageError{person}{Person `#1' doesn't exist.}{}% }% }% \if@endfor #3% \else #2% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\iffemale} % If the person given by the label in the first argument is female, % do the second argument, otherwise do the third argument. % \begin{macrocode} \newcommand{\iffemale}[3]{% \ifpersonexists{#1}% {% \edef\@gender{\csname person@\@thisperson @gender\endcsname}% \ifx\@gender\@female@label #2% \else #3% \fi }% {% \PackageError{person}{Person `#1' doesn't exist.}{}% }% } \def\@female@label{female} % \end{macrocode} %\end{macro} % %\begin{macro}{\ifallfemale} % If all people listed in first argument are female, do the second % argument otherwise do the third argument. % \begin{macrocode} \newcommand{\ifallfemale}[3][\@people@list]{% \@for\@thisperson:=#1\do{% \edef\@gender{\csname person@\@thisperson @gender\endcsname}% \ifx\@gender\@female@label \else \@endfortrue \fi }% \if@endfor #3% \else #2% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\foreachperson} %\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} % Iterates through list of people the \cs{in}\marg{list} is optional. % If omitted, the list of all defined people is used. % \begin{macrocode} \def\foreachperson(#1,#2,#3,#4)#5{% \ifx#5\in \def\@do@foreachperson{\@foreachperson(#1,#2,#3,#4)#5}% \else \def\@do@foreachperson{% \@foreachperson(#1,#2,#3,#4)\in\@people@list#5}% \fi \@do@foreachperson } \long\def\@foreachperson(#1,#2,#3,#4)\in#5\do#6{% \@for#4:=#5\do{% \ifx#4\@empty \else \ifpersonexists{#4}% {% \expandafter \let\expandafter#1\csname person@#4@name\endcsname \expandafter \let\expandafter#2\csname person@#4@fullname\endcsname \expandafter \let\expandafter#3\csname person@#4@gender\endcsname \ifx#3\@male@label \let#3\malename \else \ifx#3\@female@label \let#3\femalename \fi \fi #6% }% {% \PackageError{person}{Person `#4' doesn't exist}{}% }% \fi }% } % \end{macrocode} %\end{macro} % %\subsection{Predefined Words}\label{sec:code:peoplenames} % These commands should be redefined if % you are writing in another language, but note that these % are structured according to English grammar. %\begin{macro}{\malepronoun} % \begin{macrocode} \newcommand*{\malepronoun}{he} % \end{macrocode} %\end{macro} %\begin{macro}{\femalepronoun} % \begin{macrocode} \newcommand*{\femalepronoun}{she} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralpronoun} % \begin{macrocode} \newcommand*{\pluralpronoun}{they} % \end{macrocode} %\end{macro} %\begin{macro}{\maleobjpronoun} % \begin{macrocode} \newcommand*{\maleobjpronoun}{him} % \end{macrocode} %\end{macro} %\begin{macro}{\femaleobjpronoun} % \begin{macrocode} \newcommand*{\femaleobjpronoun}{her} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralobjpronoun} % \begin{macrocode} \newcommand*{\pluralobjpronoun}{them} % \end{macrocode} %\end{macro} %\begin{macro}{\malepossadj} % \begin{macrocode} \newcommand*{\malepossadj}{his} % \end{macrocode} %\end{macro} %\begin{macro}{\femalepossadj} % \begin{macrocode} \newcommand*{\femalepossadj}{her} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralpossadj} % \begin{macrocode} \newcommand*{\pluralpossadj}{their} % \end{macrocode} %\end{macro} %\begin{macro}{\maleposspronoun} % \begin{macrocode} \newcommand*{\maleposspronoun}{his} % \end{macrocode} %\end{macro} %\begin{macro}{\femaleposspronoun} % \begin{macrocode} \newcommand*{\femaleposspronoun}{hers} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralposspronoun} % \begin{macrocode} \newcommand*{\pluralposspronoun}{theirs} % \end{macrocode} %\end{macro} %\begin{macro}{\malechild} % \begin{macrocode} \newcommand*{\malechild}{son} % \end{macrocode} %\end{macro} %\begin{macro}{\femalechild} % \begin{macrocode} \newcommand*{\femalechild}{daughter} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralchild} % \begin{macrocode} \newcommand*{\pluralchild}{children} % \end{macrocode} %\end{macro} %\begin{macro}{\malechildren} % \begin{macrocode} \newcommand*{\malechildren}{sons} % \end{macrocode} %\end{macro} %\begin{macro}{\femalechildren} % \begin{macrocode} \newcommand*{\femalechildren}{daughters} % \end{macrocode} %\end{macro} %\begin{macro}{\maleparent} % \begin{macrocode} \newcommand*{\maleparent}{father} % \end{macrocode} %\end{macro} %\begin{macro}{\femaleparent} % \begin{macrocode} \newcommand*{\femaleparent}{mother} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralparent} % \begin{macrocode} \newcommand*{\pluralparent}{parents} % \end{macrocode} %\end{macro} %\begin{macro}{\malesibling} % \begin{macrocode} \newcommand*{\malesibling}{brother} % \end{macrocode} %\end{macro} %\begin{macro}{\femalesibling} % \begin{macrocode} \newcommand*{\femalesibling}{sister} % \end{macrocode} %\end{macro} %\begin{macro}{\pluralsibling} % \begin{macrocode} \newcommand*{\pluralsibling}{siblings} % \end{macrocode} %\end{macro} %\begin{macro}{\malesiblings} % \begin{macrocode} \newcommand*{\malesiblings}{brothers} % \end{macrocode} %\end{macro} %\begin{macro}{\femalesiblings} % \begin{macrocode} \newcommand*{\femalesiblings}{sisters} % \end{macrocode} %\end{macro} % %\begin{macro}{\andname} % Define \cs{andname} if it hasn't already been defined: % \begin{macrocode} \providecommand*{\andname}{and} % \end{macrocode} %\end{macro} %\begin{macro}{\malename} % \begin{macrocode} \newcommand*{\malename}{male} % \end{macrocode} %\end{macro} %\begin{macro}{\femalename} % \begin{macrocode} \newcommand*{\femalename}{female} % \end{macrocode} %\end{macro} % %\begin{macro}{\personsep} % Separator to use between people (but not the between the last % two). % \begin{macrocode} \newcommand*{\personsep}{, } % \end{macrocode} %\end{macro} %\begin{macro}{\personlastsep} % Separator to use between last two people. % \begin{macrocode} \newcommand*{\personlastsep}{\space\andname\space} % \end{macrocode} %\end{macro} %\begin{macro}{\twopeoplesep} % Separator to use when list only contains two people. % \begin{macrocode} \newcommand*{\twopeoplesep}{\space\andname\space} % \end{macrocode} %\end{macro} % %\subsection{Displaying Information} %\begin{macro}{\personfullname} % The person's full name can be displayed using % \cs{personfullname}\oarg{label}, where \meta{label} is the % unique label used when defining that person. If \meta{label} % is omitted, \texttt{anon} is used. % \begin{macrocode} \newcommand*{\personfullname}[1][anon]{% \@ifundefined{person@#1@fullname}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \csname person@#1@fullname\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\peoplefullname} % List all defined people's full names. This iterates through all % labels in \cs{@people@list}. % \begin{macrocode} \newcommand*{\peoplefullname}{% \setcounter{person}{1}% \@for\@thisperson:=\@people@list\do{% \ifthenelse{\equal{\@thisperson}{}}% {}% {% \personfullname[\@thisperson]% \stepcounter{person}% \ifnum\c@people=1\relax \else \ifnum\c@person=\c@people \ifnum\c@people=2\relax \twopeoplesep \else \personlastsep \fi \else \ifnum\c@person<\c@people \personsep \fi \fi \fi }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\personname} % As \cs{personfullname}, but for the person's familiar name. % \begin{macrocode} \newcommand*{\personname}[1][anon]{% \@ifundefined{person@#1@name}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \csname person@#1@name\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\peoplename} % List all defined people's familiar names. This iterates through all % labels in \cs{@people@list}. % \begin{macrocode} \newcommand*{\peoplename}{% \setcounter{person}{1}% \@for\@thisperson:=\@people@list\do{% \ifthenelse{\equal{\@thisperson}{}}% {}% {% \personname[\@thisperson]% \stepcounter{person}% \ifnum\c@people=1\relax \else \ifnum\c@person=\c@people \ifnum\c@people=2\relax \twopeoplesep \else \personlastsep \fi \else \ifnum\c@person<\c@people \personsep \fi \fi \fi }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\personpronoun} % Display the pronoun (he/she) according to the person's gender. % \begin{macrocode} \newcommand*{\personpronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender pronoun\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\Personpronoun} % As above, but make the first letter uppercase. % \begin{macrocode} \newcommand*{\Personpronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter \MakeUppercase\csname\@gender pronoun\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\peoplepronoun} % If there is more than one person, \cs{peoplepronoun} will use % \cs{pluralpronoun}, otherwise it will use \cs{personpronoun}. % \begin{macrocode} \newcommand*{\peoplepronoun}{% \ifnum\c@people>1\relax \pluralpronoun \else \@get@firstperson{\@thisperson}% \personpronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\Peoplepronoun} % As above, but first letter in upper case % \begin{macrocode} \newcommand*{\Peoplepronoun}{% \ifnum\c@people>1\relax \expandafter\MakeUppercase\pluralpronoun \else \@get@firstperson{\@thisperson}% \Personpronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\personobjpronoun} % Display the objective pronoun (him/her) according to the person's % gender. % \begin{macrocode} \newcommand*{\personobjpronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender objpronoun\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\Personobjpronoun} % As above, but make the first letter uppercase. % \begin{macrocode} \newcommand*{\Personobjpronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter \MakeUppercase\csname\@gender objpronoun\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\peopleobjpronoun} % If there is more than one person, \cs{peopleobjpronoun} will use % \cs{pluralobjpronoun}, otherwise it will use \cs{personobjpronoun}. % \begin{macrocode} \newcommand*{\peopleobjpronoun}{% \ifnum\c@people>1\relax \pluralobjpronoun \else \@get@firstperson{\@thisperson}% \personobjpronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\Peopleobjpronoun} % As above, but first letter in upper case % \begin{macrocode} \newcommand*{\Peopleobjpronoun}{% \ifnum\c@people>1\relax \expandafter\MakeUppercase\pluralobjpronoun \else \@get@firstperson{\@thisperson}% \Personobjpronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\personpssadj} % Display the possessive adjective (his/her) according to the person's % gender. % \begin{macrocode} \newcommand*{\personpossadj}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender possadj\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\Personpossadj} % As above, but make the first letter uppercase. % \begin{macrocode} \newcommand*{\Personpossadj}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter \MakeUppercase\csname\@gender possadj\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\peoplepossadj} % If there is more than one person, \cs{peoplepossadj} will use % \cs{pluralpossadj}, otherwise it will use \cs{personpossadj}. % \begin{macrocode} \newcommand*{\peoplepossadj}{% \ifnum\c@people>1\relax \pluralpossadj \else \@get@firstperson{\@thisperson}% \personpossadj[\@thisperson]% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\Peoplepossadj} % As above, but first letter in upper case % \begin{macrocode} \newcommand*{\Peoplepossadj}{% \ifnum\c@people>1\relax \expandafter\MakeUppercase\pluralpossadj \else \@get@firstperson{\@thisperson}% \Personpossadj[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\personposspronoun} % Display possessive pronoun (his/hers) according to the % person's gender. % \begin{macrocode} \newcommand*{\personposspronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender posspronoun\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\Personposspronoun} % As above, but make the first letter uppercase. % \begin{macrocode} \newcommand*{\Personposspronoun}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter \MakeUppercase\csname\@gender posspronoun\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\peopleposspronoun} % If there is more than one person, \cs{peopleposspronoun} will use % \cs{pluralposspronoun}, otherwise it will use \cs{personposspronoun}. % \begin{macrocode} \newcommand*{\peopleposspronoun}{% \ifnum\c@people>1\relax \pluralposspronoun \else \@get@firstperson{\@thisperson}% \personposspronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\Peopleposspronoun} % As above, but first letter in upper case % \begin{macrocode} \newcommand*{\Peopleposspronoun}{% \ifnum\c@people>1\relax \expandafter\MakeUppercase\pluralposspronoun \else \@get@firstperson{\@thisperson}% \Personposspronoun[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\personchild} % Display this person's relationship to their parent (i.e.\ son % or daughter). % \begin{macrocode} \newcommand*{\personchild}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender child\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\Personchild} % As above, but make first letter uppercase. % \begin{macrocode} \newcommand*{\Personchild}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter\MakeUppercase \csname\@gender child\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\peoplechild} % If there is more than one person, \cs{peoplechild} will use % \cs{malechildren} (if all male), \cs{femalechildren} (if all % female) or \cs{pluralchild} (if mixed), otherwise it will use % \cs{personchild}. % \begin{macrocode} \newcommand*{\peoplechild}{% \ifnum\c@people>1\relax \ifallmale {\malechildren}% {\ifallfemale{\femalechildren}{\pluralchild}}% \else \@get@firstperson{\@thisperson}% \personchild[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\Peoplechild} % As above but first letter is made uppercase. % \begin{macrocode} \newcommand*{\Peoplechild}{% \ifnum\c@people>1\relax \ifallmale {\expandafter\MakeUppercase\malechildren}% {\ifallfemale {\expandafter\MakeUppercase\femalechildren} {\expandafter\MakeUppercase\pluralchild}}% \else \@get@firstperson{\@thisperson}% \Personchild[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\personparent} % Display this person's relationship to their child (i.e.\ father % or mother). % \begin{macrocode} \newcommand*{\personparent}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender parent\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\Personparent} % As above, but make the first letter uppercase. % \begin{macrocode} \newcommand*{\Personparent}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter\MakeUppercase \csname\@gender parent\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\peopleparent} % If there is more than one person, \cs{peopleparent} will use % \cs{pluralparent}, otherwise it will use \cs{personparent}. % \begin{macrocode} \newcommand*{\peopleparent}{% \ifnum\c@people>1\relax \pluralparent \else \@get@firstperson{\@thisperson}% \personparent[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\Peopleparent} % As above, but make first letter uppercase. % \begin{macrocode} \newcommand*{\Peopleparent}{% \ifnum\c@people>1\relax \expandafter\MakeUppercase\pluralparent \else \@get@firstperson{\@thisperson}% \Personparent[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\personsibling} % Display this person's relationship to their siblings (i.e.\ % brother or sister). % \begin{macrocode} \newcommand*{\personsibling}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \csname\@gender sibling\endcsname }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\Personsibling} % Display this person's relationship to their siblings (i.e.\ % brother or sister). % \begin{macrocode} \newcommand*{\Personsibling}[1][anon]{% \@ifundefined{person@#1@gender}% {% \PackageError{person}{Person `#1' has not been defined}{}% }% {% \edef\@gender{\csname person@#1@gender\endcsname}% \expandafter\expandafter\expandafter\MakeUppercase \csname\@gender sibling\endcsname }% } % \end{macrocode} %\end{macro} %\begin{macro}{\peoplesibling} % If there is more than one person, \cs{peoplesibling} will use % \cs{malesiblings} (if all male), \cs{femalesiblings} (if all % female) or \cs{pluralsibling} (if mixed), otherwise it will use % \cs{personsibling}. % \begin{macrocode} \newcommand*{\peoplesibling}{% \ifnum\c@people>1\relax \ifallmale {\malesiblings}% {\ifallfemale{\femalesiblings}{\pluralsibling}}% \else \@get@firstperson{\@thisperson}% \personsibling[\@thisperson]% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\persongender} % Displays the given person's gender (\cs{malename} or % \cs{femalename}). % \begin{macrocode} \newcommand*{\persongender}[1]{% \ifpersonmale{#1}{\malename}{\femalename}% } % \end{macrocode} %\end{macro} % %\subsection{Extracting Information} % %\begin{macro}{\getpersongender} % Gets person's gender and stores in first argument which must be % a control sequence. % \begin{macrocode} \newcommand*{\getpersongender}[2]{% \ifpersonmale{#2}{\let#1\malename}{\let#1\femalename}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\getpersonname} % Gets person's name and stores in first argument which must be % a control sequence. % \begin{macrocode} \newcommand*{\getpersonname}[2]{% \ifpersonexists{#2}% {% \expandafter\let\expandafter#1\csname person@#2@name\endcsname }% {% \PackageError{person}{Person `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\getpersonfullname} % Gets person's full name and stores in first argument which must be % a control sequence. % \begin{macrocode} \newcommand*{\getpersonfullname}[2]{% \ifpersonexists{#2}% {% \expandafter \let\expandafter#1\csname person@#2@fullname\endcsname }% {% \PackageError{person}{Person `#2' doesn't exist}{}% }% } % \end{macrocode} %\end{macro} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\Finale \endinput