根据内容生成条件行表格

根据内容生成条件行表格

我想定义适当的列类型来抑制整个表格全部的列(除标题列,即第一列外)为空。即,内容tabular如下:

Label 1 & 62  & 79 \\
Label 2 &     &    \\
Label 3 &     & 31 \\
Label 4 & 45  &    \\

我想自动抑制带有 的行Label 2

我的尝试:

我定义了一个T列类型,此时确定前一行是否要通过以下方式排版:

\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
}

所有其他列的类型为在遇到非空单元格时L将布尔值设置DisplayThisRow为:true

\newcommand{\ColumnL}[1]{%
    \AddTableTokens{#1}% <--- Need a leading & here
    \IfStrEq{#1}{}{}{% Enable printing of row if non-empty content encoutered
        \global\toggletrue{DisplayThisRow}%
    }%
}

我的尝试基于

得出

在此处输入图片描述

可能不是最好的方法。目前存在的问题包括:

  1. 当需要抑制某一行时,会输出空白。

  2. \AddTableTokens{& #1}缺少列分隔符。在宏的调用中包含列分隔符\ColumnL会导致

    对齐制表符 & 位置错误。

  3. 我原本以为会出现一个问题,即由于没有后续T列,因此不会打印最后一行,但由于某些奇怪的原因,最后一行Label 4却被首先打印!

代码:

\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}

答案1

我使用listofitems包来解析\BODYtabular对于每一行,我都会搜索 2-n 列以查找空格以外的数据。如果找到,我将设置为\rowstatusT如果\rowstatus最终为T,我将行的标记附加到宏 ( \tabdatatoks) 中以供以后使用。否则,我会在 [失败] 的空白行的标记中搜索\hline。如果找到,我还会将其附加到已保存的标记列表中,即使该行原本是空白的。

搜索完成后,我tabular使用已保存的标记列表进行编写。

已编辑以处理额外的行分隔符,例如\toprule,除了 之外,\midrule和。其他内容可以轻松添加到行中,但有一个条件...行分隔符不能接受参数(例如)。\bottomrule\hline\setsepchar{\hline||\bottomrule||\toprule}\cline{1,3}

REEDITED 现已正确处理\cmidrule(x){x-x}和的实例。任何采用和\cline{x-x}以外的参数的行分隔符都需要添加额外的代码。\cmidrule\cline

\documentclass{article}
\usepackage{listofitems,environ,booktabs}
\makeatletter
\NewEnviron{mytab}[2][c]{%
  \setsepchar{\\/&}%
  \readlist\mytabdata{\BODY}%
  \def\tabdatatoks{}%
  \foreachitem\tabrow\in\mytabdata[]{%
    \gdef\rowstatus{F}%
    \foreachitem\tabcol\in\mytabdata[\tabrowcnt]{%
      \ifnum\tabcolcnt=1\relax\else%
        \setsepchar{ }%
        \readlist\mytabcell{\tabcol}%
        \foreachitem\cellpart\in\mytabcell[]{%
          \expandafter\ifx\expandafter\relax\cellpart\relax\else\gdef\rowstatus{T}\fi%
        }%
      \fi%
    }%
    \if T\rowstatus%
%     ADD NONEMPTY ROW DATA TO TOKEN LIST
      \expandafter\g@addto@macro\expandafter\tabdatatoks\expandafter{\tabrow\\}%
    \else%
%     FOR EMPTY ROWS, SEARCH FOR AND RETAIN ROW SEPARATOR LINES
      \setsepchar{\hline||\cline||\bottomrule||\midrule||\toprule||\cmidrule}%
      \expandafter\readlist\expandafter\rowsep\expandafter{\tabrow\ }%
      \foreachitem\x\in\rowsep[]{%
        \ifnum\xcnt=\listlen\rowsep[]\else%
%         ADD ROW SEPARATOR TO TOKEN LIST
          \expandafter\expandafter\expandafter\g@addto@macro%
            \expandafter\expandafter\expandafter\tabdatatoks%
            \expandafter\expandafter\expandafter{\rowsepsep[\xcnt]}%
%         SPECIAL PROVISIONS FOR ROW SEPARATORS WITH ARGUMENTS:
          \checkforsep{\cmidrule}{\getcmidruleargs}%
          \checkforsep{\cline}{\getclineargs}%
        \fi%
      }%
    \fi%
  }%
  \def\tmp{\begin{tabular}[#1]{#2}}\expandafter\tmp\tabdatatoks\end{tabular}%
}
\newcommand\checkforsep[2]{%
  \expandafter\expandafter\expandafter\ifx\rowsepsep[\xcnt]#1%
    \expandafter\expandafter\expandafter#2\rowsep[\numexpr\xcnt+1\relax]\relax\fi%
}
\def\getcmidruleargs(#1)#2#3\relax{\g@addto@macro\tabdatatoks{(#1){#2}}}
\def\getclineargs#1#2\relax{\g@addto@macro\tabdatatoks{{#1}}}
\makeatother
\begin{document}
\begin{mytab}{lrr}
\toprule
Label 1 & 62  & 79     \\
\cmidrule(r){1-1}\cmidrule(r){3-3}
Label 2 &     &        \\
Label 3 &     & 31     \\
\cline{1-1}\cline{3-3}
Label 4 &     &      \\
Label 5 & 45  & \today \\
\bottomrule
\end{mytab}\bigskip

For comparison, normal tabular:\medskip

\begin{tabular}{lrr}
\toprule
Label 1 & 62  & 79     \\
\cmidrule(r){1-1}\cmidrule(r){3-3}
Label 2 &     &        \\
Label 3 &     & 31     \\
\cline{1-1}\cline{3-3}
Label 4 &     &      \\
Label 5 & 45  & \today \\
\bottomrule
\end{tabular}
\end{document}

在此处输入图片描述

相关内容