From 916b6828e77bd92bd88d57bad094c4520f0ad65c Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Wed, 30 Jun 2021 03:03:03 +0000 Subject: CTAN sync 202106300303 --- macros/latex/contrib/csvsimple/CHANGES | 115 - macros/latex/contrib/csvsimple/CHANGES.md | 293 + macros/latex/contrib/csvsimple/README | 50 - macros/latex/contrib/csvsimple/README.md | 62 + macros/latex/contrib/csvsimple/csvsimple-doc.sty | 106 + .../latex/contrib/csvsimple/csvsimple-example.pdf | Bin 75627 -> 75627 bytes .../latex/contrib/csvsimple/csvsimple-example.tex | 14 +- macros/latex/contrib/csvsimple/csvsimple-l3.pdf | Bin 0 -> 988201 bytes macros/latex/contrib/csvsimple/csvsimple-l3.sty | 1260 + macros/latex/contrib/csvsimple/csvsimple-l3.tex | 2504 + .../latex/contrib/csvsimple/csvsimple-legacy.pdf | Bin 0 -> 810666 bytes .../latex/contrib/csvsimple/csvsimple-legacy.sty | 795 + .../latex/contrib/csvsimple/csvsimple-legacy.tex | 1970 + macros/latex/contrib/csvsimple/csvsimple-title.png | Bin 0 -> 127249 bytes macros/latex/contrib/csvsimple/csvsimple.pdf | Bin 832329 -> 309385 bytes macros/latex/contrib/csvsimple/csvsimple.sty | 795 +- macros/latex/contrib/csvsimple/csvsimple.tex | 2132 +- macros/latex/contrib/hvfloat/Changes | 4 + macros/latex/contrib/hvfloat/doc/hvfloat.pdf | Bin 7126601 -> 5722381 bytes macros/latex/contrib/hvfloat/doc/hvfloat.tex | 18 +- .../hvfloat/doc/images/felsen-wasser-small.pdf | Bin 0 -> 1362739 bytes .../contrib/hvfloat/doc/images/sonne-meer.jpg | Bin 0 -> 501524 bytes macros/latex/contrib/hvfloat/latex/hvfloat-fps.sty | 10 +- macros/latex/contrib/hvfloat/latex/hvfloat.sty | 55 +- macros/latex/contrib/keyfloat/README.txt | 2 +- macros/latex/contrib/keyfloat/keyfloat.dtx | 745 +- macros/latex/contrib/keyfloat/keyfloat.pdf | Bin 1010471 -> 1025675 bytes macros/latex/contrib/lwarp/README.txt | 2 +- macros/latex/contrib/lwarp/lwarp.dtx | 277 +- macros/latex/contrib/lwarp/lwarp.pdf | Bin 3203770 -> 3210245 bytes macros/latex/contrib/lwarp/lwarpmk.lua | 18 +- .../contrib/pdfmanagement-testphase/CHANGELOG.md | 4 + .../contrib/pdfmanagement-testphase/README.md | 2 +- .../contrib/pdfmanagement-testphase/color-ltx.sty | 2 +- .../pdfmanagement-testphase/hyperref-generic.dtx | 4 +- .../pdfmanagement-testphase/hyperref-generic.pdf | Bin 947285 -> 947374 bytes .../hyperxmp-patches-tmp-ltx.sty | 2 +- .../l3backend-testphase.dtx | 14 +- .../l3backend-testphase.pdf | Bin 588643 -> 588657 bytes .../contrib/pdfmanagement-testphase/l3pdfannot.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfannot.pdf | Bin 573830 -> 573839 bytes .../contrib/pdfmanagement-testphase/l3pdfdict.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfdict.pdf | Bin 527359 -> 527212 bytes .../pdfmanagement-testphase/l3pdffield-action.dtx | 2 +- .../pdfmanagement-testphase/l3pdffield-action.pdf | Bin 547960 -> 547968 bytes .../l3pdffield-checkbox.dtx | 2 +- .../l3pdffield-checkbox.pdf | Bin 530998 -> 531008 bytes .../pdfmanagement-testphase/l3pdffield-choice.dtx | 2 +- .../pdfmanagement-testphase/l3pdffield-choice.pdf | Bin 534214 -> 534217 bytes .../l3pdffield-pushbutton.dtx | 2 +- .../l3pdffield-pushbutton.pdf | Bin 526289 -> 526297 bytes .../l3pdffield-radiobutton.dtx | 2 +- .../l3pdffield-radiobutton.pdf | Bin 576391 -> 576394 bytes .../l3pdffield-textfield.dtx | 2 +- .../l3pdffield-textfield.pdf | Bin 505625 -> 505648 bytes .../contrib/pdfmanagement-testphase/l3pdffield.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdffield.pdf | Bin 739350 -> 739355 bytes .../contrib/pdfmanagement-testphase/l3pdffile.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdffile.pdf | Bin 553291 -> 553295 bytes .../pdfmanagement-testphase/l3pdfmanagement.dtx | 4 +- .../pdfmanagement-testphase/l3pdfmanagement.pdf | Bin 659120 -> 658998 bytes .../contrib/pdfmanagement-testphase/l3pdfmeta.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfmeta.pdf | Bin 663941 -> 663954 bytes .../contrib/pdfmanagement-testphase/l3pdftools.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdftools.pdf | Bin 518384 -> 518377 bytes .../contrib/pdfmanagement-testphase/l3pdfxform.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfxform.pdf | Bin 436061 -> 435902 bytes .../contrib/pdfmanagement-testphase/l3ref-tmp.sty | 17 +- .../contrib/pdfmanagement-testphase/ltdocinit.dtx | 4 +- .../contrib/pdfmanagement-testphase/ltdocinit.pdf | Bin 553013 -> 552844 bytes .../pdfmanagement-testphase/pdflscape-ltx.sty | 2 +- .../pdfmanagement-firstaid.dtx | 4 +- .../pdfmanagement-firstaid.pdf | Bin 422418 -> 422433 bytes .../pdfmanagement-testphase.dtx | 6 +- .../pdfmanagement-testphase.pdf | Bin 446685 -> 446514 bytes .../pdfmanagement-testphase/transparent-ltx.sty | 2 +- .../xcolor-patches-tmp-ltx.sty | 2 +- macros/latex/contrib/semantex/semantex.pdf | Bin 370872 -> 384088 bytes macros/latex/contrib/semantex/semantex.sty | 562 +- macros/latex/contrib/semantex/semantex.tex | 16 +- macros/latex/contrib/semantex/stripsemantex.sty | 2 +- macros/latex/contrib/siunitx/CHANGELOG.md | 8 +- macros/latex/contrib/siunitx/siunitx-code.pdf | Bin 1493627 -> 1493737 bytes macros/latex/contrib/siunitx/siunitx-command.dtx | 34 +- macros/latex/contrib/siunitx/siunitx.dtx | 2 +- macros/latex/contrib/siunitx/siunitx.pdf | Bin 635011 -> 635011 bytes macros/latex/contrib/tagpdf/README.md | 4 +- macros/latex/contrib/tagpdf/global-ex.png | Bin 0 -> 8281 bytes macros/latex/contrib/tagpdf/tagpdf-backend.dtx | 1059 +- macros/latex/contrib/tagpdf/tagpdf-checks.dtx | 643 +- macros/latex/contrib/tagpdf/tagpdf-code.pdf | Bin 0 -> 1082873 bytes macros/latex/contrib/tagpdf/tagpdf-code.tex | 94 + macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx | 389 + macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx | 490 + macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx | 442 + macros/latex/contrib/tagpdf/tagpdf-mc.dtx | 818 - macros/latex/contrib/tagpdf/tagpdf-roles.dtx | 165 +- macros/latex/contrib/tagpdf/tagpdf-space.dtx | 130 +- macros/latex/contrib/tagpdf/tagpdf-struct.dtx | 1024 +- macros/latex/contrib/tagpdf/tagpdf-tree.dtx | 343 +- macros/latex/contrib/tagpdf/tagpdf-user.dtx | 585 + macros/latex/contrib/tagpdf/tagpdf.dtx | 865 +- macros/latex/contrib/tagpdf/tagpdf.ins | 47 +- macros/latex/contrib/tagpdf/tagpdf.pdf | 52979 ++++++++++--------- macros/latex/contrib/tagpdf/tagpdf.tex | 277 +- macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty | 50 +- 106 files changed, 41517 insertions(+), 30847 deletions(-) delete mode 100644 macros/latex/contrib/csvsimple/CHANGES create mode 100644 macros/latex/contrib/csvsimple/CHANGES.md delete mode 100644 macros/latex/contrib/csvsimple/README create mode 100644 macros/latex/contrib/csvsimple/README.md create mode 100644 macros/latex/contrib/csvsimple/csvsimple-doc.sty create mode 100644 macros/latex/contrib/csvsimple/csvsimple-l3.pdf create mode 100644 macros/latex/contrib/csvsimple/csvsimple-l3.sty create mode 100644 macros/latex/contrib/csvsimple/csvsimple-l3.tex create mode 100644 macros/latex/contrib/csvsimple/csvsimple-legacy.pdf create mode 100644 macros/latex/contrib/csvsimple/csvsimple-legacy.sty create mode 100644 macros/latex/contrib/csvsimple/csvsimple-legacy.tex create mode 100644 macros/latex/contrib/csvsimple/csvsimple-title.png create mode 100644 macros/latex/contrib/hvfloat/doc/images/felsen-wasser-small.pdf create mode 100644 macros/latex/contrib/hvfloat/doc/images/sonne-meer.jpg create mode 100644 macros/latex/contrib/tagpdf/global-ex.png create mode 100644 macros/latex/contrib/tagpdf/tagpdf-code.pdf create mode 100644 macros/latex/contrib/tagpdf/tagpdf-code.tex create mode 100644 macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx create mode 100644 macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx create mode 100644 macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx delete mode 100644 macros/latex/contrib/tagpdf/tagpdf-mc.dtx create mode 100644 macros/latex/contrib/tagpdf/tagpdf-user.dtx (limited to 'macros/latex') diff --git a/macros/latex/contrib/csvsimple/CHANGES b/macros/latex/contrib/csvsimple/CHANGES deleted file mode 100644 index 3e17f605c7..0000000000 --- a/macros/latex/contrib/csvsimple/CHANGES +++ /dev/null @@ -1,115 +0,0 @@ -%% The LaTeX package csvsimple - version 1.22 (2021/06/07) -%% -%% ------------------------------------------------------------------------------------------- -%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm -%% ------------------------------------------------------------------------------------------- -%% -%% 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 - -version 1.22 (2021/06/07): -- (#7) new option 'head to column names prefix' -- (#11) Due to changes in the LaTeX kernel 2021-06-01, the empty line - detection of csvsimple had to be adapted. Updating csvsimple is - essential to avoid problems with kernel 2021-06-01. diff --git a/macros/latex/contrib/csvsimple/CHANGES.md b/macros/latex/contrib/csvsimple/CHANGES.md new file mode 100644 index 0000000000..1899dbf1f8 --- /dev/null +++ b/macros/latex/contrib/csvsimple/CHANGES.md @@ -0,0 +1,293 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on +[Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to +[Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + + + +## [2.0.0] - 2021-06-29 + +### Added +- New documentation `csvsimple-l3.pdf` for the new LaTeX3 version + (revised, adapted and extended from the old documentation) +- `\thecsvcolumncount` +- Option `autotabular*` +- Option `autobooktabular*` +- Option `autolongtable*` +- Option `autobooklongtable*` +- Option `filter bool` +- Option `filter fp` +- Option `range` +- `\csvautotabular*` +- `\csvautobooktabular*` +- `\csvautolongtable*` +- `\csvautobooklongtable*` +- `\csvfilterbool` +- `\ifcsvfirstrow` +- `\ifcsvoddrow` +- `\ifcsvfpcmp` +- `\ifcsvintcmp` +- `\csvsortingrule` + +### Changed +- Complete re-implementation of the hitherto existing latex package + as LaTeX3 package using the expl3 interface. From now on, three package + files are provided: + ** `csvsimple-legacy.sty` identical to csvsimple until version 1.22 ** + ** `csvsimple-l3.sty` LaTeX3 package of csvsimple ** + ** `csvsimple.sty` stub to select `l3` or `legacy` (default) ** +- The LaTeX2e version (`csvsimple-legacy`) will be maintained in its + current state with no intended changes with exceptions of bug fixes. +- The LaTeX3 version (`csvsimple-l3`) is regarded to be the main package + and may receive feature upgrades in the future +- Existing documents using csvsimple v1.22 need no change since loading + `csvsimple` will load `csvsimple-legacy`. +- `cvsimple-l3` is a *nearly* drop-in replacement for `csvsimple-legacy`. + Only very few things phased out and the user interface is quite identical. + The most significant difference is that `l3keys` are used instead of `pgfkeys` + which may need adaptions on user side (for examples, if .styles are used) +- New documents are encouraged to apply `cvsimple-l3` instead of `csvsimple-legacy`. +- For the complete package is valid: do not upgrade from version 1.22, if your + TeX installation has no current LateX3/expl3 support a.k.a *is too old* +- `csvinputline` and `csvrow` are no longer LaTeX2e counters +- The hitherto existing documentation `csvsimple.pdf` is now `csvsimple-legacy.pdf` +- `csvsimple.pdf` documents the stub package and differences + between `csvsimple-l3.sty` and `csvsimple-legacy.sty` +- `column count = 0` means automatic column number detection for CSV files without head +- Option `head` does not change option `check column count` anymore +- Changelog moved from CHANGES to CHANGES.md and adapted to + [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +- From now on version numbers adhere to + [Semantic Versioning](http://semver.org/spec/v2.0.0.html) + +### Deprecated +- `\csviffirstrow` +- `\csvifoddrow` + +### Removed +- `\csvheadset` +- Option `filter` +- Option `nofilter` +- Option `nohead` + + + + +## [1.22] - 2021-06-07 + +### Added +- Option `head to column names prefix` (issue #7) + +### Changed +- Due to changes in the LaTeX kernel 2021-06-01, the empty line + detection of csvsimple had to be adapted. Updating csvsimple is + essential to avoid problems with kernel 2021-06-01. (issue #11) + + + +## [1.21] - 2019-04-09 + +### Changed +- Package `pgfrcs` added as required package +- Introduction augmented with additional hints for first time users (issue #3) + +### Fixed +- Spurious blank in sorting code removed + + + +## [1.20] - 2016-07-01 + +### Added +- New string comparison macros: +- `\ifcsvstrequal` +- `\ifcsvprostrequal` +- `\ifcsvstrcmp` +- `\ifcsvnotstrcmp` +- New filter options: +- Option `filter ifthen` +- Option `filter test` +- Option `filter expr` +- Option `full filter` +- Option `filter strcmp` +- Option `filter not strcmp` + +### Changed +- Implementation changed from `\roman` to `\romannumeral` +- `\write18` replaced by `\ShellEscape` from the shellesc package +- `\csvlinetotablerow` implemented more efficiently +- `\csvloop` made long +- Code optimizations +- Documentation revised + + + +## [1.12] - 2014-07-14 + +### Added +- Option `csvsorter token` +- Documentation extended with siunitx examples + +### Changed +- Success of CSV-Sorter call is checked (Note: Update to CSV-Sorter v0.94 or newer!) +- Encircling column entry braces removed for all entries for better siunitx compatibility +- Documentation revised + +### Fixed +- CSV-Sorter call incompatibilities with the ngerman package (not babel) + + + +## [1.11] - 2014-07-08 + +### Changed +- If a CSV file with an empty first line is found, csvsimple + stops with an error message + +### Fixed +- Sorting preprocessor overwrites the input data in some combinations + + + +## [1.10] - 2014-07-07 + +### Added +- `\csvautobooktabular` +- `\csvautobooklongtable` +- External sorting specifically supported for the CSV-Sorter tool with the new options +- Option `csvsorter command` +- Option `csvsorter configpath` +- Option `csvsorter log` +- Option `sort by` +- Option `new sorting rule` +- New keys for respecting special characters: +- Option `respect tab` +- Option `respect percent` +- Option `respect sharp` +- Option `respect dollar` +- Option `respect and` +- Option `respect backslash` +- Option `respect underscore` +- Option `respect tilde` +- Option `respect circumflex` +- Option `respect leftbrace` +- Option `respect rightbrace` +- Option `respect all` +- Option `respect none` +- Option setting `separator = tab` + +### Changed +- If a CSV file is not found, csvsimple stops with an error message instead of a warning + +### Fixed +- Table head names in curly brackets were not recognized for some cases + + + +## [1.07] - 2013-09-25 + +### Added +- Option `separator` to set the data value separator to + `comma`, `semicolon`, or `pipe` + +### Changed +- Internal macro `\TrimSpaces` renamed to avoid name clashed with `xparse` + + + +## [1.06] - 2012-11-08 + +### Changed +- 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` + + + +## [1.05] - 2012-03-12 + +### Added +- Source code of the documentation added +- Provision of the csvsimple.tds.zip file for easier installation +- Option `preprocessed file` +- Option `preprocessor` +- Option `no preprocessing` + +### Changed +- Documentation language changed from German to English +- Option `nocheckcolumncount` renamed to `no check column count` +- Option `nofilter` renamed to `no check column count` +- Option `nocheckcolumncount` renamed to `no filter` +- Option `nohead` renamed to `no head` + +### Deprecated +- Option `nofilter` +- Option `nohead` + +### Removed +- Option `@table` removed from the documentation + +### Fixed +- Error in `nocheckcolumncount` corrected and key renamed to 'no check column count' + + + +## [1.04] - 2011-11-11 + +### Added +- Option `head to column names` (automatic column names) +- Option `no table` +- Column numbers can now be used for column macro definitions + +### Changed +- Internal behaviour of `before reading` and `after reading` + changed for tables + +### Fixed +- documentation update and correction + + + +## [1.03] - 2011-11-04 + +### Fixed +- Processing error for lines starting with '00' corrected + + + +## [1.02] - 2011-04-04 + +### Added +- `\csvfilteraccept` +- `\csvfilterreject` +- Option `filter accept all` +- Option `filter reject all` + +### Fixed +- Error in the documentation for longtable und tabbing corrected + + + +## [1.01] - 2010-11-10 + +### Added +- Option `after first line` +- Option `late after first line` +- New example for key evaluation in the documentation + +### Changed +- Documentation of some options clarified + + + +## [1.00] - 2010-07-28 + +### Added +- Initial public release diff --git a/macros/latex/contrib/csvsimple/README b/macros/latex/contrib/csvsimple/README deleted file mode 100644 index 58bc68766f..0000000000 --- a/macros/latex/contrib/csvsimple/README +++ /dev/null @@ -1,50 +0,0 @@ -%% The LaTeX package csvsimple - version 1.22 (2021/06/07) -%% -%% ------------------------------------------------------------------------------------------- -%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm -%% ------------------------------------------------------------------------------------------- -%% -%% 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/README.md b/macros/latex/contrib/csvsimple/README.md new file mode 100644 index 0000000000..d0f920dd8c --- /dev/null +++ b/macros/latex/contrib/csvsimple/README.md @@ -0,0 +1,62 @@ +# The LaTeX package csvsimple - version 2.0.0 (2021/06/29) + +> +> Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +> +> 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.md +> + +`csvsimple` provides a simple *LaTeX* interface for the processing of files +with comma separated values (CSV). `csvsimple` relies heavily on a key value +syntax which results 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.md` this file +- `CHANGES.md` log of changes (history) +- `csvsimple.sty` LaTeX package file (style file) +- `csvsimple-l3.sty` LaTeX package file (style file) +- `csvsimple-legacy.sty` LaTeX package file (style file) +- `csvsimple.pdf` Documentation for csvsimple +- `csvsimple-l3.pdf` Documentation for csvsimple (LaTeX3) +- `csvsimple-legacy.pdf` Documentation for csvsimple (Legacy) +- `csvsimple.tex` Source code of the documentation +- `csvsimple-l3.tex` Source code of the documentation +- `csvsimple-legacy.tex` Source code of the documentation +- `csvsimple-doc.sty` Source code of the documentation +- `csvsimple-title.png` Picture for 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 +- `csvsimple-l3.sty` -> /tex/latex/csvsimple +- `csvsimple-legacy.sty` -> /tex/latex/csvsimple +- all other files -> /doc/latex/csvsimple diff --git a/macros/latex/contrib/csvsimple/csvsimple-doc.sty b/macros/latex/contrib/csvsimple/csvsimple-doc.sty new file mode 100644 index 0000000000..6fd611a12c --- /dev/null +++ b/macros/latex/contrib/csvsimple/csvsimple-doc.sty @@ -0,0 +1,106 @@ +% !TeX encoding=UTF-8 +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) +%% csvsimple-doc.sty: style file for the documentation +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +%% ------------------------------------------------------------------------------------------- +%% +%% 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.md +%% +\def\version{2.0.0}% +\def\datum{2021/06/29}% + +\IfFileExists{csvsimple-doc.cfg}{\input{csvsimple-doc.cfg}}{}\providecommand\csvpkgprefix{} + +\RequirePackage[T1]{fontenc} +\RequirePackage[utf8]{inputenc} +\RequirePackage[english]{babel} +\RequirePackage{lmodern,parskip,array,ifthen,calc,makeidx} +\RequirePackage{amsmath,amssymb} +\RequirePackage[svgnames,table,hyperref]{xcolor} +\RequirePackage{tikz,siunitx,xfp} +\RequirePackage{varioref} +\RequirePackage[pdftex,bookmarks,raiselinks,pageanchor,hyperindex,colorlinks]{hyperref} +\urlstyle{sf} +\RequirePackage{cleveref} + +\RequirePackage[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} +\RequirePackage{fancyhdr} +\fancyhf{} +\fancyfoot[C]{\thepage}% +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{0pt} +\pagestyle{fancy} +\tolerance=2000% +\setlength{\emergencystretch}{20pt}% + +\RequirePackage{longtable,booktabs,ifthen,etoolbox} + +\RequirePackage{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, + fontlower=\footnotesize, + colframe=green!25!yellow!50!black, + colback=green!25!yellow!7, + colbacklower=white, + 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} + +\NewDocumentCommand{\csvsorter}{}{\textsf{\bfseries\color{red!20!black}CSV-Sorter}} + +\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,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{"}} + + +\makeindex + +\pdfsuppresswarningpagegroup=1 diff --git a/macros/latex/contrib/csvsimple/csvsimple-example.pdf b/macros/latex/contrib/csvsimple/csvsimple-example.pdf index b6c4967de6..79a66bb9a2 100644 Binary files a/macros/latex/contrib/csvsimple/csvsimple-example.pdf and b/macros/latex/contrib/csvsimple/csvsimple-example.pdf differ diff --git a/macros/latex/contrib/csvsimple/csvsimple-example.tex b/macros/latex/contrib/csvsimple/csvsimple-example.tex index 030ad63878..4f8a80dcfd 100644 --- a/macros/latex/contrib/csvsimple/csvsimple-example.tex +++ b/macros/latex/contrib/csvsimple/csvsimple-example.tex @@ -1,4 +1,4 @@ -%% The LaTeX package csvsimple - version 1.22 (2021/06/07) +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) %% csvsimple-example.tex: an example for csvsimple %% %% ------------------------------------------------------------------------------------------- @@ -15,11 +15,15 @@ %% %% This work has the LPPL maintenance status `author-maintained'. %% -%% This work consists of all files listed in README +%% This work consists of all files listed in README.md %% \documentclass{article} -\usepackage{array,booktabs} -\usepackage{csvsimple} +\usepackage{ifthen,array,booktabs} + +\IfFileExists{csvsimple-doc.cfg}{\input{csvsimple-doc.cfg}}{}% ignore this line +\providecommand\csvpkgprefix{} % ignore this line + +\usepackage{\csvpkgprefix csvsimple-l3}% \usepackage{csvsimple-l3} \begin{document} @@ -65,7 +69,7 @@ %---------------------------------------------------------- \section{More filter fun} -\csvreader[my names, filter=\birthyear<1980, centered tabular=rllr, +\csvreader[my names, filter ifthen=\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]% diff --git a/macros/latex/contrib/csvsimple/csvsimple-l3.pdf b/macros/latex/contrib/csvsimple/csvsimple-l3.pdf new file mode 100644 index 0000000000..a25286a842 Binary files /dev/null and b/macros/latex/contrib/csvsimple/csvsimple-l3.pdf differ diff --git a/macros/latex/contrib/csvsimple/csvsimple-l3.sty b/macros/latex/contrib/csvsimple/csvsimple-l3.sty new file mode 100644 index 0000000000..da7e62f47d --- /dev/null +++ b/macros/latex/contrib/csvsimple/csvsimple-l3.sty @@ -0,0 +1,1260 @@ +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) +%% csvsimple-l3.sty: Simple LaTeX CSV file processing (LaTeX3) +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +%% ------------------------------------------------------------------------------------------- +%% +%% 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.md +%% +\ProvidesExplPackage{csvsimple-l3}{2021/06/29}{2.0.0} + {LaTeX3 CSV file processing} + + + +%---- check package + +\cs_if_exist:NT \c__csvsim_package_expl_bool + { + \msg_new:nnn { csvsimple }{ l3 / package-loaded } + { Package~'csvsimple-legacy'~seems~already~be~loaded!~ + 'csvsimple-l3'~cannot~be~loaded~simultaneously.~ + Therefore,~loading~of~'csvsimple-l3'~stops~now.} + \msg_warning:nn { csvsimple }{ l3 / package-loaded } + \tex_endinput:D + } +\bool_const:Nn \c__csvsim_package_expl_bool { 1 } + + + +%---- declarations and expl3 variants + +\bool_new:N \g__csvsim_check_column_count_bool +\bool_new:N \g__csvsim_firstline_bool +\bool_new:N \g__csvsim_head_bool +\bool_new:N \g__csvsim_head_to_colnames_bool +\bool_new:N \g__csvsim_line_accepted_bool +\bool_new:N \l__csvsim_respect_and_bool +\bool_new:N \l__csvsim_respect_backslash_bool +\bool_new:N \l__csvsim_respect_circumflex_bool +\bool_new:N \l__csvsim_respect_dollar_bool +\bool_new:N \l__csvsim_respect_leftbrace_bool +\bool_new:N \l__csvsim_respect_percent_bool +\bool_new:N \l__csvsim_respect_rightbrace_bool +\bool_new:N \l__csvsim_respect_sharp_bool +\bool_new:N \l__csvsim_respect_tab_bool +\bool_new:N \l__csvsim_respect_tilde_bool +\bool_new:N \l__csvsim_respect_underscore_bool + +\int_new:N \g__csvsim_col_int +\int_new:N \g__csvsim_colmax_int +\int_new:N \g_csvsim_inputline_int +\int_new:N \g_csvsim_row_int +\int_new:N \g_csvsim_columncount_int + +\seq_new:N \g__csvsim_colname_seq +\seq_new:N \g__csvsim_line_seq +\seq_new:N \g__csvsim_range_seq + +\str_new:N \g__csvsim_curfilename_str +\str_new:N \g__csvsim_filename_str +\str_new:N \l__csvsim_csvsorter_command_str +\str_new:N \l__csvsim_csvsorter_configpath_str +\str_new:N \l__csvsim_csvsorter_log_str +\str_new:N \l__csvsim_csvsorter_token_str +\str_new:N \l__csvsim_ppfilename_str +\str_new:N \l__csvsim_temp_filename_str + +\tl_const:Nn \c__csvsim_par_tl { \par } + +\tl_new:N \g__csvsim_after_table_tl +\tl_new:N \g__csvsim_before_table_tl +\tl_new:N \g__csvsim_body_tl +\tl_new:N \g__csvsim_catcode_tl + +\tl_new:N \g__csvsim_columnnames_tl +\tl_new:N \g__csvsim_filter_tl +\tl_new:N \g__csvsim_headname_prefix_tl +\tl_new:N \g__csvsim_hook_after_first_line_tl +\tl_new:N \g__csvsim_hook_after_head_tl +\tl_new:N \g__csvsim_hook_after_line_tl +\tl_new:N \g__csvsim_hook_after_reading_tl +\tl_new:N \g__csvsim_hook_before_filter_tl +\tl_new:N \g__csvsim_hook_before_first_line_tl +\tl_new:N \g__csvsim_hook_before_line_tl +\tl_new:N \g__csvsim_hook_before_reading_tl +\tl_new:N \g__csvsim_hook_columncounterror_tl +\tl_new:N \g__csvsim_hook_late_after_first_line_tl +\tl_new:N \g__csvsim_hook_late_after_head_tl +\tl_new:N \g__csvsim_hook_late_after_last_line_tl +\tl_new:N \g__csvsim_hook_late_after_line_tl +\tl_new:N \g__csvsim_hook_table_begin_tl +\tl_new:N \g__csvsim_hook_table_end_tl +\tl_new:N \g__csvsim_preprocessor_tl +\tl_new:N \g__csvsim_separator_tl +\tl_new:N \g__csvsim_table_foot_tl +\tl_new:N \g__csvsim_table_head_tl + +\group_begin: + \char_set_catcode_other:n { 9 } + \str_const:Nn \c__csvsim_tab_str { ^^I } +\group_end: + +\regex_const:Nn \c__csvsim_integer_regex {\A\d+\Z} + +\cs_generate_variant:Nn \seq_gset_split:Nnn { NVV } + + +%---- messages + +\msg_new:nnnn { csvsimple }{ column-name } + { Unknown~column~key~'#1'. } + { The~key~'#1'~you~used~in~'column~names'~is~unknown.\\ + Therefore,~the~macro~#2 is~not~defined. + } + +\msg_new:nnn { csvsimple }{ empty-head } + { File~'#1'~starts~with~an~empty~line~(empty~head)!.} + +\msg_new:nnn { csvsimple }{ file-error } + { File~'#1'~not~existent,~not~readable,~or~empty!} + +\msg_new:nnn { csvsimple }{ column-wrong-count } + { #1~instead~of~#2~columns~for~input~line~#3~of~file~'#4'} + +\msg_new:nnn { csvsimple }{ sort-info } + { Sort~'#1'~by~'#2' } + +\msg_new:nnn { csvsimple }{ sort-shell-escape } + { You~need~to~use~'-shell-escape'~to~run~CSV-Sorter } + +\msg_new:nnnn { csvsimple }{ sort-error } + { Call~of~CSV-Sorter~failed! } + { See~log~file~'\l__csvsim_csvsorter_log_str'. } + + + +%---- core loop processing + +\cs_new_protected_nopar:Npn \__csvsim_read_line: + { + \group_begin: + \g__csvsim_catcode_tl + \ior_get:NNTF \g__csvsim_ior \l_tmpa_tl + { + \tl_gset_eq:NN \csvline \l_tmpa_tl + \int_gincr:N \g_csvsim_inputline_int + } + { + \msg_error:nnx { csvsimple }{ file-error }{ \g__csvsim_curfilename_str } + } + \group_end: + } + + +\cs_new_protected_nopar:Npn \__csvsim_scan_line: + { + \int_gzero:N \g__csvsim_col_int + \seq_gset_split:NVV \g__csvsim_line_seq \g__csvsim_separator_tl \csvline + \seq_map_inline:Nn \g__csvsim_line_seq + { + \int_gincr:N \g__csvsim_col_int + \tl_gset:cn {csvcol \int_to_roman:n \g__csvsim_col_int}{##1} + } + \int_compare:nNnT \g__csvsim_colmax_int < \g__csvsim_col_int + { + \int_gset_eq:NN \g__csvsim_colmax_int \g__csvsim_col_int + } + \int_compare:nNnT \g_csvsim_columncount_int < \c_one_int + { + \int_gset_eq:NN \g_csvsim_columncount_int \g__csvsim_col_int + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_process_head_name:n #1 + { + \tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{#1} \cs_end:} + \exp_args:NnV \cs_set_nopar:cpn {__csvsim__/\l_tmpa_tl} \l_tmpa_tl + + \bool_if:NT \g__csvsim_head_to_colnames_bool + { + \tl_set:No \l_tmpb_tl {\cs:w \g__csvsim_headname_prefix_tl \l_tmpa_tl \cs_end:} + \tl_put_right:NV \l_tmpb_tl \l_tmpa_tl + \exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpb_tl + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_read_head: + { + \__csvsim_read_line: + \tl_if_eq:NNTF \csvline \c__csvsim_par_tl + { + \msg_error:nnx { csvsimple }{ empty-head }{ \g__csvsim_filename_str } + } + { + \int_zero:N \g_csvsim_columncount_int + \__csvsim_scan_line: + \int_step_function:nN \g_csvsim_columncount_int \__csvsim_process_head_name:n + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_process_colname:nn #1#2 + { + \cs_if_exist:cTF {__csvsim__/#1} + { + \tl_set:Nv \l_tmpa_tl {__csvsim__/#1} + \tl_put_left:Nn \l_tmpa_tl {#2} + \exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpa_tl + } + { + \regex_match:NnTF \c__csvsim_integer_regex {#1} + { + \tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{#1} \cs_end:} + \tl_put_left:Nn \l_tmpa_tl {#2} + \exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpa_tl + } + { + \str_set:Nn \l_tmpb_str {#2} + \msg_error:nnxx { csvsimple }{ column-name }{ #1 }{ \l_tmpb_str } + } + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_set_colnames: + { + \seq_map_inline:Nn \g__csvsim_colname_seq + { + \tl_gset_eq:NN ##1 + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_loop: + { + % preprocess + \tl_if_empty:NTF \l__csvsim_preprocessor_tl + { + \str_gset_eq:NN \g__csvsim_curfilename_str \g__csvsim_filename_str + } + { + \l__csvsim_preprocessor_tl \g__csvsim_filename_str \l__csvsim_ppfilename_str + \str_gset_eq:NN \g__csvsim_curfilename_str \l__csvsim_ppfilename_str + } + + % initialize + \cs_if_exist:NF \g__csvsim_ior + { + \ior_new:N \g__csvsim_ior + } + \__csvsim_setup_catcode_list: + \seq_gclear:N \g__csvsim_colname_seq + \int_gzero:N \g_csvsim_inputline_int + \int_gzero:N \g_csvsim_row_int + \int_gset_eq:NN \g__csvsim_colmax_int \c_one_int + + % open file + \g__csvsim_hook_before_reading_tl + \g__csvsim_hook_table_begin_tl + \ior_open:Nn \g__csvsim_ior { \g__csvsim_curfilename_str } + + % read head line + \bool_if:NT \g__csvsim_head_bool + { + \__csvsim_read_head: + } + \exp_args:NNNV \keyval_parse:NNn \use_none:n + \__csvsim_process_colname:nn \g__csvsim_columnnames_tl + \bool_if:NT \g__csvsim_head_bool + { + \g__csvsim_hook_after_head_tl + } + + % read body lines + \bool_gset_true:N \g__csvsim_line_firstline_bool + \bool_until_do:nn {\ior_if_eof_p:N \g__csvsim_ior} + { + \__csvsim_read_line: + \tl_if_eq:NNF \csvline \c__csvsim_par_tl + { + \bool_gset_true:N \g__csvsim_line_accepted_bool + \__csvsim_scan_line: + \__csvsim_set_colnames: + \bool_if:NT \g__csvsim_check_column_count_bool + { + \int_compare:nNnF \g__csvsim_col_int = \g_csvsim_columncount_int + { + \bool_gset_false:N \g__csvsim_line_accepted_bool + \g__csvsim_hook_columncounterror_tl + } + } + \bool_if:NT \g__csvsim_line_accepted_bool + { + \g__csvsim_hook_before_filter_tl + \g__csvsim_filter_tl + \bool_if:NT \g__csvsim_line_accepted_bool + { + \int_gincr:N \g_csvsim_row_int + \__csvsim_check_range: + \bool_if:NT \g__csvsim_line_accepted_bool + { + \bool_if:NTF \g__csvsim_line_firstline_bool + { + \bool_if:NT \g__csvsim_head_bool + { + \g__csvsim_hook_late_after_head_tl + } + \g__csvsim_hook_before_first_line_tl + \g__csvsim_body_tl + \g__csvsim_hook_after_first_line_tl + \bool_gset_false:N \g__csvsim_line_firstline_bool + } + { + \g__csvsim_hook_late_after_line_tl + \g__csvsim_hook_before_line_tl + \g__csvsim_body_tl + \g__csvsim_hook_after_line_tl + } + } + } + } + } + } + + % close file + \ior_close:N \g__csvsim_ior + + % clear macros + \int_step_inline:nn \g__csvsim_colmax_int + { + \tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{##1} \cs_end:} + \use:x + { + \exp_not:N\tl_gclear:N \exp_not:V\l_tmpa_tl + } + } + \__csvsim_set_colnames: + \seq_gclear:N \g__csvsim_colname_seq + \bool_if:NF \g__csvsim_line_firstline_bool + { + \g__csvsim_hook_late_after_last_line_tl + } + \g__csvsim_hook_table_end_tl + \g__csvsim_hook_after_reading_tl + } + + +\NewDocumentCommand \csvloop { +m } + { + \keys_set:nn { csvsim } { default, every~csv, #1} + \__csvsim_loop: + } + + +\NewDocumentCommand \csvreader { +O{} m m +m } + { + \keys_set:nn { csvsim } { default, every~csv, #1, file={#2}, column~names={#3} } + \tl_gset:Nn \g__csvsim_body_tl {#4} + \__csvsim_loop: + } + + + +%---- auxiliary user macros + +\NewDocumentCommand \csvlinetotablerow { } + { + \tl_clear:N \l_tmpa_tl + \bool_set_false:N \l_tmpa_bool + \seq_map_inline:Nn \g__csvsim_line_seq + { + \bool_if:NTF \l_tmpa_bool + { + \tl_put_right:Nn \l_tmpa_tl { & ##1 } + } + { + \tl_put_right:Nn \l_tmpa_tl { ##1 } + \bool_set_true:N \l_tmpa_bool + } + } + \l_tmpa_tl + } + + +\NewExpandableDocumentCommand \thecsvrow { } + { + \int_use:N \g_csvsim_row_int + } + + +\NewExpandableDocumentCommand \thecsvcolumncount { } + { + \int_use:N \g_csvsim_columncount_int + } + + +\NewExpandableDocumentCommand \thecsvinputline { } + { + \int_use:N \g_csvsim_inputline_int + } + + +\NewExpandableDocumentCommand \ifcsvfirstrow { } + { + \bool_if:NTF \g__csvsim_firstline_bool + } + +% deprecated +\NewExpandableDocumentCommand \csviffirstrow { } + { + \bool_if:NTF \g__csvsim_firstline_bool + } + + +\NewExpandableDocumentCommand \ifcsvoddrow { } + { + \int_if_odd:nTF {\g_csvsim_row_int} + } + +% deprecated +\NewExpandableDocumentCommand \csvifoddrow { } + { + \int_if_odd:nTF {\g_csvsim_row_int} + } + + +\NewExpandableDocumentCommand \ifcsvstrcmp { m m } + { + \str_compare:eNeTF {#1} = {#2} + } + + +\NewExpandableDocumentCommand \ifcsvnotstrcmp { m m +m +m } + { + \ifcsvstrcmp{#1}{#2}{#4}{#3} + } + + +\NewDocumentCommand \ifcsvstrequal { m m } + { + \tl_set:Nx \l_tmpa_tl {#1} + \tl_set:Nx \l_tmpb_tl {#2} + \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl + } + + +\NewDocumentCommand \ifcsvprostrequal { m m } + { + \protected@edef \l_tmpa_tl {#1} + \protected@edef \l_tmpb_tl {#2} + \tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl + } + + +\NewExpandableDocumentCommand \ifcsvfpcmp { m } + { + \fp_compare:nTF {#1} + } + + +\NewExpandableDocumentCommand \ifcsvintcmp { m } + { + \int_compare:nTF {#1} + } + + +%---- filename functions + +\cs_new_protected_nopar:Npn \__csvsim_set_temp_filename:nnn #1#2#3 + { + \str_set:Nn \l__csvsim_temp_filename_str {#2#3} + \str_if_empty:NTF \l__csvsim_temp_filename_str + { + \str_set:Nn \l__csvsim_temp_filename_str {#1} + } + { + \str_set:Nn \l_tmpa_str {#1} + \str_if_empty:NF \l_tmpa_str + { + \str_compare:eNeF { \str_item:Nn \l_tmpa_str {-1} } = { / } + { + \str_put_right:Nn \l_tmpa_str {/} + } + \str_concat:NNN \l__csvsim_temp_filename_str + \l_tmpa_str \l__csvsim_temp_filename_str + } + } + } + + +\cs_new_protected_nopar:Npn \__csvsim_set_temp_filename:n #1 + { + \file_parse_full_name_apply:nN { #1 } \__csvsim_set_temp_filename:nnn + } + + +\cs_new_protected_nopar:Npn \__csvsim_set_filename:Nn #1#2 + { + \__csvsim_set_temp_filename:n { #2 } + \str_set_eq:NN #1 \l__csvsim_temp_filename_str + } + + +\cs_new_protected_nopar:Npn \__csvsim_gset_filename:Nn #1#2 + { + \__csvsim_set_temp_filename:n { #2 } + \str_gset_eq:NN #1 \l__csvsim_temp_filename_str + } + + + +%---- keys + +\NewDocumentCommand \csvset { +m } + { + \keys_set:nn { csvsim } { #1 } + } + + +\NewDocumentCommand \csvstyle { m +m } + { + \keys_define:nn { csvsim } + { + #1 .meta:n = { #2 } + } + } + + +\NewDocumentCommand \csvnames { m m } + { + \keys_define:nn { csvsim } + { + #1 .meta:n = { column~names={#2} } + } + } + + +\keys_define:nn { csvsim } + { + file .code:n = \__csvsim_gset_filename:Nn \g__csvsim_filename_str {#1}, + column~names~reset .code:n = \tl_gclear:N \g__csvsim_columnnames_tl, + column~names .code:n = + { + \tl_if_empty:NTF \g__csvsim_columnnames_tl + { + \tl_gset:Nn \g__csvsim_columnnames_tl {#1} + } + { + \tl_gput_right:Nn \g__csvsim_columnnames_tl {,#1} + } + }, + command .tl_gset:N = \g__csvsim_body_tl, + check~column~count .bool_gset:N = \g__csvsim_check_column_count_bool, + on~column~count~error .tl_gset:N = \g__csvsim_hook_columncounterror_tl, + head .bool_gset:N = \g__csvsim_head_bool, + head~to~column~names~prefix .tl_gset:N = \g__csvsim_headname_prefix_tl, + head~to~column~names .bool_gset:N = \g__csvsim_head_to_colnames_bool, + column~count .int_gset:N = \g_csvsim_columncount_int, + separator .choice:, + separator/comma .code:n = + { + \tl_gset:Nn \g__csvsim_separator_tl {,} + }, + separator/semicolon .code:n = + { + \tl_gset:Nn \g__csvsim_separator_tl {;} + }, + separator/pipe .code:n = + { + \tl_gset:Nn \g__csvsim_separator_tl {|} + }, + separator/tab .code:n = + { + \tl_gset:NV \g__csvsim_separator_tl \c__csvsim_tab_str + \csvset{respect~tab} + }, + every~csv .meta:n = {}, + no~head .meta:n = { head=false }, + no~check~column~count .meta:n = { check~column~count=false }, + warn~on~column~count~error .meta:n = { on~column~count~error= + { + \msg_warning:nnxxxx { csvsimple }{ column-wrong-count } + { \int_use:N\g__csvsim_col_int } + { \int_use:N\g_csvsim_columncount_int } + { \int_use:N\g_csvsim_inputline_int } + { \g__csvsim_filename_str } + }}, + } + + +%---- hooks + +\keys_define:nn { csvsim } + { + before~reading .tl_gset:N = \g__csvsim_hook_before_reading_tl, + after~head .tl_gset:N = \g__csvsim_hook_after_head_tl, + before~filter .tl_gset:N = \g__csvsim_hook_before_filter_tl, + late~after~head .tl_gset:N = \g__csvsim_hook_late_after_head_tl, + late~after~first~line .tl_gset:N = \g__csvsim_hook_late_after_first_line_tl, + late~after~last~line .tl_gset:N = \g__csvsim_hook_late_after_last_line_tl, + before~first~line .tl_gset:N = \g__csvsim_hook_before_first_line_tl, + after~first~line .tl_gset:N = \g__csvsim_hook_after_first_line_tl, + after~reading .tl_gset:N = \g__csvsim_hook_after_reading_tl, + late~after~line .code:n = + { + \tl_gset:Nn \g__csvsim_hook_late_after_line_tl {#1} + \tl_gset_eq:NN \g__csvsim_hook_late_after_first_line_tl \g__csvsim_hook_late_after_line_tl + \tl_gset_eq:NN \g__csvsim_hook_late_after_last_line_tl \g__csvsim_hook_late_after_line_tl + }, + before~line .code:n = + { + \tl_gset:Nn \g__csvsim_hook_before_line_tl {#1} + \tl_gset_eq:NN \g__csvsim_hook_before_first_line_tl \g__csvsim_hook_before_line_tl + }, + after~line .code:n = + { + \tl_gset:Nn \g__csvsim_hook_after_line_tl {#1} + \tl_gset_eq:NN \g__csvsim_hook_after_first_line_tl \g__csvsim_hook_after_line_tl + }, + } + + +%---- filter + +\cs_new_protected_nopar:Npn \__csvsim_set_filter:n #1 + { + \tl_gset:Nn \g__csvsim_filter_tl + { + #1 + } + } + + +\NewDocumentCommand \csvfilteraccept { } + { + \__csvsim_set_filter:n + { + \bool_gset_true:N \g__csvsim_line_accepted_bool + } + } + + +\NewDocumentCommand \csvfilterreject { } + { + \__csvsim_set_filter:n + { + \bool_gset_false:N \g__csvsim_line_accepted_bool + } + } + + +\keys_define:nn { csvsim } + { + no~filter .code:n = + { + \csvfilteraccept + }, + filter~reject~all .code:n = + { + \csvfilterreject + }, + filter~accept~all .code:n = + { + \csvfilteraccept + }, + full~filter. tl_gset:N = \g__csvsim_hook_before_filter_tl, + filter~test .code:n = + { + \__csvsim_set_filter:n + { + #1 + { \bool_gset_true:N \g__csvsim_line_accepted_bool } + { \bool_gset_false:N \g__csvsim_line_accepted_bool } + } + }, + filter~bool .code:n = + { + \__csvsim_set_filter:n + { + \bool_gset:Nn \g__csvsim_line_accepted_bool { #1 } + } + }, + filter~fp .code:n = + { + \__csvsim_set_filter:n + { + \bool_gset:Nn \g__csvsim_line_accepted_bool { \fp_compare_p:n{#1} } + } + }, + filter~strcmp .meta:n = { filter~test=\ifcsvstrcmp #1 }, + filter~not~strcmp .meta:n = { filter~test=\ifcsvnotstrcmp #1 }, + } + + +\NewDocumentCommand \csvfilterbool { m m } + { + \keys_define:nn { csvsim } + { + #1 .meta:n = { filter~bool={#2} } + } + } + + +% ifthen +\keys_define:nn { csvsim } + { + filter~ifthen .code:n = + { + \__csvsim_set_filter:n + { + \ifthenelse{#1} + { \bool_gset_true:N \g__csvsim_line_accepted_bool } + { \bool_gset_false:N \g__csvsim_line_accepted_bool } + } + }, + filter~equal .meta:n = { filter~ifthen=\equal #1 }, + filter~not~equal .meta:n = { filter~ifthen=\not\equal #1 }, + } + + +% etoolbox +\keys_define:nn { csvsim } + { + filter~expr .code:n = + { + \__csvsim_set_filter:n + { + \ifboolexpr{#1} + { \bool_gset_true:N \g__csvsim_line_accepted_bool } + { \bool_gset_false:N \g__csvsim_line_accepted_bool } + } + }, + } + + + +%---- range + + +\cs_new_protected_nopar:Npn \__csvsim_add_range:n #1 + { + \tl_if_in:nnTF {#1}{-} + { + \seq_set_split:Nnn \l_tmpa_seq {-} {#1} + \seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl + \tl_if_empty:NTF \l_tmpa_tl + { + \int_set_eq:NN \l_tmpa_int \c_one_int + } + { + \int_set:Nn \l_tmpa_int { \l_tmpa_tl } + } + \tl_if_empty:NTF \l_tmpb_tl + { + \int_set_eq:NN \l_tmpb_int \c_max_int + } + { + \int_set:Nn \l_tmpb_int { \l_tmpb_tl } + } + } + { + \tl_if_in:nnTF {#1}{+} + { + \seq_set_split:Nnn \l_tmpa_seq {+} {#1} + \seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl + \tl_if_empty:NTF \l_tmpa_tl + { + \int_set:Nn \l_tmpa_int { 1 } + } + { + \int_set:Nn \l_tmpa_int { \l_tmpa_tl } + } + \tl_if_empty:NTF \l_tmpb_tl + { + \int_set_eq:NN \l_tmpb_int \l_tmpa_int + } + { + \int_set:Nn \l_tmpb_int { \l_tmpa_int + \l_tmpb_tl - 1 } + } + } + { + \int_set:Nn \l_tmpa_int {#1} + \int_set_eq:NN \l_tmpb_int \l_tmpa_int + } + } + \seq_gput_right:Nx \g__csvsim_range_seq {{\int_use:N \l_tmpa_int}{\int_use:N \l_tmpb_int}} + } + + +\cs_new_protected_nopar:Npn \__csvsim_set_range:n #1 + { + \seq_gclear:N \g__csvsim_range_seq + \keyval_parse:NNn + \__csvsim_add_range:n + \use_none:nn + { #1 } + } + + +\keys_define:nn { csvsim } + { + range .code:n = + { + \__csvsim_set_range:n {#1} + }, + } + + +\prg_new_conditional:Npnn \__csvsim_if_in_range:nn #1#2 { p , T } + { + \if_int_compare:w #1 > \g_csvsim_row_int + \prg_return_false: + \else: + \if_int_compare:w #2 < \g_csvsim_row_int + \prg_return_false: + \else: + \prg_return_true: + \fi: + \fi: + } + + +\cs_new_protected_nopar:Npn \__csvsim_check_range: + { + \seq_if_empty:NF \g__csvsim_range_seq + { + \bool_gset_false:N \g__csvsim_line_accepted_bool + \seq_map_inline:Nn \g__csvsim_range_seq + { + \__csvsim_if_in_range:nnT ##1 + { + \bool_gset_true:N \g__csvsim_line_accepted_bool + \seq_map_break: + } + } + } + } + + + +%---- catcodes + +\cs_new_protected_nopar:Npn \__csvsim_setup_catcode_list: + { + \tl_gclear:N \g__csvsim_catcode_tl + \bool_if:NT \l__csvsim_respect_tab_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 9 } } + } + \bool_if:NT \l__csvsim_respect_percent_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 37 } } + } + \bool_if:NT \l__csvsim_respect_sharp_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 35 } } + } + \bool_if:NT \l__csvsim_respect_dollar_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 36 } } + } + \bool_if:NT \l__csvsim_respect_and_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 38 } } + } + \bool_if:NT \l__csvsim_respect_backslash_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 92 } } + } + \bool_if:NT \l__csvsim_respect_underscore_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 95 } } + } + \bool_if:NT \l__csvsim_respect_tilde_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 126 } } + } + \bool_if:NT \l__csvsim_respect_circumflex_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 94 } } + } + \bool_if:NT \l__csvsim_respect_leftbrace_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 123 } } + } + \bool_if:NT \l__csvsim_respect_rightbrace_bool + { + \tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 125 } } + } + } + + +\keys_define:nn { csvsim } + { + respect~tab .bool_set:N = \l__csvsim_respect_tab_bool, + respect~percent .bool_set:N = \l__csvsim_respect_percent_bool, + respect~sharp .bool_set:N = \l__csvsim_respect_sharp_bool, + respect~dollar .bool_set:N = \l__csvsim_respect_dollar_bool, + respect~and .bool_set:N = \l__csvsim_respect_and_bool, + respect~backslash .bool_set:N = \l__csvsim_respect_backslash_bool, + respect~underscore .bool_set:N = \l__csvsim_respect_underscore_bool, + respect~tilde .bool_set:N = \l__csvsim_respect_tilde_bool, + respect~circumflex .bool_set:N = \l__csvsim_respect_circumflex_bool, + respect~leftbrace .bool_set:N = \l__csvsim_respect_leftbrace_bool, + respect~rightbrace .bool_set:N = \l__csvsim_respect_rightbrace_bool, + respect~all .meta:n = + { + respect~tab, respect~percent, respect~sharp, respect~dollar, + respect~and, respect~backslash, respect~underscore, respect~tilde, + respect~circumflex, respect~leftbrace, respect~rightbrace + }, + respect~none .meta:n = + { + 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 + }, + } + + + +%---- tables + +\cs_new_protected_nopar:Npn \__csvsim_key_table:nn #1#2 + { + \tl_gset:Nn \g__csvsim_hook_table_begin_tl {#1} + \tl_gset:Nn \g__csvsim_hook_table_end_tl {#2} + } + + +\keys_define:nn { csvsim } + { + before~table .tl_gset:N = \g__csvsim_before_table_tl, + after~table .tl_gset:N = \g__csvsim_after_table_tl, + table~head .tl_gset:N = \g__csvsim_table_head_tl, + table~foot .tl_gset:N = \g__csvsim_table_foot_tl, + _table_ .code:n = \__csvsim_key_table:nn #1, + no~table .meta:n = { _table_={}{} }, + tabular .meta:n = + { + _table_ = { \g__csvsim_before_table_tl\begin{tabular}{#1}\g__csvsim_table_head_tl } + { \g__csvsim_table_foot_tl\end{tabular}\g__csvsim_after_table_tl }, + late~after~line = \\ + }, + centered~tabular .meta:n = + { + _table_ = { \begin{center}\g__csvsim_before_table_tl\begin{tabular}{#1}\g__csvsim_table_head_tl } + { \g__csvsim_table_foot_tl\end{tabular}\g__csvsim_after_table_tl\end{center} }, + late~after~line = \\ + }, + longtable .meta:n = + { + _table_ = { \g__csvsim_before_table_tl\begin{longtable}{#1}\g__csvsim_table_head_tl } + { \g__csvsim_table_foot_tl\end{longtable}\g__csvsim_after_table_tl }, + late~after~line = \\ + }, + tabbing .meta:n = + { + _table_ = { \g__csvsim_before_table_tl\begin{tabbing}\g__csvsim_table_head_tl } + { \g__csvsim_table_foot_tl\end{tabbing}\g__csvsim_after_table_tl }, + late~after~line = \\, + late~after~last~line = + }, + centered~tabbing .meta:n = + { + _table_ = { \begin{center}\g__csvsim_before_table_tl\begin{tabbing}\g__csvsim_table_head_tl } + { \g__csvsim_table_foot_tl\end{tabbing}\g__csvsim_after_table_tl\end{center} }, + late~after~line = \\, + late~after~last~line = + }, + _autotab_ .meta:n = + { + file = #1, + late~after~line = \\, + command = \csvlinetotablerow + }, + _autotabular_ .meta:n = + { + _autotab_ = #1, + late~after~last~line = \g__csvsim_table_foot_tl + \end{tabular} + \g__csvsim_after_table_tl, + }, + autotabular .meta:n = + { + _autotabular_ = #1, + head, + after~head = \g__csvsim_before_table_tl + \begin{tabular}{|*{\int_use:N\g__csvsim_col_int}{l|}} + \g__csvsim_table_head_tl, + table~head = \hline\csvlinetotablerow\\\hline, + table~foot = \\\hline, + }, + autotabular* .meta:n = + { + _autotabular_ = #1, + no~head, + before~first~line = \g__csvsim_before_table_tl + \begin{tabular}{|*{\int_use:N\g__csvsim_col_int}{l|}} + \g__csvsim_table_head_tl, + table~head = \hline, + table~foot = \\\hline, + }, + autobooktabular .meta:n = + { + _autotabular_ = #1, + head, + after~head = \g__csvsim_before_table_tl + \begin{tabular}{*{\int_use:N\g__csvsim_col_int}{l}} + \g__csvsim_table_head_tl, + table~head = \toprule\csvlinetotablerow\\\midrule, + table~foot = \\\bottomrule, + }, + autobooktabular* .meta:n = + { + _autotabular_ = #1, + no~head, + before~first~line = \g__csvsim_before_table_tl + \begin{tabular}{*{\int_use:N\g__csvsim_col_int}{l}} + \g__csvsim_table_head_tl, + table~head = \toprule, + table~foot = \\\bottomrule, + }, + _autolongtable_ .meta:n = + { + _autotab_ = #1, + late~after~last~line = \end{longtable} + \g__csvsim_after_table_tl, + }, + autolongtable .meta:n = + { + _autolongtable_ = #1, + head, + after~head = \g__csvsim_before_table_tl + \begin{longtable}{|*{\int_use:N\g__csvsim_col_int}{l|}} + \g__csvsim_table_head_tl, + table~head = \hline\csvlinetotablerow\\\hline\endhead + \hline\endfoot, + }, + autolongtable* .meta:n = + { + _autolongtable_ = #1, + no~head, + before~first~line = \g__csvsim_before_table_tl + \begin{longtable}{|*{\int_use:N\g__csvsim_col_int}{l|}} + \g__csvsim_table_head_tl, + table~head = \hline\endhead + \hline\endfoot, + }, + autobooklongtable .meta:n = + { + _autolongtable_ = #1, + head, + after~head = \g__csvsim_before_table_tl + \begin{longtable}{*{\int_use:N\g__csvsim_col_int}{l}} + \g__csvsim_table_head_tl, + table~head = \toprule\csvlinetotablerow\\\midrule\endhead + \bottomrule\endfoot, + }, + autobooklongtable* .meta:n = + { + _autolongtable_ = #1, + no~head, + before~first~line = \g__csvsim_before_table_tl + \begin{longtable}{*{\int_use:N\g__csvsim_col_int}{l}} + \g__csvsim_table_head_tl, + table~head = \toprule\endhead + \bottomrule\endfoot, + }, + } + + +\NewDocumentCommand \csvautotabular { s +O{} m } + { + \IfBooleanTF {#1} + { + \keys_set:nn { csvsim } { default, every~csv, autotabular*={#3}, #2} + } + { + \keys_set:nn { csvsim } { default, every~csv, autotabular={#3}, #2} + } + \__csvsim_loop: + } + + +\NewDocumentCommand \csvautolongtable { s +O{} m } + { + \IfBooleanTF {#1} + { + \keys_set:nn { csvsim } { default, every~csv, autolongtable*={#3}, #2} + } + { + \keys_set:nn { csvsim } { default, every~csv, autolongtable={#3}, #2} + } + \__csvsim_loop: + } + + +\NewDocumentCommand \csvautobooktabular { s +O{} m } + { + \IfBooleanTF {#1} + { + \keys_set:nn { csvsim } { default, every~csv, autobooktabular*={#3}, #2} + } + { + \keys_set:nn { csvsim } { default, every~csv, autobooktabular={#3}, #2} + } + \__csvsim_loop: + } + + +\NewDocumentCommand \csvautobooklongtable { s +O{} m } + { + \IfBooleanTF {#1} + { + \keys_set:nn { csvsim } { default, every~csv, autobooklongtable*={#3}, #2} + } + { + \keys_set:nn { csvsim } { default, every~csv, autobooklongtable={#3}, #2} + } + \__csvsim_loop: + } + + + +%---- sorting + +\cs_new_protected_nopar:Npn \__csvsim_key_new_sorting_rule:nn #1#2 + { + \keys_define:nn { csvsim } + { + sort~by~#1 .meta:n = { sort~by={#2} }, + } + } + + +\NewDocumentCommand \csvsortingrule { } + { + \__csvsim_key_new_sorting_rule:nn + } + + +\keys_define:nn { csvsim } + { + preprocessor .tl_gset:N = \l__csvsim_preprocessor_tl, + preprocessed~file .code:n = \__csvsim_set_filename:Nn \l__csvsim_ppfilename_str {#1}, + csvsorter~command .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_command_str {#1}, + csvsorter~configpath .code:n = \__csvsim_set_filename:Nn\l__csvsim_csvsorter_configpath_str {#1}, + csvsorter~log .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_log_str {#1}, + csvsorter~token .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_token_str {#1}, + no~preprocessing .meta:n = { preprocessor= }, + sort~by .meta:n = + { + preprocessor= + { + \__csvsim_processor_csvsorter:nnn {#1} + } + }, + new~sorting~rule .code:n = \__csvsim_key_new_sorting_rule:nn #1, + new~sorting~rule .value_required:n = true , +} + + +\keys_set:nn { csvsim } + { + preprocessed~file = \c_sys_jobname_str _sorted._csv, + csvsorter~command = csvsorter, + csvsorter~configpath = ., + csvsorter~log = csvsorter.log, + csvsorter~token = \c_sys_jobname_str.csvtoken, + } + + +\cs_new_protected_nopar:Npn \__csvsim_processor_csvsorter:nnn #1#2#3 + { + \sys_if_shell_unrestricted:TF + { + \__csvsim_set_temp_filename:n { #1 } + \msg_note:nnxx { csvsimple }{ sort-info }{ #2 }{ \l__csvsim_temp_filename_str } + \cs_if_exist:NF \g__csvsim_iow + { + \iow_new:N \g__csvsim_iow + } + \iow_open:Nn \g__csvsim_iow { \l__csvsim_csvsorter_token_str } + \iow_now:Nn \g__csvsim_iow { \ExplSyntaxOn \msg_error:nn { csvsimple }{ sort-error } \ExplSyntaxOff } + \iow_close:N \g__csvsim_iow + \sys_shell_now:x + { + "\l__csvsim_csvsorter_command_str" \c_space_tl + -c~ "\l__csvsim_csvsorter_configpath_str/\l__csvsim_temp_filename_str" \c_space_tl + -l~ "\l__csvsim_csvsorter_log_str" \c_space_tl + -t~ "\l__csvsim_csvsorter_token_str" \c_space_tl + -i~ "#2" \c_space_tl + -o~ "#3" \c_space_tl + -q~1 + } + \file_input:n { \l__csvsim_csvsorter_token_str } + } + { + \msg_error:nn { csvsimple }{ sort-shell-escape } + } + } + + + +%---- default + +\keys_define:nn { csvsim } + { + % default for reset + default .meta:n = + { + file = unknown.csv, + no~preprocessing, + command = \csvline, + column~names~reset, + head, + check~column~count, + head~to~column~names~prefix = , + head~to~column~names = false, + column~count = 0, + 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, + respect~none, + }, + } + +\keys_set:nn { csvsim } + { + default + } diff --git a/macros/latex/contrib/csvsimple/csvsimple-l3.tex b/macros/latex/contrib/csvsimple/csvsimple-l3.tex new file mode 100644 index 0000000000..a3e61e241f --- /dev/null +++ b/macros/latex/contrib/csvsimple/csvsimple-l3.tex @@ -0,0 +1,2504 @@ +% \LaTeX-Main\ +% !TeX encoding=UTF-8 +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) +%% csvsimple.tex: Manual +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +%% ------------------------------------------------------------------------------------------- +%% +%% 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.md +%% +\documentclass[a4paper,11pt]{ltxdoc} +\usepackage{csvsimple-doc} + +\usepackage{\csvpkgprefix csvsimple-l3} + +\tcbmakedocSubKey{docCsvKey}{csvsim} +\tcbmakedocSubKeys{docCsvKeys}{csvsim} + +\hypersetup{ + pdftitle={Manual for the csvsimple-l3 package}, + pdfauthor={Thomas F. Sturm}, + pdfsubject={csv file processing with LaTeX3}, + pdfkeywords={csv file, comma separated values, key value syntax} +} + +\usepackage{incgraph} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\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-l3} 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{https://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(-l3)| provides a simple \LaTeX\ interface for the processing of files with + comma separated values (CSV). |csvsimple-l3| relies heavily on the key value + syntax from |l3keys| which results 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} + +\vspace{1cm} + +\includegraphics[width=\linewidth]{csvsimple-title.png} +% Source code for the title picture - omitted for PDF viewer compatibility +\begin{tcolorbox}[void] +\begin{NoHyper} +\begin{inctext}[] +\begin{tikzpicture} +\fill[top color=blue!50!gray!50,bottom color=red!50!gray!50] (-8,-5) rectangle (8,5); +\node at (0,2.5) {\tcbinputlisting{listing file=csvsimple-example.csv,listing only,width=11cm,blankest,colupper=blue!50!black}}; +\node[red!50!black] at (0,-2.5) {\csvautotabular{csvsimple-example.csv}}; +\begin{scope}[transparency group=knockout] +\fill [top color=blue!50!gray!10,bottom color=red!50!gray!10] (-7.7,-4.7) rectangle (7.7,4.7); +\node at (0,2.5) {\tcbinputlisting{listing file=csvsimple-example.csv,listing only,width=11cm,blankest,colupper=blue!20}}; +\node[red!20] at (0,-2.5) {\csvautotabular{csvsimple-example.csv}}; +\node at (0,2.5) [opacity=0,font=\fontencoding{T1}\fontfamily{lmr}\fontsize{7cm}{7cm}\bfseries] {csv}; +\node at (0,-2.5) [opacity=0,font=\fontencoding{T1}\fontfamily{lmr}\fontsize{4.8cm}{4.8cm}\bfseries] {simple}; +\end{scope} +\end{tikzpicture} +\end{inctext} +\end{NoHyper} +\end{tcolorbox} + + +\clearpage +\tableofcontents + +\clearpage +\section{Introduction}% +The |csvsimple-l3| 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 |l3keys|. Sample applications of the package +are tabular lists, serial letters, and charts. + +An alternative to |csvsimple-l3| is the |datatool| package +which provides considerably more functions and allows sorting of data by \LaTeX. +|csvsimple-l3| 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 either 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} +|csvsimple-l3| is loaded with \emph{one} of the following +alternatives inside the preamble: +\begin{dispListing} +\usepackage[l3]{csvsimple} + % or alternatively (not simultaneously!) +\usepackage{csvsimple-l3} +\end{dispListing} + +Not automatically loaded, but used for many examples are the packages +|longtable|, |booktabs|, |ifthen|, and |booktabs|. + + +\clearpage +\subsection{First Steps} +Every line of a processable CSV file has to contain an identical amount of +comma\footnote{See \refKey{/csvsim/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{/csvsim/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 +meta key (called style here) which contains the whole table creation +using \refCom{csvstyle} or |keys_define:nn| from |l3keys|. + +\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} + + +\clearpage +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{/csvsim/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 manually like in the examples +above. Here, we also add a \refKey{/csvsim/head to column names prefix} to avoid +macro name clashes. + +\begin{dispExample} +\csvstyle{myTableStyle}{ + tabular = |r|l|c|, + table head = \hline & Person & Matr.~No.\\\hline\hline, + late after line = \\\hline, + head to column names, + head to column names prefix = MY, + } + +\csvreader[myTableStyle] + {grade.csv}{}{% + \thecsvrow & \MYgivenname~\MYname & \MYmatriculation + } +\end{dispExample} + + +\smallskip +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 |l3keys| syntax allows to create own meta options +(styles) for a consistent and centralized design. The following example is easily +modified to obtain more or less option settings. + +\begin{dispExample} +\csvstyle{myStudentList}{% + 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}} + \refCom{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 as comma separated list of 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 \textbf{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{/csvsim/file} and \refKey{/csvsim/command} +is useless for |\csvreader|. +\end{docCommand} + + +\clearpage +\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} + +\bigskip + +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{docCommands}[ + doc parameter = \oarg{options}\marg{file name} + ] + { + { doc name = csvautotabular }, + { doc name = csvautotabular*, doc new = 2021-06-25 } + } + |\csvautotabular| or |\csvautotabular*| + is an abbreviation for the application of the option key + \refKey{/csvsim/autotabular} or \refKey{/csvsim/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. + The star variant treats the first line as data line and not as header line. +\begin{dispExample} +\csvautotabular*{grade.csv} +\end{dispExample} +\begin{dispExample} +\csvautotabular[filter equal={\csvcoliv}{f}]{grade.csv} +\end{dispExample} +\end{docCommands} + +\clearpage + +\begin{docCommands}[ + doc parameter = \oarg{options}\marg{file name} + ] + { + { doc name = csvautolongtable }, + { doc name = csvautolongtable*, doc new = 2021-06-25 } + } + |\csvautolongtable| or |\csvautolongtable*| + is an abbreviation for the application of the option key + \refKey{/csvsim/autolongtable} or \refKey{/csvsim/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. + The star variant treats the first line as data line and not as header line. +\begin{dispListing} +\csvautolongtable{grade.csv} +\end{dispListing} +\csvautolongtable{grade.csv} +\end{docCommands} + + + +\begin{docCommands}[ + doc parameter = \oarg{options}\marg{file name} + ] + { + { doc name = csvautobooktabular }, + { doc name = csvautobooktabular*, doc new = 2021-06-25 } + } + |\csvautobooktabular| or |\csvautobooktabular*| + is an abbreviation for the application of the option key + \refKey{/csvsim/autobooktabular} or \refKey{/csvsim/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. + The star variant treats the first line as data line and not as header line. +\begin{dispExample} +\csvautobooktabular{grade.csv} +\end{dispExample} +\end{docCommands} + + +\begin{docCommands}[ + doc parameter = \oarg{options}\marg{file name} + ] + { + { doc name = csvautobooklongtable }, + { doc name = csvautobooklongtable*, doc new = 2021-06-25 } + } + |\csvautobooklongtable| or |\csvautobooklongtable*| + is an abbreviation for the application of the option key + \refKey{/csvsim/autobooklongtable} or \refKey{/csvsim/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. + The star variant treats the first line as data line and not as header line. +\begin{dispListing} +\csvautobooklongtable{grade.csv} +\end{dispListing} +\csvautobooklongtable{grade.csv} +\end{docCommands} + + + +\clearpage + +\begin{docCommand}[doc updated = 2021-06-25]{csvset}{\marg{options}} + Sets \meta{options} for every following + \refCom{csvreader} and \refCom{csvloop}. + Note that most options are set to default values at the begin of these + commands and therefore cannot be defined reasonable by \refCom{csvset}. + But it may be used for options like \refKey{/csvsim/csvsorter command} + to give global settings. Also see \refKey{/csvsim/every csv}. +\end{docCommand} + + +\begin{docCommand}{csvstyle}{\marg{key}\marg{options}} + Defines a new |l3keys| meta key to call other keys. It is used to + make abbreviations for convenient key set applications. + The new \meta{key} can take one parameter. The name \refCom{csvstyle} + originates from an old version of |csvsimple| which used |pgfkeys| + instead of |l3keys|. + +\begin{dispExample} +\csvstyle{grade list}{ + column names = {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}{csvnames}{\marg{key}\marg{assignments}} + Abbreviation for |\csvstyle{|\meta{key}|}{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}[doc updated=2021-06-28]{ifcsvoddrow}{\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. + \refCom{ifcsvoddrow} is expandable. +\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}{}{% + \ifcsvoddrow{\slshape\thecsvrow & \slshape\name, \givenname & \slshape\grade}% + {\bfseries\thecsvrow & \bfseries\name, \givenname & \bfseries\grade} + } +\end{dispExample} + +The |\ifcsvoddrow| 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 = \ifcsvoddrow{\\\rowcolor{yellow!50}}{\\\rowcolor{red!25}} + ]{grade.csv}{}{% + \thecsvrow & \givenname~\name & \matriculation & \grade + } +\end{dispExample} + +Alternatively, |\rowcolors| from the |xcolor| package can be used for this +purpose: + +\begin{dispExample} +% This example needs the xcolor package +\csvreader[ + head to column names, + 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 + ]{grade.csv}{}{% + \thecsvrow & \givenname~\name & \matriculation & \grade + } +\end{dispExample} + + The deprecated, but still available alias for this command is + \docAuxCommand{csvifoddrow}. +\end{docCommand} + +\clearpage + +\begin{docCommand}[doc updated=2021-06-28]{ifcsvfirstrow}{\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. + \refCom{ifcsvfirstrow} is expandable. +\begin{dispExample} +\csvreader[ + tabbing, + head to column names, + table head = {\hspace*{3cm}\=\kill} + ]{grade.csv}{}{% + \givenname~\name \> (\ifcsvfirstrow{first entry!!}{following entry}) + } +\end{dispExample} + The deprecated, but still available alias for this command is + \docAuxCommand{csviffirstrow}. +\end{docCommand} + +\medskip + + +\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{/csvsim/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}[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 +\begin{docCommands}{ + { doc name = thecsvrow , doc updated = 2021-06-25 }, + { doc name = g_csvsim_row_int, doc new = 2021-06-25 } + } + Typesets the current data line number. This is the + current number of accepted data lines without the header line. + Despite of the name, there is no associated \LaTeX\ counter |csvrow|, + but \refCom{thecsvrow} is an accessor the \LaTeX3 integer + \refCom{g_csvsim_row_int}. +\end{docCommands} + + +\begin{docCommands}[doc new=2021-06-25]{ + { doc name = thecsvcolumncount }, + { doc name = g_csvsim_columncount_int } + } + Typesets the number of columns of the current CSV file. This number + is either computed from the first valid line (header or data) or + given by \refKey{/csvsim/column count}. + Despite of the name, there is no associated \LaTeX\ counter |csvcolumncount|, + but \refCom{thecsvcolumncount} is an accessor the \LaTeX3 integer + \refCom{g_csvsim_columncount_int}. +\begin{dispExample} +\csvreader{grade.csv}{}{}% +The last file consists of \thecsvcolumncount{} columns and +\thecsvrow{} accepted data lines. The total number of lines +ist \thecsvinputline{}. +\end{dispExample} +\end{docCommands} + + +\begin{docCommands}{ + { doc name = thecsvinputline , doc updated = 2021-06-25 }, + { doc name = g_csvsim_inputline_int, doc new = 2021-06-25 } + } + Typesets the current file line number. This is the + current number of all data lines including the header line and all + lines filtered out. + Despite of the name, there is no associated \LaTeX\ counter |csvinputline|, + but \refCom{thecsvinputline} is an accessor the \LaTeX3 integer + \refCom{g_csvsim_inputline_int}. +\begin{dispExample} +\csvreader[ + no head, + filter test = \ifnumequal{\thecsvinputline}{3} + ]{grade.csv}{}{% + The line with number \thecsvinputline\ contains: \csvline + } +\end{dispExample} +\end{docCommands} + + + + + +\clearpage +\section{Option Keys}\label{sec:schluessel}% +For the \meta{options} in \refCom{csvreader} respectively \refCom{csvloop} +the following |l3keys| keys can be applied. The \meta{module} name |/csvsim/| 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 opened. +\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. + \refCom{thecsvcolumncount} and header entries are available. +\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 e.g. \refKey{/csvsim/filter ifthen}. + Also see \refKey{/csvsim/full filter}. + All line entries are available. +\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. + These operations are executed before further processing of this line. + \meta{code} should not refer to any data content, but may be something + like |\\|. +\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{/csvsim/before filter}). + These operations are executed before further processing of this line. + \meta{code} should not refer to any data content, but may be something + like |\\|. + \refKey{/csvsim/late after line} overwrites + \refKey{/csvsim/late after first line} and + \refKey{/csvsim/late after last line}. + Note that table options like \refKey{/csvsim/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{/csvsim/late after line}. + \meta{code} should not refer to any data content. + This key has to be set after \refKey{/csvsim/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{/csvsim/late after line}. + \meta{code} should not refer to any data content. + This key has to be set after \refKey{/csvsim/late after line}. +\end{docCsvKey} + + +\begin{docCsvKey}{before line}{=\meta{code}}{no default, initially empty} + Sets the \meta{code} to be executed after \refKey{/csvsim/late after line} + and before \refKey{/csvsim/command}. + All line entries are available. + \refKey{/csvsim/before line} overwrites + \refKey{/csvsim/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{/csvsim/before line} + for the first accepted data line. + All line entries are available. + This key has to be set after \refKey{/csvsim/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. + It is executed between \refKey{/csvsim/before line} and \refKey{/csvsim/after line}. + \refKey{/csvsim/command} describes the main processing of the line + entries. \refCom{csvreader} sets \refKey{/csvsim/command} as mandatory + parameter. +\end{docCsvKey} + +\pagebreak + +\begin{docCsvKey}{after line}{=\meta{code}}{no default, initially empty} + Sets the \meta{code} to be executed for every accepted data line + after \refKey{/csvsim/command}. + All line entries are still available. + \refKey{/csvsim/after line} overwrites \refKey{/csvsim/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{/csvsim/after line} + for the first accepted data line. + All line entries are still available. + This key has to be set after \refKey{/csvsim/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 closed. +\end{docCsvKey} + +\bigskip + +The following example illustrates the sequence of command execution. +Note that \refKey{/csvsim/command} is set by the mandatory last +parameter of \refCom{csvreader}. + +\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}. + +\clearpage +\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 + the |\csvauto...| commands like \refCom{csvautotabular}, etc. + Instead, there are \emph{star} variants like \refCom{csvautotabular*} to + process files without header line. + See Section~\ref{noheader} on page~\pageref{noheader} for examples. +\end{docCsvKey} + +\begin{docCsvKey}{column names}{=\marg{assignments}}{no default, initially empty} + Adds some new \meta{assignments} of macros to columns in key value syntax. + Existing assignments are kept.\par + The \meta{assignments} are given as comma separated list of 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. +\begin{dispListing} + column names = {name=\surname, givenname=\firstname, grade=\grade} +\end{dispListing} +\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. + Note that the macro definition is \emph{global} and may therefore override + existing macros for the rest of the document. Adding + \refKey{/csvsim/head to column names prefix} may help to avoid unwanted + overrides. +\end{docCsvKey} + + +\begin{docCsvKey}[][doc new=2019-07-16]{head to column names prefix}{=\meta{text}}{no default, initially empty} + The given \meta{text} is prefixed to the name of all macros generated by + \refKey{/csvsim/head to column names}. For example, if you use the settings +\begin{dispListing} + head to column names, + head to column names prefix=MY, +\end{dispListing} + a header entry |section| will generate the corresponding macro + |\MYsection| instead of destroying the standard \LaTeX\ |\section| macro. +\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}[][doc updated=2021-06-24]{column count}{=\meta{number}}{no default, initially |0|} + Sets the \meta{number} of feasible entries per data line. + If \refKey{/csvsim/column count} is set to |0|, the number of entries of + the first non-empty line determines the column count (automatic detection). + + This setting is only useful in connection with \refKey{/csvsim/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}\label{subsec:filtering}% + +Applying a \emph{filter} means that data lines are only processed / displayed, +if they fulfill a given \emph{condition}. + +The following string compare filters \refKey{/csvsim/filter strcmp} and +\refKey{/csvsim/filter equal} are identical by logic, but differ in implementation. + +\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}. +\begin{dispExample} +% \usepackage{booktabs} +\csvreader[ + head to column names, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + filter strcmp = {\gender}{f}, %>> list only female persons << + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} +\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}{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| package (loading required!). +\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| package (loading required!). +\end{docCsvKey} + + +\begin{docCsvKey}[][doc new=2021-06-25]{filter fp}{=\meta{floating point expression}}{no default} + Only data lines which fulfill a \LaTeX3 \meta{floating point expression} + (|l3fp|, |xfp|) are accepted. +\begin{dispExample} +% \usepackage{booktabs} +\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 fp = { \matriculation > 20000 && \grade < 4.0 }, + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} +\end{docCsvKey} + + +\clearpage + +\begin{docCsvKey}[][doc new=2021-06-25]{filter bool}{=\meta{boolean expression}}{no default} + Only data lines which fulfill a \LaTeX3 \meta{boolean expression} are accepted. + Note that such an \meta{boolean expression} needs expl3 code. + To preprocess the data line before testing the \meta{condition}, + the option key \refKey{/csvsim/before filter} can be used. +\begin{dispExample} +% For convenience, we save the filter +\ExplSyntaxOn +%>> list only matriculation numbers greater than 20000, list only men << +\csvstyle{myfilter} + { + filter~bool = + { + \int_compare_p:n { \matriculation > 20000 } && + \str_compare_p:eNe { \gender } = { m } + } + } +\ExplSyntaxOff + +\csvreader[ + head to column names, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + myfilter + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} +\end{docCsvKey} + +\medskip +\begin{docCommand}[doc new=2021-06-25]{csvfilterbool}{\marg{key}\marg{boolean expression}} + Defines a new |l3keys| meta key which applies \refKey{/csvsim/filter bool} + with the given \meta{boolean expression}. +\begin{dispExample} +% For convenience, we save the filter +\ExplSyntaxOn +%>> list only matriculation numbers greater than 20000, list only men << +\csvfilterbool{myfilter} + { + \int_compare_p:n { \matriculation > 20000 } && + \str_compare_p:eNe { \gender } = { m } + } +\ExplSyntaxOff + +\csvreader[ + head to column names, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + myfilter + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} +\end{docCommand} + + + +\clearpage + +\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 like + |\ifnumcomp|, |\ifdimgreater|, etc. and from \Fullref{sec:stringtests} can be used. + Also, arbitrary own macros fulfilling this signature can be applied. +\begin{dispExample} +% \usepackage{etoolbox,booktabs} +\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} + + +\medskip +\begin{docCsvKey}[][doc new=2016-07-01]{filter expr}{=\meta{boolean expression}}{no default} + Only data lines which fulfill a \meta{boolean expression} are accepted. + Every \meta{boolean expression} + from the |etoolbox| package is feasible (package loading required!). + To preprocess the data line before testing the \meta{condition}, + the option key \refKey{/csvsim/before filter} can be used. +\begin{dispExample} +% \usepackage{etoolbox,booktabs} +\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{boolean expression}}{no default} + Only data lines which fulfill a \meta{boolean expression} are accepted. + For the \meta{boolean expression}, every term from the |ifthen| package + is feasible (package loading required!). + To preprocess the data line before testing the \meta{condition}, + the option key \refKey{/csvsim/before filter} can be used. + +\begin{dispExample} +% \usepackage{ifthen,booktabs} +\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}{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} + + +\begin{docCsvKey}[][doc new=2016-07-01]{full filter}{=\meta{code}}{no default} + Technically, this key is an alias for \refKey{/csvsim/before filter}. + Philosophically, \refKey{/csvsim/before filter} computes something before + a filter condition is set, but \refKey{/csvsim/full filter} should implement + the full filtering. Especially, \refCom{csvfilteraccept} or + \refCom{csvfilterreject} \emph{should} be set inside the \meta{code}. +\begin{dispExample} +% \usepackage{etoolbox,booktabs} +\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{Line Range}\label{subsec:linerange} + +Applying a \emph{line range} means to select certain line numbers to be +displayed. These line numbers are not necessarily line numbers of +the input file, see \refCom{thecsvinputline}, but line numbers of +type \refCom{thecsvrow}. + +For example, if a \emph{filter} was applied, see \Fullref{subsec:filtering}, +and 42 lines are accepted, a \emph{range} could select the first 20 of them or +line 10 to 30 of the accepted lines. + + +\begin{docCsvKey}[][doc new=2021-06-29]{range}{=\brackets{\meta{range1},\meta{range2},\meta{range3},... }}{no default, initially empty} + Defines a comma separated list of line ranges. If a line number \refCom{thecsvrow} + satisfies one or more of the given \meta{range1}, \meta{range2}, \ldots, + the corresponding line is processed and displayed. + If \refKey{/csvsim/range} is set to empty, all lines are accepted. + + Every \meta{range} can + corresponds to one of the following variants: + \begin{tabbing} + \hspace*{2cm}\=\kill + \texttt{\meta{a}-\meta{b}} \> meaning line numbers \meta{a} to \meta{b}.\\ + \texttt{\meta{a}-} \> meaning line numbers \meta{a} to |\c_max_int|=2 147 483 647.\\ + \texttt{-\meta{b}} \> meaning line numbers 1 to \meta{b}.\\ + \texttt{-} \> meaning line numbers 1 to 2 147 483 647 (inefficient; don't use).\\ + \texttt{\meta{a}} \> meaning line numbers \meta{a} to \meta{a} (i.e. only \meta{a}).\\ + \texttt{\meta{a}+\meta{d}} \> meaning line numbers \meta{a} to \meta{a}$+$\meta{d}$-1$.\\ + \texttt{\meta{a}+} \> meaning line numbers \meta{a} to \meta{a} (i.e. only \meta{a}).\\ + \texttt{+\meta{d}} \> meaning line numbers 1 to \meta{d}.\\ + \texttt{+} \> meaning line numbers 1 to 1 (i.e. only 1; weird).\\ + \end{tabbing} + +\begin{dispExample} +% \usepackage{booktabs} +\csvreader[ + head to column names, + range = 2-3, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} + + +\begin{dispExample} +% \usepackage{booktabs} +\csvreader[ + head to column names, + range = 3-, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} + + +\begin{dispExample} +% \usepackage{booktabs} +\csvreader[ + head to column names, + range = 2+2, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} + +\begin{dispExample} +% \usepackage{booktabs} +\csvreader[ + head to column names, + range = {2,4}, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + ]{grade.csv}{}{% + \thecsvrow & \slshape\name, \givenname & \matriculation & \grade + } +\end{dispExample} + +To select the last $n$ lines, you have to know or count the line numbers first. +The following example displays the last three line numbers: + +\begin{dispExample} +% \usepackage{booktabs} +\csvreader{grade.csv}{}{}% count line numbers +\csvreader[ + head to column names, + range = {\thecsvrow-2}-, + tabular = llll, + table head = \toprule & \bfseries Name & \bfseries Matr & \bfseries Grade\\\midrule, + table foot = \bottomrule, + ]{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{/csvsim/before table}, \refKey{/csvsim/table head}, \refKey{/csvsim/table foot}, + and \refKey{/csvsim/after table} are executed at the appropriate places. +\end{docCsvKey} + + +\begin{docCsvKey}{centered tabular}{=\meta{table format}}{style, no default} + Like \refKey{/csvsim/tabular} but inside an additional |center| environment. +\end{docCsvKey} + + +\begin{docCsvKey}{longtable}{=\meta{table format}}{style, no default} + Like \refKey{/csvsim/tabular} but for the |longtable| environment. + This requires the package |longtable| (not loaded automatically). +\end{docCsvKey} + + +\begin{docCsvKey}{tabbing}{}{style, no value} + Like \refKey{/csvsim/tabular} but for the |tabbing| environment. +\end{docCsvKey} + + +\begin{docCsvKey}{centered tabbing}{}{style, no value} + Like \refKey{/csvsim/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} + +\clearpage + +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{docCsvKeys}[ + doc parameter = {=\meta{file name}}, + doc description = no default, + ] + { + { doc name = autotabular }, + { doc name = autotabular* }, + } + Reads the whole CSV file denoted \meta{file name} with an automated formatting. + The star variant treats the first line as data line and not as header line. +\end{docCsvKeys} + + +\begin{docCsvKeys}[ + doc parameter = {=\meta{file name}}, + doc description = no default, + ] + { + { doc name = autolongtable }, + { doc name = autolongtable* }, + } + Reads the whole CSV file denoted \meta{file name} with an automated formatting + using the required |longtable| package. + The star variant treats the first line as data line and not as header line. +\end{docCsvKeys} + + +\begin{docCsvKeys}[ + doc parameter = {=\meta{file name}}, + doc description = no default, + ] + { + { doc name = autobooktabular }, + { doc name = autobooktabular* }, + } + Reads the whole CSV file denoted \meta{file name} with an automated formatting + using the required |booktabs| package. + The star variant treats the first line as data line and not as header line. +\end{docCsvKeys} + + +\begin{docCsvKeys}[ + doc parameter = {=\meta{file name}}, + doc description = no default, + ] + { + { doc name = autobooklongtable }, + { doc name = autobooklongtable* }, + } + Reads the whole CSV file denoted \meta{file name} with an automated formatting + using the required |booktabs| and |longtable| packages. + The star variant treats the first line as data line and not as header line. +\end{docCsvKeys} + + +\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 (|\catcode| 12, other), 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{/csvsim/respect tab} is set also. + \end{itemize} +\end{docCsvKey} + +\clearpage +\subsection{Miscellaneous}% + +\begin{docCsvKey}{every csv}{}{style, initially empty} + A meta key (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. +\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. + \refCom{csvreader} sets this option by a mandatory parameter. +\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{/csvsim/file}. + The second argument is the preprocessed CSV file + which is set by \refKey{/csvsim/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-l3| 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-l3|. +For the third method, the \refKey{/csvsim/preprocessor} option is made for. +This allows to access an external tool for sorting. +\emph{Which tool} is your choice. + +\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{https://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\ before! +\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{/csvsim/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{/csvsim/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[ + head to column names, + sort by = namesort.xml, + 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[ + head to column names, + sort by = gradesort.xml, + 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[ + head to column names, + sort by = matriculationsort.xml, + 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{/csvsim/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} + + +\begin{docCommand}[doc new=2021-06-28]{csvsortingrule}{\marg{name}\marg{file name}} + Identical in function to \refKey{/csvsim/new sorting rule}, see above. +A good place for setting up a new sorting rule would be inside the preamble: + +\csvsortingrule{name}{namesort.xml} +\begin{dispListing} +\csvsortingrule{name}{namesort.xml} +\end{dispListing} + +Now, we can use the new rule: +\begin{dispExample} +\csvautotabular[sort by name]{grade.csv} +\end{dispExample} +\end{docCommand} + + + +\clearpage +\section{String and Number Tests}\label{sec:stringtests}% + +The following string tests are complementing the string tests +from packages like |etoolbox|. They all do the same, i.e., +comparing expanded strings for equality. To some extent, they are +provided for backward compatibility. +\begin{itemize} +\item\refCom{ifcsvstrcmp} may be the most efficient method, because it uses + the 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 and updated={2016-07-01}{2021-06-28}]{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 |\str_compare:eNeTF|. + \refCom{ifcsvstrcmp} is expandable. +\end{docCommand} + + +\begin{docCommand}[doc new and updated={2016-07-01}{2021-06-28}]{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}. + \refCom{ifcsvstrcmp} is expandable. +\end{docCommand} + + +\begin{docCommand}[doc new and updated={2016-07-01}{2021-06-28}]{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 + and the comparison is done using |\tl_if_eq:NNTF|. + \refCom{ifcsvstrequal} is not expandable. +\end{docCommand} + + +\begin{docCommand}[doc new and updated={2016-07-01}{2021-06-28}]{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. + The comparison is done using |\tl_if_eq:NNTF|. + \refCom{ifcsvprostrequal} is not expandable. +\end{docCommand} + + +The following number tests are wrappers for corresponding \LaTeX3 conditionals. + +\begin{docCommand}[doc new={2021-06-28}]{ifcsvfpcmp}{\marg{floating point expression}\marg{true}\marg{false}} + Evaluates the given \meta{floating point expression} + and executes \meta{true} or \meta{false} appropriately. + The evaluation is done using |\fp_compare:nTF|. + \refCom{ifcsvfpcmp} is expandable. +\end{docCommand} + +\begin{docCommand}[doc new={2021-06-28}]{ifcsvintcmp}{\marg{integer expression}\marg{true}\marg{false}} + Evaluates the given \meta{integer expression} + and executes \meta{true} or \meta{false} appropriately. + The evaluation is done using |\int_compare:nTF|. + \refCom{ifcsvintcmp} is expandable. +\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. + +%-- 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 strcmp={\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} + +\medskip + +The |siunitx| package provides a huge amount of formatting options for +numbers. A good and robust way to apply formatting by |siunitx| inside +tables generated by |csvsimple-l3| is the |\tablenum| macro from +|siunitx|. + +\begin{dispExample} +% \usepackage{siunitx,array,booktabs} +\csvreader[ + head to column names, + before reading = \begin{center}\sisetup{table-number-alignment=center}, + tabular = cc, + table head = \toprule \textbf{Cats} & \textbf{Dogs} \\\midrule, + table foot = \bottomrule, + after reading = \end{center} + ]{data_numbers.csv}{}{% + \tablenum[table-format=2.2e1]{\cats} & \tablenum{\dogs} + } +\end{dispExample} + +\clearpage + +It is also possible to create on-the-fly tables using calcations of +the given data. The following example shows cat values bisected and +dog values doubled. + +\begin{dispExample} +% \usepackage{siunitx,array,booktabs,xfp} +\csvreader[ + head to column names, + before reading = \begin{center}\sisetup{table-number-alignment=center}, + tabular = cccc, + table head = \toprule \textbf{Cats} & \textbf{Dogs} + & \textbf{Halfcats} & \textbf{Doubledogs} \\\midrule, + table foot = \bottomrule, + after reading = \end{center} + ]{data_numbers.csv}{}{% + \tablenum[table-format=2.2e1]{\cats} & \tablenum{\dogs} + & \tablenum[exponent-mode=scientific, round-precision=3, + round-mode=places, table-format=1.3e1]{\fpeval{\cats/2}} + & \tablenum{\fpeval{\dogs*2}} + } +\end{dispExample} + + +\clearpage + +The |siunitx| package also provides a new column type |S| +which can align material using a number of different strategies. +Special care is needed, if the \emph{first} or the \emph{last} column is to be formatted with +the column type |S|. The number detection of |siunitx| is disturbed by +the line reading code of |csvsimple-l3| which actually is present at the +first and last column. To avoid this problem, the utilization of +|\tablenum| is appropriate, see above. +Alternatively, a very nifty workaround suggested by Enrico Gregorio is to +add an invisible dummy column with |c@{}| as first column +and |@{}c| as last column: + +\begin{dispExample} +% \usepackage{siunitx,array,booktabs} +\csvreader[ + head to column names, + before reading = \begin{center}\sisetup{table-number-alignment=center}, + tabular = {c@{}S[table-format=2.2e1]S@{}c}, + table head = \toprule & \textbf{Cats} & \textbf{Dogs} & \\\midrule, + table foot = \bottomrule, + after reading = \end{center} + ]{data_numbers.csv}{}{% + & \cats & \dogs & + } +\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 +\csvreader[ + head to column names, + sort by = catsort.xml, + before reading = \begin{center}\sisetup{table-number-alignment=center}, + tabular = lcc, + table head = \toprule \textbf{Month} & \textbf{Dogs} & \textbf{Cats} \\\midrule, + table foot = \bottomrule, + after reading = \end{center} + ]{data_numbers.csv}{}{% + \month & \tablenum{\dogs} & \tablenum[table-format=2.2e1]{\cats} + } +\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{/csvsim/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, the \emph{star} versions of the auto tabular +commands can be used. + +\begin{dispExample} +\csvautobooktabular*{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 + ]{data_headless.csv} +\end{dispExample} + + +\clearpage + +For the normal \refCom{csvreader} command, the \refKey{/csvsim/no head} option +should be applied. Of course, we cannot use \refKey{/csvsim/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-l3| 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-l3|: +\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 + +\printindex + +\end{document} diff --git a/macros/latex/contrib/csvsimple/csvsimple-legacy.pdf b/macros/latex/contrib/csvsimple/csvsimple-legacy.pdf new file mode 100644 index 0000000000..93c22e5fc3 Binary files /dev/null and b/macros/latex/contrib/csvsimple/csvsimple-legacy.pdf differ diff --git a/macros/latex/contrib/csvsimple/csvsimple-legacy.sty b/macros/latex/contrib/csvsimple/csvsimple-legacy.sty new file mode 100644 index 0000000000..53a30ab9e3 --- /dev/null +++ b/macros/latex/contrib/csvsimple/csvsimple-legacy.sty @@ -0,0 +1,795 @@ +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) +%% csvsimple-legacy.sty: Simple LaTeX CSV file processing (LaTeX2e) +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +%% ------------------------------------------------------------------------------------------- +%% +%% 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.md +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{csvsimple-legacy}[2021/06/29 version 2.0.0 LaTeX2e CSV file processing] + + +%---- check package +\ExplSyntaxOn +\cs_if_exist:NT \c__csvsim_package_expl_bool + { + \msg_new:nnn { csvsimple }{ legacy / package-loaded } + { Package~'csvsimple-l3'~seems~already~be~loaded!~ + 'csvsimple-legacy'~cannot~be~loaded~simultaneously.~ + Therefore,~loading~of~'csvsimple-legacy'~stops~now.} + \msg_warning:nn { csvsimple }{ legacy / package-loaded } + \tex_endinput:D + } +\bool_const:Nn \c__csvsim_package_expl_bool { 0 } +\ExplSyntaxOff + + + +\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 . 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{}% + \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@headnameprefix\csv@current@col\endcsname}% + \toks1=\expandafter{\csname csvcol\romannumeral\c@csvcol\endcsname}% + \begingroup\edef\csv@temp{\endgroup\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}% + \begingroup\edef\csv@temp{\endgroup\noexpand\pgfkeysdef{/csv head/\csv@current@col}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}% + \csv@temp% + \begingroup\edef\csv@temp{\endgroup\noexpand\pgfkeysdef{/csv head/\thecsvcol}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}% + \csv@temp% +} + +% head line +\def\csv@processheadline{% + \csvreadnext% + \ifx\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}% + \begingroup\edef\csv@temp{\endgroup\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}% +} + +\def\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% + \ifx\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 prefix/.store in=\csv@headnameprefix,% + 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 prefix=, + 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% + \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-legacy.tex b/macros/latex/contrib/csvsimple/csvsimple-legacy.tex new file mode 100644 index 0000000000..c22c56181f --- /dev/null +++ b/macros/latex/contrib/csvsimple/csvsimple-legacy.tex @@ -0,0 +1,1970 @@ +% \LaTeX-Main\ +% !TeX encoding=UTF-8 +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) +%% csvsimple.tex: Manual +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2008-2021 by Prof. Dr. Dr. Thomas F. Sturm +%% ------------------------------------------------------------------------------------------- +%% +%% 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.md +%% +\documentclass[a4paper,11pt]{ltxdoc} +\usepackage{csvsimple-doc} + +\usepackage{\csvpkgprefix csvsimple-legacy} + +\tcbmakedocSubKey{docCsvKey}{csv} + +\hypersetup{ + pdftitle={Manual for the csvsimple-legacy package}, + pdfauthor={Thomas F. Sturm}, + pdfsubject={csv file processing with LaTeX2e}, + pdfkeywords={csv file, comma separated values, key value syntax} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\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-legacy} 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{https://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(-legacy)| provides a simple \LaTeX\ interface for the processing of files with + comma separated values (CSV). |csvsimple-legacy| relies heavily on the key value + syntax from |pgfkeys| which results 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} + + +\begin{tcolorbox}[enhanced,left=8mm,right=8mm,boxrule=2pt,boxsep=3mm, + colback=red!85!gray!5!white,colframe=red!85!gray, + arc is angular,arc=5mm, + before skip=1cm] +Actually, |csvsimple-legacy| is identical to the old version 1.22 (2021/06/07) +of |csvsimple|. It is superseded by |csvsimple-l3|, a \LaTeX3 implementation +of |csvsimple| which is a \emph{nearly} drop-in for the erstwhile implementation. +\begin{itemize} +\item If you are a new user or an experienced user of |csvsimple| creating a + new document, you are encouraged to turn to |csvsimple-l3|, see\\ + \href{csvsimple-l3.pdf}{\flqq The |csvsimple-l3| package\frqq} +\item If you used |csvsimple| before version 2.00 in one or many documents, + there is \emph{no need} to change anything. Loading |csvsimple| + without options loads |csvsimple-legacy|. + |csvsimple-legacy| will be maintained to stay functional as it is for the + sake of compatibility to old documents. +\item Differences between |csvsimple-legacy| and |csvsimple-l3| are + discussed in \href{csvsimple.pdf}{\flqq The |csvsimple| package\frqq}. +\end{itemize} +\end{tcolorbox} + + +\clearpage +\tableofcontents + +\clearpage +\section{Introduction}% +The |csvsimple-legacy| 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|. Sample applications of the package +are tabular lists, serial letters, and charts. + +An alternative to |csvsimple-legacy| is the |datatool| package +which provides considerably more functions and allows sorting of data by \LaTeX. +|csvsimple-legacy| 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 either 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-legacy| loads the packages +|pgfkeys|, +|etoolbox|, +and |ifthen|. +|csvsimple-legacy| itself is loaded with \emph{one} of the following +alternatives inside the preamble: +\begin{dispListing} +\usepackage{csvsimple} + % or alternatively (not simultaneously!) +\usepackage[legacy]{csvsimple} + % or alternatively (not simultaneously!) +\usepackage{csvsimple-legacy} +\end{dispListing} + + +Not automatically loaded, but used for many examples are the packages +|longtable| +and +|booktabs|. + + +\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. Here, we also add a \refKey{/csv/head to column names prefix} to avoid +macro name clashes. + +\begin{dispExample} +\csvstyle{myTableStyle}{tabular=|r|l|c|, + table head=\hline & Person & Matr.~No.\\\hline\hline, + late after line=\\\hline, + head to column names, + head to column names prefix=MY, + } + +\csvreader[myTableStyle]{grade.csv}{}% + {\thecsvrow & \MYgivenname~\MYname & \MYmatriculation}% +\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}} + |\csvautobooktabular| 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{key}\marg{options}} + Abbreviation for |\csvset{|\meta{key}|/.style=|\marg{options}|}| + to define a new style. +\end{docCommand} + +\begin{docCommand}{csvnames}{\marg{key}\marg{assignments}} + Abbreviation for |\csvset{|\meta{key}|/.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}. + +\clearpage +\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. + Note that the macro definition is \emph{global} and may therefore override + existing macros for the rest of the document. Adding + \refKey{/csv/head to column names prefix} may help to avoid unwanted + overrides. +\end{docCsvKey} + + +\begin{docCsvKey}[][doc new=2019-07-16]{head to column names prefix}{=\meta{text}}{no default, initially empty} + The given \meta{text} is prefixed to the name of all macros generated by + \refKey{/csv/head to column names}. For example, if you use the settings +\begin{dispListing} + head to column names, + head to column names prefix=MY, +\end{dispListing} + a header entry |section| will generate the corresponding macro + |\MYsection| instead of destroying the standard \LaTeX\ |\section| macro. +\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 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 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| 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| 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| 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-legacy| 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-legacy|. +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\ 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\ 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| 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| 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 of |siunitx| 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]@{}c}, + 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} or the \emph{last} column is to be formatted with +the column type |S|. The number detection of |siunitx| is disturbed by +the line reading code of |csvsimple-legacy| which actually is present at the +first and last column. To avoid this problem, the content of the first and last column +could be formatted not by the table format definition, but by using a +suitable |\tablenum| formatting directly, see |siunitx|. + +Another and very nifty workaround suggested by Enrico Gregorio is to +add an invisible dummy column with |c@{}| as first column +and |@{}c| as last 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@{}c}, + 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]@{}c}, + 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-legacy| 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-legacy|: +\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 + +\printindex + +\end{document} diff --git a/macros/latex/contrib/csvsimple/csvsimple-title.png b/macros/latex/contrib/csvsimple/csvsimple-title.png new file mode 100644 index 0000000000..0a574bdbe7 Binary files /dev/null and b/macros/latex/contrib/csvsimple/csvsimple-title.png differ diff --git a/macros/latex/contrib/csvsimple/csvsimple.pdf b/macros/latex/contrib/csvsimple/csvsimple.pdf index 887cb48c39..805a052473 100644 Binary files a/macros/latex/contrib/csvsimple/csvsimple.pdf and b/macros/latex/contrib/csvsimple/csvsimple.pdf differ diff --git a/macros/latex/contrib/csvsimple/csvsimple.sty b/macros/latex/contrib/csvsimple/csvsimple.sty index 98d1a32866..def091859f 100644 --- a/macros/latex/contrib/csvsimple/csvsimple.sty +++ b/macros/latex/contrib/csvsimple/csvsimple.sty @@ -1,4 +1,4 @@ -%% The LaTeX package csvsimple - version 1.22 (2021/06/07) +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) %% csvsimple.sty: Simple LaTeX CSV file processing %% %% ------------------------------------------------------------------------------------------- @@ -15,766 +15,35 @@ %% %% This work has the LPPL maintenance status `author-maintained'. %% -%% This work consists of all files listed in README +%% This work consists of all files listed in README.md %% -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{csvsimple}[2021/06/07 version 1.22 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 . 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{}% - \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@headnameprefix\csv@current@col\endcsname}% - \toks1=\expandafter{\csname csvcol\romannumeral\c@csvcol\endcsname}% - \begingroup\edef\csv@temp{\endgroup\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}% - \begingroup\edef\csv@temp{\endgroup\noexpand\pgfkeysdef{/csv head/\csv@current@col}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}% - \csv@temp% - \begingroup\edef\csv@temp{\endgroup\noexpand\pgfkeysdef{/csv head/\thecsvcol}{\the\toks0{\the\toks1}\noexpand\csv@AtEndLoop{\the\toks0{}}}}% - \csv@temp% -} - -% head line -\def\csv@processheadline{% - \csvreadnext% - \ifx\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}% - \begingroup\edef\csv@temp{\endgroup\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}% -} - -\def\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% - \ifx\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 prefix/.store in=\csv@headnameprefix,% - 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 prefix=, - 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}} +\RequirePackage{l3keys2e} + +\ProvidesExplPackage{csvsimple}{2021/06/29}{2.0.0} + {LaTeX CSV file processing} + +\cs_if_exist:NT \c__csvsim_package_expl_bool + { + \msg_new:nnn { csvsimple }{ package-loaded } + { Package~'#1'~seems~already~be~loaded! } + \bool_if:NTF \c__csvsim_package_expl_bool + { + \msg_warning:nn { csvsimple }{ package-loaded }{ csvsimple-l3 } + } + { + \msg_warning:nn { csvsimple }{ package-loaded }{ csvsimple-legacy } + } + \tex_endinput:D + } + +\keys_define:nn { csvsimple } + { + l3 .code:n = \tl_set:Nn \l__csvsim_package_expl_tl { l3 }, + legacy .code:n = \tl_set:Nn \l__csvsim_package_expl_tl { legacy }, + } + +\keys_set:nn { csvsimple } { legacy } + +\ProcessKeysPackageOptions { csvsimple } + +\RequirePackage{csvsimple-\l__csvsim_package_expl_tl} diff --git a/macros/latex/contrib/csvsimple/csvsimple.tex b/macros/latex/contrib/csvsimple/csvsimple.tex index 924a819584..305f949631 100644 --- a/macros/latex/contrib/csvsimple/csvsimple.tex +++ b/macros/latex/contrib/csvsimple/csvsimple.tex @@ -1,6 +1,6 @@ % \LaTeX-Main\ % !TeX encoding=UTF-8 -%% The LaTeX package csvsimple - version 1.22 (2021/06/07) +%% The LaTeX package csvsimple - version 2.0.0 (2021/06/29) %% csvsimple.tex: Manual %% %% ------------------------------------------------------------------------------------------- @@ -17,105 +17,12 @@ %% %% This work has the LPPL maintenance status `author-maintained'. %% -%% This work consists of all files listed in README +%% This work consists of all files listed in README.md %% \documentclass[a4paper,11pt]{ltxdoc} +\usepackage{csvsimple-doc} -\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{"}} +\usepackage{\csvpkgprefix csvsimple-legacy} \hypersetup{ pdftitle={Manual for the csvsimple package}, @@ -124,11 +31,6 @@ pdfkeywords={csv file, comma separated values, key value syntax} } -\def\version{1.22}% -\def\datum{2021/06/07}% -\makeindex - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} \begin{center} @@ -151,1963 +53,123 @@ \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. + comma separated values (CSV). |csvsimple| relies heavily on a key value + syntax which results 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. +\section{Package Options}% -Mind the following restrictions: +|csvsimple| is a stub which merely selects to load exclusively one of the +following packages: \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 either 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: +\item \href{csvsimple-l3.pdf}{\flqq The |csvsimple-l3| package\frqq}:\\ + This is the pure \LaTeX3 version of |csvsimple|. It is considered + to be the \emph{current} version. + New documents are encouraged to use this package.\par + |csvsimple-l3| is loaded with \emph{one} of the following + alternatives inside the preamble: \begin{dispListing} -\usepackage{csvsimple} +\usepackage[l3]{csvsimple} + % or alternatively (not simultaneously!) +\usepackage{csvsimple-l3} \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. Here, we also add a \refKey{/csv/head to column names prefix} to avoid -macro name clashes. - -\begin{dispExample} -\csvstyle{myTableStyle}{tabular=|r|l|c|, - table head=\hline & Person & Matr.~No.\\\hline\hline, - late after line=\\\hline, - head to column names, - head to column names prefix=MY, - } - -\csvreader[myTableStyle]{grade.csv}{}% - {\thecsvrow & \MYgivenname~\MYname & \MYmatriculation}% -\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}. - -\clearpage -\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. - Note that the macro definition is \emph{global} and may therefore override - existing macros for the rest of the document. Adding - \refKey{/csv/head to column names prefix} may help to avoid unwanted - overrides. -\end{docCsvKey} - - -\begin{docCsvKey}[][doc new=2019-07-16]{head to column names prefix}{=\meta{text}}{no default, initially empty} - The given \meta{text} is prefixed to the name of all macros generated by - \refKey{/csv/head to column names}. For example, if you use the settings -\begin{dispListing} - head to column names, - head to column names prefix=MY, -\end{dispListing} - a header entry |section| will generate the corresponding macro - |\MYsection| instead of destroying the standard \LaTeX\ |\section| macro. -\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}. +\item \href{csvsimple-l3.pdf}{\flqq The |csvsimple-legacy| package\frqq}:\\ + This is the \LaTeXe{} version of |csvsimple|. It is considered + to be the \emph{superseded} version identical to version 1.22 of |csvsimple|. + Documents based on that former version do \emph{not have to be changed} + and stay compilable in future.\par + |csvsimple-legacy| is loaded with \emph{one} of the following + alternatives inside the preamble: \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 -} +\usepackage{csvsimple} + % or alternatively (not simultaneously!) +\usepackage[legacy]{csvsimple} + % or alternatively (not simultaneously!) +\usepackage{csvsimple-legacy} \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} +\section{Differences between \texttt{csvsimple-l3} and \texttt{csvsimple-legacy}} +This section is intended for users who know |csvsimple| before version~2.00. -\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} +|csvsimple-l3| is a \emph{nearly} drop-in replacement for +|csvsimple-legacy|. Although old documents have no \emph{need} to be changed, +adopting the new \LaTeX3 version for existing documents should impose not +too much effort. Actually, it depends on how intense |pgfkeys| specific +styles were used. -Now, we can use the new rule: -\begin{dispExample} -\csvautotabular[sort by name]{grade.csv} -\end{dispExample} +That brings us to the differences between the two packages and a more precise +understanding what \emph{nearly} drop-in replacement means. The following enumeration +does not list new features of \texttt{csvsimple-l3} (if any), but takes an +upgrade point of view. -\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}|. +\item Any patches or additions using undocumented internals of |csvsimple-legacy| + will stop to function, because |csvsimple-l3| has a completely implementation. +\item |csvsimple-l3| is programmed in |expl3| code using the \LaTeX3 interfaces. + No additional packages are loaded or needed with exception of several options + which allow to access methods from |ifthen|, |etoolbox|, |longtable|, etc. + On the other hand, |csvsimple-legacy| is programmed in \LaTeXe{} with + dirty tricks from here and there. +\item The most significant change of the user interface is that the key value + engine of |csvsimple-legacy| is |pgfkeys| (root \docAuxKey*[csv]{}) while |csvsimple-l3| uses + |l3keys| (root \docAuxKey*[csvsim]{}). + Names und usage of the keys are \emph{unchanged}. + But, if + you made own |pgfkeys| \emph{styles} using the |pgfkeys| style handler, + these \emph{styles} have to be adapted to |.meta| keys of |l3keys|. + The good news is that styles + made with \docAuxCommand*{csvstyle} become |.meta| keys automatically. +\item The macro \docAuxCommand*{csvheadset} is removed. It is not supportable + by the new implementation. I never used it and I forgot why I ever wrote it + -- I hope the same is true for you. If not, |csvsimple-legacy| can be + used for documents which needs it. +\item Option \docAuxKey*[csv]{filter} is removed. Instead, \docAuxKey*[csvsim]{filter ifthen} + can be used (also true with \docAuxKey*[csv]{filter ifthen} for the old version). +\item The deprecated options + \docAuxKey*[csv]{nofilter} and \docAuxKey*[csv]{nohead} are removed. + They were not documented any more since years. Obviously, use + \docAuxKey*[csvsim]{no filter} and \docAuxKey*[csvsim]{no head} instead. +\item Compilation problems are to be expected, if an |S| column of the |siunitx| package + is used as first or last column. Documents neglecting this rule successfully + for |csvsimple-legacy|, may fail to compile with |csvsimple-l3.| +\item The \LaTeX{} counters \docCounter*{csvinputline} + and \docCounter*{csvrow} + are replaced by \LaTeX3 integers + \docCounter*{g_csvsim_inputline_int} + and \docCounter*{g_csvsim_row_int}, but accessors + \docAuxCommand*{thecsvinputline} and + \docAuxCommand*{thecsvrow} are still valid. +\item The packages |pgfrcs|, |pgfkeys|, |ifthen|, |etoolbox|, and |shellesc| + are not included anymore (include manually, if needed). +\item + \docAuxCommand*{csviffirstrow} and + \docAuxCommand*{csvifoddrow} are deprecated and replaced by + \docAuxCommand*{ifcsvfirstrow} + \docAuxCommand*{ifcsvoddrow} + which are more consistent in nomenclature. +\item For |csvsimple-l3|, data lines are allowed to begin with an backslash. +\item Assigned macros like |\myname| for e.g. the third column contain + not |\csvcoliii| anymore, but are equal to the content of |\csvcoliii| now. +\item Character code changes with \docAuxKey*[csvsim]{respect percent} etc. + and the tabulator as separator should work for |csvsimple-l3| as expected in every + situation (not always worked for |csvsimple-legacy|). +\item A drawback of |csvsimple-l3| against |csvsimple-legacy| is + a higher compilation time. This may vary by used compiler. + An example document of 5061 pages using a CSV file with 166 992 lines + took about 28 seconds with |csvsimple-legacy| and + about 51 seconds with |csvsimple-l3| on my machine + (just a singular observation, no scientific analysis at all). \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/hvfloat/Changes b/macros/latex/contrib/hvfloat/Changes index 676ac9822c..3de2f35087 100644 --- a/macros/latex/contrib/hvfloat/Changes +++ b/macros/latex/contrib/hvfloat/Changes @@ -1,4 +1,8 @@ hvfloat.sty: +2.32 2021-06-29 - make multi and multisubflots caption align with the bottom + - added graphicx option doublefullPage + - prevent vertical centering for a doublepage on the right + page, if there is no text. 2.31 2021-06-26 - suppress "Overful hbox" message for full page or double page floats 2.30 2021-06-20 - fix for introduced bug for multifloats diff --git a/macros/latex/contrib/hvfloat/doc/hvfloat.pdf b/macros/latex/contrib/hvfloat/doc/hvfloat.pdf index 918e5f5f67..3fcd284a96 100644 Binary files a/macros/latex/contrib/hvfloat/doc/hvfloat.pdf and b/macros/latex/contrib/hvfloat/doc/hvfloat.pdf differ diff --git a/macros/latex/contrib/hvfloat/doc/hvfloat.tex b/macros/latex/contrib/hvfloat/doc/hvfloat.tex index 5382371f7e..afe13b5bc4 100644 --- a/macros/latex/contrib/hvfloat/doc/hvfloat.tex +++ b/macros/latex/contrib/hvfloat/doc/hvfloat.tex @@ -2621,7 +2621,7 @@ in the inner margin on both pages. \begin{lstlisting} \hvFloat[doubleFULLPAGE,capPos=right]% {figure}% - {\includegraphics[height=\paperheight]{images/rheinsberg}}% + {\includegraphics[height=\paperheight]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed on the right-hand part of the illustration. The illustration begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2632,7 +2632,7 @@ in the inner margin on both pages. \marginnote{Fig.~\ref{fig:doubleFULLPAGE1}} \hvFloat[doubleFULLPAGE,capPos=right]% {figure}% - {\includegraphics[height=\paperheight]{images/rheinsberg}}% + {\includegraphics[height=\paperheight]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed on the right-hand part of the illustration. The illustration begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2660,7 +2660,7 @@ and the right part on page~\pageref{bar-2}. All three labels points to the same \hvFloat[doubleFULLPAGE,capPos=after]% {figure}% {\includegraphics[doubleFULLPAGE, - keepaspectratio=false]{images/rheinsberg}}% + keepaspectratio=false]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed \textbf{after} the image. The image begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2673,7 +2673,7 @@ and the right part on page~\pageref{bar-2}. All three labels points to the same \marginnote{Fig.~\ref{foo}} \hvFloat[doubleFULLPAGE,capPos=after]% {figure}% - {\includegraphics[doubleFULLPAGE]{images/rheinsberg}}% + {\includegraphics[doubleFULLPAGE]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed \textbf{after} the image. The image begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2694,7 +2694,7 @@ and the right part on page~\pageref{bar-2}. All three labels points to the same \hvFloat[doubleFULLPAGE,capPos=before]% {figure}% {\includegraphics[height=\paperheight,width=2\paperwidth, - keepaspectratio=false]{images/rheinsberg}}% + keepaspectratio=false]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed \textbf{before} the image. The image begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2705,7 +2705,7 @@ and the right part on page~\pageref{bar-2}. All three labels points to the same \marginnote{Fig.~\ref{bar}} \hvFloat[doubleFULLPAGE,capPos=before]% {figure}% - {\includegraphics[height=\paperheight,width=2\paperwidth,keepaspectratio=false]{images/rheinsberg}}% + {\includegraphics[height=\paperheight,width=2\paperwidth,keepaspectratio=false]{images/rheinsberg-1000}}% {A caption for a double-sided image that will be placed \textbf{before} the image. The image begins on the left edge of the paper. No further text is placed on the pages. A short form is used for the LOF. @@ -2762,7 +2762,7 @@ and the rest of the text area is filled with text. \begin{lstlisting} \hvFloat[doublePage,sameHeight]% {figure}% - {\includegraphics[width=2\textwidth]{images/sonne-meer}}% + {\includegraphics[doublefullPage]{images/sonne-meer}}% [A doublepage image with a caption on the right side of the right part.]% {A caption for a double-sided image that will be placed on the right side of the right-hand part of the illustration. The illustration begins on the left edge of @@ -2777,7 +2777,7 @@ and the rest of the text area is filled with text. \marginnote{Fig. \ref{fig:doublePage0sH}} \hvFloat[doublePage,sameHeight]% {figure}% - {\includegraphics[width=2\textwidth]{images/sonne-meer}}% + {\includegraphics[doublefullPage]{images/sonne-meer}}% [A doublepage image with a caption on the right side of the right part.]% {A caption for a double-sided image that will be placed on the right side of the right-hand part of the illustration. The illustration begins on the left edge of @@ -2859,7 +2859,7 @@ and the rest of the text area is filled with text. \Blindtext -\Blindtext +%\Blindtext diff --git a/macros/latex/contrib/hvfloat/doc/images/felsen-wasser-small.pdf b/macros/latex/contrib/hvfloat/doc/images/felsen-wasser-small.pdf new file mode 100644 index 0000000000..44f19b9258 Binary files /dev/null and b/macros/latex/contrib/hvfloat/doc/images/felsen-wasser-small.pdf differ diff --git a/macros/latex/contrib/hvfloat/doc/images/sonne-meer.jpg b/macros/latex/contrib/hvfloat/doc/images/sonne-meer.jpg new file mode 100644 index 0000000000..e0e4b910a7 Binary files /dev/null and b/macros/latex/contrib/hvfloat/doc/images/sonne-meer.jpg differ diff --git a/macros/latex/contrib/hvfloat/latex/hvfloat-fps.sty b/macros/latex/contrib/hvfloat/latex/hvfloat-fps.sty index 99b7cbfbab..a86244b9e5 100644 --- a/macros/latex/contrib/hvfloat/latex/hvfloat-fps.sty +++ b/macros/latex/contrib/hvfloat/latex/hvfloat-fps.sty @@ -1,7 +1,6 @@ -%% $Id: hvfloat-fps.sty 35 2020-10-31 07:41:00Z herbert $ +%% $Id: hvfloat-fps.sty 121 2021-06-20 13:36:11Z herbert $ %% \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{hvfloat-fps}[2017/09/16 setting float objects] %% %% IMPORTANT NOTICE: %% @@ -16,9 +15,10 @@ %% DESCRIPTION: %% `hvfloat-fps' offers global placement of floats %% -\def\fileversion{0.02} -\def\filedate{2017/09/20} -\message{`hvfloat-fps' v\fileversion, \filedate\space (Herbert Voss)} +\def\fileversion{0.03} +\def\filedate{2020/06/20} +\ProvidesPackage{hvfloat-fps}[\filedate\space v\fileversion\space global float position setting (hv)] +%\message{`hvfloat-fps' v\fileversion, \filedate\space (Herbert Voss)} % \RequirePackage{xkeyval} % diff --git a/macros/latex/contrib/hvfloat/latex/hvfloat.sty b/macros/latex/contrib/hvfloat/latex/hvfloat.sty index 82bf238e6d..3d54b4f981 100644 --- a/macros/latex/contrib/hvfloat/latex/hvfloat.sty +++ b/macros/latex/contrib/hvfloat/latex/hvfloat.sty @@ -1,4 +1,4 @@ -%% $Id: hvfloat.sty 122 2021-06-26 12:35:53Z herbert $ +%% $Id: hvfloat.sty 126 2021-06-29 12:56:04Z herbert $ %% %% %% IMPORTANT NOTICE: @@ -15,7 +15,7 @@ %% `hvfloat' offers rotating of captions and objects for floats %% \NeedsTeXFormat{LaTeX2e} -\def\fileversion{2.31} +\def\fileversion{2.32} \def\filedate{2021/06/26} %\message{`hvfloat' v\fileversion, \filedate\space (Herbert Voss)} \ProvidesPackage{hvfloat}[\filedate\space v\fileversion\space special floating objects (hv)] @@ -59,8 +59,6 @@ \RequirePackage{stfloats}% for bottom floats in a twocolumn mode \fi % - - \providecommand*\LenToUnit[1]{\strip@pt\dimexpr#1*\p@/\unitlength} \newlength\hvObjectWidth @@ -175,7 +173,6 @@ \define@boolkey{hvSet}[hv@]{sameHeight}[true]{\@nameuse{hv@sameHeight#1}}% Write the caption only as text \define@boolkey{hvSet}[hv@]{Debug}[true]{}% give more infos in the terminal - \newif\ifhv@fullpage \newif\ifhv@FULLPAGE \newif\ifhv@doubleFULLPAGE @@ -268,10 +265,11 @@ }} \def\hv@vskip{\vspace{\hvMultiFloatSkip}} - % \newlength\hvAboveCaptionSkip \newlength\hvBelowCaptionSkip +\newlength\hv@dblfptop +\newlength\hv@fptop \newcount\hv@@capPos \newlength\fboxlinewidth @@ -290,6 +288,18 @@ \setlength\belowcaptionskip{\hvBelowCaptionSkip}% } +\newcommand\hv@set@noverticalSpace{% no space on top for a float page + \let\hv@dblfptop\@dblfptop + \let\hv@fptop\@fptop + \global\setlength{\@dblfptop}{0\p@}% + \global\setlength{\@fptop}{0\p@}% +} + +\newcommand\hv@reset@noverticalSpace{% + \global\setlength{\@dblfptop}{\hv@dblfptop}% + \global\setlength{\@fptop}{\hv@fptop}% +} + \providecommand\figcaption[2][]{}% \providecommand\tabcaption[2][]{}% \providecommand\tabcaptionbelow[2][]{}% @@ -341,6 +351,11 @@ \def\Gin@eheight{\paperheight}% \Gin@boolkey{false}{iso}% } +\define@key{Gin}{doublefullPage}[true]{% + \def\Gin@ewidth{\dimexpr2\paperwidth-2in-2\evensidemargin}% +% \def\Gin@eheight{\paperheight}% + \Gin@boolkey{true}{iso}% +} \define@key{Gin}{doubleFULLPAGEbindCorr}[true]{% \def\Gin@ewidth{\the\dimexpr2\paperwidth-2\hvSet@bindCorrection\relax}% \def\Gin@eheight{\paperheight}% @@ -1051,6 +1066,7 @@ \global\setlength\hv@leftPageObjectWidth{\dimexpr\paperwidth-1in-\evensidemargin-\hvSet@bindCorrection}% \global\setlength\hv@tempWidthA{\the\dimexpr1in+\oddsidemargin-\hvSet@bindCorrection}% \xdef\hv@caption@format@temp{\hv@caption@format}% it gets lost otherwise for next afterpage + \setlength\@dblfpbot{0\p@ \@plus 1fil}% \global\hv@switchTypefalse % \endgroup% started at main macro \hvFloat \setcounter{hv@tempCNTfigA}{\value{figure}}% @@ -1136,6 +1152,7 @@ % \def\do@hvFloat@doublePageCaptionRightObjectLeft#1{% left part of the object \begin{\hv@floatType*}[!t] + \hv@set@noverticalSpace \hfuzz=\maxdimen \let\c@hv@tempCNTfigA\c@figure \let\c@hv@tempCNTtabA\c@table @@ -1155,21 +1172,23 @@ \fi \ifhv@global@sameHeight \hv@typeout{text should be of same height of both pages}% - \par\phantom{\parbox{\textwidth}{\caption*{\hv@longCap}}}% -% \vspace{\textfloatsep}% + \par\noindent\phantom{\parbox{\textwidth}{\caption*{\hv@longCap}}}% +% \vspace{-2pt}% \fi + \hv@reset@noverticalSpace \end{\hv@floatType*}% } \def\do@hvFloat@doublePageCaptionRightObjectRight#1{% right part of the object \begin{\hv@floatType*}[!t] + \hv@set@noverticalSpace \hfuzz=\maxdimen \expandafter\hvFloatSet\expandafter{\hv@save@setting}% \global\savebox\hvObjectBox{\ifhv@useOBox\usebox{\hvOBox}\else\hv@floatObject\fi}% \hspace*{-\hv@tempWidthA}% \savebox\hv@rightBox{\clipbox*{\hv@leftPageObjectWidth{} -\depth{} \width{} \height{}}{\usebox\hvObjectBox}}% - \global\setlength\hv@tempWidthB{\dimexpr\textwidth-\wd\hv@rightBox-\hvSet@bindCorrection+1in+\oddsidemargin-\hv@floatCapSep\relax}% - \hv@typeout{Height of right box: \the\ht\hv@rightBox}% - \hv@typeout{Depth of right box : \the\dp\hv@rightBox}% + \global\setlength\hv@tempWidthB{\dimexpr\textwidth-\wd\hv@rightBox-\hvSet@bindCorrection+1in+\oddsidemargin-\hv@floatCapSep\relax}% + \hv@typeout{Height of right box: \the\ht\hv@rightBox}% + \hv@typeout{Depth of right box : \the\dp\hv@rightBox}% \ifdim\dp\hv@rightBox > \z@ \raisebox{\depth}{\usebox\hv@rightBox}% \else @@ -1227,6 +1246,7 @@ \ifx\hv@label\@empty\else\label{\hv@label-cap}\fi \fi \vspace{0pt}% + \hv@reset@noverticalSpace \end{\hv@floatType*} } % @@ -1698,10 +1718,9 @@ \def\getMultiCaptionAndLabel{% \global\sbox\hvCaptionBox{\minipage[b]{\linewidth}% + \captionsetup{aboveskip=\z@,belowskip=\z@,position=below,parbox=none}%,skip=-1ex}% \expandafter\hvFloatSet\expandafter{\hv@save@setting}% -% \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi - \setlength\belowcaptionskip{5pt}% - \setlength\abovecaptionskip{0pt}% + \parskip=-0.5\baselineskip \hv@cntb=\clist_count:N\l_clist_Type \advance\hv@cntb by \@ne \hv@cnta=1 @@ -1720,6 +1739,7 @@ \advance\hv@cnta by \@ne \ifnum\hv@cnta<\hv@cntb \repeat + \vspace{-\baselineskip}% no vspace at the end \endminipage}% } @@ -1731,7 +1751,6 @@ \minipage{\columnwidth}% \fi \expandafter\hvFloatSet\expandafter{\hv@save@setting}% -% \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi \ifx\hvSet@objectPos\hv@Right\raggedleft\else \ifx\hvSet@objectPos\hv@Left\raggedleft\else \ifx\hvSet@objectPos\hv@Center\centering @@ -1758,9 +1777,9 @@ \endminipage}% } \def\getMultiSubCaptionAndLabel{% - \global\sbox\hvCaptionBox{\minipage{\linewidth}% + \global\sbox\hvCaptionBox{% + \minipage{\linewidth}% \expandafter\hvFloatSet\expandafter{\hv@save@setting}% -% \ifx\hv@caption@format\@empty\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi \setlength\belowcaptionskip{5pt}% \setlength\abovecaptionskip{0pt}% \xdef\@captype{\clist_item:Nn\l_clist_Type{1}}% the same for all subfloats @@ -1780,6 +1799,7 @@ \expandafter\hvFloatSet\expandafter{\hv@save@setting}% \ifhv@vFill \minipage[b][\textheight][s]{\columnwidth}% + \captionsetup{belowskip=0pt}% \else \minipage{\columnwidth}% \fi @@ -1825,7 +1845,6 @@ \edef\@tempa{\clist_item:Nn\l_clist_Label{1}}% the main label at the end \ifx\@tempa\@empty \else -% \addtocounter{\@captype}{-1}% to get the same -ref as "label"-cap \edef\@temp{hv@p\@captype}% \refstepcounter{\@temp}% \expandafter\label\expandafter{\@tempa}% diff --git a/macros/latex/contrib/keyfloat/README.txt b/macros/latex/contrib/keyfloat/README.txt index f9fa62fb76..f9586fd2ba 100644 --- a/macros/latex/contrib/keyfloat/README.txt +++ b/macros/latex/contrib/keyfloat/README.txt @@ -1,7 +1,7 @@ The LaTeX keyfloat package Provides a key/value interface for generating floats. -v2.05 +v2.06 Copyright 2016-2021 Brian Dunn — www.BDTechConcepts.com LaTeX Project Public License, version 1.3 diff --git a/macros/latex/contrib/keyfloat/keyfloat.dtx b/macros/latex/contrib/keyfloat/keyfloat.dtx index 5baa10608e..a729c86a4b 100644 --- a/macros/latex/contrib/keyfloat/keyfloat.dtx +++ b/macros/latex/contrib/keyfloat/keyfloat.dtx @@ -1,7 +1,7 @@ % % \iffalse meta-comment % -% Copyright 2016 Brian Dunn +% Copyright 2016--2021 Brian Dunn % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 @@ -17,7 +17,7 @@ % \iffalse %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{keyfloat} -% [2021/06/11 v2.05 Key/value interface for floats and subfloats.] +% [2021/06/29 v2.06 Key/value interface for floats and subfloats.] % %<*driver> \documentclass{ltxdoc} @@ -71,6 +71,8 @@ \newunicodechar{‡}{\ddag} \newunicodechar{⚠}{\textwarning} + + \usepackage{metalogo} \makeatletter \@ifpackageloaded{erewhon}{ @@ -90,6 +92,8 @@ \usepackage[log-declarations=false]{xparse} + + \usepackage[svgnames]{xcolor} \definecolor{myurlcolor}{rgb}{0,0,.7} \definecolor{mylinkcolor}{rgb}{.7,0,0} @@ -235,6 +239,30 @@ frametitlerulewidth=1pt,frametitleaboveskip=5pt,% +\usepackage{splitidx} + +\newindex[Index of Objects]{idx} +\newindex[General Index]{gen} +% \newindex[Troubleshooting Index]{trb} +\newindex[Index of Indexes]{meta} + +\makeindex + +\newcommand*{\gindex}[1]{\sindex[gen]{#1}\ignorespaces} + +% \trouble[watchout phrase]{index entry} +\newcommand*{\trouble}[2][]{% +\ifblank{#1}{}{% + \watchout[#1]% +}% +% \sindex[trb]{#2}% +\gindex{#2}% +\ignorespaces% +} + + + + \newcommand{\testtable}{% \begin{tabular}{cc}% \hline\rule{0pt}{2.7ex}% @@ -255,7 +283,7 @@ D & E & F \\ \newcommand{\mainsubarg}{empty or ``\texttt{subgrp}''} -\newcommand{\keyvalsarg}{keys/values} +\newcommand{\keyvalsarg}{keys \Slash values} \setlength{\floatsep}{5ex plus 1ex minus 1ex} \setlength{\dblfloatsep}{5ex plus 1ex minus 1ex} @@ -300,6 +328,10 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% +\setlength{\marginparsep}{1em} +\setlength{\marginparpush}{.7ex} +\setlength{\IndexMin}{40ex} + \setcounter{IndexColumns}{2} \DisableCrossrefs @@ -317,7 +349,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% %<*package> % \fi % -% \CheckSum{1320} +% \CheckSum{1392} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -357,6 +389,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \changes{v2.03}{2021/05/28}{2021/05/28} % \changes{v2.04}{2021/06/08}{2021/06/08} % \changes{v2.05}{2021/06/11}{2021/06/11} +% \changes{v2.06}{2021/06/29}{2021/06/29} @@ -424,22 +457,23 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % two small figures placed vertically next to % one larger figure. % -% \vfill -% -% \noindent % As an example, a typical command to include a figure with a framed image of half \cs{linewidth} % could be: \\ % \hspace*{1em}\verb|\keyfig*[hbp]{f,lw=.5,c={A caption},l={fig:label}}{image}| % -% \vfill -% -% \noindent \pkg{keyfloat} uses the \pkg{caption}, \pkg{subcaption}, +% \pkg{keyfloat} uses the \pkg{caption}, \pkg{subcaption}, % \pkg{newfloat} or \pkg{float}, and \pkg{wrapfig} packages, -% \watchout +% \watchout[incompatible packages] % and cannot be used with the % \pkg{subfig}, \pkg{subfigure}, \pkg{subfloat}, \pkg{floatrow}, % or \pkg{floatflt} packages. % +% See the \nameref{sec:indexgen} for an index of topics and troubleshooting. +% \watchout[Need help?] +% +% For the latest updates, see \nameref{sec:updates}. +% \margintag{What's new?} +% % \vfill % % \footnotesize @@ -585,8 +619,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \margintag{examples} % the resulting float. % -% A customized index is included at the back of the documentation. +% A customized index is included at the back of the documentation, % \margintag{index} +% including troubleshooting issues. % % Blue margin tags are used to help quickly find information, and often % \margintag{margin tags} @@ -595,10 +630,37 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % Several warnings are noted in the text. Watch out for these special cases. % \watchout[warnings] % -% See the ``troubleshooting'' section of the index for help -% \margintag{problems} -% with specific problems which may occur. +% ^^A % See the ``troubleshooting'' section of the index for help +% ^^A % \margintag{problems} +% ^^A % with specific problems which may occur. % +% \subsection{Updates} +% +% \label{sec:updates} +% +% Recent changes include the following: +% \begin{description} +% \item[v2.06:] Added shared keys for groups of floats or subfloats. +% Added the \optn{kar} key to keep the aspect ratio of an image. +% Removed \texttt{:} for an empty caption. +% Warns if an image is too wide to fit. +% \item[v2.02, v2.04:] Added keys for wrapped floats. +% \end{description} +% +% \subsection{Other float-related packages} +% +% Several other \LaTeX\ packages related to floats include: +% \begin{description} +% \item[\pkg{caption} and \pkg{subcaption}:] Improved control over captions. +% \item[\pkg{floatrow}:] A macro-based package for creating floats; including captions, +% footnotes, and rows of floats. +% \item[\pkg{hvfloat}:] A key \Slash value system allowing the easy rotation of +% captions and floats. +% \item[\pkg{nccfloats}:] Macros for minipage floats and side-by-side floats. +% \item[\pkg{newfloat}:] Macros for the creationg of float environments. +% \item[\pkg{rotfloat}:] Environments for rotated floats. +% \item[\pkg{subfig}:] Macros to add subfloats inside a float. +% \end{description} % % % \clearpage @@ -710,25 +772,29 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{docsidebar} % % -% \DescribeEnv{keyfloats} * \oarg{loc} \marg{num columns} \\ +% \DescribeEnv{keyfloats} * \oarg{loc} \marg{num columns} \oarg{shared \keyvalsarg} \\ % A group of figures or tables typeset in rows. May be nested, [H], [W], or [M]. +% The optional shared \keyvalsarg\ are passed to each object within. % See \cref{ex:keyfloats}. % -% \DescribeEnv{keysubfigs} * \oarg{loc} \marg{numcols} \marg{keys} \\ +% \DescribeEnv{keysubfigs} * \oarg{loc} \marg{numcols} \marg{keys} \oarg{shared \keyvalsarg} \\ % A group of subfigures typeset in rows. % May \emph{not} be nested. May be [H], [W], or [M]. +% The optional shared \keyvalsarg\ are passed to each object within. % See \cref{ex:keysubfigs}. % % \needspace{2\baselineskip} -% \DescribeEnv{keysubtabs} * \oarg{loc} \marg{numcols} \marg{keys} \\ +% \DescribeEnv{keysubtabs} * \oarg{loc} \marg{numcols} \marg{keys} \oarg{shared \keyvalsarg} \\ % A group of subtables typeset in rows. % May \emph{not} be nested. May be [H], [W], or [M]. +% The optional shared \keyvalsarg\ are passed to each object within. % See \cref{ex:keysubtabs}. % % \needspace{2\baselineskip} -% \DescribeEnv{keysubfloats} * \oarg{loc} \marg{float type} \marg{numcols} \marg{keys} \\ +% \DescribeEnv{keysubfloats} * \oarg{loc} \marg{float type} \marg{numcols} \marg{keys} \oarg{shared \keyvalsarg} \\ % A group of subfloats typeset in rows. % May \emph{not} be nested. May be [H], [W], or [M]. +% The optional shared \keyvalsarg\ are passed to each object within. % % \DescribeEnv{keywrap} \marg{width of keyfloat} \marg{keyfloat} \\ % Displays a keyfloat next to an environment of text. @@ -800,7 +866,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \begin{keytable}[bp]{c={Keys and values — part I},l={tab:keyvals},stretch=1.5} % \centering -% \index{keys>and values} +% \gindex{keys>and values} % \begin{threeparttable} % \small % \begin{tabular}{>{\ttfamily}cc>{\raggedright}p{2.5in}>{\centering\arraybackslash}>{\ttfamily\arraybackslash}p{1in}} @@ -830,7 +896,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \bottomrule % \end{tabular} % \begin{tablenotes} -% \item[a:] All the keys in Part I may be used with the +% \item[a:] All the keys in Part I may be used with the main keys of the % \env{keysubfigs}, \env{keysubtabs}, and \env{keysubfloats} environments. % \item[b:] Artist \Slash author keys: % |al| is an artist's last name, |aul| is an author's last name, etc. @@ -851,7 +917,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \begin{keytable}{ % c={Keys and values — part II},cont,stretch=1.5} % \centering -% \index{keys>and values} +% \gindex{keys>and values} % \begin{threeparttable} % \small % \begin{tabular}{>{\ttfamily}cc>{\raggedright}p{2.5in}>{\centering\arraybackslash}>{\ttfamily\arraybackslash}p{1in}} @@ -868,8 +934,10 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % For wrapped objects, may be used with \optn{ww} for a smaller item % with a larger caption. % & w=2in \\ -% h & --- & Set the actual height, images only. & w=2in \\ -% s & --- & Set the image scale, images only. & s=3 \\ +% h & --- & Set the actual height. Images only. & w=2in \\ +% kar & --- & Keep aspect ratio: Use with \optn{w} or \optn{lw}, along with \optn{h}, +% to fit an image into a given area. Images only. & kar \\ +% s & --- & Set the image scale. Images only. & s=3 \\ % r & --- & Set the rotation angle; counter-clockwise degrees. & r=90 \\ % f & --- & Selects a loose frame with the current \cs{fboxsep}. % Only rotated with \cs{keyfig}. & f \\ @@ -888,13 +956,14 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % ww & --- & Sets the total width of the wrapped item. % May be more than the \optn{w} or \optn{lw} width. & ww=2in \\ % va & --- & Sets the vertical alignment of the outermost minipage container for the keyfloat. -% Defaults to 'c'. +% Defaults to 'c'. Ignored by \env{subfigure}, \env{subtable}. % & va=t \\ % \bottomrule % \end{tabular} % \begin{tablenotes} -% \item[c:] None of the keys in Part II are used in the -% \env{keysubfigs}, \env{keysubtabs}, and \env{keysubfloats} environments. +% \item[c:] None of the keys in Part II are used in the main keys of the +% \env{keysubfigs}, \env{keysubtabs}, or \env{keysubfloats} environments, +% but may be used in the optional shared keys to be passed to each object within. % \end{tablenotes} % \end{threeparttable} % \end{keytable} @@ -904,14 +973,14 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % except for the following: % % The keys labeled "Sub"\margintag{subfloat keys} -% \index{subfloat>keys}\index{keys>subfloats} +% \gindex{subfloat>keys}\gindex{keys>subfloats} % may be used for the \env{keysubfigs} and % \env{keysubtabs} environments, which group a number of subfloats together under % one master float. The master float has its own caption, label, and text, and % each subfloat inside the group likewise has its own set of keys. % % \env{keyfloats} does not accept any keys at all.\margintag{keyfloats keys} -% \index{keyfloats>keys}\index{keys>keyfloats} +% \gindex{keyfloats>keys}\gindex{keys>keyfloats} % % The ``artist'' keys |ap|, |af|, |al|, and |as| are only used by figures. % @@ -928,7 +997,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % % \begin{keytable}{c={Caption-related key combinations},l=tab:captions,stretch=1.5} -% \index{caption>options} +% \gindex{caption>options} % \centering % \begin{threeparttable} % \small @@ -963,7 +1032,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % for floats placed |[W]|. % % \begin{keytable}{c={Key \optn{wp}: Wrapped float placement options},l=tab:wrapplacement} -% \index{float>wrapped placement}\index{wrapped float placement} +% \gindex{float>wrapped placement}\gindex{wrapped float placement} % \centering % \begin{tabular}{ccl} % \toprule @@ -1023,7 +1092,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \margintag{natural size} % because no width or height modifiers were specified. When used alone like this, % a regular float is created. -% \index{image>natural size} +% \gindex{image>natural size} % % % \begin{dtxexample}[\Cref{fig:figbox}]{Figure with arbitrary contents\label{ex:keyfigbox}} @@ -1033,7 +1102,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % The \cs{keyfigbox} creates a figure with a box of arbitrary contents, instead of % an image from a file. Its default width is the full \cs{linewidth},\margintag{default width} -% \index{float>default width} +% \gindex{float>default width} % unless |w| or |lw| keys are used. % % @@ -1060,8 +1129,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % See \cref{ex:keytable}. % % For large tables, use the \pkg{longtable} or \pkg{supertabular} packages. -% \margintag{large tables}\index{tables>large} -% \index{troubleshooting>large tables} +% \margintag{large tables} +% \trouble{table>large} % % % \begin{dtxexample}[\Cref{tab:environment}] @@ -1096,6 +1165,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % }{image} % \end{dtxexample} % +% \gindex{text>added} +% \gindex{float>text added} +% % Width is fixed at 2\,in, a tight frame is specified (\cs{fboxsep} of 0\,pt), % a short caption appears in the List of Figures, and the additional text % is using the default fully-justified alignment. @@ -1111,8 +1183,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \Cref{fig:linewidth} is half of \cs{linewidth} in size. % \margintag{\cs{linewidth}} -% \index{image>\cs{linewidth}}\index{\cs{linewidth}} -% \index{subfloat>\cs{linewidth}}\index{keyfloats>\cs{linewidth}} +% \gindex{image>\cs{linewidth}}\gindex{\cs{linewidth}} +% \gindex{subfloat>\cs{linewidth}}\gindex{keyfloats>\cs{linewidth}} % When the |lw| key is used inside a \env{keyfloats} or \env{keysubfigs} environment, % the \cs{linewidth} will be proportional to the sub-box for each element. % When used alone, such as here, the \cs{linewidth} is the full width of the text on @@ -1160,8 +1232,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % Unless a width is given, a box is the full \cs{linewidth}. % \margintag{rotated whitespace} % When rotated, this extra horizontal space is rotated into extra vertical space. -% \index{rotate>box width and vertical space}\index{\cs{linewidth}>with rotation} -% \index{troubleshooting>rotating>extra space} +% \gindex{rotate>box width and vertical space}\gindex{\cs{linewidth}>with rotation} +% \trouble{rotate>extra space} % To avoid this extra space, set a |w| or |lw| to be wide enough % \watchout[box width] % for the table or other contents, @@ -1169,8 +1241,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % vertical space than necessary. % % Unlike an image, the frame of a box does not rotate with its contents. -% \margintag{frame rotation}\index{frame>rotation} -% \index{troubleshooting>rotating>frame} +% \margintag{frame rotation}\gindex{frame>rotation} +% \trouble{rotate>frame} % % \clearpage % @@ -1179,10 +1251,13 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \keyfig[H]{f,w=1in,c={A keyfig [H]},l=fig:here}{image} % \end{dtxexample} % +% \gindex{h=[H]ere placement} +% \gindex{float>h=[H]ere placement} +% \gindex{float>inline} % \Cref{tab:here} and \Cref{fig:here} are to be placed ``[H]ere'', and therefore may appear % \watchout[Out of sequence] % out-of-sequence with surrounding figures. -% \index{troubleshooting>float out of sequence} +% \trouble{float>out of sequence} % Place a \cs{clearpage} before or after to re-sync, if necessary. % % @@ -1192,14 +1267,16 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \keyfig[H]{f,cstar={A starred caption}}{image} % \end{dtxexample} % +% \gindex{float>unnumbered} +% % A starred caption creates a float without a number, and without % an entry in the List of Figures unless there is a non-empty short caption. % (See the next example.) % % Labels cannot be used when there is no number for a float. -% \watchout[No label] -% \index{troubleshooting>missing label} -% +% \trouble[No label]{label>missing} +% \trouble{label>unnumbered float} +% \trouble{float>unnumbered>no label} % % \begin{dtxexample} % [See fig: ``Starred caption with a short caption''.] @@ -1224,6 +1301,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % }{image2} % \end{dtxexample} % +% \gindex{float>inline without caption} +% % By using [H] and |cstar={}|, the image is placed inline % without a number or \acro{LOF} entry. % @@ -1241,9 +1320,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % }{Some contents.} % \keyfig{c=Next to a \cs{keyparbox},l=fig:nexttoparbox}{image} % \end{keyfloats} -% \keyparbox[H]{f,lw=.5}{A \cs{keyparbox} [H], outside the row.} +% \keyparbox[H]{f,lw=.5}{A \cs{keyparbox} [H], outside the keyfloats.} % \end{dtxexample} % +% \gindex{float>without caption} +% % A \cs{keyparbox} is a \cs{keyfigbox} with |cstar={}|, % and is mostly useful as an information box inside a row or a set of subfloats. % @@ -1252,64 +1333,97 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \clearpage % -% \subsubsection{Groups of floats} +% \subsubsection{Groups of floats, shared keys, keep aspect ratio} % % \begin{dtxexample}[\Cref{fig:firstinrow} to \Cref{tab:seventhinrow}]{Groups of figures — \env{keyfloats} environment\label{ex:keyfloats}} % \begin{keyfloats}{2} -% \keyfig{lw=1,f,c={First in a group}, +% \keyfig{lw=1,c={First in a group}, % l=fig:firstinrow,tl={\cs{raggedright} text} % }{image} % \keyparbox{}{\centering A \cs{keyparbox} describing something. % \par With several paragraphs.} -% \begin{keyfloats}{2} -% \keyfig{lw=1,c={Third in a group}, -% l=fig:thirdinarow}{image} -% \keyfig{lw=1,c={Fourth in a group}}{image2} -% \keyfig{lw=1,c={Fifth in a group}}{image} -% \keyfig{lw=1,c={Sixth in a group}, -% l=fig:sixthinarow}{image2} +% \begin{keyfloats}{2}[f,lw=1,h=3em,kar,va=t] +% \keyfig{lw=1,c={Third in a group}, +% l=fig:thirdinarow}{image} +% \keyfig{lw=1,c={Fourth in a group, with a longer caption}}{image2} +% \keyfig{lw=1,c={Fifth in a group}}{image} +% \keyfig{lw=1,c={Sixth in a group}, +% l=fig:sixthinarow}{image2} % \end{keyfloats} % \keytab{c={Seventh in a group},l=tab:seventhinrow}{\testwidetable} % \end{keyfloats} % \end{dtxexample} % % -% \Cref{fig:firstinrow} to \cref{tab:seventhinrow} are in a \env{keyfloats} environment. -% Furthermore, \Crefrange{fig:thirdinarow}{fig:sixthinarow} are in an -% additional nested \env{keyfloats} environment, forming a small box of floats inside -% the larger group. -% % The \env{keyfloats} environment takes an argument for the number of columns. -% Additional floats are automatically placed on following rows. +% Additional floats +% \margintag{automatic layout} +% are automatically placed on following rows. % Changing the number of columns will cause the floats to automatically readjust as % necessary. Leftovers will be centered on the last row. +% An optional argument +% \margintag{shared keys} +% \gindex{group>shared keys} +% \gindex{float>shared keys} +% \gindex{keys>shared in a group} +% may contain keys and values which are passed to each object +% inside the group. +% +% \Cref{fig:firstinrow} to \cref{tab:seventhinrow} are in a \env{keyfloats} environment. +% Furthermore, +% \margintag{nested groups} +% \Crefrange{fig:thirdinarow}{fig:sixthinarow} are in an +% additional nested \env{keyfloats} environment, forming a small box of floats inside +% the larger group. +% In this subgroup, shared keys are set so that each image is framed +% and keeps its aspect ratio while being resized to fit a fixed width and height. % % Note that \cs{linewidth} is adjusted for each row and nested row, % \watchout[\cs{linewidth}] -% so the |lw| key will need to be changed if a float is moved to a different nesting level. -% \index{troubleshooting>\cs{linewidth}}\index{\cs{linewidth}>subfloats} -% \index{subfloat>\cs{linewidth}} +% so the |lw| key may need to be changed if a float is moved to a different nesting level. +% \trouble{\cs{linewidth}}\gindex{\cs{linewidth}>subfloats} +% \gindex{subfloat>\cs{linewidth}} % % Fixed-width or fixed-height floats may be too large to fit % \watchout[image too large] -% if they are moved into a group. +% if they are moved into a group. A warning is issued if so. % It is the user's responsibility to adjust |w|, |h|, or |lw| as necessary. -% \index{troubleshooting>image too large} +% \trouble{image>too large} +% To allow images to automatically adjust, use |lw=1| or less, which adjusts +% to the \cs{linewidth}. % -% Keyfloats may be located [H], [M], or located [W] set with half the line width:\\ +% Keyfloats may be located +% \margintag{location} +% [H], [M], or located [W] set with half the line width:\\ % \hspace*{2em}|\begin{keyfloats}[H]{2}| \dots % -% Keyfloats may be starred to span both columns in a two-column format: \\ +% Keyfloats may be starred +% \margintag{two columns} +% to span both columns in a two-column format: \\ % \hspace*{2em}|\begin{keyfloats}*{2}| \dots % +% As shown in the sub group above, +% \margintag{grid of images} +% \gindex{group>nested} +% \gindex{float>nested group} +% \gindex{image>grid of} +% \gindex{image>keep aspect ratio} +% \gindex{aspect ratio} +% \gindex{keep aspect ratio} +% to display a group of images of varying shape inside a grid, use the shared option to +% select a maximum size, keep aspect ratio, and align at the top so that captions +% of varying length may wrap below each image: +% \begin{sourceverb} +% \begin{keyfloats}{2}[lw=1,h=3em,kar,va=t] +% ... +% \end{keyfloats} +% \end{sourceverb} +% % % \clearpage % % \subsubsection{Subfloats} % -% -% -% % \begin{dtxexample}[\Cref{fig:subfigs}]{Subfigures — \env{keysubfigs} environment\label{ex:keysubfigs}} % \begin{keysubfigs}{3}{c=Subfigures,l=fig:subfigs} % \keyfig{lw=1,f,c={First subfigure}, @@ -1319,9 +1433,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % t=Lots of lots of lots of lots of text.} % {image2} % \begin{keyfloats}{1} -% \keyfig{lw=1,f,c={Third subfigure},l=fig:thirdsubfig}{image} -% \keytab{c={Fourth subfigure},l=fig:fourthsubfig}{\testtable} -% \keyfig{lw=.5,f,c={Fifth subfigure},l=fig:fifthsubfig}{image} +% \keyfig{lw=1,f,c={Third subfigure},l=fig:thirdsubfig}{image} +% \keytab{c={Fourth subfigure},l=fig:fourthsubfig}{\testtable} +% \keyfig{lw=.5,f,c={Fifth subfigure},l=fig:fifthsubfig}{image} % \end{keyfloats} % \end{keysubfigs} % \end{dtxexample} @@ -1339,28 +1453,43 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % subcaption does not appear in the \acro{LOF}/\acro{LOT}. % % All subfloats are forced to have the same type as -% its containing float.\index{troubleshooting>mixed subfloats} +% its containing float.\trouble{mixed subfloats} % \watchout[mixed subfloats] % A table inside a figure will be labeled as a figure, for example. % This avoids miss-labeling as each subfloat must clearly be identified % as a child of its containing float. % % \env{keysubfigs} and \env{keysubtabs} may not be used inside\watchout[nested subfloats] -% \index{troubleshooting>nested subfloats}\index{subfloat>nested} +% \trouble{nested subfloats}\gindex{subfloat>nested} % the \env{keyfloats} environment, % and cannot be nested inside each other. (No subfloat |12aa|, |12ab|, |12ba|, etc.) % % The \env{keyfloats} environment may be used inside \env{keysubfigs} or -% \margintag{nested keyfloats}\index{keyfloats>nested} +% \margintag{nested keyfloats}\gindex{keyfloats>nested} % \env{keysubtabs} to gather subfloats together, such as the % three right-most figures in \cref{fig:subfigs}. % -% Subfloats may be located [H], [M], or located [W] set with half the line width: \\ +% Subfloats may be located +% \margintag{location} +% [H], [M], or located [W] set with half the line width: \\ % \hspace*{2em}|\begin{keysubfigs}[H]{3}{|key/vals \dots|}| % -% Subfloats may be starred to span both columns in a two-column format: \\ +% Subfloats may be starred +% \margintag{two columns} +% to span both columns in a two-column format: \\ % \hspace*{2em}|\begin{keysubfigs}*{2}{|key/vals \dots|}| % +% A group of subfloats +% \margintag{shared keys} +% \gindex{group>shared keys} +% \gindex{subfloat>shared keys} +% \gindex{keys>shared in a group} +% may have an optional argument for shared keys and values, +% which are then passed to each subfloat within. +% +% The vertical alignment +% \watchout[va] +% option |va| does not work with subfloats. % % \begin{dtxexample}[\Cref{tab:subtabs}]{Subtables [H] — \env{keysubtabs} environment\label{ex:keysubtabs}} % \begin{keysubtabs}[H]{2}{c=Subtables [H],l=tab:subtabs} @@ -1375,6 +1504,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \subsubsection{Continued floats} % +% \gindex{float>continued} +% \gindex{continued float} +% % The |cont| key may be used to generate a ``continued'' float. % The continued float receives the same number as the previous float, % and it is assumed that they are the same float, except that @@ -1393,7 +1525,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \clearpage % \subsubsection{Continued subfloats} -% +% +% \gindex{float>subfloat continued} +% \gindex{subfloat>continued} +% \gindex{continued subfloat} +% % The \env{keysubfigs} and \env{keysubtabs} environments may also % be given the |cont| key. % The containing environment's float receives the same number as the previous float @@ -1415,6 +1551,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \subsubsection{Margin floats} % \changes{v0.12}{2016/12/02}{Docs: Margin float examples.} % +% \gindex{float>margin placement} +% \gindex{margin placement} +% % When a keyfloat is located [M], it will be placed in the margin. % % \DescribeClass{tufte-book} @@ -1469,7 +1608,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % To set the minimum-allowed distance between \cs{marginpar}s and margin floats: % \margintag{distance between floats} -% \index{distance between floats}\index{float>distance between} +% \gindex{distance between floats}\gindex{float>distance between} % \begin{sourceverb} % \setlength{\marginparpush}{3ex} % \end{sourceverb} @@ -1574,7 +1713,6 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \clearpage % \subsubsection{Custom frames} % -% % \begin{dtxexample}[\Cref{fig:customframe,fig:customlooseframe}] % {Custom frames with \pkg{mdframed}\label{ex:customframe}} % \renewcommand{\KFLTtightframe}[1]{% @@ -1598,6 +1736,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % l=fig:customlooseframe}{A loosely-framed box.} % \end{dtxexample} % +% \gindex{frame>mdframed} +% \gindex{mdframed} +% % \DescribePackage{mdframed} % \Cref{ex:customframe} shows custom frames % created with the \pkg{mdframed} package along with \pkg{tikz}. @@ -1609,8 +1750,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % whose width is precomputed based on the object itself, then % set in \cs{KFLTimageboxwidth}. Any shadow may fall outside this % box. -% \index{troubleshooting>rotating>extra space} -% \index{troubleshooting>mdframed} +% \trouble{rotate>extra space} +% \trouble{mdframed} % % See \cref{sec:customframes} for more details. % @@ -1637,6 +1778,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % l=fig:customlooseshadow}{A loosely-framed shadow box.} % \end{dtxexample} % +% \gindex{fancybox} +% \gindex{frame>fancybox} +% % \DescribePackage{fancybox} % \Cref{ex:customshadow} shows custom shadow frames % created with the \pkg{fancybox} package. @@ -1669,6 +1813,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \clearpage % \subsubsection{Artist's name} % +% \gindex{author's or artist's name} +% \gindex{name>author or artist} +% % \begin{dtxexample}[\Cref{fig:artist}]{Artist's name — image} % \keyfig{ft,ap=Mr.,af=First,al=Last,as={~III}, % tc={\textit{About the illustration.}}, @@ -1723,7 +1870,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \subsubsection{Custom frames} % \label{sec:customframes} % -% \index{frame>custom} +% \gindex{frame>custom} % % There are two user-redefinable framing macros: \\ % \hspace*{2em}\cs{KFLTtightframe} and \cs{KFLTlooseframe} @@ -1766,10 +1913,10 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % % \subsubsection{Distance between floats and rows} -% \index{distance between floats} -% \index{subfloat>distance between} -% \index{float>distance between} -% \index{troubleshooting>rows too close or far} +% \gindex{distance between floats} +% \gindex{subfloat>distance between} +% \gindex{float>distance between} +% \trouble{table>rows too close or far} % To spread out the distance between floats and/or rows of floats % \margintag{rows too close/far} % on a busy page, the following settings may be changed. @@ -1782,9 +1929,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \subsubsection{Formatting the captions} % -% \index{troubleshooting>caption format} +% ^^A \trouble{caption format} % To modify the typesetting of the captions, see the \pkg{caption} package. -% \index{caption>formatting} +% \gindex{caption>formatting} % The settings used in this documentation are: % \begin{sourceverb} % % default applied to margin floats: @@ -1819,8 +1966,115 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \clearpage % -% \StopEventually{\PrintChanges\PrintIndex} -% +% ^^A \StopEventually{\PrintChanges\PrintIndex} +% +% \makeatletter +% +% \StopEventually{ +% ^^A \part{Change History and Index} +% ^^A \part{Change History} +% +% +% \pagestyle{plain} +% +% ^^A Each index has a prologue which creates its own \part, label, +% ^^A and meta index entry. +% \GlossaryPrologue{ +% \part{Change History} +% ^^A \section{Chg Hist} +% \label{sec:changehistory} +% \sindex[meta]{Change History} +% \markboth{{Change History}}{{Change History}} +% +% For the most recent changes, see page \pageref{sec:changesend}. +% +% } +% \PrintChanges +% \phantomsection +% \label{sec:changesend} +% +% +% ^^A The instructions for the Index of Objects: +% \IndexPrologue{ +% \clearpage +% \expandafter\part\expandafter{\indexname} +% \label{sec:index\indexshortcut} +% \sindex[meta]{\indexname} +% \markboth{Index of Objects}{Index of Objects}% +% +% This is an index of macros, environments, booleans, counters, lengths, +% packages, classes, options, keys, files, and various other programming objects. +% Each is listed by itself, and also by category. +% In some cases, they are further subdivided by [class]. +% +% Numbers written in italic refer to the page +% where the corresponding entry is described; +% numbers underlined refer to the +% \ifcodeline@index +% code line of the +% \fi +% definition. +% ^^A ; numbers in roman refer to the +% ^^A \ifcodeline@index +% ^^A code lines +% ^^A \else +% ^^A pages +% ^^A \fi +% ^^A where the entry is used. +% } +% +% \printindex[idx][Index of Objects] +% +% +% ^^A The instructions for the General Index: +% \IndexPrologue{ +% \clearpage +% \expandafter\part\expandafter{\indexname} +% \label{sec:index\indexshortcut} +% \sindex[meta]{\indexname} +% +% ^^A This is an index of instructions and concepts. +% ^^A Look here when wondering how to do something, and +% ^^A check the Troubleshooting Index when something goes wrong. +% This is a general index, including how-to and troubleshooting. +% } +% +% \printindex[gen][General Index] +% +% +% ^^A% The instructions for the Troubleshooting Index: +% ^^A% \IndexPrologue{ +% ^^A% \clearpage +% ^^A% \expandafter\part\expandafter{\indexname} +% ^^A% \label{sec:index\indexshortcut} +% ^^A% \sindex[meta]{\indexname} +% ^^A% +% ^^A% This index is a sorted reference of problems and solutions. +% ^^A% In order to make it easier to locate a solution, +% ^^A% the same issue may be addressed by more than one entry. +% ^^A% +% ^^A% Entries with higher page numbers are often duplicates of entries with +% ^^A% lower page numbers, as the same warning may occur within the user manual +% ^^A% and again within the source code for a given package. +% ^^A% } +% ^^A% +% ^^A% \printindex[trb][Troubleshooting Index] +% +% +% ^^A The meta index does not get a meta index entry pointing to itself: +% \IndexPrologue{ + +% \clearpage +% \expandafter\part\expandafter{\indexname} +% \label{sec:index\indexshortcut} +% } +% +% \printindex[meta][Index of Indexes] +% } +% +% \makeatother +% +% % % % \section{Code} @@ -2234,6 +2488,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% \providecommand{\tdauthorright}{} % \end{macrocode} % +% % \DescribeKey[main]{t} Additional text, justified alignment. % \begin{macrocode} \define@key{KFLT@keys}{t}{% @@ -2242,6 +2497,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% } % \end{macrocode} % +% % \DescribeKey[main]{tc} Additional text, centered alignment. % \begin{macrocode} \define@key{KFLT@keys}{tc}{% @@ -2250,6 +2506,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% } % \end{macrocode} % +% % \DescribeKey[main]{tr} Additional text, aligned to the right. % \begin{macrocode} \define@key{KFLT@keys}{tr}{% @@ -2258,6 +2515,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% } % \end{macrocode} % +% % \DescribeKey[main]{tl} Additional text, aligned to the left. % \begin{macrocode} \define@key{KFLT@keys}{tl}{% @@ -2267,7 +2525,6 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % % -% % \DescribeKey[main]{lw} Fraction of \cs{linewidth} % \begin{macrocode} \define@key{KFLT@keys}{lw}{% @@ -2282,6 +2539,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% % \DescribeKey[main]{w} Fixed width % \begin{macrocode} \define@key{KFLT@keys}{w}{% @@ -2296,6 +2554,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% % \DescribeKey[main]{h} Fixed height % \begin{macrocode} \define@key{KFLT@keys}{h}{\setlength{\KFLT@h}{#1}} @@ -2307,6 +2566,23 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% +% \DescribeKey[main]{kar} Keep aspect ratio +% \changes{v2.06}{2021/06/25}{Added \optn{kar}.} +% \begin{macrocode} +\define@key{KFLT@keys}{kar}[false]{% + \renewcommand{\KFLT@keepaspectratio}{keepaspectratio}% +} +% \end{macrocode} +% +% \begin{macro}{\KFLT@keepaspectratio} Stores ``\optn{keepaspectratio}'' if set. +% \changes{v2.06}{2021/06/25}{Added \optn{kar}.} +% \begin{macrocode} +\newcommand{\KFLT@keepaspectratio}{} +% \end{macrocode} +% \end{macro} +% +% % \DescribeKey[main]{s} Scale % \begin{macrocode} \define@key{KFLT@keys}{s}{\renewcommand{\KFLT@s}{#1}} @@ -2318,6 +2594,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% % \DescribeKey[main]{r} Angle. 90 is counter-clockwise 90 degrees. % \begin{macrocode} \define@key{KFLT@keys}{r}{\renewcommand{\KFLT@r}{#1}} @@ -2329,6 +2606,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% % \DescribeKey[main]{f} Frame the image with \cs{KFLTlooseframe}. % \begin{macrocode} \define@key{KFLT@keys}{f}[true]{\setboolean{KFLT@f}{#1}} @@ -2338,7 +2616,8 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \begin{macrocode} \newboolean{KFLT@f} % \end{macrocode} - +% +% % \DescribeKey[main]{ft} Tightly frame the image using \cs{KFLTtightframe}. % This is useful for photographs, or diagrams which % already have built-in margins. @@ -2436,6 +2715,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} % +% % \DescribeKey[main]{ww} Wrapped figure, fixed width % \changes{v2.02}{2021/05/27}{Added \optn{ww} and \optn{wlw}.} % \begin{macrocode} @@ -2790,9 +3070,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % A user-redefinable macro and length to tightly frame the contents. % -% \cs{KFLTtightframe} may be redefined to a macro which frames its contents. -% \cs{KFLTtightframewidth} should be redefined to the total width of the new -% frame and its separation. +% \begin{description} +% \item [\cs{KFLTtightframe}:] Redefine to a macro which frames its contents. +% \item [\cs{KFLTtightframewidth}:] Redefine to the total width of the new. +% frame and its separation. +% \end{description} % % \begin{macro}{\KFLTtightframe} \marg{contents} % \begin{macrocode} @@ -2817,9 +3099,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % A user-redefinable macro and length to loosely frame the contents. % -% \cs{KFLTlooseframe} may be redefined to a macro which frames its contents. -% \cs{KFLTlooseframewidth} should be redefine to the total width of the new -% frame and its separation. +% \begin{description} +% \item[\cs{KFLTlooseframe}:] Redefine to a macro which frames its contents. +% \item[\cs{KFLTlooseframewidth}:] Redefine to the total width of the new +% frame and its separation. +% \end{description} % % \begin{macrocode} \newcommand{\KFLTlooseframe}[1]{% @@ -2877,11 +3161,61 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \subsection{A graphics image from a file} % +% \DescribeLength{\KFLT@testwidth} Used to find the width of a graphics image. +% \begin{macrocode} +\newlength{\KFLT@testwidth} +% \end{macrocode} +% +% +% \begin{macro}{\KFLT@includegraphics} \oarg{keys} \marg{file name} +% +% Issue a warning if the image will be too wide, then display the image. +% \begin{macrocode} +\newcommand*{\KFLT@includegraphics}[2][]{% +% \end{macrocode} +% +% Find the width of the image: +% \begin{macrocode} + \settowidth{\KFLT@testwidth}{\includegraphics[#1]{#2}}% +% \end{macrocode} +% +% Avoid rounding errors when using the \optn{lw} option, +% and also avoid the exact line width in case images are side-by-side. +% +% If close to \cs{linewidth}, use slightly less than the \cs{linewidth}: +% \changes{v2.06}{2021/06/25}{Clip if close to \cs{linewidth}.} +% \begin{macrocode} + \ifboolexpr{% + test {\ifdimgreater{\KFLT@testwidth}{\linewidth-.01pt}} and + test {\ifdimless{\KFLT@testwidth}{\linewidth+1pt}} + }% + {\setlength{\KFLT@testwidth}{\linewidth-.01pt}}% + {}% +% \end{macrocode} +% +% +% Issue a warning if wider than the \cs{linewidth}: +% \changes{v2.06}{2021/06/25}{Warn if image too wide.} +% \begin{macrocode} + \ifdimgreater{\KFLT@testwidth}{\linewidth}{% + \PackageWarning{keyfloat}{The image is wider than the line width}% + }{}% +% \end{macrocode} +% +% Display the image: +% \begin{macrocode} + \includegraphics[#1]{#2}% +} +% \end{macrocode} +% \end{macro} +% +% % \begin{macro}{\KFLT@onefigureimage} \marg{filename} % % Create an image with size, frame, and turn. % % \changes{v2.00}{2019/03/12}{Filename in arg instead of \cs{KFLT@i}.} +% \changes{v2.06}{2021/06/25}{Added \optn{kar}.} % \begin{macrocode} \NewDocumentCommand{\KFLT@onefigureimage}{m}% {% @@ -2906,16 +3240,22 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % Width and height are both given: % \begin{macrocode} {% w and h - \includegraphics% - [scale=\KFLT@s,% - width=\KFLT@imagewidth,height=\KFLT@h]{#1}% + \KFLT@includegraphics[% + scale=\KFLT@s,% + width=\KFLT@imagewidth,% + height=\KFLT@h,% + \KFLT@keepaspectratio,% + ]{#1}% }% w and h % \end{macrocode} % Only width: % \begin{macrocode} {% only w - \includegraphics% - [scale=\KFLT@s,width=\KFLT@imagewidth]{#1}% + \KFLT@includegraphics[% + scale=\KFLT@s,% + width=\KFLT@imagewidth,% + \KFLT@keepaspectratio,% + ]{#1}% }% only w }% width is given % \end{macrocode} @@ -2926,15 +3266,44 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % |h| was given: % \begin{macrocode} - {\includegraphics[scale=\KFLT@s,height=\KFLT@h]{#1}}% + {% + \KFLT@includegraphics[% + scale=\KFLT@s,% + height=\KFLT@h,% + \KFLT@keepaspectratio,% + ]{#1}% + }% % \end{macrocode} % If none were given, use the image's natural size: % \begin{macrocode} - {\includegraphics[scale=\KFLT@s]{#1}}% + {% + \KFLT@includegraphics[% + scale=\KFLT@s,% + \KFLT@keepaspectratio,% + ]{#1}% + }% }% width is not given }% not linewidth {% linewidth given - \includegraphics[scale=\KFLT@s,width=\KFLT@imagewidth]{#1}% +% \end{macrocode} +% \changes{v2.06}{2021/06/25}{Fix: \optn{lw} with \optn{h}.} +% \begin{macrocode} + \ifdimgreater{\KFLT@h}{0pt}% + {% lw and h given + \KFLT@includegraphics[% + scale=\KFLT@s,% + width=\KFLT@imagewidth,% + height=\KFLT@h,% + \KFLT@keepaspectratio,% + ]{#1}% + }% + {% lw w/o h + \KFLT@includegraphics[% + scale=\KFLT@s,% + width=\KFLT@imagewidth,% + \KFLT@keepaspectratio,% + ]{#1}% + }% }% \end{lrbox}% \unskip% @@ -3164,22 +3533,34 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% {\csuse{KFLT@#1type}}{\KFLT@sc}% }% non-empty cstar and sc % \end{macrocode} +% +% In the following, +% the test for an empty caption is because the \pkg{caption} package does not +% detect an empty caption if it is given as a macro. +% % |cstar| was given, so create an unnumbered caption: +% \changes{v2.06}{2019/06/29}{Fix for empty caption.} % \begin{macrocode} - \KFLT@docaption*{\csuse{KFLT@#1c}}{#1}% + \ifcsempty{KFLT@#1c}% + {\KFLT@docaption*{}{#1}}% + {\KFLT@docaption*{\csuse{KFLT@#1c}}{#1}}% }% }% starred caption % \end{macrocode} % Unstarred caption |c| was given, so number this float: +% \changes{v2.06}{2019/06/29}{Fix for empty caption.} % \begin{macrocode} {% unstarred caption \ifcsempty{KFLT@#1sc}% {% no short cap - \KFLT@docaption{\csuse{KFLT@#1c}}{#1}% + \ifcsempty{KFLT@#1c}% + {\KFLT@docaption{}{#1}}% + {\KFLT@docaption{\csuse{KFLT@#1c}}{#1}}% }% no short cap {% short cap - \KFLT@docaption[\csuse{KFLT@#1sc}]% - {\csuse{KFLT@#1c}}{#1}% + \ifcsempty{KFLT@#1c}% + {\KFLT@docaption[\csuse{KFLT@#1sc}]{}{#1}}% + {\KFLT@docaption[\csuse{KFLT@#1sc}]{\csuse{KFLT@#1c}}{#1}}% }% short cap % \end{macrocode} % Optional label: @@ -3196,6 +3577,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \subsection{Defaults for a new float} % \begin{macro}{\KFLT@defaults} Defaults all settings before reading the keys. +% \changes{v2.06}{2021/06/25}{Added \optn{kar}.} % \begin{macrocode} \newcommand*{\KFLT@defaults}{% \setboolean{KFLT@cont}{false}% @@ -3218,6 +3600,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% \renewcommand{\KFLT@lw}{}% \setlength{\KFLT@w}{0pt}% \setlength{\KFLT@h}{0pt}% + \renewcommand{\KFLT@keepaspectratio}{}% \renewcommand{\KFLT@s}{1}% \renewcommand{\KFLT@r}{0}% \setboolean{KFLT@f}{false}% @@ -3535,14 +3918,38 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{environment} +% \begin{macro}{\KFLT@sharedkeys} +% Key/values to apply to each object in this group, +% such as a \env{keyfloats} or \env{keysubfigs}. +% \changes{v2.06}{2021/06/25}{Added shared keys.} +% \begin{macrocode} +\newcommand*{\KFLT@sharedkeys}{} +% \end{macrocode} +% \end{macro} + % \begin{macro}{\KFLT@boxkeys} \marg{keys} \marg{float type} % % Default the options, adjust for a table, then parse the keys: +% \changes{v2.06}{2021/06/25}{Added shared keys.} % \begin{macrocode} \NewDocumentCommand{\KFLT@boxkeys}{+m m} {% +% \end{macrocode} +% Set the key defaults: +% \begin{macrocode} \KFLT@defaults% +% \end{macrocode} +% Remember the float type: +% \begin{macrocode} \renewcommand{\KFLT@type}{#2}% +% \end{macrocode} +% Set the shared keys. Expansion seems to be required for \pkg{xkeyval}. +% \begin{macrocode} + \edef\next{\noexpand\setkeys{KFLT@keys}{\KFLT@sharedkeys}}% + \next% +% \end{macrocode} +% Set the float-specific keys, which might overright the group's keys: +% \begin{macrocode} \setkeys{KFLT@keys}{#1}% } % \end{macrocode} @@ -3728,7 +4135,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % Place the caption above the contents depending on \pkg{caption} \optn{position} option: % \changes{v2.01}{2019/09/11}{Fix: Positions with \brand{Komascript}.} % \begin{macrocode} - \caption@iftop{\booltrue{KFLT@captionistop}}{\boolfalse{KFLT@captionistop}}% + \caption@iftop% + {\booltrue{KFLT@captionistop}}% + {\boolfalse{KFLT@captionistop}}% \ifbool{KFLT@captionistop}{\KFLT@caption{}}{}% % \end{macrocode} % Typeset the contents: @@ -4182,9 +4591,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% (Not in outer par mode.)% }% {% - The subcaption package do not support nested environments,\MessageBreak + The subcaption package do not support nested environments,% + \MessageBreak so the keyfloat package cannot place a\MessageBreak - keysubfigs or keysubtabs environment inside another,\MessageBreak + keysubfigs or keysubtabs environment inside another,% + \MessageBreak or inside a keyfloats.% }% }% @@ -4201,16 +4612,19 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macro} -% \begin{environment}{KFLT@LWR@hook@keyfloatsminipage} Modified by \pkg{lwarp}. +% \begin{environment}{KFLT@LWR@hook@keyfloatsminipage} \marg{contents} +% +% Modified by \pkg{lwarp}. +% \changes{v2.06}{2021/06/25}{Added vertical alignment.} % \begin{macrocode} \newenvironment*{KFLT@LWR@hook@keyfloatsminipage}[1] - {\noindent\minipage{#1}} - {\endminipage}% + {\noindent\minipage[\KFLT@va]{#1}} + {\endminipage} % \end{macrocode} % \end{environment} -% \begin{environment}{keyfloats} * \oarg{loc} \marg{num columns} +% \begin{environment}{keyfloats} * \oarg{loc} \marg{num columns} \oarg{shared keys/values} % % User-level macro to create rows of figures/tables. % Wrapping occurs after the number of specified columns. @@ -4230,7 +4644,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \changes{v0.15}{2017/05/12}{Adjustments for \protect\env{keywrap}.} % % \begin{macrocode} -\NewDocumentEnvironment{keyfloats}{s O{tbp} m} +\NewDocumentEnvironment{keyfloats}{s O{tbp} m O{}} {% \KFLT@envignorespaces% % \end{macrocode} @@ -4242,6 +4656,12 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \begin{macrocode} \addtocounter{KFLT@keyfloatdepth}{1}% % \end{macrocode} +% Nest the group's keys. +% \changes{v2.06}{2021/06/25}{Added shared keys.} +% \begin{macrocode} + \edef\KFLT@outersharedkeys{\KFLT@sharedkeys}% + \edef\KFLT@sharedkeys{\KFLT@sharedkeys,#4}% +% \end{macrocode} % If [H], nested, subfloats, or keywrap, use a minipage instead of a float: % \begin{macrocode} \ifboolexpr{% @@ -4263,6 +4683,16 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% bool {KFLT@inkeysubfloats} }% {% +% \end{macrocode} +% Use the keys from the outer container. +% Expansion required for \pkg{xkeyval}. +% \changes{v2.06}{2021/06/25}{Added shared keys.} +% \begin{macrocode} + \edef\next{\noexpand\setkeys{KFLT@keys}{\KFLT@outersharedkeys}}% + \next% +% \end{macrocode} +% Create the containing minipage: +% \begin{macrocode} \KFLT@LWR@hook@keyfloatsminipage{\KFLT@rowboxwidth}% }% {% @@ -4569,7 +4999,9 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % Place the caption above the contents depending on \pkg{caption} \optn{position} option: % \changes{v2.01}{2019/09/11}{Fix: Positions with \brand{Komascript}.} % \begin{macrocode} - \caption@iftop{\booltrue{KFLT@subcaptionistop}}{\boolfalse{KFLT@subcaptionistop}}% + \caption@iftop% + {\booltrue{KFLT@subcaptionistop}}% + {\boolfalse{KFLT@subcaptionistop}}% \ifbool{KFLT@subcaptionistop}{\KFLT@caption{subgrp}}{}% % \end{macrocode} % Not yet started a row of subfloats. @@ -4661,12 +5093,14 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{macrocode} % \end{macro} -% \begin{environment}{KFLT@keysubfloats} \marg{star?} \marg{loc} \marg{float type} \marg{numcols} \marg{\keyvalsarg} +% \begin{environment}{KFLT@keysubfloats} \marg{1: star?} +% \marg{2: loc} \marg{3: float type} \marg{4: numcols} +% \marg{5: \keyvalsarg} \marg{6: shared keys/values} % % A group of subfigures typeset in rows. % % \begin{macrocode} -\NewDocumentEnvironment{KFLT@keysubfloats}{m m m m +m} +\NewDocumentEnvironment{KFLT@keysubfloats}{m m m m +m m} {% % \end{macrocode} % Error if trying to nest environments: @@ -4681,6 +5115,11 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \begin{macrocode} \KFLT@subgrpdefaults% % \end{macrocode} +% Nest the group's keys: +% \changes{v2.06}{2021/06/25}{Added shared keys.} +% \begin{macrocode} + \edef\KFLT@sharedkeys{\KFLT@sharedkeys,#6}% +% \end{macrocode} % Default to figure float type: % \begin{macrocode} \renewcommand{\KFLT@subgrptype}{#3}% @@ -4699,54 +5138,49 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{environment} -% \begin{environment}{keysubfloats} * \oarg{loc} \marg{float type} \marg{numcols} \marg{\keyvalsarg} +% \begin{environment}{keysubfloats} * \oarg{2: loc} \marg{3: float type} +% \marg{4: numcols} \marg{5: \keyvalsarg} \oarg{6: shared \keyvalsarg} % % A group of subfloats typeset in rows. % +% \changes{v2.06}{2021/06/25}{Added shared keys.} % \begin{macrocode} -\NewDocumentEnvironment{keysubfloats}{s O{tbp} m m +m} -{% - \KFLT@keysubfloats{#1}{#2}{#3}{#4}{#5}% -}{% - \endKFLT@keysubfloats% -} +\NewDocumentEnvironment{keysubfloats}{s O{tbp} m m +m O{}} + {\KFLT@keysubfloats{#1}{#2}{#3}{#4}{#5}{#6}} + {\endKFLT@keysubfloats} % \end{macrocode} % \end{environment} -% \begin{environment}{keysubfigs} * \oarg{loc} \marg{numcols} \marg{\keyvalsarg} +% \begin{environment}{keysubfigs} * \oarg{2: loc} \marg{3: numcols} +% \marg{4: \keyvalsarg} \oarg{5: shared \keyvalsarg} % % A group of subfigures typeset in rows. % +% \changes{v2.06}{2021/06/25}{Added shared keys.} % \begin{macrocode} -\NewDocumentEnvironment{keysubfigs}{s O{tbp} m +m} -{% - \KFLT@keysubfloats{#1}{#2}{figure}{#3}{#4}% -}{% - \endKFLT@keysubfloats% -} +\NewDocumentEnvironment{keysubfigs}{s O{tbp} m +m O{}} + {\KFLT@keysubfloats{#1}{#2}{figure}{#3}{#4}{#5}} + {\endKFLT@keysubfloats} % \end{macrocode} % \end{environment} -% \begin{environment}{keysubtabs} * \oarg{loc} \marg{numcols} \marg{\keyvalsarg} +% \begin{environment}{keysubtabs} * \oarg{2: loc} \marg{3: numcols} +% \marg{4: \keyvalsarg} \oarg{5: shared \keyvalsarg} % % A group of subtables typeset in rows. +% \changes{v2.06}{2021/06/25}{Added shared keys.} % \begin{macrocode} -\NewDocumentEnvironment{keysubtabs}{s O{tbp} m +m} -{% - \KFLT@keysubfloats{#1}{#2}{table}{#3}{#4}% -}{% - \endKFLT@keysubfloats% -} +\NewDocumentEnvironment{keysubtabs}{s O{tbp} m +m O{}} + {\KFLT@keysubfloats{#1}{#2}{table}{#3}{#4}{#5}} + {\endKFLT@keysubfloats} % \end{macrocode} % \end{environment} % % % % -% -% % \subsection{Margin floats} % % \begin{environment}{KFLT@marginfloat} \oarg{offset} \marg{type} @@ -4876,6 +5310,21 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % \end{environment} % % +% \section{\pkg{keyfloat} package maintenance} +% +% To compile the \pkg{keyfloat} documentation from \filenm{keyfloat.dtx} and +% \filenm{keyfloat.ins}: +% +% \begin{sourceverb} +% pdflatex keyfloat.ins +% pdflatex keyfloat.dtx +% pdflatex keyfloat.dtx +% pdflatex keyfloat.dtx +% makeindex -s gglo.ist -o keyfloat.gls keyfloat.glo +% splitindex keyfloat.idx -- -s gind.ist +% pdflatex keyfloat.dtx +% pdflatex keyfloat.dtx +% \end{sourceverb} % % % \iffalse @@ -4890,7 +5339,7 @@ Keywords={LaTeX, floats, key/val, subcaption, rows}% % % \renewcommand{\partname}{} % \renewcommand{\thepart}{} -% \part{Change History and Index} +% ^^A \part{Change History and Index} % % % \Finale diff --git a/macros/latex/contrib/keyfloat/keyfloat.pdf b/macros/latex/contrib/keyfloat/keyfloat.pdf index c9b9c1987c..6493f59785 100644 Binary files a/macros/latex/contrib/keyfloat/keyfloat.pdf and b/macros/latex/contrib/keyfloat/keyfloat.pdf differ diff --git a/macros/latex/contrib/lwarp/README.txt b/macros/latex/contrib/lwarp/README.txt index 3c6e60f99a..f89d6b4dd8 100644 --- a/macros/latex/contrib/lwarp/README.txt +++ b/macros/latex/contrib/lwarp/README.txt @@ -1,5 +1,5 @@ -LaTeX lwarp package v0.898 README.txt +LaTeX lwarp package v0.899 README.txt Files included are: diff --git a/macros/latex/contrib/lwarp/lwarp.dtx b/macros/latex/contrib/lwarp/lwarp.dtx index 0692faa1a3..54b4857907 100644 --- a/macros/latex/contrib/lwarp/lwarp.dtx +++ b/macros/latex/contrib/lwarp/lwarp.dtx @@ -16,7 +16,7 @@ % \iffalse %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{lwarp} -% [2021/05/24 v0.898 Allows LaTeX to directly produce HTML5 output.] +% [2021/06/29 v0.899 Allows LaTeX to directly produce HTML5 output.] % %<*driver> \documentclass{ltxdoc} @@ -2828,6 +2828,8 @@ use an absolute width for \cs{keyfig}, instead of \optn{lw}-proportional widths. (The \optn{[H]} option forces the use of a minipage, which internally adjusts for a virtual 6-inch wide minipage, which then corrupts the \optn{lw} option.) + +For wrapped figures, overhang and number of lines are ignored. } \newcommand{\limitssiunitx}{% @@ -3098,7 +3100,7 @@ This boolean may be tested by the user for later use. %<*package> % \fi % -% \CheckSum{54272} +% \CheckSum{54297} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -3238,6 +3240,7 @@ This boolean may be tested by the user for later use. % \changes{v0.896}{2021/04/08}{\ 2021/04/08} % \changes{v0.897}{2021/05/24}{\ 2021/05/24} % \changes{v0.898}{2021/05/29}{\ 2021/05/29} +% \changes{v0.899}{2021/06/29}{\ 2021/06/29} @@ -3341,6 +3344,8 @@ This boolean may be tested by the user for later use. % \begin{center} % \setlength{\parskip}{1ex} % \color{blue} +% For a quick-start tutorial, see \cref{sec:tutorial}, \nameref{sec:tutorial}. +% % For a list of supported features, see \cref{tab:supported}: \nameref{tab:supported}. % % To update existing projects, see \cref{sec:updates}: \nameref{sec:updates}. @@ -3461,6 +3466,15 @@ This boolean may be tested by the user for later use. % % \begin{description} % \needspace{2\baselineskip} +% \item[v0.899:] Minor updates. +% \begin{itemize} +% \item \prog{lwarpmk}: Warns if |\usepackage{lwarp}| is not detected. +% \item \pkg{graphics}: Added support for \optn{keepaspectratio}. +% \margintag{packages} +% \item \pkg{keyfloat}: Fix: \optn{lw} with \optn{h}. +% \item \pkg{multicol}: Improved \CSS. +% \end{itemize} +% \needspace{2\baselineskip} % \item[v0.898:] Minor updates. % \begin{itemize} % \item Fewer underfull \cs{hbox} warnings. @@ -6790,6 +6804,16 @@ This boolean may be tested by the user for later use. % % \subsection{Compiling the print version with \prog{lwarpmk}} % +% \newcommand*{\LWRenablelwarpmk}{% +% If you have not yet done so, +% \trouble[Enable \prog{lwarpmk}]{lwarpmk=\filenm{lwarpmk.conf}} +% \trouble{lwarpmk=\prog{lwarpmk}} +% add \texttt{\cs{usepackage}\{lwarp\}} to the document, +% then compile the project a single time using \prog{pdflatex}, \prog{lualatex}, +% or \prog{xelatex}. This generates the file \filenm{lwarpmk.conf}, +% which then allows the \prog{lwarpmk} program to be used. +% } +% % The \prog{lwarpmk} utility program is used to compile either the printed or % the \HTML\ version of the document. % @@ -6797,6 +6821,8 @@ This boolean may be tested by the user for later use. % % \begin{enumerate} % +% \item \LWRenablelwarpmk +% % \item Re-compile the print version: \userentry{lwarpmk print} % % \prog{lwarpmk} prints an introduction then checks to see if the document @@ -6846,6 +6872,7 @@ This boolean may be tested by the user for later use. % |lwarpmk html| is used to recompile an \HTML\ version of the document. % % \begin{enumerate} +% \item \LWRenablelwarpmk % \item Compile the \HTML\ version: % \userentry{lwarpmk html} % @@ -17720,6 +17747,7 @@ This boolean may be tested by the user for later use. % \changes{v0.893}{2020/10/18}{\filenm{lwarp.css}: Added \pkg{keystroke}.} % \changes{v0.894}{2020/12/15}{\filenm{lwarp.css}: \TeX\ logos no longer below baseline.} % \changes{v0.896}{2021/03/04}{\filenm{lwarp.css}: Added \element{main}, adjusted \element{sidetoccontainer} margin.} +% \changes{v0.899}{2021/06/25}{\filenm{lwarp.css}: Improved \pkg{multicol}.} % % ^^A *lwarp.css % @@ -19103,8 +19131,11 @@ section.textbody { margin: 0ex 1em 0ex 1em ;} div.multicolsheading { -webkit-column-span: all; -moz-column-span: all; column-span: all; } -div.multicols { -webkit-columns: 3 380px ; - -moz-columns: 3 380px ; columns: 3 380px ; } +div.multicols { + -webkit-columns: 3 auto ; + -moz-columns: 3 auto ; + columns: 3 auto ; +} div.multicols p {margin-top: 0ex} @@ -19412,6 +19443,14 @@ nav.botnavigation { display:none; } /* Only display the sidetoc's webpage title if a small screen */ span.sidetocthetitle { display: none } +@media screen and (max-width: 100em) { + div.multicols { + -webkit-columns: 2 auto ; + -moz-columns: 2 auto ; + columns: 2 auto ; + } +} + @media screen and (max-width: 50em) { div.sidetoccontainer { float: none ; @@ -19432,6 +19471,11 @@ span.sidetocthetitle { display: none } display:block ; margin: 1ex 1em 1ex 1em ; } + div.multicols { + -webkit-columns: 1 auto ; + -moz-columns: 1 auto ; + columns: 1 auto ; + } } @media print { @@ -20505,6 +20549,7 @@ MathJax = { % \changes{v0.81}{2020/03/04}{\prog{lwarpmk}: Improved error if in \pkg{lwarp} source directory.} % \changes{v0.84}{2020/03/30}{\prog{lwarpmk}: \optn{clean} also removes \filenm{comment_*.cut}} % \changes{v0.89}{2020/08/29}{\prog{lwarpmk}: \optn{clean} also removes \filenm{*.bbl}} +% \changes{v0.899}{2021/05/30}{\prog{lwarpmk}: Warn if \pkg{lwarp} package not detected.} % % The following is only generated if the \optn{lwarpmk} option % was given to \pkg{lwarp}. @@ -20520,7 +20565,7 @@ MathJax = { -- Copyright 2016-2021 Brian Dunn -printversion = "v0.898" +printversion = "v0.899" requiredconfversion = "2" -- also at *lwarpmk.conf function printhelp () @@ -20587,7 +20632,9 @@ function splitfile (destfile,sourcefile) -- Split one large sourcefile into a number of files, -- starting with destfile. -- The file is split at each occurance of