5

With the datatool package there is a \DTLiffirstrow. I am looking for a similar command to detect the last row, \DTLiflastrow, but could not find one. I attempted to create my own but was not successful.

If the title row is separate form the data one can use

\DTLiffirstrow{\\\Midrule}{\\\cmidrule{1-2}}

to produce the horizontal lines as in:

enter image description here

But if the title is part of the data, I don't see how to do that without an equivalent of \DTLiflastrow. Without which I get an extra blank line at the bottom:

enter image description here

If you un-comment my attempt of \DTLifLastRow you get:

! Missing number, treated as zero. \dtlrows@

Code:

\documentclass{article}

\usepackage{datatool} \usepackage{booktabs} \def\Midrule{\midrule[\heavyrulewidth]}

% Make csv in question \usepackage{filecontents} \begin{filecontents}{scientists2.csv} name,surname, First,Last Albert,Einstein, Marie,Curie, Thomas,Edison, \end{filecontents}

\newcommand{\DTLifLastRow}[3]{% % #1 = db % #2 = code for last row % #3 = code for all other rows \dtlifnumeq {\DTLrowcount{#1}} {\DTLcurrentindex}% {\value{DTLrowi}}% {#2}{#3}% }

\begin{document}

\DTLloaddb{myDB}{scientists2.csv} %\DTLdisplaydb{myDB}% Useful for debugging.

\begin{tabular}{ll}\toprule \textbf{First Name} & \textbf{Last Name}% \DTLforeach*{myDB}{\Name=name,\Surname=surname}{% \DTLiffirstrow{\\Midrule}{\\cmidrule{1-2}}% \Name & \Surname }% \\bottomrule \end{tabular}

\bigskip\noindent But what if the first row of the table was the header row. How do I produce the above table format without the manual header. \medskip

\begin{tabular}{ll}\toprule \DTLforeach*{myDB}{\Name=name,\Surname=surname}{% \Name & \Surname \DTLiffirstrow{\\Midrule}{\\cmidrule{1-2}}% % I think I need to replace the above with something like this: %\DTLiffirstrow{\\Midrule}{% % \DTLifLastRow{}{myDB}{\\cmidrule{1-2}}% %}% }% \\bottomrule \end{tabular} \end{document}

Peter Grill
  • 223,288

1 Answers1

4

It seems to be one of the usual problems of doing things already inside a tabular. The best seems to be first populating a token register with the table contents and then delivering it inside the tabular:

\documentclass{article}

\usepackage{datatool}
\usepackage{booktabs}
\def\Midrule{\midrule[\heavyrulewidth]}

% Make csv in question
\usepackage{filecontents}
\begin{filecontents*}{scientists2.csv}
name,surname,
First,Last
Albert,Einstein,
Marie,Curie,
Thomas,Edison,
\end{filecontents*}

\newcommand{\DTLifLastRow}[3]{%
  % #1 = db
  % #2 = code for last row
  % #3 = code for all other rows
  \dtlifnumeq
    {\DTLrowcount{#1}}
    {\DTLcurrentindex}%
    {#2}{#3}%
}

\newtoks\grilltoks

\begin{document}

\DTLloaddb{myDB}{scientists2.csv}
%\DTLdisplaydb{myDB}% Useful for debugging.

\grilltoks={}
\DTLforeach*{myDB}{\Name=name,\Surname=surname}
 {%
  \edef\temp{\Name & \Surname}%
  \grilltoks=\expandafter{\the\expandafter\grilltoks\temp}%
  \DTLiffirstrow
   {\grilltoks=\expandafter{\the\grilltoks\\\Midrule}}
   {%
    \DTLifLastRow{myDB}{}{\grilltoks=\expandafter{\the\grilltoks\\\cmidrule{1-2}}}%
   }%
 }
\begin{tabular}{ll}\toprule
\the\grilltoks
    \\\bottomrule
\end{tabular}
\end{document}

enter image description here

Actually, datatool has a \DTLiflastrow command, which however doesn't work as expected: indeed

\DTLforeach*{myDB}{\Name=name,\Surname=surname}
  {\DTLiflastrow{LAST\endgraf}{NOT LAST\endgraf}}

prints

NOT LAST
NOT LAST
LAST
NOT LAST

egreg
  • 1,121,712