I would like to define appropriate column types which suppress an entire row of a table if all of the columns (besides the title column, ie the first column) are empty. That is, with the tabular content as:
Label 1 & 62 & 79 \\
Label 2 & & \\
Label 3 & & 31 \\
Label 4 & 45 & \\
I would like to automatically suppress the row with Label 2.
My Attempt:
I defined a T column type at which time it is determined if the prior row is to be typeset via:
\newcommand{\TitleColumn}[1]{% We are starting a new row
%% If there was a previous row that needed to be output, display that now
\iftoggle{DisplayThisRow}{%
\PrintTableTokens% Print prior row
\global\togglefalse{DisplayThisRow}% Assume entire row is empty
}{%
%\vspace*{-\baselineskip}% Attempt to fix empty rows.
}%
\ResetTableTokens%
\AddTableTokens{#1}% Start a new row with the row label
}
All other columns are of type L which sets the boolean DisplayThisRow to true upon encountering a non-empty cell:
\newcommand{\ColumnL}[1]{%
\AddTableTokens{#1}% <--- Need a leading & here
\IfStrEq{#1}{}{}{% Enable printing of row if non-empty content encoutered
\global\toggletrue{DisplayThisRow}%
}%
}
My attempt, based on
- How do I use the ampersand (&) inside a foreach or conditional (or other group/environment) when building tables?
- Build tabular content via \foreach
which yields
may not be the best approach. The current problems with it include:
A blank like is output when a row is to be suppressed.
The column separators are missing. Including a column separators in the call to
\AddTableTokens{& #1}in the\ColumnLmacro leads toMisplaced alignment tab character &.
I was expecting a problem in that the last row would not be printed as there was no subsequent
Tcolumn, but for some bizarre reason, the last row,Label 4, is printed first!
Code:
\documentclass{article}
\usepackage{collcell}
\usepackage{tabularx}
\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{showframe}
%% This is based on:
%% https://tex.stackexchange.com/q/165126/4301
%% https://tex.stackexchange.com/q/175568/4301
%%
\makeatletter
\newcommand{@MyTempTableTokens}{}%
\newtoks@tabtoks
%%% assignments to @tabtoks must be global, in case they are done in \foreach
\newcommand\AddTableTokens[1]{\global@tabtoks\expandafter{\the@tabtoks#1}}
\newcommand\eAddTableTokens[1]{% Do NOT add a tailing \ for each line
\protected@edef@MyTempTableTokens{#1}%
\expandafter\AddTableTokens\expandafter{@MyTempTableTokens \}%
}%
%%% variable should be operated on always locally or always globally
\newcommand\ResetTableTokens{\global@tabtoks{}}
\newcommand*\PrintTableTokens{\the@tabtoks}
\makeatother
\newcommand{\ColumnL}[1]{%
\AddTableTokens{#1}% <--- Need a leading & here
\IfStrEq{#1}{}{}{% Enable printing of row if non-empty content encoutered
\global\toggletrue{DisplayThisRow}%
}%
}
\newtoggle{DisplayThisRow}%
\togglefalse{DisplayThisRow}%
\newcommand{\TitleColumn}[1]{% We are starting a new row
%% If there was a previous row that needed to be output, display that now
\iftoggle{DisplayThisRow}{%
\PrintTableTokens% Print prior row
\global\togglefalse{DisplayThisRow}% Assume entire row is empty
}{%
%\vspace*{-\baselineskip}% Attempt to fix empty rows.
}%
\ResetTableTokens%
\AddTableTokens{#1}% Start a new row with the row label
}
\newcolumntype{L}{>{\collectcell\ColumnL}l<{\endcollectcell}}
\newcolumntype{T}{>{\collectcell\TitleColumn}X<{\endcollectcell}}
\begin{document}
%\showcols
\noindent
\begin{tabularx}{\linewidth}{@{}TLL@{}}
Label 1 & 62 & 79 \
Label 2 & & \
Label 3 & & 31 \
Label 4 & 45 & \
\end{tabularx}
\end{document}


\hlineto include other separators? I was able to include\bottomruleby duplicating the lines in the\elseclause but wondering if there is an easier way. Similarly, I was using\cmidrule(r){1-2}and wrapping that in a macro\newcommand*{\Divider}{\cmidrule(r){1-2}}, I was able to get it to work by again duplicating the three lines in the\elseclause to check for\Divider. – Peter Grill Oct 24 '18 at 17:50\cline{}. If that is a big issue, I can give it more thought. – Steven B. Segletes Oct 24 '18 at 18:02\newcommand*{\Divider}{\cmidrule(r){1-2}}and using\Dividerseems to be working. I was expecting to have to add\Dividerto the list of possible separators, so wondering if I am missing something here? Also,\cmidrule(r){1-2}used directly seems to work too!!!! Huh? – Peter Grill Oct 24 '18 at 18:09\cmidrule(r){1-2}directly (without defining a separate macro) followingLabel 2seems to work too with this new version. It didn't in an earlier version. – Peter Grill Oct 24 '18 at 18:18listofitemsinitial parse is on the basis of\\/&meaning the "row" data is what falls between successive double backslashes. Thus, if your\cmidrulefalls prior to (not following) Label 2, it will technically be in the same row data as Label 2. That is when it will be affected. – Steven B. Segletes Oct 24 '18 at 18:23\hlinebeforeLabe 2end up being a\toprulestyle line? – Peter Grill Oct 24 '18 at 18:53booktabs, don't use\hline, but rather\midrule. I am about to post the ultimate fix for the issue. – Steven B. Segletes Oct 24 '18 at 18:56\clineas well. – Steven B. Segletes Oct 24 '18 at 19:13