自定义表格环境 - \rowcolor 没有 \\ 会导致下一个表格出现问题 - colortbl 中有错误吗?

自定义表格环境 - \rowcolor 没有 \\ 会导致下一个表格出现问题 - colortbl 中有错误吗?

我把问题归结为更简单的 MWE。请参阅下面的更新。

我尝试自定义表格环境,以便在整个论文中轻松使用连贯的风格。我希望表格环境能够

  • 在表格主体的每一行后自动添加\addlinespace(最后一行除外)
  • 自动交替显示行颜色 - 不是针对单行,而是针对多行(大多数情况下是 3 行,在 stackexchange 的其他地方也有人推荐这样做

我知道有\arraystretch,但这也会影响标题,因此如果两种类型的表格彼此靠近使用,看起来会很别扭。我也知道\rowcolors有该命令,但它不允许对行组进行着色(据我所知)。

我在自定义环境中进行了所有这些修改,我可以使用命令选择其中一项(或两项)修改。这两个选项都有效,但不幸的是,行颜色对下一个表格环境,即不是我修改的环境。

我准备了一个最小的工作示例:

\documentclass[a4paper,11pt]{book}

\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{booktabs}
\usepackage[table]{xcolor}
\usepackage{ifthen}
\usepackage{calc}

\input{tables}

\begin{document}

\begin{stable}
\srowgroupcolors{2}{white}{orange}
\begin{tabular}{ccc}
\toprule
a & b & c\\ 
\midrule
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\bottomrule
\end{tabular}
\end{stable}

\begin{stable}
\begin{tabular}{ccc}
\toprule
a & b & c\\ 
\midrule
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\bottomrule
\end{tabular}
\end{stable}

\begin{stable}
\begin{tabular}{ccc}
\toprule
a & b & c\\ 
\midrule
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\bottomrule
\end{tabular}
\end{stable}

\end{document}

第一个表中的命令\srowgroupscolors{2}{white}{orange}激活了行着色。第二个表在第一行的第一列(\toprule 之后)中显示了问题。第三个表按预期工作。请注意,即使使用第二个表格环境而没有周围的稳定环境,问题仍然存在。

结果如下所示(对于稳定环境中的第二个表):

表

稳定的代码定义在tables.tex下面的文件中。我删除了用于自动行距的部分,因为它不会引起任何问题。它仍然相当长(尽管它包含的注释比代码多)。

它的作用如下:它计算表格行数,但仅限于正文,即\midrule使用后。在标题中,计数器保持为零。对于每个正文行,\stable@color@step由覆盖的命令调用\@arraycr。(请注意,stable@color@step在中定义\srowgroupcolors,否则为空。)它调用\stable@calc@rowcolor(在\noalign命令中)根据颜色计算颜色下一个 行并将相应\rowcolor命令存储在 中\stable@rowcolor。后者在\noalign命令之后直接调用。因此\rowcolor下一行的命令在 之后立即发出\\

 \makeatletter                                                                                                                                                                                                                           

% counter for the line number (modulo 2 * group@size)
\newcounter{stable@counter}
% size of groups (row coloring)
\newcounter{stable@group@size}
% modulo value, used to get the right color
\newcounter{stable@modulo}
% whether array / tabular have already been patched
\newboolean{stable@patched}

% replacement for table
% arguments:
% #1 - placement - default is !htb
\newenvironment{stable}[1][!htb]{%
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % internal commands for auto spacing and coloring of rows
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %   
    % set the group size and calculate the modulo
    \newcommand*{\stable@set@group@size}[1]{%
        \setcounter{stable@group@size}{##1}%
        \setcounter{stable@modulo}{2*\value{stable@group@size}}%
    }%  
    %   
    % calculate the rowcolor based on the row number
    % step the rownumber (module 2 * group size) if > 0 (body)
    % TODO refactor: extract a step method
    \newcommand{\stable@calc@rowcolor}{%
        \ifthenelse{\value{stable@counter}=0}%
            % we're still in the header
            {\gdef\stable@rowcolor{}}%
            % we're in the body
            {%  
                % 1 - group size: color 1, above group size: color 2
                \ifthenelse{\value{stable@counter}>\value{stable@group@size}}%
                    {\gdef\stable@rowcolor{\rowcolor{stable@color2}}}%
                    {\gdef\stable@rowcolor{\rowcolor{stable@color1}}}%
                % increase counter -> number of the NEXT row 
                \stepcounter{stable@counter}%
                % modulo operation
                \ifthenelse{\value{stable@counter}>\value{stable@modulo}}%
                    % reset to 1 (sic!), as 0 would be header
                    {\setcounter{stable@counter}{1}}%
                    {}% 
            }%  
    }%  
    %   
    % shortcut: call stable@calc@color in a \noalign, use the calculated color
    % the default implementation does nothing, the command has to be changed
    \def\stable@color@step{}
    %   
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % modify the array / tabular package
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    % backup the original array / tabular commands
    \newcommand{\stable@arraycr}{}%
    \let\stable@arraycr\@arraycr%
    \newcommand{\stable@midrule}{}%
    \let\stable@midrule\midrule%
    %
    % patch the array / tabular commands
    % lazy patching makes sure this does not break anything
    \newcommand*{\stable@patch@array}{%
        \ifthenelse{\boolean{stable@patched}}%
            % already patched, do nothing
            {}%
            {%
                \setboolean{stable@patched}{true}%
                % replace the \\ command (@arraycr): integrate coloring and spacing
                \renewcommand{\@arraycr}{%
                    \stable@arraycr%
                    \stable@color@step%
                }%
                %
                % replace \midrule: start coloring and spacing
                \renewcommand{\midrule}{%
                    \stable@midrule%
                    % set counter to 1 (end of heading}
                    \noalign{%
                        \setcounter{stable@counter}{1}%
                    }%
                    % start coloring (1st row)
                    \stable@color@step%
                }%
            }%
    }%
    %
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % external commands for tables
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    % alternating colored groups of rows
    % arguments:
    % #1 - group size
    % #2 - first color (tables always start with this color)
    % #3 - second color
    \newcommand{\srowgroupcolors}[3]{%
        % shortcut: call stable@calc@color in a \noalign, use the calculated color
        \def\stable@color@step{\noalign{\stable@calc@rowcolor}\stable@rowcolor}%
        % store the settings
        \stable@set@group@size{##1}%
        \colorlet{stable@color1}{##2}%
        \colorlet{stable@color2}{##3}%
        % patch the array commands
        \stable@patch@array
    }%
    %
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % configuration / defaults
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    % prepare row counter
    % (count rows modulo (2 * colored group size), value 0 means: header)
    \setcounter{stable@counter}{0}%
    % initialize with default values                                                                                                                                                                                                       
    \stable@set@group@size{1}%
    % array / tabular commands have not yet been patched
    \setboolean{stable@patched}{false}%
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % start of the actual table
    % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    % use small sized sans serif font
    \begin{table}[#1]%
}{%
    \end{table}%
}%

\makeatother

尽管一切都是在稳定组中完成的,但我的代码一定是设法破坏了表格中的某些内容。唯一的例外是在用于临时存储(如果需要)的\gdef中使用。我使用了这种解决方法(取自\stable@calc@rowcolor\addlinespace这个问题) 以避免!Misplaced \noalign错误。

有人知道这些问题的根源是什么吗?

更新

以下代码会触发同样的问题 - 这正是我的表格扩展所做的:

\documentclass[a4paper,11pt]{book}

\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{booktabs}
\usepackage[table]{xcolor}

\begin{document}

\begin{table}
\begin{tabular}{ccc}
\toprule
a & b & c\\                                           
\midrule
\rowcolor{white} 0 & 0 & 0 \\
\rowcolor{white} 0 & 1 & 1 \\
\rowcolor{orange} 1 & 0 & 1 \\
\rowcolor{orange} 1 & 1 & 0 \\
\rowcolor{orange} \bottomrule
\end{tabular}
\end{table}

\begin{table}
\begin{tabular}{ccc}
\toprule
a & b & c\\ 
\midrule
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\bottomrule
\end{tabular}
\end{table}

\begin{table}
\begin{tabular}{ccc}
\toprule
a & b & c\\ 
\midrule
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\bottomrule
\end{tabular}
\end{table}

\end{document}

这是通过\rowcolor在 之后直接添加命令\\(使用\everycr或通过覆盖\@arraycr)来触发的。此时不清楚是否还有另一行。出于某种原因,\rowcolor如果最后一行是 a\bottomrule或 a ,则表格环境不喜欢最后一行中的 a \hline

有办法解决这个问题吗? tabular 是否在行首提供了一个钩子,我可以使用它来代替? 是否可以检查某一行是否不包含\bottomrule

或者有没有办法“撤消”\rowcolor覆盖的命令\bottomrule?实际上,这就是我为使间距部分(示例中未显示)正常工作所做的工作。

更新 2

我进一步调查了这个问题。归根结底是 colortbl 中的一个问题。当\rowcolor使用 而后面没有 时\\,下一个表格会显示错误。我发现的最简单的例子如下:

\documentclass{article}                                      

\usepackage[english]{babel}
\usepackage{colortbl}

\begin{document}

\begin{tabular}{c}
a \\                                        
\rowcolor{orange}
\end{tabular}

\begin{tabular}{c}
a \\
\end{tabular}

\end{document}

结果如下:

表

在我看来,这似乎是 colortbl 中的一个错误。即使这个“尾随”\rowcolor完全没有意义,它也不应该对下一个表格产生影响。

我尝试查看如何\rowcolors解决该问题 - 它似乎没有生成这样的“尾随”rowcolor命令,但我不完全了解其来源。

我的解决方法是在保存框中创建下一个表格,然后将其丢弃。保存框之后创建的表格不会显示该问题。

\documentclass{article}

\usepackage[english]{babel}
\usepackage{colortbl}

\begin{document}

\begin{tabular}{c}
a \\                                           
\rowcolor{orange}
\end{tabular}

\newsavebox{\bin}
\savebox{\bin}{\tabular{c}\\\endtabular}

\begin{tabular}{c}
a \\
\end{tabular}

\end{document}

无论如何,如果有更好的方法可以修复我的扩展,我会很乐意使用它,而不是这个丑陋的解决方法。

答案1

似乎没有任何用例需要\rowcolor在所有的行之后添加,但是如果这样做了,您可以在表之后清除其设置:

\documentclass{article}                                      

\usepackage[english]{babel}
\usepackage{colortbl}

\begin{document}

\begin{tabular}{c}
a \\                                        
\rowcolor{orange}
\end{tabular}

\makeatletter\global\let\CT@do@color\relax\makeatother

\begin{tabular}{c}
a \\
\end{tabular}

\end{document}

在此处输入图片描述

相关内容