summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/csvsimple
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/csvsimple
Initial commit
Diffstat (limited to 'macros/latex/contrib/csvsimple')
-rw-r--r--macros/latex/contrib/csvsimple/CHANGES109
-rw-r--r--macros/latex/contrib/csvsimple/README50
-rw-r--r--macros/latex/contrib/csvsimple/amountsort.xml8
-rw-r--r--macros/latex/contrib/csvsimple/catsort.xml7
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple-example.csv5
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple-example.pdfbin0 -> 72195 bytes
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple-example.tex106
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple.pdfbin0 -> 810437 bytes
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple.sty778
-rw-r--r--macros/latex/contrib/csvsimple/csvsimple.tex2095
-rw-r--r--macros/latex/contrib/csvsimple/encoding.xml6
-rw-r--r--macros/latex/contrib/csvsimple/gradesort.xml9
-rw-r--r--macros/latex/contrib/csvsimple/matriculationsort.xml7
-rw-r--r--macros/latex/contrib/csvsimple/namesort.xml8
-rw-r--r--macros/latex/contrib/csvsimple/transform.xml7
15 files changed, 3195 insertions, 0 deletions
diff --git a/macros/latex/contrib/csvsimple/CHANGES b/macros/latex/contrib/csvsimple/CHANGES
new file mode 100644
index 0000000000..10a0bcd925
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/CHANGES
@@ -0,0 +1,109 @@
+%% The LaTeX package csvsimple - version 1.21 (2019/04/09)
+%%
+%% -------------------------------------------------------------------------------------------
+%% Copyright (c) 2008-2019 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
+%% -------------------------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `author-maintained'.
+%%
+%% This work consists of all files listed in README
+%%
+
+version 1.00 (2010/07/28): initial public release
+
+version 1.01 (2010/11/10):
+- documentation of some keys clarified
+- new key: after first line
+- new key: late after first line
+- new example for key evaluation in the documentation
+
+version 1.02 (2011/04/04):
+- error in the documentation for longtable und tabbing corrected
+- new macros: \csvfilteraccept, \csvfilterreject
+- new keys: filter accept all, filter reject all
+
+version 1.03 (2011/11/04):
+- processing error for lines starting with '00' corrected
+
+version 1.04 (2011/11/11):
+- new key: head to column names (automatic column names)
+- new key: no table
+- column numbers can now be used for column macro definitions
+- documentation update and correction
+- internal behaviour of 'before reading' and 'after reading' changed for tables
+
+version 1.05 (2012/03/12):
+- documentation language changed from German to English
+- source code of the documentation added
+- provision of the csvsimple.tds.zip file for easier installation
+- key @table removed from the documentation
+- new keys: preprocessed file, preprocessor, no preprocessing
+ for preprocessing support (e.g. sorting)
+- error in 'nocheckcolumncount' corrected and key renamed to 'no check column count'
+- key nofilter renamed to 'no filter' and 'nohead' to 'no head' (the old names
+ are kept as deprecated key names)
+
+version 1.06 (2012/11/08):
+- implementation for line breaking changed from full macro expansion to
+ token expansion. This allows quite arbitrary macro code inside the data.
+ Note that this may be a breaking change if your application expects
+ expanded column values.
+- option values added for \csvautotabular and \csvautolongtable
+
+version 1.07 (2013/09/25):
+- internal macro '\TrimSpaces' renamed to avoid name clashed with 'xparse'
+- new option 'separator' to set the data value separator to
+ 'comma', 'semicolon', or 'pipe'
+
+version 1.10 (2014/07/07):
+- bug fix: table head names in curly brackets were not recognized for some cases
+- changed: if a CSV file is not found, csvsimple stops with an error message instead of a warning
+- external sorting specifically supported for the CSV-Sorter tool with the new options
+ 'csvsorter command', 'csvsorter configpath', 'csvsorter log',
+ 'sort by', 'new sorting rule'
+- new automatic tabular settings with booktabs:
+ '\csvautotabular' and '\csvautolongtable'
+- new keys for respecting special characters:
+ 'respect tab', 'respect percent', 'respect sharp', 'respect dollar',
+ 'respect and', 'respect backslash', 'respect underscore', 'respect tilde',
+ 'respect circumflex', 'respect leftbrace', 'respect rightbrace',
+ 'respect all', 'respect none'
+- new value 'tab' for the 'separator' option to use a tabulator signs
+ as separator.
+
+version 1.11 (2014/07/08):
+- bug fix (serious!): sorting preprocessor overwrites the input data in some combinations
+- changed: if a CSV file with an empty first line is found, csvsimple stops with an error message
+
+version 1.12 (2014/07/14):
+- fixed: CSV-Sorter call incompatibilities with the ngerman package (not babel)
+- changed: success of CSV-Sorter call is checked (Note: Update to CSV-Sorter v0.94 or newer!)
+ new key 'csvsorter token'
+- changed: encircling column entry braces removed for all entries for better siunitx compatibility
+- documentation revised and extended with siunitx examples
+
+version 1.20 (2016/07/01):
+- implementation changed from \roman to \romannumeral
+- write18 replace by \ShellEscape from the shellesc package
+- '\csvlinetotablerow' implemented more efficiently
+- '\csvloop' made long
+- new string comparison macros:
+ '\ifcsvstrequal', '\ifcsvprostrequal', '\ifcsvstrcmp', '\ifcsvnotstrcmp'
+- new filter options:
+ 'filter ifthen', 'filter test', 'filter expr', 'full filter',
+ 'filter strcmp', 'filter not strcmp'
+- code optimizations
+- documentation revised
+
+version 1.21 (2019/04/09):
+- spurious blank in sorting code removed
+- package 'pgfrcs' added as required package
+- (#3): introduction augmented with additional hints for first time users
diff --git a/macros/latex/contrib/csvsimple/README b/macros/latex/contrib/csvsimple/README
new file mode 100644
index 0000000000..ee2f9c807e
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/README
@@ -0,0 +1,50 @@
+%% The LaTeX package csvsimple - version 1.21 (2019/04/09)
+%%
+%% -------------------------------------------------------------------------------------------
+%% Copyright (c) 2008-2019 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
+%% -------------------------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `author-maintained'.
+%%
+%% This work consists of all files listed in README
+%%
+
+csvsimple provides a simple LaTeX interface for the processing of files with
+comma separated values (CSV). csvsimple relies heavily on the key value syntax
+from pgfkeys which results (hopefully) in an easy way of usage. Filtering and
+table generation is especially supported. Since the package is considered as a
+lightweight tool, there is no support for data sorting or data base storage.
+
+Contents of the package
+=======================
+ 'README' this file
+ 'CHANGES' log of changes (history)
+ 'csvsimple.sty' LaTeX package file (style file)
+ 'csvsimple.pdf' Documentation for csvsimple
+ 'csvsimple.tex' Source code of the documentation
+ 'csvsimple-example.tex' Example file for package usage
+ 'csvsimple-example.csv' CSV file as part of the example
+ 'csvsimple-example.pdf' Compiled example
+ 'amountsort.xml' csvsorter configuration file (example)
+ 'catsort.xml' csvsorter configuration file (example)
+ 'encoding.xml' csvsorter configuration file (example)
+ 'gradesort.xml' csvsorter configuration file (example)
+ 'matriculationsort.xml' csvsorter configuration file (example)
+ 'namesort.xml' csvsorter configuration file (example)
+ 'transform.xml' csvsorter configuration file (example)
+
+Installation
+============
+Copy the contents of the 'csvsimple.tds.zip' from CTAN to your local TeX file tree.
+
+Alternatively, put the files to their respective locations within the TeX installation:
+ 'csvsimple.sty' -> /tex/latex/csvsimple
+ all other files -> /doc/latex/csvsimple
diff --git a/macros/latex/contrib/csvsimple/amountsort.xml b/macros/latex/contrib/csvsimple/amountsort.xml
new file mode 100644
index 0000000000..1f37624a7d
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/amountsort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket empty="true" />
+ <sortlines>
+ <column name="amount" order="descending" type="double"/>
+ <column name="land" order="ascending" type="string"/>
+ </sortlines>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/catsort.xml b/macros/latex/contrib/csvsimple/catsort.xml
new file mode 100644
index 0000000000..ac8e44aad3
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/catsort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket empty="true" />
+ <sortlines>
+ <column name="cats" order="ascending" type="double"/>
+ </sortlines>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/csvsimple-example.csv b/macros/latex/contrib/csvsimple/csvsimple-example.csv
new file mode 100644
index 0000000000..9a988ac743
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple-example.csv
@@ -0,0 +1,5 @@
+last name,first name,address,zip,telephone,year of birth
+Appleby,Anne,Shrimpsbury,SH-124,555-4455,1960
+Brown,Carl,Midsomer Garden,MD-945,555-2423,1982
+Smith,John,Shrimpsbury,SH-123,555-4584,1978
+Underwood,Mary,Oglsby,OG-345,555-3434,1956
diff --git a/macros/latex/contrib/csvsimple/csvsimple-example.pdf b/macros/latex/contrib/csvsimple/csvsimple-example.pdf
new file mode 100644
index 0000000000..0965f75e26
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple-example.pdf
Binary files differ
diff --git a/macros/latex/contrib/csvsimple/csvsimple-example.tex b/macros/latex/contrib/csvsimple/csvsimple-example.tex
new file mode 100644
index 0000000000..87a327f300
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple-example.tex
@@ -0,0 +1,106 @@
+%% The LaTeX package csvsimple - version 1.21 (2019/04/09)
+%% csvsimple-example.tex: an example for csvsimple
+%%
+%% -------------------------------------------------------------------------------------------
+%% Copyright (c) 2008-2019 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
+%% -------------------------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `author-maintained'.
+%%
+%% This work consists of all files listed in README
+%%
+\documentclass{article}
+\usepackage{array,booktabs}
+\usepackage{csvsimple}
+
+\begin{document}
+
+%----------------------------------------------------------
+\section{Automatic table generation (for testing)}
+
+{\small
+\csvautotabular{csvsimple-example.csv}}
+
+
+%----------------------------------------------------------
+\section{My first CSV table}
+\csvreader[tabular=|l|l|,
+ table head=\hline\multicolumn{2}{|c|}{\bfseries My telephone book}\\\hline
+ \bfseries Name & \bfseries Number\\\hline\hline,
+ late after line=\\\hline]%
+ {csvsimple-example.csv}{last name=\surname,first name=\givenname,telephone=\telephone}{%
+ \givenname\ \surname & \telephone
+}
+
+
+%----------------------------------------------------------
+\section{Remembering the names}
+\csvnames{my names}{last name=\surname,first name=\givenname,address=\address,zip=\zip,telephone=\telephone,year of birth=\birthyear}
+
+\csvreader[my names, late after line=\\, late after last line=]%
+ {csvsimple-example.csv}{}{%
+ \givenname\ was born in \birthyear\ and lives in \address.
+}
+
+
+%----------------------------------------------------------
+\section{Filter fun}
+
+\csvreader[my names, filter equal={\address}{Shrimpsbury}, tabbing,
+ table head=\bfseries Shrimpsbury friends: \=\hspace*{3cm}\=\+\kill,
+ before first line=\<\bfseries Shrimpsbury friends:\>]%
+ {csvsimple-example.csv}{}{%
+ \surname, \givenname \> \telephone
+}
+
+
+%----------------------------------------------------------
+\section{More filter fun}
+
+\csvreader[my names, filter=\birthyear<1980, centered tabular=rllr,
+ table head=\multicolumn{4}{c}{\bfseries People born before 1980}\\\toprule
+ \# & Name & Postal address & input line no.\\\midrule,
+ late after line=\\, late after last line=\\\bottomrule]%
+ {csvsimple-example.csv}{}{%
+ \thecsvrow & \givenname\ \surname & \zip\ \address & \thecsvinputline
+}
+
+
+%----------------------------------------------------------
+\section{Again and again}
+
+\csvstyle{my table}{my names,
+ centered tabular=|r|l|l|l|,
+ table head=\hline\multicolumn{4}{|c|}{\bfseries #1}\\\hline
+ \# & Name & Telephone & Postal address\\\hline\hline,
+ late after line=\\, late after last line=\\\hline}
+
+\csvreader[my table=Predefined table]{csvsimple-example.csv}{}{%
+ \thecsvrow & \givenname\ \surname & \telephone & \zip\ \address
+}
+
+\csvreader[my table=Filtering for Smith, filter equal={\surname}{Smith}]%
+ {csvsimple-example.csv}{}{%
+ \thecsvrow & \givenname\ \surname & \telephone & \zip\ \address
+}
+
+\csvstyle{all and everything}{my table=#1, file={csvsimple-example.csv},
+ command=\thecsvrow & \givenname\ \surname & \telephone & \zip\ \address}
+
+\csvloop{all and everything=Loop instead of reader}
+
+\csvloop{all and everything=With Shrimpsbury filter, filter equal={\address}{Shrimpsbury}}
+
+\csvloop{all and everything=A little modification, late after line=\\\hline}
+
+
+\end{document}
+
diff --git a/macros/latex/contrib/csvsimple/csvsimple.pdf b/macros/latex/contrib/csvsimple/csvsimple.pdf
new file mode 100644
index 0000000000..02f43bf81c
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple.pdf
Binary files differ
diff --git a/macros/latex/contrib/csvsimple/csvsimple.sty b/macros/latex/contrib/csvsimple/csvsimple.sty
new file mode 100644
index 0000000000..ed4b83b1c3
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple.sty
@@ -0,0 +1,778 @@
+%% The LaTeX package csvsimple - version 1.21 (2019/04/09)
+%% csvsimple.sty: Simple LaTeX CSV file processing
+%%
+%% -------------------------------------------------------------------------------------------
+%% Copyright (c) 2008-2019 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
+%% -------------------------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `author-maintained'.
+%%
+%% This work consists of all files listed in README
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{csvsimple}[2019/04/09 version 1.21 LaTeX CSV file processing]
+
+\RequirePackage{pgfrcs,pgfkeys,ifthen,etoolbox,shellesc}
+
+
+%---- general
+
+\def\csv@warning#1{\PackageWarning{csvsimple}{#1}}
+\def\csv@error#1#2{\PackageError{csvsimple}{#1}{#2}}
+
+\newread\csv@file
+\newcounter{csvinputline}
+\newcounter{csvrow}
+\newcounter{csvcol}
+
+\def\csv@empty{}
+
+\long\def\csviffirstrow#1#2{%
+ \ifnum\c@csvrow=1%
+ \long\def\csviffirstrow@doit{#1}%
+ \else%
+ \long\def\csviffirstrow@doit{#2}%
+ \fi%
+ \csviffirstrow@doit%
+}
+
+\long\def\csvifoddrow#1#2{%
+ \ifodd\c@csvrow%
+ \long\def\csvifoddrow@doit{#1}%
+ \else%
+ \long\def\csvifoddrow@doit{#2}%
+ \fi%
+ \csvifoddrow@doit%
+}
+
+\def\csv@assemble@csvlinetotablerow{%
+ \global\c@csvcol 1\relax%
+ \xdef\csvlinetotablerow{\expandonce{\csname csvcol\romannumeral\c@csvcol\endcsname}}%
+ \ifnum\c@csvcol<\csv@columncount\relax%
+ \loop%
+ \global\advance\c@csvcol 1\relax%
+ \xappto\csvlinetotablerow{\noexpand&\expandonce{\csname csvcol\romannumeral\c@csvcol\endcsname}}%
+ \ifnum\c@csvcol<\csv@columncount\relax\repeat%
+ \fi%
+ \csvlinetotablerow%
+}
+
+
+%---- breaking lines
+
+% This command removes leading and trailing spaces from <Token>. I found
+% the original code on the web. The original author was Michael Downes, who
+% provided the code as an answer to 'around the bend' question #15.
+\catcode`\Q=3
+\def\csv@TrimSpaces#1{%
+ \begingroup%
+ \aftergroup\toks\aftergroup0\aftergroup{%
+ \expandafter\csv@trimb\expandafter\noexpand#1Q Q}%
+ \global\edef#1{\the\toks0}%
+}
+\def\csv@trimb#1 Q{\csv@trimc#1Q}
+\def\csv@trimc#1Q#2{\afterassignment\endgroup \vfuzz\the\vfuzz#1}
+\catcode`\Q=11
+
+\def\csv@TrimBraces#1{\expandafter\csv@TrimBraces@#1\@nil{#1}}
+\def\csv@TrimBraces@#1\@nil#2{\def#2{#1}}
+
+\def\csv@breakline@kernel#1{%
+ \ifx\csv@termination#1\let\nextcol=\relax\else%
+ \let\nextcol=\csv@breakline%
+ \global\advance\c@csvcol 1\relax%
+ \def\csv@col@body{#1}%
+ \csv@TrimSpaces\csv@col@body%
+ \csv@TrimBraces\csv@col@body%
+ \toks@\expandafter{\csv@col@body}%
+ \expandafter\xdef\csname csvcol\romannumeral\c@csvcol\endcsname{\the\toks@}%
+ \fi%
+ \nextcol%
+}
+
+% comma
+\def\csv@breakline@A#1,{\csv@breakline@kernel{#1}}
+
+\def\csv@scanline@A#1{%
+ \global\c@csvcol 0\relax%
+ \csv@breakline#1,\csv@termination,%
+}
+
+% semi colon
+\def\csv@breakline@B#1;{\csv@breakline@kernel{#1}}
+
+\def\csv@scanline@B#1{%
+ \global\c@csvcol 0\relax%
+ \csv@breakline#1;\csv@termination;%
+}
+
+% pipe
+\def\csv@breakline@C#1|{\csv@breakline@kernel{#1}}
+
+\def\csv@scanline@C#1{%
+ \global\c@csvcol 0\relax%
+ \csv@breakline#1|\csv@termination|%
+}
+
+% tab
+\catcode`\^^I=12
+\def\csv@breakline@D#1^^I{\csv@breakline@kernel{#1}}
+
+\def\csv@scanline@D#1{%
+ \global\c@csvcol 0\relax%
+ \csv@breakline#1^^I\csv@termination^^I%
+}
+\catcode`\^^I=10
+
+% expands a CSV line and scans content
+\def\csv@escanline#1{%
+ \toks@\expandafter{#1}%
+ \edef\@csv@scanline{\noexpand\csv@scanline{\the\toks@}}%
+ \@csv@scanline%
+}
+
+{
+ \catcode`\"=12%
+ \gdef\csv@passivquotes{"}
+}
+
+\newwrite\csv@out
+
+\def\csv@preprocessor@csvsorter#1#2#3{%
+ \begingroup%
+ \typeout{<sort \csv@passivquotes#2\csv@passivquotes\space by \csv@passivquotes#1\csv@passivquotes>}%
+ \immediate\openout\csv@out=\csv@csvsorter@token%
+ \immediate\write\csv@out{\string\makeatletter\string\csv@error{Call of CSV-Sorter failed! Use '-shell-escape' option or check log file '\csv@csvsorter@log'.}{}}%
+ \immediate\closeout\csv@out%
+ \ShellEscape{\csv@csvsorter@command\space
+ -c \csv@passivquotes#1\csv@passivquotes\space
+ -l \csv@passivquotes\csv@csvsorter@log\csv@passivquotes\space
+ -t \csv@passivquotes\csv@csvsorter@token\csv@passivquotes\space
+ -i \csv@passivquotes#2\csv@passivquotes\space
+ -o \csv@passivquotes#3\csv@passivquotes\space -q 1}%
+ \input{\csv@csvsorter@token}%
+ \endgroup%
+}
+
+
+\def\csv@preprocss@none{%
+ \let\csv@input@filename=\csv@filename%
+}
+
+\def\csv@preprocss@procedure{%
+ \csv@preprocessor{\csv@filename}{\csv@ppfilename}%
+ \let\csv@input@filename=\csv@ppfilename%
+}
+
+
+%---- the loop
+
+\def\csv@AtEndLoop{\gappto\@endloophook}
+\let\@endloophook\csv@empty
+
+\def\csv@current@col{\csname csvcol\romannumeral\c@csvcol\endcsname}
+
+% auto head names
+\def\set@csv@autohead{%
+ \toks0=\expandafter{\csname\csv@current@col\endcsname}%
+ \toks1=\expandafter{\csname csvcol\romannumeral\c@csvcol\endcsname}%
+ \edef\csv@temp{\noexpand\gdef\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\noexpand\gdef\the\toks0{}}}%
+ \csv@temp%
+}
+
+% head names and numbers
+\def\set@csv@head{%
+ \toks0={\gdef##1}%
+ \toks1=\expandafter{\csname csvcol\romannumeral\c@csvcol\endcsname}%
+ \edef\csv@temp{\noexpand\pgfkeysdef{/csv head/\csv@current@col}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}%
+ \csv@temp%
+ \edef\csv@temp{\noexpand\pgfkeysdef{/csv head/\thecsvcol}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}%
+ \csv@temp%
+}
+
+% head line
+\def\csv@processheadline{%
+ \csvreadnext%
+ \if\csv@par\csvline\relax%
+ \csv@error{File '\csv@input@filename' starts with an empty line!}{}%
+ \else\csv@escanline{\csvline}%
+ \fi%
+ \xdef\csv@columncount{\thecsvcol}%
+ \global\c@csvcol 0\relax%
+ \loop%
+ \global\advance\c@csvcol 1\relax%
+ \csv@opt@headtocolumnames%
+ \set@csv@head%
+ \ifnum\c@csvcol<\csv@columncount\repeat%
+ \toks@=\expandafter{\csv@columnnames}%
+ \edef\csv@processkeys{\noexpand\pgfkeys{/csv head/.cd,\the\toks@}}%
+ \csv@processkeys%
+ \csv@posthead%
+}
+
+% head numbers for no head
+\def\set@csv@nohead{%
+ \toks0={\gdef##1}%
+ \toks1=\expandafter{\csname csvcol\romannumeral\c@csvcol\endcsname}%
+ \edef\csv@temp{\noexpand\pgfkeysdef{/csv head/\thecsvcol}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}%
+ \csv@temp%
+}
+
+% no head line
+\def\csv@noheadline{%
+ \global\c@csvcol 0\relax%
+ \loop%
+ \global\advance\c@csvcol 1\relax%
+ \set@csv@nohead%
+ \ifnum\c@csvcol<\csv@columncount\repeat%
+ \toks@=\expandafter{\csv@columnnames}%
+ \edef\csv@processkeys{\noexpand\pgfkeys{/csv head/.cd,\the\toks@}}%
+ \csv@processkeys%
+}
+
+% check filter
+\def\csv@checkfilter{%
+ \csv@prefiltercommand%
+ \csv@iffilter{%
+ \stepcounter{csvrow}%
+ \let\csv@usage=\csv@do@linecommand%
+ }{}%
+}
+
+\def\csv@truefilter#1#2{#1}
+
+\def\csv@falsefilter#1#2{#2}
+
+\def\csvfilteraccept{\global\let\csv@iffilter=\csv@truefilter}
+
+\def\csvfilterreject{\global\let\csv@iffilter=\csv@falsefilter}
+
+% check columns
+\def\csv@checkcolumncount{%
+ \ifnum\c@csvcol=\csv@columncount\relax%
+ \csv@checkfilter%
+ \else%
+ \csv@columncounterror%
+ \fi%
+}
+
+\def\csv@nocheckcolumncount{%
+ \csv@checkfilter%
+}
+
+% normal line
+\def\csv@do@linecommand{%
+ \csv@do@latepostline%
+ \csv@do@preline%
+ \csv@body\relax%
+ \csv@do@postline%
+}
+
+\gdef\csvreadnext{%
+ \global\read\csv@file to\csvline%
+ \stepcounter{csvinputline}%
+}
+
+\let\csv@par=\par
+
+% reads and processes a CSV file
+\long\def\csvloop#1{%
+ % reset
+ \global\let\@endloophook\csv@empty%
+ \global\let\csvlinetotablerow\csv@assemble@csvlinetotablerow%
+ % options
+ \csvset{default,every csv,#1}%
+ \csv@preprocss%
+ \csv@set@catcodes%
+ \csv@prereading%
+ \csv@table@begin%
+ \setcounter{csvinputline}{0}%
+ % start reading
+ \openin\csv@file=\csv@input@filename\relax%
+ \ifeof\csv@file%
+ \csv@error{File '\csv@input@filename' not existent, not readable, or empty!}{}%
+ \else%
+ % the head line
+ \csv@opt@processheadline%
+ \fi%
+ %
+ \setcounter{csvrow}{0}%
+ \gdef\csv@do@preline{%
+ \csv@prefirstline%
+ \global\let\csv@do@preline=\csv@preline%
+ }%
+ \gdef\csv@do@postline{%
+ \csv@postfirstline%
+ \global\let\csv@do@postline=\csv@postline%
+ }%
+ \gdef\csv@do@@latepostline{%
+ \csv@latepostfirstline%
+ \global\let\csv@do@latepostline=\csv@latepostline%
+ }%
+ \gdef\csv@do@latepostline{%
+ \csv@lateposthead%
+ \global\let\csv@do@latepostline=\csv@do@@latepostline%
+ }%
+ % command for the reading loop
+ \gdef\csv@iterate{%
+ \let\csv@usage=\csv@empty%
+ \csvreadnext%
+ \ifeof\csv@file%
+ \global\let\csv@next=\csv@empty%
+ \else%
+ \global\let\csv@next=\csv@iterate%
+ \if\csv@par\csvline\relax%
+ \else%
+ \csv@escanline{\csvline}%
+ % check and decide
+ \csv@opt@checkcolumncount%
+ \fi%
+ \fi%
+ % do or do not
+ \csv@usage%
+ \csv@next}%
+ \ifeof\csv@file%
+ \global\let\csv@next=\csv@empty%
+ \else%
+ \global\let\csv@next=\csv@iterate%
+ \fi%
+ \csv@next%
+ \closein\csv@file%
+ \@endloophook%
+ \csv@latepostlastline%
+ \csv@table@end%
+ \csv@postreading%
+ \csv@reset@catcodes%
+}
+
+% user command
+\long\def\csv@reader[#1]#2#3#4{%
+ \global\long\def\csv@@body{#4}%
+ \csvloop{#1,file={#2},column names={#3},command=\csv@@body}%
+}
+
+\def\csvreader{%
+ \@ifnextchar[{\csv@reader}{\csv@reader[]}}
+
+
+%---- keys
+
+\pgfkeys{/handlers/.gstore in/.code=\pgfkeysalso{\pgfkeyscurrentpath/.code=\gdef#1{##1}}}
+\pgfkeys{/csv/.is family}
+\pgfkeys{/csv head/.is family}
+
+\def\csvset{\pgfqkeys{/csv}}
+\def\csvheadset{\pgfqkeys{/csv head}}
+
+\csvset{%
+ file/.gstore in=\csv@filename,%
+ preprocessed file/.gstore in=\csv@ppfilename,%
+ preprocessor/.code={\gdef\csv@preprocessor{#1}\let\csv@preprocss=\csv@preprocss@procedure},%
+ no preprocessing/.code={\let\csv@preprocss=\csv@preprocss@none},
+ column names reset/.code={\gdef\csv@columnnames{}},%
+ column names/.code={%
+ \toks0=\expandafter{\csv@columnnames}%
+ \def\temp{#1}\toks1=\expandafter{\temp}%
+ \xdef\csv@columnnames{\the\toks0,\the\toks1}%
+ },
+ command/.gstore in=\csv@body,%
+ check column count/.is choice,%
+ check column count/.default=true,%
+ check column count/true/.code={\global\let\csv@opt@checkcolumncount=\csv@checkcolumncount},%
+ check column count/false/.code={\global\let\csv@opt@checkcolumncount=\csv@nocheckcolumncount},%
+ on column count error/.gstore in=\csv@columncounterror,
+ head/.is choice,%
+ head/.default=true,%
+ head/true/.code={\global\let\csv@opt@processheadline=\csv@processheadline%
+ \pgfkeysalso{check column count}},%
+ head/false/.code={\global\let\csv@opt@processheadline=\csv@noheadline%
+ \pgfkeysalso{check column count=false,late after head=}},%
+ head to column names/.is choice,%
+ head to column names/.default=true,%
+ head to column names/true/.code={\global\let\csv@opt@headtocolumnames=\set@csv@autohead},%
+ head to column names/false/.code={\global\let\csv@opt@headtocolumnames=\csv@empty},%
+ column count/.gstore in=\csv@columncount,%
+ filter/.code={\gdef\csv@iffilter{\ifthenelse{#1}}},
+ filter ifthen/.code={\gdef\csv@iffilter{\ifthenelse{#1}}},
+ filter test/.code={\gdef\csv@iffilter{#1}},
+ filter expr/.code={\gdef\csv@iffilter{\ifboolexpr{#1}}},
+ no filter/.code={\csvfilteraccept},
+ filter reject all/.code={\csvfilterreject},
+ filter accept all/.code={\csvfilteraccept},
+ before filter/.gstore in=\csv@prefiltercommand,
+ full filter/.gstore in=\csv@prefiltercommand,
+ before first line/.gstore in=\csv@prefirstline,
+ before line/.code={\gdef\csv@preline{#1}\pgfkeysalso{before first line=#1}},
+ after first line/.gstore in=\csv@postfirstline,
+ after line/.code={\gdef\csv@postline{#1}\pgfkeysalso{after first line=#1}},
+ late after first line/.gstore in=\csv@latepostfirstline,
+ late after last line/.gstore in=\csv@latepostlastline,
+ late after line/.code={\gdef\csv@latepostline{#1}\pgfkeysalso{late after first line=#1,late after last line=#1}},
+ after head/.gstore in=\csv@posthead,
+ late after head/.gstore in=\csv@lateposthead,
+ before reading/.gstore in=\csv@prereading,
+ after reading/.gstore in=\csv@postreading,
+ before table/.gstore in=\csv@pretable,
+ after table/.gstore in=\csv@posttable,
+ table head/.gstore in=\csv@tablehead,
+ table foot/.gstore in=\csv@tablefoot,
+ @table/.code 2 args={\gdef\csv@table@begin{#1}\gdef\csv@table@end{#2}},
+ no table/.style={@table={}{}},
+ separator/.is choice,
+ separator/comma/.code={\global\let\csv@scanline=\csv@scanline@A%
+ \global\let\csv@breakline\csv@breakline@A},
+ separator/semicolon/.code={\global\let\csv@scanline=\csv@scanline@B%
+ \global\let\csv@breakline\csv@breakline@B},
+ separator/pipe/.code={\global\let\csv@scanline=\csv@scanline@C%
+ \global\let\csv@breakline\csv@breakline@C},
+ separator/tab/.code={\global\let\csv@scanline=\csv@scanline@D%
+ \global\let\csv@breakline\csv@breakline@D%
+ \csvset{respect tab}},
+ %
+ csvsorter command/.store in=\csv@csvsorter@command,
+ csvsorter configpath/.store in=\csv@csvsorter@configpath,
+ sort by/.style={preprocessor={\csv@preprocessor@csvsorter{\csv@csvsorter@configpath/#1}}},
+ new sorting rule/.style 2 args={sort by #1/.style={sort by={#2}}},
+ csvsorter log/.store in=\csv@csvsorter@log,
+ csvsorter token/.store in=\csv@csvsorter@token,
+ csvsorter command=csvsorter,
+ csvsorter configpath=.,
+ preprocessed file={\jobname_sorted._csv},
+ csvsorter log={csvsorter.log},
+ csvsorter token={\jobname.csvtoken},
+ %
+ % default for reset
+ default/.style={
+ file=unknown.csv,
+ no preprocessing,
+ command=\csvline,
+ column names reset,
+ head,
+ head to column names=false,
+ column count=10,
+ on column count error=,
+ no filter,
+ before filter=,
+ before line=,
+ after line=,
+ late after line=,
+ after head=,
+ late after head=,
+ before reading=,
+ after reading=,
+ before table=,
+ after table=,
+ table head=,
+ table foot=,
+ no table,
+ separator=comma,
+ },
+ default,
+ %
+ % styles
+ every csv/.style={},
+ no head/.style={head=false},
+ no check column count/.style={check column count=false},
+ warn on column count error/.style={on column count error={\csv@warning{>\thecsvcol< instead of >\csv@columncount< columns for input line >\thecsvinputline< of file >\csv@ppfilename<}}},
+ filter equal/.style 2 args={filter ifthen=\equal{#1}{#2}},
+ filter not equal/.style 2 args={filter ifthen=\not\equal{#1}{#2}},
+ filter strcmp/.style 2 args={filter test=\ifcsvstrcmp{#1}{#2}},
+ filter not strcmp/.style 2 args={filter test=\ifcsvnotstrcmp{#1}{#2}},
+ tabular/.style={
+ @table={\csv@pretable\begin{tabular}{#1}\csv@tablehead}{\csv@tablefoot\end{tabular}\csv@posttable},
+ late after line=\\},
+ centered tabular/.style={
+ @table={\begin{center}\csv@pretable\begin{tabular}{#1}\csv@tablehead}{\csv@tablefoot\end{tabular}\csv@posttable\end{center}},
+ late after line=\\},
+ longtable/.style={
+ @table={\csv@pretable\begin{longtable}{#1}\csv@tablehead}{\csv@tablefoot\end{longtable}\csv@posttable},
+ late after line=\\},
+ tabbing/.style={
+ @table={\csv@pretable\begin{tabbing}\csv@tablehead}{\csv@tablefoot\end{tabbing}\csv@posttable},
+ late after line=\\,
+ late after last line=},
+ centered tabbing/.style={
+ @table={\begin{center}\csv@pretable\begin{tabbing}\csv@tablehead}{\csv@tablefoot\end{tabbing}\csv@posttable\end{center}},
+ late after line=\\,
+ late after last line=},
+ autotabular/.style={
+ file=#1,
+ after head=\csv@pretable\begin{tabular}{|*{\csv@columncount}{l|}}\csv@tablehead,
+ table head=\hline\csvlinetotablerow\\\hline,
+ late after line=\\,
+ table foot=\\\hline,
+ late after last line=\csv@tablefoot\end{tabular}\csv@posttable,
+ command=\csvlinetotablerow},
+ autolongtable/.style={
+ file=#1,
+ after head=\csv@pretable\begin{longtable}{|*{\csv@columncount}{l|}}\csv@tablehead,
+ table head=\hline\csvlinetotablerow\\\hline\endhead\hline\endfoot,
+ late after line=\\,
+ late after last line=\csv@tablefoot\end{longtable}\csv@posttable,
+ command=\csvlinetotablerow},
+ autobooktabular/.style={
+ file=#1,
+ after head=\csv@pretable\begin{tabular}{*{\csv@columncount}{l}}\csv@tablehead,
+ table head=\toprule\csvlinetotablerow\\\midrule,
+ late after line=\\,
+ table foot=\\\bottomrule,
+ late after last line=\csv@tablefoot\end{tabular}\csv@posttable,
+ command=\csvlinetotablerow},
+ autobooklongtable/.style={
+ file=#1,
+ after head=\csv@pretable\begin{longtable}{*{\csv@columncount}{l}}\csv@tablehead,
+ table head=\toprule\csvlinetotablerow\\\midrule\endhead\bottomrule\endfoot,
+ late after line=\\,
+ late after last line=\csv@tablefoot\end{longtable}\csv@posttable,
+ command=\csvlinetotablerow},
+}
+
+% deprecated keys
+\csvset{
+ nofilter/.style=no filter,
+ nohead/.style=no head,
+}
+
+% catcodes
+\def\csv@set@catcodes{%
+ \csv@catcode@tab@set%
+ \csv@catcode@tilde@set%
+ \csv@catcode@circumflex@set%
+ \csv@catcode@underscore@set%
+ \csv@catcode@and@set%
+ \csv@catcode@sharp@set%
+ \csv@catcode@dollar@set%
+ \csv@catcode@backslash@set%
+ \csv@catcode@leftbrace@set%
+ \csv@catcode@rightbrace@set%
+ \csv@catcode@percent@set}
+
+\def\csv@reset@catcodes{\csv@catcode@percent@reset%
+ \csv@catcode@rightbrace@reset%
+ \csv@catcode@leftbrace@reset%
+ \csv@catcode@backslash@reset%
+ \csv@catcode@dollar@reset%
+ \csv@catcode@sharp@reset%
+ \csv@catcode@and@reset%
+ \csv@catcode@underscore@reset%
+ \csv@catcode@circumflex@reset%
+ \csv@catcode@tilde@reset%
+ \csv@catcode@tab@reset%
+}
+
+
+\csvset{
+ respect tab/.is choice,
+ respect tab/true/.code={%
+ \gdef\csv@catcode@tab@set{%
+ \xdef\csv@catcode@tab@value{\the\catcode`\^^I}%
+ \catcode`\^^I=12}%
+ \gdef\csv@catcode@tab@reset{\catcode`\^^I=\csv@catcode@tab@value}},
+ respect tab/false/.code={%
+ \global\let\csv@catcode@tab@set\csv@empty%
+ \global\let\csv@catcode@tab@reset\csv@empty},
+ respect tab/.default=true,
+ %
+ respect percent/.is choice,
+ respect percent/true/.code={%
+ \gdef\csv@catcode@percent@set{%
+ \xdef\csv@catcode@percent@value{\the\catcode`\%}%
+ \catcode`\%=12}%
+ \gdef\csv@catcode@percent@reset{\catcode`\%=\csv@catcode@percent@value}},
+ respect percent/false/.code={%
+ \global\let\csv@catcode@percent@set\csv@empty%
+ \global\let\csv@catcode@percent@reset\csv@empty},
+ respect percent/.default=true,
+ %
+ respect sharp/.is choice,
+ respect sharp/true/.code={%
+ \gdef\csv@catcode@sharp@set{%
+ \xdef\csv@catcode@sharp@value{\the\catcode`\#}%
+ \catcode`\#=12}%
+ \gdef\csv@catcode@sharp@reset{\catcode`\#=\csv@catcode@sharp@value}},
+ respect sharp/false/.code={%
+ \global\let\csv@catcode@sharp@set\csv@empty%
+ \global\let\csv@catcode@sharp@reset\csv@empty},
+ respect sharp/.default=true,
+ %
+ respect dollar/.is choice,
+ respect dollar/true/.code={%
+ \gdef\csv@catcode@dollar@set{%
+ \xdef\csv@catcode@dollar@value{\the\catcode`\$}%
+ \catcode`\$=12}%
+ \gdef\csv@catcode@dollar@reset{\catcode`\$=\csv@catcode@dollar@value}},
+ respect dollar/false/.code={%
+ \global\let\csv@catcode@dollar@set\csv@empty%
+ \global\let\csv@catcode@dollar@reset\csv@empty},
+ respect dollar/.default=true,
+ %
+ respect and/.is choice,
+ respect and/true/.code={%
+ \gdef\csv@catcode@and@set{%
+ \xdef\csv@catcode@and@value{\the\catcode`\&}%
+ \catcode`\&=12}%
+ \gdef\csv@catcode@and@reset{\catcode`\&=\csv@catcode@and@value}},
+ respect and/false/.code={%
+ \global\let\csv@catcode@and@set\csv@empty%
+ \global\let\csv@catcode@and@reset\csv@empty},
+ respect and/.default=true,
+ %
+ respect backslash/.is choice,
+ respect backslash/true/.code={%
+ \gdef\csv@catcode@backslash@set{%
+ \xdef\csv@catcode@backslash@value{\the\catcode`\\}%
+ \catcode`\\=12}%
+ \gdef\csv@catcode@backslash@reset{\catcode`\\=\csv@catcode@backslash@value}},
+ respect backslash/false/.code={%
+ \global\let\csv@catcode@backslash@set\csv@empty%
+ \global\let\csv@catcode@backslash@reset\csv@empty},
+ respect backslash/.default=true,
+ %
+ respect underscore/.is choice,
+ respect underscore/true/.code={%
+ \gdef\csv@catcode@underscore@set{%
+ \xdef\csv@catcode@underscore@value{\the\catcode`\_}%
+ \catcode`\_=12}%
+ \gdef\csv@catcode@underscore@reset{\catcode`\_=\csv@catcode@underscore@value}},
+ respect underscore/false/.code={%
+ \global\let\csv@catcode@underscore@set\csv@empty%
+ \global\let\csv@catcode@underscore@reset\csv@empty},
+ respect underscore/.default=true,
+ %
+ respect tilde/.is choice,
+ respect tilde/true/.code={%
+ \gdef\csv@catcode@tilde@set{%
+ \xdef\csv@catcode@tilde@value{\the\catcode`\~}%
+ \catcode`\~=12}%
+ \gdef\csv@catcode@tilde@reset{\catcode`\~=\csv@catcode@tilde@value}},
+ respect tilde/false/.code={%
+ \global\let\csv@catcode@tilde@set\csv@empty%
+ \global\let\csv@catcode@tilde@reset\csv@empty},
+ respect tilde/.default=true,
+ %
+ respect circumflex/.is choice,
+ respect circumflex/true/.code={%
+ \gdef\csv@catcode@circumflex@set{%
+ \xdef\csv@catcode@circumflex@value{\the\catcode`\^}%
+ \catcode`\^=12}%
+ \gdef\csv@catcode@circumflex@reset{\catcode`\^=\csv@catcode@circumflex@value}},
+ respect circumflex/false/.code={%
+ \global\let\csv@catcode@circumflex@set\csv@empty%
+ \global\let\csv@catcode@circumflex@reset\csv@empty},
+ respect circumflex/.default=true,
+ %
+ respect leftbrace/.is choice,
+ respect leftbrace/true/.code={%
+ \gdef\csv@catcode@leftbrace@set{%
+ \xdef\csv@catcode@leftbrace@value{\the\catcode`\{}%
+ \catcode`\{=12}%
+ \gdef\csv@catcode@leftbrace@reset{\catcode`\{=\csv@catcode@leftbrace@value}},
+ respect leftbrace/false/.code={%
+ \global\let\csv@catcode@leftbrace@set\csv@empty%
+ \global\let\csv@catcode@leftbrace@reset\csv@empty},
+ respect leftbrace/.default=true,
+ %
+ respect rightbrace/.is choice,
+ respect rightbrace/true/.code={%
+ \gdef\csv@catcode@rightbrace@set{%
+ \xdef\csv@catcode@rightbrace@value{\the\catcode`\}}%
+ \catcode`\}=12}%
+ \gdef\csv@catcode@rightbrace@reset{\catcode`\}=\csv@catcode@rightbrace@value}},
+ respect rightbrace/false/.code={%
+ \global\let\csv@catcode@rightbrace@set\csv@empty%
+ \global\let\csv@catcode@rightbrace@reset\csv@empty},
+ respect rightbrace/.default=true,
+ %
+ respect all/.style={respect tab,respect percent,respect sharp,respect dollar,
+ respect and,respect backslash,respect underscore,respect tilde,respect circumflex,
+ respect leftbrace,respect rightbrace},
+ respect none/.style={respect tab=false,respect percent=false,respect sharp=false,
+ respect dollar=false,respect and=false,respect backslash=false,
+ respect underscore=false,respect tilde=false,respect circumflex=false,
+ respect leftbrace=false,respect rightbrace=false},
+ respect none
+}
+
+
+\long\def\csv@autotabular[#1]#2{\csvloop{autotabular={#2},#1}}
+
+\def\csvautotabular{%
+ \@ifnextchar[{\csv@autotabular}{\csv@autotabular[]}}
+
+\long\def\csv@autolongtable[#1]#2{\csvloop{autolongtable={#2},#1}}
+
+\def\csvautolongtable{%
+ \@ifnextchar[{\csv@autolongtable}{\csv@autolongtable[]}}
+
+\long\def\csv@autobooktabular[#1]#2{\csvloop{autobooktabular={#2},#1}}
+
+\def\csvautobooktabular{%
+ \@ifnextchar[{\csv@autobooktabular}{\csv@autobooktabular[]}}
+
+
+\long\def\csv@autobooklongtable[#1]#2{\csvloop{autobooklongtable={#2},#1}}
+
+\def\csvautobooklongtable{%
+ \@ifnextchar[{\csv@autobooklongtable}{\csv@autobooklongtable[]}}
+
+
+\def\csvstyle#1#2{\csvset{#1/.style={#2}}}
+
+\def\csvnames#1#2{\csvset{#1/.style={column names={#2}}}}
+
+% string comparison
+
+\newrobustcmd{\ifcsvstrequal}[2]{%
+ \begingroup%
+ \protected@edef\csv@tempa{#1}%
+ \protected@edef\csv@tempb{#2}%
+ \edef\csv@tempa{#1}%
+ \edef\csv@tempb{#2}%
+ \ifx\csv@tempa\csv@tempb%
+ \aftergroup\@firstoftwo%
+ \else%
+ \aftergroup\@secondoftwo%
+ \fi%
+ \endgroup%
+}%
+
+\newrobustcmd{\ifcsvprostrequal}[2]{%
+ \begingroup%
+ \protected@edef\csv@tempa{#1}%
+ \protected@edef\csv@tempb{#2}%
+ \ifx\csv@tempa\csv@tempb%
+ \aftergroup\@firstoftwo%
+ \else%
+ \aftergroup\@secondoftwo%
+ \fi%
+ \endgroup%
+}%
+
+\AtBeginDocument{%
+ \ifdefined\pdfstrcmp%
+ \let\csv@strcmp\pdfstrcmp%
+ \else\ifdefined\pdf@strcmp%
+ \let\csv@strcmp\pdf@strcmp%
+ \fi\fi%
+ \ifdefined\csv@strcmp%
+ \newrobustcmd{\ifcsvstrcmp}[2]{%
+ \ifnum\csv@strcmp{#1}{#2}=\z@\relax%
+ \expandafter\@firstoftwo%
+ \else%
+ \expandafter\@secondoftwo%
+ \fi%
+ }%
+ \else%
+ \let\ifcsvstrcmp\ifcsvstrequal%
+ \fi%
+}
+
+\newrobustcmd{\ifcsvnotstrcmp}[4]{\ifcsvstrcmp{#1}{#2}{#4}{#3}}
diff --git a/macros/latex/contrib/csvsimple/csvsimple.tex b/macros/latex/contrib/csvsimple/csvsimple.tex
new file mode 100644
index 0000000000..73855697f6
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/csvsimple.tex
@@ -0,0 +1,2095 @@
+% \LaTeX-Main\
+% !TeX encoding=UTF-8
+%% The LaTeX package csvsimple - version 1.21 (2019/04/09)
+%% csvsimple.tex: Manual
+%%
+%% -------------------------------------------------------------------------------------------
+%% Copyright (c) 2008-2019 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
+%% -------------------------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `author-maintained'.
+%%
+%% This work consists of all files listed in README
+%%
+\documentclass[a4paper,11pt]{ltxdoc}
+
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[english]{babel}
+\usepackage{lmodern,parskip,array,ifthen,calc,makeidx}
+\usepackage{amsmath,amssymb}
+\usepackage[svgnames,table,hyperref]{xcolor}
+\usepackage{tikz,siunitx}
+\usepackage{varioref}
+\usepackage[pdftex,bookmarks,raiselinks,pageanchor,hyperindex,colorlinks]{hyperref}
+\urlstyle{sf}
+\usepackage{cleveref}
+
+\usepackage[a4paper,left=2.5cm,right=2.5cm,top=1.5cm,bottom=1.5cm,
+ marginparsep=3mm,marginparwidth=18mm,
+ headheight=0mm,headsep=0cm,
+ footskip=1.5cm,includeheadfoot]{geometry}
+\usepackage{fancyhdr}
+\fancyhf{}
+\fancyfoot[C]{\thepage}%
+\renewcommand{\headrulewidth}{0pt}
+\renewcommand{\footrulewidth}{0pt}
+\pagestyle{fancy}
+\tolerance=2000%
+\setlength{\emergencystretch}{20pt}%
+
+\RequirePackage{csquotes}
+\RequirePackage[style=numeric-comp,sorting=nyt,
+ maxnames=8,minnames=8,abbreviate=false,backend=biber]{biblatex}
+\DeclareFieldFormat{url}{\newline\url{#1}}%
+\DeclareListFormat{language}{}%
+\setlength{\bibitemsep}{\smallskipamount}
+\addbibresource{\jobname.bib}
+
+\usepackage{longtable,booktabs}
+\usepackage{csvsimple}
+
+\usepackage{tcolorbox}
+\tcbuselibrary{skins,xparse,minted,breakable,documentation,raster}
+
+\definecolor{Green_Dark}{rgb}{0.078431,0.407843,0.176471}
+\definecolor{Blue_Dark}{rgb}{0.090196,0.211765,0.364706}
+\definecolor{Blue_Bright}{rgb}{0.858824,0.898039,0.945098}
+
+\tcbset{skin=enhanced,
+ minted options={fontsize=\footnotesize},
+ doc head={colback=yellow!10!white,interior style=fill},
+ doc head key={colback=magenta!5!white,interior style=fill},
+ color key=DarkViolet,
+ color value=Teal,
+ color color=Teal,
+ color counter=Orange!85!black,
+ color length=Orange!85!black,
+ index colorize,
+ index annotate,
+ beforeafter example/.style={
+ before skip=4pt plus 2pt minus 1pt,
+ after skip=8pt plus 4pt minus 2pt
+ },
+ docexample/.style={bicolor,
+ beforeafter example,
+ arc is angular,fonttitle=\bfseries,
+ %fontupper=\tiny\itshape,
+ fontlower=\footnotesize,
+ %colframe=Blue_Dark,
+ %colback=Blue_Bright!75,
+ colframe=green!25!yellow!50!black,
+ colback=green!25!yellow!7,
+ colbacklower=white,
+% drop fuzzy shadow,
+ drop fuzzy shadow=green!25!yellow!50!black,
+ listing engine=minted,
+ documentation minted style=colorful,
+ documentation minted options={fontsize=\footnotesize},
+ },
+}
+
+\renewcommand*{\tcbdocnew}[1]{\textcolor{green!50!black}{\sffamily\bfseries N} #1}
+\renewcommand*{\tcbdocupdated}[1]{\textcolor{blue!75!black}{\sffamily\bfseries U} #1}
+
+\tcbmakedocSubKey{docCsvKey}{csv}
+
+\NewDocumentCommand{\csvsorter}{}{\textsf{\bfseries\color{red!20!black}CSV-Sorter}}
+
+%\newtcbinputlisting{\csvlisting}[1]{docexample,listing style=tcbdocumentation,fonttitle=\bfseries,
+% listing only,title={CSV file \flqq\texttt{\detokenize{#1.csv}}\frqq},listing file=#1.csv}
+\newtcbinputlisting{\csvlisting}[1]{docexample,minted options={fontsize=\footnotesize},minted language=latex,
+ fonttitle=\bfseries,listing only,title={CSV file \flqq\texttt{\detokenize{#1.csv}}\frqq},listing file=#1.csv}
+
+%\newtcbinputlisting{\xmllisting}[1]{docexample,listing options={style=tcbdocumentation,language=XML},
+% fonttitle=\bfseries,listing only,title={Configuration file \flqq\texttt{\detokenize{#1.xml}}\frqq},listing file=#1.xml}
+\newtcbinputlisting{\xmllisting}[1]{docexample,minted options={fontsize=\footnotesize},minted language=xml,
+ fonttitle=\bfseries,listing only,title={Configuration file \flqq\texttt{\detokenize{#1.xml}}\frqq},listing file=#1.xml}
+
+\NewTotalTCBox{\verbbox}{m}{enhanced,on line,size=fbox,frame empty,colback=red!5!white,
+ colupper=red!85!black,fontupper=\bfseries\ttfamily}{\detokenize{"}#1\detokenize{"}}
+
+\hypersetup{
+ pdftitle={Manual for the csvsimple package},
+ pdfauthor={Thomas F. Sturm},
+ pdfsubject={csv file processing with LaTeX},
+ pdfkeywords={csv file, comma separated values, key value syntax}
+}
+
+\def\version{1.21}%
+\def\datum{2019/04/09}%
+\makeindex
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begin{document}
+\begin{center}
+\begin{tcolorbox}[enhanced,hbox,tikznode,left=8mm,right=8mm,boxrule=0.4pt,
+ colback=white,colframe=black!50!yellow,
+ drop lifted shadow=black!50!yellow,arc is angular,
+ before=\par\vspace*{5mm},after=\par\bigskip]
+{\bfseries\LARGE The \texttt{csvsimple} package}\\[3mm]
+{\large Manual for version \version\ (\datum)}
+\end{tcolorbox}
+{\large Thomas F.~Sturm%
+ \footnote{Prof.~Dr.~Dr.~Thomas F.~Sturm, Institut f\"{u}r Mathematik und Informatik,
+ Universit\"{a}t der Bundeswehr M\"{u}nchen, D-85577 Neubiberg, Germany;
+ email: \href{mailto:thomas.sturm@unibw.de}{thomas.sturm@unibw.de}}\par\medskip
+\normalsize\url{http://www.ctan.org/pkg/csvsimple}\par
+\url{https://github.com/T-F-S/csvsimple}
+}
+\end{center}
+\bigskip
+\begin{absquote}
+ \begin{center}\bfseries Abstract\end{center}
+ |csvsimple| provides a simple \LaTeX\ interface for the processing of files with
+ comma separated values (CSV). |csvsimple| relies heavily on the key value
+ syntax from |pgfkeys| which results (hopefully) in an easy way of usage.
+ Filtering and table generation is especially supported. Since the package
+ is considered as a lightweight tool, there is no support for data sorting
+ or data base storage.
+\end{absquote}
+
+\clearpage
+\tableofcontents
+
+\clearpage
+\section{Introduction}%
+The |csvsimple| package is applied to the processing of
+CSV\footnote{CSV file: file with comma separated values.} files.
+This processing is controlled by key value assignments according to the
+syntax of |pgfkeys| \cite{tantau:tikz}. Sample applications of the package
+are tabular lists, serial letters, and charts.
+
+An alternative to |csvsimple| is the |datatool| package \cite{talbot:datatool}
+which provides considerably more functions and allows sorting of data by \LaTeX.
+|csvsimple| has a different approach for the user interface and
+is deliberately restricted to some basic functions with fast
+processing speed.
+
+Mind the following restrictions:
+\begin{itemize}
+\item Sorting is not supported directly but can be done
+ with external tools, see \Fullref{sec:Sorting}.
+\item Values are expected to be comma separated, but the package
+ provides support for other separators, see \Fullref{sec:separators}.
+\item Values are expected to be not quoted or quoted with
+ curly braces |{}| of \TeX\ groups. Other quotes like doublequotes
+ are not supported directly, but can be achieved
+ with external tools, see \Fullref{sec:importeddata}.
+\item Every data line is expected to contain the same amount of values.
+ Unfeasible data lines are silently ignored by default, but this can
+ be configured, see \Fullref{sec:consistency}.
+\end{itemize}
+
+
+\subsection{Loading the Package}
+The package |csvsimple| loads the packages
+|pgfkeys| \cite{tantau:tikz},
+|etoolbox| \cite{lehmannwright:etoolbox},
+and |ifthen| \cite{carlisle:2014c}.
+|csvsimple| itself is loaded in the usual manner in the preamble:
+\begin{dispListing}
+\usepackage{csvsimple}
+\end{dispListing}
+
+Not automatically loaded, but used for many examples are the packages
+|longtable| \cite{carlisle:2014d}
+and
+|booktabs| \cite{fear:2016a}.
+
+
+\clearpage
+\subsection{First Steps}
+Every line of a processable CSV file has to contain an identical amount of
+comma\footnote{See \refKey{/csv/separator} for other separators than comma.} separated values. The curly braces |{}| of \TeX\ groups can be used
+to mask a block which may contain commas not to be processed as separators.
+
+The first line of such a CSV file is usually but not necessarily a header line
+which contains the identifiers for each column.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{grade.csv}
+name,givenname,matriculation,gender,grade
+Maier,Hans,12345,m,1.0
+Huber,Anna,23456,f,2.3
+Weißbäck,Werner,34567,m,5.0
+Bauer,Maria,19202,f,3.3
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{grade}
+
+\smallskip
+The most simple way to display a CSV file in tabular form is the processing
+with the \refCom{csvautotabular} command.
+
+\begin{dispExample}
+\csvautotabular{grade.csv}
+\end{dispExample}
+
+
+Typically, one would use \refCom{csvreader} instead of |\csvautotabular| to
+gain full control over the interpretation of the included data.
+
+In the following example, the entries of the header line are automatically
+assigned to \TeX\ macros which may be used deliberately.
+
+
+\begin{dispExample}
+\begin{tabular}{|l|c|}\hline%
+\bfseries Person & \bfseries Matr.~No.
+\csvreader[head to column names]{grade.csv}{}%
+{\\\givenname\ \name & \matriculation}%
+ \\\hline
+\end{tabular}
+\end{dispExample}
+
+
+\clearpage
+|\csvreader| is controlled by a plenty of options. For example, for table
+applications line breaks are easily inserted by
+\refKey{/csv/late after line}. This defines a macro execution just before
+the following line.
+Additionally, the assignment of columns to \TeX\ macros is shown in a non automated
+way.
+
+\begin{dispExample}
+\begin{tabular}{|r|l|c|}\hline%
+& Person & Matr.~No.\\\hline\hline
+\csvreader[late after line=\\\hline]%
+ {grade.csv}{name=\name,givenname=\firstname,matriculation=\matnumber}%
+ {\thecsvrow & \firstname~\name & \matnumber}%
+\end{tabular}
+\end{dispExample}
+
+\smallskip
+An even more comfortable and preferrable way to create a table is setting
+appropriate option keys. Note, that this gives you the possibility to create a
+|pgfkeys| style which contains the whole table creation.
+
+\begin{dispExample}
+\csvreader[tabular=|r|l|c|,
+ table head=\hline & Person & Matr.~No.\\\hline\hline,
+ late after line=\\\hline]%
+ {grade.csv}{name=\name,givenname=\firstname,matriculation=\matnumber}%
+ {\thecsvrow & \firstname~\name & \matnumber}%
+\end{dispExample}
+
+\smallskip
+The next example shows such a style definition with the convenience macro
+\refCom{csvstyle}. Here, we see again the automated assignment of header
+entries to column names by \refKey{/csv/head to column names}.
+For this, the header entries have to be without spaces and special characters.
+But you can always assign entries to canonical macro names by hand like in the examples
+above.
+
+\begin{dispExample}
+\csvstyle{myTableStyle}{tabular=|r|l|c|,
+ table head=\hline & Person & Matr.~No.\\\hline\hline,
+ late after line=\\\hline,
+ head to column names}
+
+\csvreader[myTableStyle]{grade.csv}{}%
+ {\thecsvrow & \givenname~\name & \matriculation}%
+\end{dispExample}
+
+
+\clearpage
+Another way to address columns is to use their roman numbers.
+The direct addressing is done by |\csvcoli|, |\csvcolii|, |\csvcoliii|, \ldots:
+
+\begin{dispExample}
+\csvreader[tabular=|r|l|c|,
+ table head=\hline & Person & Matr.~No.\\\hline\hline,
+ late after line=\\\hline]%
+ {grade.csv}{}%
+ {\thecsvrow & \csvcolii~\csvcoli & \csvcoliii}%
+\end{dispExample}
+
+\smallskip
+And yet another method to assign macros to columns is to use arabic numbers
+for the assignment:
+
+\begin{dispExample}
+\csvreader[tabular=|r|l|c|,
+ table head=\hline & Person & Matr.~No.\\\hline\hline,
+ late after line=\\\hline]%
+ {grade.csv}{1=\name,2=\firstname,3=\matnumber}%
+ {\thecsvrow & \firstname~\name & \matnumber}%
+\end{dispExample}
+
+\smallskip
+For recurring applications, the |pgfkeys| syntax allows to create own styles
+for a consistent and centralized design. The following example is easily
+modified to obtain more or less option settings.
+
+\begin{dispExample}
+\csvset{myStudentList/.style={%
+ tabular=|r|l|c|,
+ table head=\hline & Person & #1\\\hline\hline,
+ late after line=\\\hline,
+ column names={name=\name,givenname=\firstname}
+ }}
+
+\csvreader[myStudentList={Matr.~No.}]{grade.csv}{matriculation=\matnumber}%
+{\thecsvrow & \firstname~\name & \matnumber}%
+\hfill%
+\csvreader[myStudentList={Grade}]{grade.csv}{grade=\grade}%
+{\thecsvrow & \firstname~\name & \grade}%
+\end{dispExample}
+
+
+\clearpage
+Alternatively, column names can be set by \refCom{csvnames}
+and style definitions by \refCom{csvstyle}.
+With this, the last example is rewritten as follows:
+
+\begin{dispExample}
+\csvnames{myNames}{1=\name,2=\firstname,3=\matnumber,5=\grade}
+\csvstyle{myStudentList}{tabular=|r|l|c|,
+ table head=\hline & Person & #1\\\hline\hline,
+ late after line=\\\hline, myNames}
+
+\csvreader[myStudentList={Matr.~No.}]{grade.csv}{}%
+{\thecsvrow & \firstname~\name & \matnumber}%
+\hfill%
+\csvreader[myStudentList={Grade}]{grade.csv}{}%
+{\thecsvrow & \firstname~\name & \grade}%
+\end{dispExample}
+
+\smallskip
+The data lines of a CSV file can also be filtered. In the following example,
+a certificate is printed only for students with grade unequal to 5.0.
+
+\begin{dispExample}
+\csvreader[filter not strcmp={\grade}{5.0}]%
+ {grade.csv}{1=\name,2=\firstname,3=\matnumber,4=\gender,5=\grade}%
+ {\begin{center}\Large\bfseries Certificate in Mathematics\end{center}
+ \large\ifcsvstrcmp{\gender}{f}{Ms.}{Mr.}
+ \firstname~\name, matriculation number \matnumber, has passed the test
+ in mathematics with grade \grade.\par\ldots\par
+ }%
+\end{dispExample}
+
+
+\clearpage
+\section{Macros for the Processing of CSV Files}\label{sec:makros}%
+
+\begin{docCommand}{csvreader}{\oarg{options}\marg{file name}\marg{assignments}\marg{command list}}
+ |\csvreader| reads the file denoted by \meta{file name} line by line.
+ Every line of the file has to contain an identical amount of
+ comma separated values. The curly braces |{}| of \TeX\ groups can be used
+ to mask a block which may contain commas not to be processed as separators.\smallskip
+
+ The first line of such a CSV file is by default but not necessarily
+ processed as a header line which contains the identifiers for each column.
+ The entries of this line can be used to give \meta{assignments} to \TeX\ macros
+ to address the columns. The number of entries of this first line
+ determines the accepted number of entries for all following lines.
+ Every line which contains a higher or lower number of entries is ignored
+ during standard processing.\smallskip
+
+ The \meta{assignments} are given by key value pairs
+ \mbox{\meta{name}|=|\meta{macro}}. Here, \meta{name} is an entry from the
+ header line \emph{or} the arabic number of the addressed column.
+ \meta{macro} is some \TeX\ macro which gets the content of the addressed column.\smallskip
+
+ The \meta{command list} is executed for every accepted data line. Inside the
+ \meta{command list} is applicable:
+ \begin{itemize}
+ \item \docAuxCommand{thecsvrow} or the counter |csvrow| which contains the number of the
+ current data line (starting with 1).
+ \item \docAuxCommand{csvcoli}, \docAuxCommand{csvcolii}, \docAuxCommand{csvcoliii}, \ldots,
+ which contain the contents of the column entries of the current data line.
+ Alternatively can be used:
+ \item \meta{macro} from the \meta{assignments} to have a logical
+ addressing of a column entry.
+ \end{itemize}
+ Note, that the \meta{command list} is allowed to contain |\par| and
+ that all macro definitions are made global to be used for table applications.\smallskip
+
+ The processing of the given CSV file can be controlled by various
+ \meta{options} given as key value list. The feasible option keys
+ are described in section \ref{sec:schluessel} from page \pageref{sec:schluessel}.
+
+\begin{dispExample}
+\csvreader[tabular=|r|l|l|, table head=\hline, table foot=\hline]{grade.csv}%
+ {name=\name,givenname=\firstname,grade=\grade}%
+ {\grade & \firstname~\name & \csvcoliii}
+\end{dispExample}
+
+Mainly, the |\csvreader| command consists of a \refCom{csvloop} macro with
+following parameters:\par
+|\csvloop{|\meta{options}|, file=|\meta{file name}|, column names=|\meta{assignments}|,|\\
+ \hspace*{2cm} |command=|\meta{command list}|}|\par
+ Therefore, the application of the keys \refKey{/csv/file} and \refKey{/csv/command}
+is useless for |\csvreader|.
+\end{docCommand}
+
+\begin{docCommand}{csvloop}{\marg{options}}
+ Usually, \refCom{csvreader} may be preferred instead of |\csvloop|.
+ \refCom{csvreader} is based on |\csvloop| which takes a mandatory list of
+ \meta{options} in key value syntax.
+ This list of \meta{options} controls the total processing. Especially,
+ it has to contain the CSV file name.
+\begin{dispExample}
+\csvloop{file={grade.csv}, head to column names, command=\name,
+ before reading={List of students:\ },
+ late after line={{,}\ }, late after last line=.}
+\end{dispExample}
+\end{docCommand}
+
+\clearpage
+The following |\csvauto...| commands are intended for quick data overview
+with limited formatting potential.
+See Subsection~\ref{subsec:tabsupport} on page \pageref{subsec:tabsupport}
+for the general table options in combination with \refCom{csvreader} and
+\refCom{csvloop}.
+
+\begin{docCommand}{csvautotabular}{\oarg{options}\marg{file name}}
+ |\csvautotabular| is an abbreviation for the application of the option key
+ \refKey{/csv/autotabular} together with other \meta{options} to \refCom{csvloop}.
+ This macro reads the whole CSV file denoted by \meta{file name}
+ with an automated formatting.
+\begin{dispExample}
+\csvautotabular{grade.csv}
+\end{dispExample}
+\begin{dispExample}
+\csvautotabular[filter equal={\csvcoliv}{f}]{grade.csv}
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvautolongtable}{\oarg{options}\marg{file name}}
+ |csvautolongtable| is an abbreviation for the application of the option key
+ \refKey{/csv/autolongtable} together with other \meta{options} to \refCom{csvloop}.
+ This macro reads the whole CSV file denoted by \meta{file name}
+ with an automated formatting.
+ For application, the package |longtable| is required which has to be
+ loaded in the preamble.
+\begin{dispListing}
+\csvautolongtable{grade.csv}
+\end{dispListing}
+\csvautolongtable{grade.csv}
+\end{docCommand}
+
+\clearpage
+
+\begin{docCommand}{csvautobooktabular}{\oarg{options}\marg{file name}}
+ |\csvautotabular| is an abbreviation for the application of the option key
+ \refKey{/csv/autobooktabular} together with other \meta{options} to \refCom{csvloop}.
+ This macro reads the whole CSV file denoted by \meta{file name}
+ with an automated formatting.
+ For application, the package |booktabs| is required which has to be
+ loaded in the preamble.
+\begin{dispExample}
+\csvautobooktabular{grade.csv}
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvautobooklongtable}{\oarg{options}\marg{file name}}
+ |csvautobooklongtable| is an abbreviation for the application of the option key
+ \refKey{/csv/autobooklongtable} together with other \meta{options} to \refCom{csvloop}.
+ This macro reads the whole CSV file denoted by \meta{file name}
+ with an automated formatting.
+ For application, the packages |booktabs| and |longtable| are required which have to be
+ loaded in the preamble.
+\begin{dispListing}
+\csvautobooklongtable{grade.csv}
+\end{dispListing}
+\csvautobooklongtable{grade.csv}
+\end{docCommand}
+
+
+
+\clearpage
+
+\begin{docCommand}{csvset}{\marg{options}}
+ Sets \meta{options} for every following
+ \refCom{csvreader} and \refCom{csvloop}. For example, this command may
+ be used for style definitions.
+\begin{dispExample}
+\csvset{grade list/.style=
+ {column names={name=\name,givenname=\firstname,grade=\grade}},
+ passed/.style={filter not strcmp={\grade}{5.0}} }
+
+The following students passed the test in mathematics:
+\csvreader[grade list,passed]{grade.csv}{}{\firstname\ \name\ (\grade); }%
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvstyle}{\marg{Stilname}\marg{options}}
+ Abbreviation for |\csvset{|\meta{style name}|/.style=|\marg{options}|}|
+ to define a new style.
+\end{docCommand}
+
+\begin{docCommand}{csvnames}{\marg{Stilname}\marg{Zuweisungsliste}}
+ Abbreviation for |\csvset{|\meta{style name}|/.style={column names=|\marg{assignments}|}}|
+ to define additional \meta{assignments} of macros to columns.
+\begin{dispExample}
+\csvnames{grade list}{name=\name,givenname=\firstname,grade=\grade}
+\csvstyle{passed}{filter not strcmp={\grade}{5.0}}
+
+The following students passed the test in mathematics:
+\csvreader[grade list,passed]{grade.csv}{}{\firstname\ \name\ (\grade); }%
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvheadset}{\marg{assignments}}
+ For some special cases, this command can be used to change the
+ \meta{assignments} of macros to columns during execution of
+ \refCom{csvreader} and \refCom{csvloop}.
+\begin{dispExample}
+\csvreader{grade.csv}{}%
+ { \csvheadset{name=\n} \fbox{\n}
+ \csvheadset{givenname=\n} \ldots\ \fbox{\n} }%
+\end{dispExample}
+\end{docCommand}
+
+\clearpage
+
+\begin{docCommand}{csviffirstrow}{\marg{then macros}\marg{else macros}}
+ Inside the command list of \refCom{csvreader}, the \meta{then macros}
+ are executed for the first data line, and the \meta{else macros}
+ are executed for all following lines.
+\begin{dispExample}
+\csvreader[tabbing, head to column names, table head=\hspace*{3cm}\=\kill]%
+ {grade.csv}{}%
+ {\givenname~\name \> (\csviffirstrow{first entry!!}{following entry})}
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvifoddrow}{\marg{then macros}\marg{else macros}}
+ Inside the command list of \refCom{csvreader}, the \meta{then macros}
+ are executed for odd-numbered data lines, and the \meta{else macros}
+ are executed for even-numbered lines.
+\begin{dispExample}
+\csvreader[head to column names,tabular=|l|l|l|l|,
+ table head=\hline\bfseries \# & \bfseries Name & \bfseries Grade\\\hline,
+ table foot=\hline]{grade.csv}{}{%
+ \csvifoddrow{\slshape\thecsvrow & \slshape\name, \givenname & \slshape\grade}%
+ {\bfseries\thecsvrow & \bfseries\name, \givenname & \bfseries\grade}}
+\end{dispExample}
+
+The |\csvifoddrow| macro may be used for striped tables:
+
+\begin{dispExample}
+% This example needs the xcolor package
+\csvreader[head to column names,tabular=rlcc,
+ table head=\hline\rowcolor{red!50!black}\color{white}\# & \color{white}Person
+ & \color{white}Matr.~No. & \color{white}Grade,
+ late after head=\\\hline\rowcolor{yellow!50},
+ late after line=\csvifoddrow{\\\rowcolor{yellow!50}}{\\\rowcolor{red!25}}]%
+ {grade.csv}{}%
+ {\thecsvrow & \givenname~\name & \matriculation & \grade}%
+\end{dispExample}
+
+\enlargethispage*{1cm}
+Alternatively, |\rowcolors| from the |xcolor| package can be used for this
+purpose:
+
+\begin{dispExample}
+% This example needs the xcolor package
+\csvreader[tabular=rlcc, before table=\rowcolors{2}{red!25}{yellow!50},
+ table head=\hline\rowcolor{red!50!black}\color{white}\# & \color{white}Person
+ & \color{white}Matr.~No. & \color{white}Grade\\\hline,
+ head to column names]{grade.csv}{}%
+ {\thecsvrow & \givenname~\name & \matriculation & \grade}%
+\end{dispExample}
+\end{docCommand}
+
+\clearpage
+
+\begin{docCommand}{csvfilteraccept}{}
+ All following consistent data lines will be accepted and processed.
+ This command overwrites all previous filter settings and may be used
+ inside \refKey{/csv/full filter} to implement
+ an own filtering rule together with |\csvfilterreject|.
+\begin{dispExample}
+\csvreader[autotabular,
+ full filter=\ifcsvstrcmp{\csvcoliv}{m}{\csvfilteraccept}{\csvfilterreject}
+ ]{grade.csv}{}{\csvlinetotablerow}%
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{csvfilterreject}{}
+ All following data lines will be ignored.
+ This command overwrites all previous filter settings.
+\end{docCommand}
+
+
+\begin{docCommand}{csvline}{}
+ This macro contains the current and unprocessed data line.
+\begin{dispExample}
+\csvreader[no head, tabbing, table head=\textit{line XX:}\=\kill]%
+ {grade.csv}{}{\textit{line \thecsvrow:} \> \csvline}%
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}{thecsvrow}{}
+ Typesets the current data line number. This is the
+ current number of accepted data lines without the header line.
+ The \LaTeX\ counter |csvrow| can be addressed directly in the usual way,
+ e.\,g. by |\roman{csvrow}|.
+\end{docCommand}
+
+
+\begin{docCommand}{thecsvinputline}{}
+ Typesets the current file line number. This is the
+ current number of all data lines including the header line.
+ The \LaTeX\ counter |csvinputline| can be addressed directly in the usual way,
+ e.\,g. by |\roman{csvinputline}|.
+\begin{dispExample}
+\csvreader[no head, filter test=\ifnumequal{\thecsvinputline}{3}]%
+ {grade.csv}{}%
+ {The line with number \thecsvinputline\ contains: \csvline}%
+\end{dispExample}
+\end{docCommand}
+
+
+\begin{docCommand}[doc updated=2016-07-01]{csvlinetotablerow}{}
+ Typesets the current processed data line with |&| between the entries.
+ %Most users will never apply this command.
+\end{docCommand}
+
+
+
+\clearpage
+\section{Option Keys}\label{sec:schluessel}%
+For the \meta{options} in \refCom{csvreader} respectively \refCom{csvloop}
+the following |pgf| keys can be applied. The key tree path |/csv/| is not
+to be used inside these macros.
+
+
+\subsection{Command Definition}%--------%[[
+
+\begin{docCsvKey}{before reading}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed before the CSV file is processed.
+\end{docCsvKey}
+
+\begin{docCsvKey}{after head}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after the header line is read.
+\end{docCsvKey}
+
+\begin{docCsvKey}{before filter}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after reading and consistency checking
+ of a data line. They are executed before any filter condition is checked,
+ see \refKey{/csv/filter}.
+ Also see \refKey{/csv/full filter}.
+\end{docCsvKey}
+
+\begin{docCsvKey}{late after head}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after reading and disassembling
+ of the first accepted data line. They are executed before further processing
+ of this line.
+\end{docCsvKey}
+
+\begin{docCsvKey}{late after line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after reading and disassembling
+ of the next accepted data line (after \refKey{/csv/before filter}).
+ They are executed before further processing of this next line.
+ |late after line| overwrites |late after first line| and |late after last line|.
+ Note that table options like \refKey{/csv/tabular} set this key to |\\|
+ automatically.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{late after first line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after reading and disassembling
+ of the second accepted data line instead of \refKey{/csv/late after line}.
+ This key has to be set after |late after line|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{late after last line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after processing of the last
+ accepted data line instead of \refKey{/csv/late after line}.
+ This key has to be set after |late after line|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{before line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after \refKey{/csv/late after line}
+ and before \refKey{/csv/command}.
+ |before line| overwrites |before first line|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{before first line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed instead of \refKey{/csv/before line}
+ for the first accepted data line.
+ This key has to be set after |before line|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{command}{=\meta{code}}{no default, initially \cs{csvline}}
+ Sets the \meta{code} to be executed for every accepted data line.
+ They are executed between \refKey{/csv/before line} and \refKey{/csv/after line}.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{after line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed for every accepted data line
+ after \refKey{/csv/command}.
+ |after line| overwrites |after first line|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{after first line}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed instead of \refKey{/csv/after line}
+ for the first accepted data line.
+ This key has to be set after |after line|.
+\end{docCsvKey}
+
+\begin{docCsvKey}{after reading}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after the CSV file is processed.
+\end{docCsvKey}
+
+
+\begin{dispExample}
+\csvreader[
+ before reading = \meta{before reading}\\,
+ after head = \meta{after head},
+ before filter = \\\meta{before filter},
+ late after head = \meta{late after head},
+ late after line = \meta{late after line},
+ late after first line = \meta{late after first line},
+ late after last line = \\\meta{late after last line},
+ before line = \meta{before line},
+ before first line = \meta{before first line},
+ after line = \meta{after line},
+ after first line = \meta{after first line},
+ after reading = \\\meta{after reading}
+ ]{grade.csv}{name=\name}{\textbf{\name}}%
+\end{dispExample}
+
+Additional command definition keys are provided for the supported tables,
+see Section~\ref{subsec:tabsupport} from page~\pageref{subsec:tabsupport}.
+
+
+\subsection{Header Processing and Column Name Assignment}%
+
+\begin{docCsvKey}{head}{\colOpt{=true\textbar false}}{default |true|, initially |true|}
+ If this key is set, the first line of the CSV file is treated as a header
+ line which can be used for column name assignments.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{no head}{}{no value}
+ Abbreviation for |head=false|, i.\,e. the first line of the CSV file is
+ treated as data line.
+ Note that this option cannot be used in combination with
+ \refCom{csvautotabular}, \refKey{/csv/autotabular}, and similar automated commands/options.
+ See Section~\ref{noheader} on page~\pageref{noheader} for assistance.
+\end{docCsvKey}
+
+\begin{docCsvKey}{column names}{=\meta{assignments}}{no default, initially empty}
+ Adds some new \meta{assignments} of macros to columns in key value syntax.
+ Existing assignments are kept.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{column names reset}{}{no value}
+ Clears all assignments of macros to columns.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{head to column names}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, the entries of the header line are used automatically
+ as macro names for the columns. This option can be used only, if
+ the header entries do not contain spaces and special characters to be
+ used as feasible \LaTeX\ macro names.
+\end{docCsvKey}
+
+
+\clearpage
+\subsection{Consistency Check}\label{sec:consistency}%
+
+\begin{docCsvKey}{check column count}{\colOpt{=true\textbar false}}{default |true|, initially |true|}
+ This key defines, wether the number of entries in a data line is checked against
+ an expected value or not.\\
+ If |true|, every non consistent line is ignored without announcement.\\
+ If |false|, every line is accepted and may produce an error during
+ further processing.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{no check column count}{}{no value}
+ Abbreviation for |check column count=false|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{column count}{=\meta{number}}{no default}
+ Sets the \meta{number} of feasible entries per data line.
+ This setting is only useful in connection with \refKey{/csv/no head},
+ since \meta{number} would be replaced by the number of entries in the
+ header line otherwise.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{on column count error}{=\meta{code}}{no default, initially empty}
+ \meta{code} to be executed for unfeasible data lines.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{warn on column count error}{}{style, no value}
+ Display of a warning for unfeasible data lines.
+\end{docCsvKey}
+
+
+\clearpage
+\subsection{Filtering}%
+
+\begin{docCsvKey}[][doc new=2016-07-01]{filter test}{=\meta{condition}}{no default}
+ Only data lines which fulfill a logical \meta{condition} are accepted.
+ For the \meta{condition}, every single test normally employed like
+\begin{dispListing}
+\iftest{some testing}{true}{false}
+\end{dispListing}
+ can be used as
+\begin{dispListing}
+filter test=\iftest{some testing},
+\end{dispListing}
+ For |\iftest|, tests from the |etoolbox| package \cite{lehmannwright:etoolbox} like
+ |\ifnumcomp|, |\ifdimgreater|, etc. and from \Fullref{sec:stringtests} can be used.
+
+\begin{dispExample}
+\csvreader[head to column names,tabular=llll,
+ table head=\toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule,
+ table foot=\bottomrule,
+ %>> list only matriculation numbers greater than 20000 <<
+ filter test=\ifnumgreater{\matriculation}{20000},
+ ]{grade.csv}{}{%
+ \thecsvrow & \slshape\name, \givenname & \matriculation & \grade}
+\end{dispExample}
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter strcmp}{=\marg{stringA}\marg{stringB}}{style, no default}
+ Only lines where \meta{stringA} and \meta{stringB} are equal after expansion
+ are accepted.
+ The implementation is done with \refCom{ifcsvstrcmp}.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter not strcmp}{=\marg{stringA}\marg{stringB}}{style, no default}
+ Only lines where \meta{stringA} and \meta{stringB} are not equal after expansion
+ are accepted.
+ The implementation is done with \refCom{ifcsvnotstrcmp}.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}[][doc new=2016-07-01]{filter expr}{=\meta{condition}}{no default}
+ Only data lines which fulfill a logical \meta{condition} are accepted.
+ For the \meta{condition}, every boolean expression
+ from the |etoolbox| package \cite{lehmannwright:etoolbox} is feasible.
+ To preprocess the data line before testing the \meta{condition},
+ the option key \refKey{/csv/before filter} can be used.
+\begin{dispExample}
+\csvreader[head to column names,tabular=llll,
+ table head=\toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule,
+ table foot=\bottomrule,
+ %>> list only matriculation numbers greater than 20000
+ % and grade less than 4.0 <<
+ filter expr={ test{\ifnumgreater{\matriculation}{20000}}
+ and test{\ifdimless{\grade pt}{4.0pt}} },
+ ]{grade.csv}{}{%
+ \thecsvrow & \slshape\name, \givenname & \matriculation & \grade}
+\end{dispExample}
+\end{docCsvKey}
+
+\clearpage
+\begin{docCsvKey}[][doc new=2016-07-01]{filter ifthen}{=\meta{condition}}{no default}
+ Only data lines which fulfill a logical \meta{condition} are accepted.
+ For the \meta{condition}, every term from the |ifthen| \cite{carlisle:2014c} package
+ is feasible.
+ To preprocess the data line before testing the \meta{condition},
+ the option key \refKey{/csv/before filter} can be used.
+
+\begin{dispExample}
+\csvreader[head to column names,tabular=llll,
+ table head=\toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule,
+ table foot=\bottomrule,
+ %>> list only female persons <<
+ filter ifthen=\equal{\gender}{f},
+ ]{grade.csv}{}{%
+ \thecsvrow & \slshape\name, \givenname & \matriculation & \grade}
+\end{dispExample}
+
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter}{=\meta{condition}}{no default}
+ Alias for \refKey{/csv/filter ifthen}.
+\end{docCsvKey}
+
+\begin{docCsvKey}{filter equal}{=\marg{stringA}\marg{stringB}}{style, no default}
+ Only lines where \meta{stringA} and \meta{stringB} are equal after expansion
+ are accepted.
+ The implementation is done with the |ifthen| \cite{carlisle:2014c} package.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter not equal}{=\marg{stringA}\marg{stringB}}{style, no default}
+ Only lines where \meta{stringA} and \meta{stringB} are not equal after expansion
+ are accepted.
+ The implementation is done with the |ifthen| \cite{carlisle:2014c} package.
+\end{docCsvKey}
+
+
+
+\begin{docCsvKey}{no filter}{}{no value, initially set}
+ Clears a set filter.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter accept all}{}{no value, initially set}
+ Alias for |no filter|. All consistent data lines are accepted.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{filter reject all}{}{no value}
+ All data line are ignored.
+\end{docCsvKey}
+
+
+
+\enlargethispage*{2cm}
+\begin{docCsvKey}[][doc new=2016-07-01]{full filter}{=\meta{code}}{no default}
+ Technically, this key is an alias for \refKey{/csv/before filter}.
+ Philosophically, \refKey{/csv/before filter} computes something before
+ a filter condition is set, but \refKey{/csv/full filter} should implement
+ the full filtering. Especially, \refCom{csvfilteraccept} or
+ \refCom{csvfilterreject} \emph{should} be set inside the \meta{code}.
+\begin{dispExample}
+\csvreader[head to column names,tabular=llll,
+ table head=\toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule,
+ table foot=\bottomrule,
+ %>> list only matriculation numbers greater than 20000
+ % and grade less than 4.0 <<
+ full filter=\ifnumgreater{\matriculation}{20000}
+ {\ifdimless{\grade pt}{4.0pt}{\csvfilteraccept}{\csvfilterreject}}
+ {\csvfilterreject},
+ ]{grade.csv}{}{%
+ \thecsvrow & \slshape\name, \givenname & \matriculation & \grade}
+\end{dispExample}
+\end{docCsvKey}
+
+
+
+%]]
+
+
+\clearpage
+\subsection{Table Support}\label{subsec:tabsupport}%--------%[[
+
+\begin{docCsvKey}{tabular}{=\meta{table format}}{style, no default}
+ Surrounds the CSV processing with |\begin{tabular}|\marg{table format}
+ at begin and with |\end{tabular}| at end.
+Additionally, the commands defined by the key values of
+ \refKey{/csv/before table}, \refKey{/csv/table head}, \refKey{/csv/table foot},
+ and \refKey{/csv/after table} are executed at the appropriate places.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{centered tabular}{=\meta{table format}}{style, no default}
+ Like \refKey{/csv/tabular} but inside an additional |center| environment.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{longtable}{=\meta{table format}}{style, no default}
+ Like \refKey{/csv/tabular} but for the |longtable| environment.
+ This requires the package |longtable| (not loaded automatically).
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{tabbing}{}{style, no value}
+ Like \refKey{/csv/tabular} but for the |tabbing| environment.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{centered tabbing}{}{style, no value}
+ Like \refKey{/csv/tabbing} but inside an additional |center| environment.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{no table}{}{style, no value}
+ Deactivates |tabular|, |longtable|, and |tabbing|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{before table}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed before |\begin{tabular}| or before |\begin{longtable}|
+ or before |\begin{tabbing}|, respectively.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{table head}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after |\begin{tabular}| or after |\begin{longtable}|
+ or after |\begin{tabbing}|, respectively.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{table foot}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed before |\end{tabular}| or before |\end{longtable}|
+ or before |\end{tabbing}|, respectively.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{after table}{=\meta{code}}{no default, initially empty}
+ Sets the \meta{code} to be executed after |\end{tabular}| or after |\end{longtable}|
+ or after |\end{tabbing}|, respectively.
+\end{docCsvKey}
+
+\bigskip
+
+The following |auto| options are the counterparts for the respective quick
+overview commands like \refCom{csvautotabular}. They are listed for
+completeness, but are unlikely to be used directly.
+
+\begin{docCsvKey}{autotabular}{=\meta{file name}}{no default}
+ Reads the whole CSV file denoted \meta{file name} with an automated formatting.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{autolongtable}{=\meta{file name}}{no default}
+ Reads the whole CSV file denoted \meta{file name} with an automated formatting
+ using the required |longtable| package.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{autobooktabular}{=\meta{file name}}{no default}
+ Reads the whole CSV file denoted \meta{file name} with an automated formatting
+ using the required |booktabs| package.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{autobooklongtable}{=\meta{file name}}{no default}
+ Reads the whole CSV file denoted \meta{file name} with an automated formatting
+ using the required |booktabs| and |longtable| packages.
+\end{docCsvKey}
+
+
+\clearpage
+\subsection{Special Characters}\label{subsec:specchar}
+Be default, the CSV content is treated like normal \LaTeX\ text, see
+Subsection~\ref{macrocodexample} on page~\pageref{macrocodexample}.
+But, \TeX\ special characters of the CSV content may also be interpreted
+as normal characters, if one or more of the following options are used.
+
+\begin{docCsvKey}{respect tab}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ tabulator sign
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect percent}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ percent sign \verbbox{\%}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect sharp}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ sharp sign \verbbox{\#}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect dollar}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ dollar sign \verbbox{\$}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect and}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ and sign \verbbox{\&}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect backslash}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ backslash sign \verbbox{\textbackslash}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect underscore}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ underscore sign \verbbox{\_}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect tilde}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ tilde sign \verbbox{\textasciitilde}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect circumflex}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ circumflex sign \verbbox{\textasciicircum}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect leftbrace}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ left brace sign \verbbox{\textbraceleft}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect rightbrace}{\colOpt{=true\textbar false}}{default |true|, initially |false|}
+ If this key is set, every
+ right brace sign \verbbox{\textbraceright}
+ inside the CSV content is a normal character.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect all}{}{style, no value, initially unset}
+ Set all special characters from above to normal characters. This means
+ a quite verbatim interpretation of the CSV content.
+\end{docCsvKey}
+
+\begin{docCsvKey}{respect none}{}{style, no value, initially set}
+ Do not change any special character from above to normal character.
+\end{docCsvKey}
+
+\clearpage
+\subsection{Separators}\label{sec:separators}%
+\begin{docCsvKey}{separator}{=\meta{sign}}{no default, initially |comma|}
+ \catcode `|=12
+ Sets the \meta{sign} which is treates as separator between the data values
+ of a data line. Feasible values are:
+ \begin{itemize}
+ \item\docValue{comma}: This is the initial value with '\texttt{,}' as separator.
+ \medskip
+
+ \item\docValue{semicolon}: Sets the separator to '\texttt{;}'.
+\begin{dispExample}
+% \usepackage{tcolorbox} for tcbverbatimwrite
+\begin{tcbverbatimwrite}{testsemi.csv}
+ name;givenname;matriculation;gender;grade
+ Maier;Hans;12345;m;1.0
+ Huber;Anna;23456;f;2.3
+ Weißbäck;Werner;34567;m;5.0
+\end{tcbverbatimwrite}
+
+\csvautobooktabular[separator=semicolon]{testsemi.csv}
+\end{dispExample}
+\medskip
+
+\item\docValue{pipe}: Sets the separator to '\texttt{|}'.
+\begin{dispExample}
+% \usepackage{tcolorbox} for tcbverbatimwrite
+\begin{tcbverbatimwrite}{pipe.csv}
+ name|givenname|matriculation|gender|grade
+ Maier|Hans|12345|m|1.0
+ Huber|Anna|23456|f|2.3
+ Weißbäck|Werner|34567|m|5.0
+\end{tcbverbatimwrite}
+
+\csvautobooktabular[separator=pipe]{pipe.csv}
+\end{dispExample}
+\medskip
+
+\item\docValue{tab}: Sets the separator to the tabulator sign.
+ Automatically, \refKey{/csv/respect tab} is set also.
+ \end{itemize}
+\end{docCsvKey}
+
+\clearpage
+\subsection{Miscellaneous}%
+
+\begin{docCsvKey}{every csv}{}{style, initially empty}
+ A style definition which is used for every following CSV file.
+ This definition can be overwritten with user code.
+\begin{dispListing}
+% Sets a warning message for unfeasible data lines.
+\csvset{every csv/.style={warn on column count error}}
+% Alternatively:
+\csvstyle{every csv}{warn on column count error}
+\end{dispListing}
+\end{docCsvKey}
+
+\begin{docCsvKey}{default}{}{style}
+ A style definition which is used for every following CSV file which
+ resets all settings to default values\footnote{\texttt{default} is used
+ because of the global nature of most settings.}.
+ This key should not be used or changed by the user if there is not a
+ really good reason (and you know what you do).
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{file}{=\meta{file name}}{no default, initially |unknown.csv|}
+ Sets the \meta{file name} of the CSV file to be processed.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{preprocessed file}{=\meta{file name}}{no default, initially \texttt{\textbackslash\detokenize{jobname_sorted.csv}}}
+ Sets the \meta{file name} of the CSV file which is the output of a
+ preprocessor.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{preprocessor}{=\meta{macro}}{no default}
+ Defines a preprocessor for the given CSV file.
+ The \meta{macro} has to have two mandatory arguments. The first argument
+ is the original CSV file which is set by \refKey{/csv/file}.
+ The second argument is the preprocessed CSV file
+ which is set by \refKey{/csv/preprocessed file}.\par\smallskip
+ Typically, the \meta{macro} may call an external program which preprocesses
+ the original CSV file (e.\,g. sorting the file) and creates the
+ preprocessed CSV file. The later file is used by \refCom{csvreader}
+ or \refCom{csvloop}.
+\begin{dispListing}
+\newcommand{\mySortTool}[2]{%
+ % call to an external program to sort file #1 with resulting file #2
+}
+
+\csvreader[%
+ preprocessed file=\jobname_sorted.csv,
+ preprocessor=\mySortTool,
+ ]{some.csv}{}{%
+ % do something
+}
+\end{dispListing}
+See Subsection~\ref{sec:Sorting} on page~\pageref{sec:Sorting} for a
+concrete sorting preprocessing implemented with an external tool.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{no preprocessing}{}{style, no value, initially set}
+ Clears any preprocessing, i.\,e. preprocessing is switched of.
+\end{docCsvKey}
+
+
+
+\clearpage
+\subsection{Sorting}\label{sec:Sorting}%
+\TeX/\LaTeX\ was not born under a sorting planet. |csvsimple| provides no
+sorting of data lines by \LaTeX-methods since sorting can be done much faster
+and much better by external tools.
+
+First, one should consider the appropriate \emph{place} for sorting:
+\begin{itemize}
+\item CSV files may be sorted by a tool \emph{before} the \LaTeX\ document is processed
+ at all. If the CSV data is not likely to change, this is the most efficient method.
+\item CSV files may be sorted by a tool every time before the \LaTeX\ document is compiled.
+ This could be automated by a shell script or some processing tool like |arara|.
+\item CSV files may be sorted on-the-fly by a tool during compilation of
+ a \LaTeX\ document. This is the most elegant but not the most efficient way.
+\end{itemize}
+
+The first two methods are decoupled from anything concerning |csvsimple|.
+For the third method, the \refKey{/csv/preprocessor} option is made for.
+This allows to access an external tool for sorting.
+\emph{Which tool} is your choice.
+
+\csvsorter\ \cite{sturm:csvsorter}
+was written as a companion tool for |csvsimple|.
+It is an open source Java command-line tool for sorting CSV files, available at\\
+\url{http://T-F-S.github.io/csvsorter/}\quad or\quad
+\url{https://github.com/T-F-S/csvsorter}
+
+It can be
+used for all three sorting approaches described above.
+There is special support for on-the-fly sorting with \csvsorter\ using the
+following options.
+
+\begin{enumerate}\bfseries
+\item To use the sorting options, you have to install \csvsorter\ \cite{sturm:csvsorter} before!\\
+ |csvsimple| v1.12 or newer needs \csvsorter\ v0.94 of newer!
+\item You have to give permission to call external tools during
+ compilation, i.\,e.\ the command-line options for |latex| have to include
+ |-shell-escape|.
+\end{enumerate}
+
+\bigskip
+
+\begin{docCsvKey}{csvsorter command}{=\meta{system command}}{no default, initially |csvsorter|}
+ The \meta{system command} specifies the system call for \csvsorter\ (without the options).
+ If \csvsorter\ was completely installed following its documentation, there is
+ nothing to change here. If the |csvsorter.jar| file is inside the same
+ directory as the \LaTeX\ source file, you may configure:% preferrably inside the preamble:
+\begin{dispListing}
+\csvset{csvsorter command=java -jar csvsorter.jar}
+\end{dispListing}
+\end{docCsvKey}
+
+\begin{docCsvKey}{csvsorter configpath}{=\meta{path}}{no default, initially |.|}
+ Sorting with \csvsorter\ is done using XML configuration files. If these files
+ are not stored inside the same directory as the \LaTeX\ source file, a
+ \meta{path} to access them can be configured:
+\begin{dispListing}
+\csvset{csvsorter configpath=xmlfiles}
+\end{dispListing}
+ Here, the configuration files would be stored in a subdirectory named |xmlfiles|.
+\end{docCsvKey}
+
+\begin{docCsvKey}{csvsorter log}{=\meta{file name}}{no default, initially |csvsorter.log|}
+ Sets the log file of \csvsorter\ to the given \meta{file name}.
+\begin{dispListing}
+\csvset{csvsorter log=outdir/csvsorter.log}
+\end{dispListing}
+ Here, the log file is written to a subdirectory named |outdir|.
+\end{docCsvKey}
+
+\clearpage
+\begin{docCsvKey}{csvsorter token}{=\meta{file name}}{no default, initially |\textbackslash jobname.csvtoken|}
+ Sets \meta{file name} as token file. This is an auxiliary file which
+ communicates the success of \csvsorter\ to |csvsimple|.
+\begin{dispListing}
+\csvset{csvsorter log=outdir/\jobname.csvtoken}
+\end{dispListing}
+ Here, the token file is written to a subdirectory named |outdir|.
+\end{docCsvKey}
+
+
+\begin{docCsvKey}{sort by}{=\meta{file name}}{style, initially unset}
+ The \meta{file name} denotes an XML configuration file for \csvsorter.
+ Setting this option inside \refCom{csvreader} or
+ \refCom{csvloop} will issue a system call to \csvsorter.
+ \begin{itemize}
+ \item \csvsorter\ uses the given CSV file as input file.
+ \item \csvsorter\ uses \meta{file name} as configuration file.
+ \item The output CSV file is denoted by \refKey{/csv/preprocessed file}
+ which is by default \texttt{\textbackslash\detokenize{jobname_sorted.csv}}.
+ This output file is this actual file processed by \refCom{csvreader} or \refCom{csvloop}.
+ \item \csvsorter\ also generates a log file denoted by \refKey{/csv/csvsorter log} which is by default |csvsorter.log|.
+ \end{itemize}
+
+\par\medskip\textbf{First example:}
+ To sort our example |grade.csv| file according to |name| and |givenname|, we
+ use the following XML configuration file. Since \csvsorter\ uses double quotes
+ as default brackets for column values, we remove bracket recognition to avoid
+ a clash with the escaped umlauts of the example CSV file.\par\smallskip
+
+\xmllisting{namesort}
+\begin{dispExample}
+% \usepackage{booktabs}
+\csvreader[sort by=namesort.xml,
+ head to column names,
+ tabular=>{\color{red}}lllll,
+ table head=\toprule Name & Given Name & Matriculation & Gender & Grade\\\midrule,
+ table foot=\bottomrule]
+ {grade.csv}{}{\csvlinetotablerow}
+\end{dispExample}
+
+\clearpage\textbf{Second example:}
+ To sort our example |grade.csv| file according to |grade|, we
+ use the following XML configuration file. Further, persons with the same |grade|
+ are sorted by |name| and |givenname|. Since \csvsorter\ uses double quotes
+ as default brackets for column values, we remove bracket recognition to avoid
+ a clash with the escaped umlauts of the example CSV file.\par\smallskip
+
+\xmllisting{gradesort}
+\begin{dispExample}
+% \usepackage{booktabs}
+\csvreader[sort by=gradesort.xml,
+ head to column names,
+ tabular=llll>{\color{red}}l,
+ table head=\toprule Name & Given Name & Matriculation & Gender & Grade\\\midrule,
+ table foot=\bottomrule]
+ {grade.csv}{}{\csvlinetotablerow}
+\end{dispExample}
+
+\clearpage\textbf{Third example:}
+ To generate a matriculation/grade list, we sort our example |grade.csv| file
+ using the following XML configuration file.
+ Again, since \csvsorter\ uses double quotes
+ as default brackets for column values, we remove bracket recognition to avoid
+ a clash with the escaped umlauts of the example CSV file.\par\smallskip
+
+\xmllisting{matriculationsort}
+\begin{dispExample}
+% \usepackage{booktabs}
+\csvreader[sort by=matriculationsort.xml,
+ head to column names,
+ tabular=>{\color{red}}ll,
+ table head=\toprule Matriculation & Grade\\\midrule,
+ table foot=\bottomrule]
+ {grade.csv}{}{\matriculation & \grade}
+\end{dispExample}
+\end{docCsvKey}
+
+
+\clearpage
+\begin{docCsvKey}{new sorting rule}{=\marg{name}\marg{file name}}{style, initially unset}
+This is a convenience option to generate a new shortcut for often used
+\refKey{/csv/sort by} applications. It also adds a more semantic touch.
+The new shortcut option is
+\tcbox[on line,size=small,colback=white,colframe=red]{|sort by| \meta{name}} which expands to
+\tcbox[on line,size=small,colback=white,colframe=red]{|sort by=|\marg{file name}}.\par\medskip
+
+Consider the following example:
+\begin{dispExample}
+\csvautotabular[sort by=namesort.xml]{grade.csv}
+\end{dispExample}
+A good place for setting up a new sorting rule would be inside the preamble:
+
+\csvset{new sorting rule={name}{namesort.xml}}
+\begin{dispListing}
+\csvset{new sorting rule={name}{namesort.xml}}
+\end{dispListing}
+
+Now, we can use the new rule:
+\begin{dispExample}
+\csvautotabular[sort by name]{grade.csv}
+\end{dispExample}
+
+\end{docCsvKey}
+
+
+\clearpage
+\section{String Tests}\label{sec:stringtests}%
+
+The following string tests are complementing the string tests
+from the |etoolbox| \cite{lehmannwright:etoolbox} package. They all do the same, i.e.,
+comparing expanded strings for equality.
+\begin{itemize}
+\item\refCom{ifcsvstrcmp} is the most efficient method, because it uses
+ native compiler string comparison (if available).
+\item\refCom{ifcsvstrequal} does not rely on a compiler. It also is the
+ fallback implementation for \refCom{ifcsvstrcmp}, if there is no
+ native comparison method.
+\item\refCom{ifcsvprostrequal} is possibly more failsafe than the other two
+ string tests. It may be used, if strings contain dirty things like |\textbf{A}|.
+\end{itemize}
+\medskip
+
+\begin{docCommand}[doc new=2016-07-01]{ifcsvstrcmp}{\marg{stringA}\marg{stringB}\marg{true}\marg{false}}
+ Compares two strings and executes \meta{true} if they are equal, and \meta{false} otherwise.
+ The comparison is done using |\pdfstrcmp|, if compilation is done with pdf\LaTeX.
+ The comparison is done using |\pdf@strcmp|, if the package |pdftexcmds| is
+ loaded and compilation is done with lua\LaTeX\ or Xe\LaTeX.
+ Otherwise, \refCom{ifcsvstrcmp} is identical to \refCom{ifcsvstrequal}.
+ This command cannot be used inside the preamble.
+\end{docCommand}
+
+
+\begin{docCommand}[doc new=2016-07-01]{ifcsvnotstrcmp}{\marg{stringA}\marg{stringB}\marg{true}\marg{false}}
+ Compares two strings and executes \meta{true} if they are \emph{not} equal, and \meta{false} otherwise.
+ The implementation uses \refCom{ifcsvstrcmp}.
+\end{docCommand}
+
+
+\begin{docCommand}[doc new=2016-07-01]{ifcsvstrequal}{\marg{stringA}\marg{stringB}\marg{true}\marg{false}}
+ Compares two strings and executes \meta{true} if they are equal, and \meta{false} otherwise.
+ The strings are expanded with |\edef| in the test.
+\end{docCommand}
+
+\begin{docCommand}[doc new=2016-07-01]{ifcsvprostrequal}{\marg{stringA}\marg{stringB}\marg{true}\marg{false}}
+ Compares two strings and executes \meta{true} if they are equal, and \meta{false} otherwise.
+ The strings are expanded with |\protected@edef| in the test, i.e. parts of the
+ strings which are protected stay unexpanded.
+\end{docCommand}
+
+
+
+\clearpage
+\section{Examples}%
+
+\subsection{A Serial Letter}%
+In this example, a serial letter is to be written to all persons with
+addresses from the following CSV file. Deliberately, the file content is
+not given in very pretty format.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{address.csv}
+name,givenname,gender,degree,street,zip,location,bonus
+Maier,Hans,m,,Am Bachweg 17,10010,Hopfingen,20
+ % next line with a comma in curly braces
+Huber,Erna,f,Dr.,{Moosstraße 32, Hinterschlag},10020,Örtingstetten,30
+Weißbäck,Werner,m,Prof. Dr.,Brauallee 10,10030,Klingenbach,40
+ % this line is ignored %
+ Siebener , Franz,m, , Blaumeisenweg 12 , 10040 , Pardauz , 50
+ % preceding and trailing spaces in entries are removed %
+Schmitt,Anton,m,,{\AE{}lfred-Esplanade, T\ae{}g 37}, 10050,\OE{}resung,60
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{address}
+
+Firstly, we survey the file content quickly using
+|\csvautotabular|.
+As can be seen, unfeasible lines are ignored automatically.
+
+\begin{dispExample}
+\tiny\csvautotabular{address.csv}
+\end{dispExample}
+
+Now, we create the serial letter where every feasible data line produces
+an own page. Here, we simulate the page by a |tcolorbox| (from the package
+|tcolorbox|).
+For the gender specific salutations, an auxiliary macro |\ifmale| is
+introduced.
+
+\begin{dispExample}
+% this example requires the tcolorbox package
+\newcommand{\ifmale}[2]{\ifcsvstrcmp{\gender}{m}{#1}{#2}}
+
+\csvreader[head to column names]{address.csv}{}{%
+\begin{tcolorbox}[colframe=DarkGray,colback=White,arc=0mm,width=(\linewidth-2pt)/2,
+ equal height group=letter,before=,after=\hfill,fonttitle=\bfseries,
+ adjusted title={Letter to \name}]
+ \ifcsvstrcmp{\degree}{}{\ifmale{Mr.}{Ms.}}{\degree}~\givenname~\name\\
+ \street\\\zip~\location
+ \tcblower
+ {\itshape Dear \ifmale{Sir}{Madam},}\\
+ we are pleased to announce you a bonus value of \bonus\%{}
+ which will be delivered to \location\ soon.\\\ldots
+\end{tcolorbox}}
+\end{dispExample}
+
+
+
+\clearpage
+\subsection{A Graphical Presentation}%
+For this example, we use some artificial statistical data given by a CSV file.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{data.csv}
+land,group,amount
+Bayern,A,1700
+Baden-Württemberg,A,2300
+Sachsen,B,1520
+Thüringen,A,1900
+Hessen,B,2100
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{data}
+
+Firstly, we survey the file content using
+|\csvautobooktabular|.
+
+\begin{dispExample}
+% needs the booktabs package
+\csvautobooktabular{data.csv}
+\end{dispExample}
+
+The amount values are presented in the following diagram by bars where
+the group classification is given using different colors.
+
+\begin{dispExample}
+% This example requires the package tikz
+\begin{tikzpicture}[Group/A/.style={left color=red!10,right color=red!20},
+ Group/B/.style={left color=blue!10,right color=blue!20}]
+\csvreader[head to column names]{data.csv}{}{%
+ \begin{scope}[yshift=-\thecsvrow cm]
+ \path [draw,Group/\group] (0,-0.45)
+ rectangle node[font=\bfseries] {\amount} (\amount/1000,0.45);
+ \node[left] at (0,0) {\land};
+ \end{scope} }
+\end{tikzpicture}
+\end{dispExample}
+
+
+\clearpage
+It would be nice to sort the bars by length, i.\,e.\ to sort the CSV file
+by the |amount| column. If the \csvsorter\ program is properly installed,
+see Subsection~\ref{sec:Sorting} on page~\pageref{sec:Sorting},
+this can be done with the following configuration file for \csvsorter:
+
+\xmllisting{amountsort}
+
+Now, we just have to add an option |sort by=amountsort.xml|:
+\begin{dispExample}
+% This example requires the package tikz
+% Also, the CSV-Sorter tool has to be installed
+\begin{tikzpicture}[Group/A/.style={left color=red!10,right color=red!20},
+ Group/B/.style={left color=blue!10,right color=blue!20}]
+\csvreader[head to column names,sort by=amountsort.xml]{data.csv}{}{%
+ \begin{scope}[yshift=-\thecsvrow cm]
+ \path [draw,Group/\group] (0,-0.45)
+ rectangle node[font=\bfseries] {\amount} (\amount/1000,0.45);
+ \node[left] at (0,0) {\land};
+ \end{scope} }
+\end{tikzpicture}
+\end{dispExample}
+
+
+
+
+\clearpage
+Next, we create a pie chart by calling |\csvreader| twice.
+In the first step, the total sum of amounts is computed, and in the second
+step the slices are drawn.
+
+\begin{dispExample}
+% Modified example from www.texample.net for pie charts
+% This example needs the packages tikz, xcolor, calc
+\definecolorseries{myseries}{rgb}{step}[rgb]{.95,.85,.55}{.17,.47,.37}
+\resetcolorseries{myseries}%
+
+% a pie slice
+\newcommand{\slice}[4]{
+ \pgfmathsetmacro{\midangle}{0.5*#1+0.5*#2}
+ \begin{scope}
+ \clip (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
+ \colorlet{SliceColor}{myseries!!+}%
+ \fill[inner color=SliceColor!30,outer color=SliceColor!60] (0,0) circle (1cm);
+ \end{scope}
+ \draw[thick] (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
+ \node[label=\midangle:#4] at (\midangle:1) {};
+ \pgfmathsetmacro{\temp}{min((#2-#1-10)/110*(-0.3),0)}
+ \pgfmathsetmacro{\innerpos}{max(\temp,-0.5) + 0.8}
+ \node at (\midangle:\innerpos) {#3};
+}
+
+% sum of amounts
+\csvreader[before reading=\def\mysum{0}]{data.csv}{amount=\amount}{%
+ \pgfmathsetmacro{\mysum}{\mysum+\amount}%
+}
+
+% drawing of the pie chart
+\begin{tikzpicture}[scale=3]%
+\def\mya{0}\def\myb{0}
+\csvreader[head to column names]{data.csv}{}{%
+ \let\mya\myb
+ \pgfmathsetmacro{\myb}{\myb+\amount}
+ \slice{\mya/\mysum*360}{\myb/\mysum*360}{\amount}{\land}
+}
+\end{tikzpicture}%
+\end{dispExample}
+
+
+\clearpage
+Finally, the filter option is demonstrated by separating the groups A and B.
+Every item is piled upon the appropriate stack.
+
+\begin{dispExample}
+\newcommand{\drawGroup}[2]{%
+ \def\mya{0}\def\myb{0}
+ \node[below=3mm] at (2.5,0) {\bfseries Group #1};
+ \csvreader[head to column names,filter equal={\group}{#1}]{data.csv}{}{%
+ \let\mya\myb
+ \pgfmathsetmacro{\myb}{\myb+\amount}
+ \path[draw,top color=#2!25,bottom color=#2!50]
+ (0,\mya/1000) rectangle node{\land\ (\amount)} (5,\myb/1000);
+}}
+
+\begin{tikzpicture}
+ \fill[gray!75] (-1,0) rectangle (13,-0.1);
+ \drawGroup{A}{red}
+ \begin{scope}[xshift=7cm]
+ \drawGroup{B}{blue}
+ \end{scope}
+\end{tikzpicture}
+
+\end{dispExample}
+
+
+\clearpage
+\subsection{Macro code inside the data}\label{macrocodexample}%
+
+If needed, the data file may contain macro code. Note that the first character
+of a data line is not allowed to be the backslash '|\|'.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{macrodata.csv}
+type,description,content
+M,A nice \textbf{formula}, $\displaystyle \int\frac{1}{x} = \ln|x|+c$
+G,A \textcolor{red}{colored} ball, {\tikz \shadedraw [shading=ball] (0,0) circle (.5cm);}
+M,\textbf{Another} formula, $\displaystyle \lim\limits_{n\to\infty} \frac{1}{n}=0$
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{macrodata}
+
+Firstly, we survey the file content using
+|\csvautobooktabular|.
+
+\begin{dispExample}
+\csvautobooktabular{macrodata.csv}
+\end{dispExample}
+
+
+\begin{dispExample}
+\csvstyle{my enumerate}{head to column names,
+ before reading=\begin{enumerate},after reading=\end{enumerate}}
+
+\csvreader[my enumerate]{macrodata.csv}{}{%
+ \item \description:\par\content}
+
+\bigskip
+Now, formulas only:
+\csvreader[my enumerate,filter equal={\type}{M}]{macrodata.csv}{}{%
+ \item \description:\qquad\content}
+\end{dispExample}
+
+\clearpage
+\subsection{Tables with Number Formatting}\label{numberformatting}%
+
+We consider a file with numerical data which should be pretty-printed.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{data_numbers.csv}
+month, dogs, cats
+January, 12.50,12.3e5
+February, 3.32, 8.7e3
+March, 43, 3.1e6
+April, 0.33, 21.2e4
+May, 5.12, 3.45e6
+June, 6.44, 6.66e6
+July, 123.2,7.3e7
+August, 12.3, 5.3e4
+September,2.3, 4.4e4
+October, 6.5, 6.5e6
+November, 0.55, 5.5e5
+December, 2.2, 3.3e3
+\end{tcbverbatimwrite}
+
+\csvlisting{data_numbers}
+
+The |siunitx| \cite{wright:siuntix} package provides a new column type |S|
+which can align material using a number of different strategies.
+The following example demonstrates the application with CSV reading.
+The package documentation \cite{wright:siuntix} contains a huge amount
+of formatting options.
+
+\begin{dispExample}
+% \usepackage{siunitx,array,booktabs}
+\csvloop{
+ file=data_numbers.csv,
+ head to column names,
+ before reading=\centering\sisetup{table-number-alignment=center},
+ tabular={lSS[table-format=2.2e1]},
+ table head=\toprule\textbf{Month} & \textbf{Dogs} & \textbf{Cats}\\\midrule,
+ command=\month & \dogs & \cats,
+ table foot=\bottomrule}
+\end{dispExample}
+
+\clearpage
+Special care is needed, if the \emph{first} column is to be formatted with
+the column type |S|. The number detection of |siunitx| is disturbed by
+the line reading code of |csvsimple| which actually is present at the
+first column. To avoid this problem, the content of the first column
+could be formatted not by the table format definition, but by using a
+suitable |\tablenum| formatting directly, see |siunitx| \cite{wright:siuntix}.
+
+Another and very nifty workaround suggested by Enrico Gregorio is to
+add an invisible dummy column with |c@{}| as first column:
+
+
+\begin{dispExample}
+% \usepackage{siunitx,array,booktabs}
+\csvloop{
+ file=data_numbers.csv,
+ head to column names,
+ before reading=\centering\sisetup{table-number-alignment=center},
+ tabular={c@{}S[table-format=2.2e1]S},
+ table head= & \textbf{Cats} & \textbf{Dogs}\\\midrule,
+ command= & \cats & \dogs,
+ table foot=\bottomrule}
+\end{dispExample}
+
+
+
+\clearpage
+Now, the preceding table shall be sorted by the \emph{cats} values.
+If the \csvsorter\ program is properly installed,
+see Subsection~\ref{sec:Sorting} on page~\pageref{sec:Sorting},
+this can be done with the following configuration file for \csvsorter:
+
+\xmllisting{catsort}
+
+Now, we just have to add an option |sort by=catsort.xml|:
+\begin{dispExample}
+% \usepackage{siunitx,array,booktabs}
+% Also, the CSV-Sorter tool has to be installed
+\csvloop{
+ file=data_numbers.csv,
+ sort by=catsort.xml,
+ head to column names,
+ before reading=\centering\sisetup{table-number-alignment=center},
+ tabular={lSS[table-format=2.2e1]},
+ table head=\toprule\textbf{Month} & \textbf{Dogs} & \textbf{Cats}\\\midrule,
+ command=\month & \dogs & \cats,
+ table foot=\bottomrule}
+\end{dispExample}
+
+
+\clearpage
+\subsection{CSV data without header line}\label{noheader}%
+CSV files with a header line are more semantic than files without header,
+but it's no problem to work with headless files.
+
+For this example, we use again some artificial statistical data given by a CSV file
+but this time without header.
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{data_headless.csv}
+Bayern,A,1700
+Baden-Württemberg,A,2300
+Sachsen,B,1520
+Thüringen,A,1900
+Hessen,B,2100
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{data_headless}
+
+Note that you cannot use the \refKey{/csv/no head} option for the auto tabular
+commands. If no options are given, the first line is interpreted as header line
+which gives an unpleasant result:
+
+\begin{dispExample}
+\csvautobooktabular{data_headless.csv}
+\end{dispExample}
+
+To get the expected result, one can redefine \refKey{/csv/table head}
+using \refCom{csvlinetotablerow} which holds the first line data for the
+|\csvauto...| commands:
+
+\begin{dispExample}
+\csvautobooktabular[table head=\toprule\csvlinetotablerow\\]{data_headless.csv}
+\end{dispExample}
+
+This example can be extended to insert a table head for this headless data:
+
+\begin{dispExample}
+\csvautobooktabular[table head=\toprule\bfseries Land & \bfseries Group
+ & \bfseries Amount\\\midrule\csvlinetotablerow\\]{data_headless.csv}
+\end{dispExample}
+
+\clearpage
+
+For the normal \refCom{csvreader} command, the \refKey{/csv/no head} option
+should be applied. Of course, we cannot use \refKey{/csv/head to column names}
+because there is no head, but the columns can be addressed by their numbers:
+
+\begin{dispExample}
+\csvreader[no head,
+ tabular=lr,
+ table head=\toprule\bfseries Land & \bfseries Amount\\\midrule,
+ table foot=\bottomrule]
+ {data_headless.csv}
+ {1=\land,3=\amount}
+ {\land & \amount}
+\end{dispExample}
+
+
+\clearpage
+\subsection{Imported CSV data}\label{sec:importeddata}%
+If data is imported from other applications, there is not always a choice
+to format in comma separated values with curly brackets.
+
+Consider the following example data file:
+
+%-- file embedded for simplicity --
+\begin{tcbverbatimwrite}{imported.csv}
+"name";"address";"email"
+"Frank Smith";"Yellow Road 123, Brimblsby";"frank.smith@organization.org"
+"Mary May";"Blue Alley 2a, London";"mmay@maybe.uk"
+"Hans Meier";"Hauptstraße 32, Berlin";"hans.meier@corporation.de"
+\end{tcbverbatimwrite}
+%-- end embedded file --
+
+\csvlisting{imported}
+
+If the \csvsorter\ program is properly installed,
+see Subsection~\ref{sec:Sorting} on page~\pageref{sec:Sorting},
+this can be transformed on-the-fly
+with the following configuration file for \csvsorter:
+
+\xmllisting{transform}
+
+Now, we just have to add an option |sort by=transform.xml| to transform
+the input data. Here, we actually do not sort.
+
+\begin{dispExample}
+% \usepackage{booktabs,array}
+% Also, the CSV-Sorter tool has to be installed
+\newcommand{\Header}[1]{\normalfont\bfseries #1}
+
+\csvreader[
+ sort by=transform.xml,
+ tabular=>{\itshape}ll>{\ttfamily}l,
+ table head=\toprule\Header{Name} & \Header{Address} & \Header{email}\\\midrule,
+ table foot=\bottomrule]
+ {imported.csv}{}{\csvlinetotablerow}
+\end{dispExample}
+
+The file which is generated on-the-fly and which is actually read by
+|csvsimple| is the following:
+
+\tcbinputlisting{docexample,listing style=tcbdocumentation,fonttitle=\bfseries,
+ listing only,listing file=\jobname_sorted._csv}
+
+
+\clearpage
+\subsection{Encoding}\label{encoding}%
+If the CSV file has a different encoding than the \LaTeX\ source file,
+then special care is needed.
+
+\begin{itemize}
+\item The most obvious treatment is to change the encoding of the CSV file
+ or the \LaTeX\ source file to match the other one (every good editor
+ supports such a conversion). This is the easiest choice, if there a no
+ good reasons against such a step. E.g., unfortunately, several tools
+ under Windows need the CSV file to be |cp1252| encoded while
+ the \LaTeX\ source file may need to be |utf8| encoded.
+
+\item The |inputenc| package allows to switch the encoding inside the
+ document, say from |utf8| to |cp1252|. Just be aware that you should only
+ use pure ASCII for additional texts inside the switched region.
+\begin{dispListing}
+% !TeX encoding=UTF-8
+% ....
+\usepackage[utf8]{inputenc}
+% ....
+\begin{document}
+% ....
+\inputencoding{latin1}% only use ASCII from here, e.g. "Uberschrift
+\csvreader[%...
+ ]{data_cp1252.csv}{%...
+ }{% ....
+ }
+\inputencoding{utf8}
+% ....
+\end{document}
+\end{dispListing}
+
+\item As a variant to the last method, the encoding switch can be done
+ using options from |csvsimple|:
+\begin{dispListing}
+% !TeX encoding=UTF-8
+% ....
+\usepackage[utf8]{inputenc}
+% ....
+\begin{document}
+% ....
+% only use ASCII from here, e.g. "Uberschrift
+\csvreader[%...
+ before reading=\inputencoding{latin1},
+ after reading=\inputencoding{utf8},
+ ]{data_cp1252.csv}{%...
+ }{% ....
+ }
+% ....
+\end{document}
+\end{dispListing}
+
+\pagebreak\item
+If the \csvsorter\ program is properly installed,
+see Subsection~\ref{sec:Sorting} on page~\pageref{sec:Sorting},
+the CSV file can be re-encoded on-the-fly
+with the following configuration file for \csvsorter:
+
+\xmllisting{encoding}
+
+\begin{dispListing}
+% !TeX encoding=UTF-8
+% ....
+\usepackage[utf8]{inputenc}
+% ....
+\begin{document}
+% ....
+\csvreader[%...
+ sort by=encoding.xml,
+ ]{data_cp1252.csv}{%...
+ }{% ....
+ }
+% ....
+\end{document}
+\end{dispListing}
+
+
+\end{itemize}
+
+
+
+
+\clearpage
+
+% Actually, it is not a good idea to include the references like this!
+% Do not follow this bad example ...
+\begin{tcbverbatimwrite}{\jobname.bib}
+@manual{tantau:tikz,
+ author = {Till Tantau},
+ title = {The TikZ and PGF Packages},
+ subtitle = {Manual for version 3.1.2},
+ url = {http://mirrors.ctan.org/graphics/pgf/base/doc/pgfmanual.pdf},
+ date = {2019-04-04},
+}
+
+@manual{carlisle:2014c,
+ author = {David Carlisle},
+ title = {The ifthen package},
+ url = {http://mirror.ctan.org/macros/latex/base/ifthen.pdf},
+ date = {2014-09-29},
+ language = {english}
+}
+
+
+@manual{talbot:datatool,
+ author = {Nicola L. C. Talbot},
+ title = {User Manual for the datatool bundle version 2.31},
+ url = {http://mirrors.ctan.org/macros/latex/contrib/datatool/datatool-user.pdf},
+ date = {2018-12-07},
+ language = {english}
+}
+
+@manual{sturm:csvsorter,
+ author = {Thomas F. Sturm},
+ title = {The CSV-Sorter program},
+ subtitle = {Manual for version 0.95 beta},
+ url = {http://T-F-S.github.io/csvsorter/csvsorter.pdf},
+ date = {2018-01-11},
+ language = {english}
+}
+
+@manual{carlisle:2014d,
+ author = {David Carlisle},
+ title = {The longtable package},
+ url = {http://mirror.ctan.org/macros/latex/required/tools/longtable.pdf},
+ date = {2014-10-28},
+ language = {english}
+}
+
+
+@manual{fear:2016a,
+ author = {Simon Fear},
+ title = {Publication quality tables in \LaTeX},
+ url = {http://mirror.ctan.org/macros/latex/contrib/booktabs/booktabs.pdf},
+ date = {2016-04-29},
+ language = {english}
+}
+
+@manual{wright:siuntix,
+ author = {Joseph Wright},
+ title = {siunitx --- A comprehensive (SI) units package},
+ url = {http://mirror.ctan.org/macros/latex/contrib/siunitx/siunitx.pdf},
+ date = {2018-05-17},
+ language = {english}
+}
+
+@manual{lehmannwright:etoolbox,
+ author = {Philipp Lehman and Joseph Wright},
+ title = {The etoolbox Package},
+ url = {http://mirror.ctan.org/macros/latex/contrib/etoolbox/etoolbox.pdf},
+ date = {2018-08-19},
+}
+
+\end{tcbverbatimwrite}
+
+
+\printbibliography[heading=bibintoc]
+
+\printindex
+
+\end{document}
diff --git a/macros/latex/contrib/csvsimple/encoding.xml b/macros/latex/contrib/csvsimple/encoding.xml
new file mode 100644
index 0000000000..e43cb6a8de
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/encoding.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <noHeader/>
+ <bracket empty="true"/>
+ <charset in="windows-1252" out="UTF-8"/>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/gradesort.xml b/macros/latex/contrib/csvsimple/gradesort.xml
new file mode 100644
index 0000000000..32c2741735
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/gradesort.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket empty="true" />
+ <sortlines>
+ <column name="grade" order="ascending" type="double"/>
+ <column name="name" order="ascending" type="string"/>
+ <column name="givenname" order="ascending" type="string"/>
+ </sortlines>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/matriculationsort.xml b/macros/latex/contrib/csvsimple/matriculationsort.xml
new file mode 100644
index 0000000000..be19e9e760
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/matriculationsort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket empty="true" />
+ <sortlines>
+ <column name="matriculation" order="ascending" type="integer"/>
+ </sortlines>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/namesort.xml b/macros/latex/contrib/csvsimple/namesort.xml
new file mode 100644
index 0000000000..6c17bd4d2a
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/namesort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket empty="true" />
+ <sortlines>
+ <column name="name" order="ascending" type="string"/>
+ <column name="givenname" order="ascending" type="string"/>
+ </sortlines>
+</csv>
diff --git a/macros/latex/contrib/csvsimple/transform.xml b/macros/latex/contrib/csvsimple/transform.xml
new file mode 100644
index 0000000000..4111c31b53
--- /dev/null
+++ b/macros/latex/contrib/csvsimple/transform.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<csv>
+ <bracket leftsymbol="doublequote" rightsymbol="doublequote" />
+ <delimiter signsymbol="semicolon" />
+ <outBracket leftsymbol="braceleft" rightsymbol="braceright" />
+ <outDelimiter signsymbol="comma" />
+</csv>