# Conditional horizontal lines in tables

I am trying to typeset data that is read from CSV files using the csvsimple package. In the input data, there is a column that will tell me where to place a horizontal line between the rows. (In the actual data it's a bit more complicated: There are lines between all of the data rows, but some are solid lines while others should be dotted lines.) The problem is that the indicator in the column is set if a line has to be placed above the line in question. I've tried to get this working for some time now:

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{etoolbox}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\csvreader[%
head to column names,
tabular = {|l|l|},
table foot = \hline,
]{sample.csv}{}{%
\edef\myflag{\theflag}\ifdefvoid{\myflag}{}{\hline}
\theline & \thetext
}

\end{document}


If I replace the \hline with --, I can see that the expression works as intended. The \hline, however, fails with a Misplaced \noalign. As far as I understand, this is because the stuff I wrote is not "expandable" - I'm not sure I get the meaning of that. Is there a way to work around this issue?

• \edef isn't expandable but even if you use an expandable test such as \if!\theflag!\hline\fi or even just \hline you get same error as it seems the csv package you are using has already done non expandable stuff. Is that package a requirement? – David Carlisle Oct 30 '14 at 22:14
• @DavidCarlisle It's not a hard requirement - if there's something else I could use, I'd be willing to give it a try. – vwegert Oct 30 '14 at 22:22

## 2 Answers

The cause of the problem is that \\ and \hline are set apart from each other in your code (with some processing in between). The \\ is automatically set for the late after line option when the tabular key is used.

So, the solution is to clear late after line and to set \\\hline directly.

Version 1:

If your table gets a line at the very beginning only by setting X, you may use the following code. This code includes the hack of Peter Grill to get rid of the extra vertical space:

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\csvreader[%
head to column names,
tabular={|l|l|},
late after line=,
table head=\vspace*{-12pt},
before line=\ifthenelse{\equal{\theflag}{}}{\\}{\\\hline},
table foot = \\\hline,
]{sample.csv}{}{%
\theline & \thetext
}

\end{document}


Version 2:

If your table should always have a line at the very beginning, then I would propose the following code which is somewhat cleaner:

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\csvreader[%
head to column names,
tabular={|l|l|},
late after line=,
table head=\hline,
before line=\ifthenelse{\equal{\theflag}{}}{\\}{\\\hline},
before first line=,
table foot = \\\hline,
]{sample.csv}{}{%
\theline & \thetext
}

\end{document}


Version 3:

Just for fun: the following is a booktabs solution:

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{booktabs}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\csvreader[%
head to column names,
tabular={ll},
late after line=,
table head=\toprule,
before line=\ifthenelse{\equal{\theflag}{}}{\\}{\\\midrule},
before first line=,
table foot=\\\bottomrule,
]{sample.csv}{}{%
\theline & \thetext
}

\end{document}


One way to do this is to use \\\hline. However this results in extra vertical spacing so you can hack that out via \vspace{-12pt}:

However, do you really need the vertical lines. It looks better just to use horizontal lines with booktabs:

Alternate: Instead of using csvsimple you could also use the datatool package as shown in the MWE below. This yields results identical to the above.

## Code:

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{etoolbox}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\newcommand*{\OptionalHline}{\edef\myflag{\theflag}\ifdefvoid{\myflag}{}{\vspace{-12pt}\\\hline}}
\csvreader[%
head to column names,
tabular = {| l | l |},
table foot = \hline,
before line=\OptionalHline
]{sample.csv}{}{%
\theline & \thetext
}

\end{document}


## Code: booktabs

\documentclass{article}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{etoolbox}
\usepackage{booktabs}

\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}

\newcommand*{\OptionalHline}{\edef\myflag{\theflag}\ifdefvoid{\myflag}{}{\vspace{-12pt}\\\cmidrule{1-2}}}
\csvreader[%
head to column names,
tabular = { l  l },
table foot = \hline,
before line=\OptionalHline
]{sample.csv}{}{%
\theline & \thetext
}
\end{document}


## Code: datatool:

\documentclass{article}
\usepackage{datatool}
\usepackage{booktabs}
\usepackage{xstring}

%\usepackage{filecontents}% <-- Commented out to prevent overwriting sample.csv
\begin{filecontents*}{sample.csv}
theline,theflag,thetext
1,X,one
2,,two
3,,three
4,X,four
5,,five
6,X,six
\end{filecontents*}

\begin{document}
\DTLloaddb{myDB}{sample.csv}
\bigskip
\begin{tabular}{l l}
\DTLforeach*{myDB}{\LineNumber=theline,\Flag=theflag,\Text=thetext}{%
\IfStrEq{\Flag}{X}
{\DTLiffirstrow{\vspace*{-12pt}}{}\\\cmidrule{1-2}}
{\DTLiffirstrow{\vspace*{-12pt}}{}\\}%
\LineNumber & \Text
}%
\end{tabular}
\end{document}