Closed dmyersturnbull closed 2 years ago
You cannot use \csvlinetotablerow
inside the table head
key.
What you could do is the following, using no head
to make the head line a normal data line:
\documentclass{article}
\RequirePackage{booktabs}
\RequirePackage{csvsimple-l3}
\begin{filecontents*}{animals.csv}
Animal,Length\:(cm)
kitten,1.3
puppy,3.2
\end{filecontents*}
\begin{document}
\csvreader[
tabular={ll},
table head = {\toprule},
table foot = {\bottomrule},
no head,
late after first line = \\\midrule,
]{animals.csv}{}{\csvlinetotablerow}
\end{document}
Currently, you will miss \midrule
in the output, because of https://github.com/T-F-S/csvsimple/issues/17
I will address this issue soon.
In the original code, OP tried to typeset the table with tabularray
, but it seems I can not use \csvlinetotablerow
with tabularray
, even if I put it after \csvexpval
:
\documentclass{article}
\RequirePackage{tabularray}
\RequirePackage{csvsimple-l3}
\begin{filecontents*}{animals.csv}
Animal,Length\:(cm)
kitten,1.3
puppy,3.2
\end{filecontents*}
\begin{document}
\csvreader[
tabularray={ll},
no head,
]{animals.csv}{}{
\csvexpval\csvlinetotablerow
}
\end{document}
Are there any mistakes in the code above?
Yes, \csvlinetotablerow
cannot be use for tabularray
, because this uses Data Collection
and cannot absorb this macro which actually contains a loop.
You could use the following:
\documentclass{article}
\RequirePackage{tabularray}
\RequirePackage{csvsimple-l3}
\begin{filecontents*}{animals.csv}
Animal,Length\:(cm)
kitten,1.3
puppy,3.2
\end{filecontents*}
\begin{document}
\csvreader[
tabularray={ll},
no head,
]{animals.csv}{}{%
\csvexpval\csvcoli & \csvexpval\csvcolii
}
\end{document}
Alternatively, a loop could be used to add data, but not inside the command
which is expanded. The next example uses after filter
for such a loop:
\documentclass{article}
\RequirePackage{tabularray}
\RequirePackage{csvsimple-l3}
\ExplSyntaxOn
\NewDocumentCommand \csvcollectlinetotablerow { }
{
\bool_set_false:N \l_tmpa_bool
\seq_map_inline:Nn \g__csvsim_line_seq
{
\bool_if:NTF \l_tmpa_bool
{
\tl_gput_right:Nn \g__csvsim_collect_tl { & ##1 }
}
{
\tl_gput_right:Nn \g__csvsim_collect_tl { ##1 }
\bool_set_true:N \l_tmpa_bool
}
}
}
\ExplSyntaxOff
\begin{filecontents*}{animals.csv}
Animal,Length\:(cm)
kitten,1.3
puppy,3.2
\end{filecontents*}
\begin{document}
\csvreader[
tabularray={ll},
no head,
after filter=\csvcollectlinetotablerow,
]{animals.csv}{}{}
\end{document}
Maybe, it would not hurt to have \csvcollectlinetotablerow
as an official macro?
I think it may be simpler to write the function above as follows:
\NewDocumentCommand \csvcollectlinetotablerow { }
{
\tl_gput_right:Nx \g__csvsim_collect_tl { \seq_use:Nn \g__csvsim_line_seq { & } }
}
What do you think about defining \csvlinetotablerow
as a tl
variable (like \csvcoli
, \csvcolii
, etc ):
\tl_set:Nx \csvlinetotablerow { \seq_use:Nn \g__csvsim_line_seq { & } }
Then tabularray
can use \csvexpval\csvlinetotablerow
inside the body of \csvreader
and tabular
can still use \csvlinetotablerow
.
Using
\RenewExpandableDocumentCommand \csvlinetotablerow { }
{
\seq_use:Nn \g__csvsim_line_seq { & }
}
seems to work.
Also, for tabularray
, this seems to work without \csvexpval
(because expansion is needed here)
Great. And it would be perfect if we can also use other predefined macros (\csvcoli
, \csvcolii
, etc) without \csvexpval
.
Tests with the expandable \csvlinetotablerow
showed no problems. I will add this for the next version.
But, \csvcoli
etc. will still need \csvexpval
, because they contain the pure data and I intend to keep it like that (for backward compatibility as well as for principle).
In csvsimple-l3.sty
, I tried to replace
\tl_gset:cn {csvcol \int_to_roman:n \g__csvsim_col_int}{##1}
with
\tl_gset:cn {csvcol \int_to_roman:n \g__csvsim_col_int}{ \exp_not:n {##1} }
And the following test showed no problems of backward compatibility:
\documentclass{article}
\RequirePackage{tabularray}
\RequirePackage{csvsimple-l3}
\begin{filecontents*}[overwrite]{animals.csv}
\def\abc{xyz}\abc,Length
kitten,1.3
puppy ,3.2
\end{filecontents*}
\begin{document}
\csvreader[
tabularray={ll},
no head,
]{animals.csv}{}{
\csvcoli & \csvcolii
}
\csvreader[
tabularray={ll},
no head,
]{animals.csv}{}{
\csvexpval\csvcoli & \csvexpval\csvcolii
}
\csvreader[
tabular={ll},
no head,
]{animals.csv}{}{
\csvcoli & \csvcolii
}
\end{document}
For many, maybe most, applications, a wrapping \exp_not:n
will not hurt, but not for all.
The following example fails, if \exp_not:n
is added:
\documentclass{article}
\RequirePackage{csvsimple-l3,xcolor}
\ExplSyntaxOn
\cs_set_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}
\tl_gset:cn {csvcol \int_to_roman:n \g__csvsim_col_int}{ \exp_not:n {##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
}
}
\NewDocumentCommand \maptoken { m }
{
\tl_map_inline:Nn #1
{
\fbox{##1}
}
}
\ExplSyntaxOff
\begin{filecontents*}{valtest.csv}
type,value
A,\textit{5}
B,2
AB,4
ABC,3
\end{filecontents*}
\begin{document}
\csvreader[
tabular={ll},
head to column names,
]{valtest.csv}{}{%
\maptoken{\csvcoli}
&
\ifcsvstrequal{\csvcoli}{B}{\color{red}\bfseries}{} \csvcolii
}
\end{document}
I want to have \csvcoli
containing the content of the first column and nothing added. The legacy csvsimple
has some drawbacks here and the L3 version is more advanced in this matter (and should continue like that).
For the version 2.3.0
released today, the expandable \csvlinetotablerow
is implemented. Also, column names detection=false
can be set to switch off column names detection.
Finally, you may like the following new example from the documentation:
Great, the example looks very nice!
I'm trying to write a variant of csvautotabular that tolerates macros inside the header. This came up using siunitx in a column -- e.g.
"Output radiant flux (\unit{\milli\watt})
, as well as textgreek and acro.From what I can tell, the issue has to do with csvsimple-l3 assigning macros for columns. The documentation lists
head to column names = false
, but that doesn't seem to solve this issue.FYI, this is an incredible package. Thanks for maintaining it.
Minimal working example
Original macro, for reference