7

I need to find a package or else learn how to make a tex command definition that does something very similar to the \rowcolors command for tables, for creating a table with alternating background color stripes, but with a couple of key differences.

First, although this is largely cosmetic, I would very much like the content of a cell to be vertically centered in the background. I notice that \rowcolor tends to leave a larger margin at the bottom than it does at the top, and this looks weird when you have a striped table. All the text seems to be offset vertically from where it is looks like it should be.

More importantly, I want to be able to define the size of the group of row to color, so that unlike \rowcolors where it alternates between two backgrounds each and every row, I want to be able to specify how many rows to group together. So while \rowcolors would effective use a group size of only 1 row, I would like to be able to specify groups of two, three or four rows to group together, for example, and so alternate colors every two, three, or four rows, respectively. This question, which I initially thought was asking the exact same question I am, requires much more explicit coding throughout the table than what I was hoping for, where I was wanting something where I could easily just define all of my tables normally, and then easily go back to it and specify alternating color groups on the tables that needed it (as well as the size of the group to use for the table, of course). The aforementioned question I have linked to here seems to require that I explicitly mark the start of each group, and uses an additional command to actually generate each individual row.

I need the ability to specify which row of a table to start alternating the colors on, as well as a way to have different sizes of groups for different tables (or to turn it off completely). Whether this is done before the table starts or embedded into the row where the alternating colors begin is not important.

It is also of great importance to me that the solution must have a single solid block of unbroken color across all adjacent rows and columns with the same background specified. That is, there can be no thin bars of the normal page background separating the columns or rows. I mention this because I have seen both \rowcolor and \columncolor exhibit this behavior, although I have come to believe that this may be a matter of which tool I am using to render the resulting pdf.

If I have to define my own command for this, I'm going to have no idea how to begin. I'm a complete TeX newbie here, so I'm really hoping that either this already exists out there somewhere, or else it's easy enough to do that it could be explained simply here.

2 Answers 2

9

I have taken a look at the code for \rowcolors and adapted it to allow groups greater one. The new command \groupedRowColors takes four mandatory and one optional argument:

  • The first mandatory argument is the group size, the number of consecutive lines to have the same color.
  • The second mandatory argument is the start line, all lines above will not be colored. This is useful to exclude a header.
  • The third and fourth mandatory arguments are the colors to be used.

If you do not like where the grouping starts or would like to start with the other color you can use the optional argument to shift the colors. Please note that integer division in \numexpr rounds the result so the required shift may be different from what one might expect. (See this question.)

\documentclass{article}

\usepackage[table]{xcolor}
\usepackage{booktabs}

\makeatletter
\newcommand{\groupedRowColors}[5][0]{% [#1: offset], #2: group size, #3: start line, #4: color 1, #5: color 2
    % copied from xcolor.sty
    \global\rownum=\z@
    \global\@rowcolorstrue
    \@ifxempty{#4}%
        {\def\@oddrowcolor{\@norowcolor}}%
        {\def\@oddrowcolor{\gdef\CT@row@color{\CT@color{#4}}}}%
    \@ifxempty{#5}%
        {\def\@evenrowcolor{\@norowcolor}}%
        {\def\@evenrowcolor{\gdef\CT@row@color{\CT@color{#5}}}}%
    % simplified (no check for \if@rowcmd)
    \def\@rowcolors{%
        \if@rowcolors
            \noalign{%
                \relax
                \ifnum\rownum<#3
                    \@norowcolor
                % I have changed this check:
                \else \ifodd \numexpr (\rownum-#1)/#2\relax
                    \@oddrowcolor
                \else
                    \@evenrowcolor
                \fi \fi
            }%
        \fi
    }%
    \CT@everycr{\@rowc@lors\the\everycr}%
    \ignorespaces
}
\makeatother


\begin{document}
\groupedRowColors{3}{2}{green!10}{blue!10}
\begin{tabular}{cc}
    \toprule
        Column~1 & Column~2 \\
    \midrule
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
    \bottomrule
\end{tabular}
\end{document}

enter image description here


EDIT: example with longtable

\documentclass{article}
\usepackage[a6paper, landscape]{geometry}

\usepackage[table]{xcolor}
\usepackage{booktabs}
\usepackage{longtable}

\makeatletter
\newcommand{\groupedRowColors}[5][0]{% [#1: offset], #2: group size, #3: start line, #4: color 1, #5: color 2
    % copied from xcolor.sty
    \global\rownum=\z@
    \global\@rowcolorstrue
    \@ifxempty{#4}%
        {\def\@oddrowcolor{\@norowcolor}}%
        {\def\@oddrowcolor{\gdef\CT@row@color{\CT@color{#4}}}}%
    \@ifxempty{#5}%
        {\def\@evenrowcolor{\@norowcolor}}%
        {\def\@evenrowcolor{\gdef\CT@row@color{\CT@color{#5}}}}%
    % simplified (no check for \if@rowcmd)
    \def\@rowcolors{%
        \if@rowcolors
            \noalign{%
                \relax
                \ifnum\rownum<#3
                    \@norowcolor
                % I have changed this check:
                \else \ifodd \numexpr (\rownum-#1)/#2\relax
                    \@oddrowcolor
                \else
                    \@evenrowcolor
                \fi \fi
            }%
        \fi
    }%
    \CT@everycr{\@rowc@lors\the\everycr}%
    \ignorespaces
}
\makeatother


\begin{document}
\groupedRowColors{3}{0}{green!10}{blue!10}
\begin{longtable}{ c c }
    \hiderowcolors
    \toprule
        Column~1 & Column~2 \\
    \midrule
\endfirsthead
        Column~1 & Column~2 \\
    \midrule
\endhead
    \midrule
        \multicolumn{2}{r@{}}{\footnotesize(to be continued on next page)}
\endfoot
    \bottomrule
\endlastfoot
    \showrowcolors
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
        (\the\rownum,0) & (\the\rownum,1) \\
\end{longtable}
\end{document}

(The definition of \groupedRowColors is unchanged.)

enter image description here

3
  • It took a little bit of fudging with the start line and shift arguments to get the look that I want, but otherwise this is almost exactly right. The only thing I needed to change to get the exact look I was after is the expression in the condition, which I changed to read as: '((\rownum-#3)/#2)-#1' instead of '(\rownum-#1)/#2'
    – Mark
    Oct 13, 2017 at 12:35
  • Hmmm... I see that this doesn't work when I have a longtable with rows that are supposed to be at the head of each page. Ideally, a solution should also start the row count from 0 at the beginning of each new page.
    – Mark
    Oct 14, 2017 at 21:05
  • @Mark I don't know a possibility to reset the row count at a page break. \global\rownum=0 between \endfirsthead and \endhead does not work.
    – jakun
    Oct 15, 2017 at 7:34
2

The lastest version of nicematrix (v 6.0 of 2021-08-10) has a command \rowlistcolors (available in the \CodeBefore) dedicated to that kind of problem.

You won't see thin white lines in the colored panels, whatever PDF viewer you use.

\documentclass{article}
\usepackage{xcolor}
\usepackage{booktabs}
\usepackage{nicematrix}

\begin{document}
\begin{NiceTabular}{cc}
\CodeBefore
  \rowlistcolors{2}{green!10,=,=,blue!10,=,=}[restart]
\Body
  \toprule
      Column~1 & Column~2 \\
  \midrule
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
      (\arabic{iRow},0) & (\arabic{iRow},1) \\
  \bottomrule
\end{NiceTabular}
\end{document}

You need several compilations (because nicematrix uses PGF/Tikz nodes under the hood).

Output of the above code

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .