# Conditional table construction with datatool

The following minimal example creates a 3-row table width a horizontal rule separating rows 2 and 3:

\documentclass{article}
\usepackage{filecontents,datatool,booktabs}
\usepackage[table]{xcolor}

\begin{filecontents*}{data.txt}
fieldA,fieldB,fieldC
A,,textA
B,,textB
C,X,textC
\end{filecontents*}
%D,X,textD% Add this row to the above file... Booooooom!

\begin{document}

\makeatletter
\gdef\tabulardata{}
\DTLforeach*{data}
{\fieldA=fieldA,\fieldB=fieldB,\fieldC=fieldC}{%
\DTLifnullorempty{\fieldB}{%
\gdef\tabularrule{}% No rule
}{% \fieldB is not NULL nor empty
\gdef\tabularrule{\noexpand\arrayrulecolor{black!15}\noexpand\cmidrule{1-3}\noexpand\arrayrulecolor{black}}% Grey rule
}
\protected@xdef\tabulardata{\tabulardata%
\tabularrule% Insert tabular rule + \fieldA
& \fieldB & \fieldC \tabularnewline
}% Construct new tabular row
}
\makeatother

\begin{tabular}{ *{3}{c} }
\toprule
Field A & Field B & Field C \\
\midrule
\tabulardata
\\[-\normalbaselineskip]\bottomrule
\end{tabular}

\end{document}


If I insert the commented fourth-row D,X,textD into the file data.txt, the example doesn't compile any more. Why is that? It should output another rule with another row:

Ideally I'd like the following output, where the \cmidrule is only placed before the first occurrence of a non-NULL/empty \fieldB:

\begin{tabular}{ *{3}{c} }
\toprule
Field A & Field B & Field C \\
\midrule
A &   & textA \\
B &   & textB \\
\arrayrulecolor{black!15}\cmidrule{1-3}\arrayrulecolor{black}
C & X & textC \\
D & X & textD \\
\\[-\normalbaselineskip]\bottomrule
\end{tabular}


\noexpand expands to nothing do on the second application of protected@xdef it os not there and the commands are unprotected. You need a mechanism that keeps them unexpanded on every application of xdef:

\documentclass{article}
\usepackage{filecontents,datatool,booktabs}
\usepackage[table]{xcolor}

\begin{filecontents*}{data.txt}
fieldA,fieldB,fieldC
A,,textA
B,,textB
C,X,textC
D,X,textD
\end{filecontents*}
%D,X,textD% Add this row to the above file... Booooooom!

\begin{document}

\makeatletter
\gdef\tabulardata{}
\DTLforeach*{data}
{\fieldA=fieldA,\fieldB=fieldB,\fieldC=fieldC}{%
\DTLifnullorempty{\fieldB}{%
\gdef\tabularrule{}% No rule
}{% \fieldB is not NULL nor empty
\gdef\tabularrule{\arrayrulecolor{black!15}\cmidrule{1-3}\arrayrulecolor{black}}% Grey rule
}
{\let\arrayrulecolor\relax
\let\cmidrule\relax
\protected@xdef\tabulardata{\tabulardata%
\tabularrule% Insert tabular rule + \fieldA
& \fieldB & \fieldC \tabularnewline
}}% Construct new tabular row
}
\makeatother

\begin{tabular}{ *{3}{c} }
\toprule
Field A & Field B & Field C \\
\midrule
\tabulardata
\\[-\normalbaselineskip]\bottomrule
\end{tabular}

\end{document}

• Okay, so the key here is to redefine the macros you don't want expanded as \relax. Good trick. – Werner Dec 30 '14 at 3:55