4

I've got a NewEnviron from the environ package which I use to enclose a table. An example of this is in the MWE below. The purpose is to handle the table formatting in the preamble and let the user provide only the content. What I need now is some ability to interact with the \BODY command of the environ so that I can properly specify the headers (via the ltablex (really the longtable) package) and have it properly display multi-page tables.

What the table content expands to now:

\caption{#1} \\ % Include the caption at the top of the table
\endfirsthead % Only show the caption for the first page
\hiderowcolors \caption{Continued} \\ % Include a caption on subsequent pages that just says continued
\showrowcolors % row coloring was turned off for the caption, now lets turn it back on
\endhead % End of header for all pages after first
\hline
\rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
Header 1 & Header 2 \\   % This is part of \BODY
Content 1 & Content 2 \\ % This is part of \BODY
Content 3 & Content 4 \\ % This is part of \BODY
\hline

What I would like it to be:

\caption{#1} \\ % Include the caption at the top of the table
\hline
\rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
Header 1 & Header 2 \\   % This is part of \BODY
\endfirsthead % Only show the caption for the first page
\hiderowcolors \caption{Continued} \\ % Include a caption on subsequent pages that just says continued
\showrowcolors % row coloring was turned off for the caption, now lets turn it back on
\hline
\rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
Header 1 & Header 2 \\   % This is part of \BODY
\endhead % End of header for all pages after first
Content 1 & Content 2 \\ % This is part of \BODY
Content 3 & Content 4 \\ % This is part of \BODY
\hline

Is there a way to achieve this?


Minimum Working Example

\documentclass{article}

\usepackage[table,dvipsnames]{xcolor}   % Provides coloring for tables and text
\usepackage{ltablex}                    % Customized table formatting (uses tabularx and longtable)
\usepackage{environ}                    % Used to define custom table environment

% Fixes conflict between variable names in tabularx and xcolor
\newcounter{tblerows}
\expandafter\let\csname c@tblerows\endcsname\rownum

\definecolor{greyblue}{rgb}{0.6353,0.6863,0.7686} % Define a color used in the tables
\newcommand\setrow[1]{\gdef\rowmac{#1}#1\ignorespaces} % Used for making a row bold
\newcommand\clearrow{\global\let\rowmac\relax} \clearrow % Used for clearing a row formatting
\newcolumntype{L}[1]{>{\hsize=#1\hsize\rowmac\raggedright\arraybackslash}X} % Left-aligned column, input is relative width of page
\keepXColumns

\NewEnviron{doctable}[1]{%
    \centering
    \rowcolors{3}{black!5}{black!15}
    \begin{tabularx}{\textwidth}{L{0.5}|L{0.5}<{\clearrow}}
        \caption{#1} \\ % Include the caption at the top of the table
        \endfirsthead % Only show the caption for the first page
        \hiderowcolors \caption{Continued} \\ % Include a caption on subsequent pages that just says continued
        \showrowcolors % row coloring was turned off for the caption, now lets turn it back on
        \endhead % End of header for all pages after first
        \hline
        \rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
        \BODY
        \hline
    \end{tabularx}
    \label{tbl:somelabel}
}

\begin{document}

    \begin{doctable}{Some Caption}
        Header 1 & Header 2 \\
        Content 1 & Content 2 \\
        Content 3 & Content 4 \\
    \end{doctable}

\end{document}
  • In my opinion, this calls for \expandafter\unexpanded and xparse. – MaestroGlanz Feb 13 '17 at 15:52
  • @MaestroGlantz Yes, I had figured as much, however I'm not nearly knowledgeable enough to know how to accomplish this. I was hoping some wizard here could point me in the right direction. – zephyr Feb 13 '17 at 16:06
2

The header line should be given as a further argument.

\documentclass{article}

\usepackage[table,dvipsnames]{xcolor}   % Provides coloring for tables and text
\usepackage{ltablex}                    % Customized table formatting (uses tabularx and longtable)
\usepackage{environ}                    % Used to define custom table environment

% Fixes conflict between variable names in tabularx and xcolor
\newcounter{tblerows}
\makeatletter
\let\c@tblerows\rownum
\makeatother

\definecolor{greyblue}{rgb}{0.6353,0.6863,0.7686} % Define a color used in the tables
\newcommand\setrow[1]{\gdef\rowmac{#1}#1\ignorespaces} % Used for making a row bold
\newcommand\clearrow{\global\let\rowmac\relax} \clearrow % Used for clearing a row formatting
\newcolumntype{L}[1]{>{\hsize=#1\hsize\rowmac\raggedright\arraybackslash}X} % Left-aligned column, input is relative width of page
\keepXColumns

\NewEnviron{doctable}[2]{%
  \centering
  \rowcolors{3}{black!5}{black!15}
  \begin{tabularx}{\textwidth}{L{0.5}|L{0.5}<{\clearrow}}
    \caption{#1} \\ % Include the caption at the top of the table
    \hline
    \rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
    #2 \\
    \hline
    \endfirsthead % Only show the caption for the first page
    \hiderowcolors \caption{Continued} \\ % Include a caption on subsequent pages that just says continued
    \showrowcolors % row coloring was turned off for the caption, now lets turn it back on
    \rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
    #2 \\
    \hline
    \endhead % End of header for all pages after first
    \BODY
    \hline
    \end{tabularx}
}

\begin{document}

\begin{doctable}
  {Some Caption\label{somelabel}}
  {Header 1 & Header 2}
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
\end{doctable}

\end{document}

enter image description here

Alternatively, but I wouldn't recommend it,

\documentclass{article}

\usepackage[table,dvipsnames]{xcolor}   % Provides coloring for tables and text
\usepackage{ltablex}                    % Customized table formatting (uses tabularx and longtable)
\usepackage{environ}                    % Used to define custom table environment

% Fixes conflict between variable names in tabularx and xcolor
\newcounter{tblerows}
\makeatletter
\let\c@tblerows\rownum
\makeatother

\definecolor{greyblue}{rgb}{0.6353,0.6863,0.7686} % Define a color used in the tables
\newcommand\setrow[1]{\gdef\rowmac{#1}#1\ignorespaces} % Used for making a row bold
\newcommand\clearrow{\global\let\rowmac\relax} \clearrow % Used for clearing a row formatting
\newcolumntype{L}[1]{>{\hsize=#1\hsize\rowmac\raggedright\arraybackslash}X} % Left-aligned column, input is relative width of page
\keepXColumns

\makeatletter
\long\def\split@doublebar#1\\#2\@nil{%
  \def\doctableheader{#1}%
  \def\doctablebody{#2}%
}

\NewEnviron{doctable}[1]{%
  \centering
  \expandafter\split@doublebar\BODY\@nil
  \rowcolors{3}{black!5}{black!15}
  \begin{tabularx}{\textwidth}{L{0.5}|L{0.5}<{\clearrow}}
    \caption{#1} \\ % Include the caption at the top of the table
    \hline
    \rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
    \doctableheader \\
    \hline
    \endfirsthead % Only show the caption for the first page
    \hiderowcolors \caption{Continued} \\ % Include a caption on subsequent pages that just says continued
    \showrowcolors % row coloring was turned off for the caption, now lets turn it back on
    \rowcolor{greyblue} \setrow{\bfseries} % Make the header row bold and colored grey-blue
    \doctableheader \\
    \hline
    \endhead % End of header for all pages after first
    \doctablebody
    \hline
    \end{tabularx}
}
\makeatother

\begin{document}

\begin{doctable}
  {Some Caption\label{somelabel}}
  Header 1 & Header 2 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
  Content 1 & Content 2 \\
  Content 3 & Content 4 \\
\end{doctable}

\end{document}
  • Thanks a lot! I did think about switching to have the header be an input to the environment, but I was trying to keep this backwards compatible. Is there any particular reason you don't recommend your second solution? Is it just because it can potentially break easily? – zephyr Feb 13 '17 at 16:59
  • @zephyr Exactly. This way you are assuming that the first \\ separates the header from the body. – egreg Feb 13 '17 at 17:00
  • What does the \@nil? – MaestroGlanz Feb 13 '17 at 17:20
  • @MaestroGlanz It delimits the second argument. – egreg Feb 13 '17 at 17:45
2

This is a complex thing, for what I dont see any simple solution.

I will provide some strategy here to solve this:

\let\rest\BODY
\def\knabbknabb#1&#2{#1\def\rest{#2}}
\def\knibbknibb#1\\#2{#1\def\rest{#2}}
\expandafter\unexpanded\knabbknabb\rest\relax
\expandafter\unexpanded\knibbknibb\rest\relax
\let\BODY\rest

First I copy \BODY into \rest, then I define my cut functions.

The output of \knabbknabb{rest} is Header 1, the output of knibbknibb{rest} is Header 2.

After that, \rest contains

Content 1 & Content 2 \\
Content 3 & Content 4 \\

and is copied back to \BODY

That would be my strategy.

  • Useful to know. Thanks for your help. I will say that this solution is specific to having two columns, which I'm not always assuming (but left in for the MWE). – zephyr Feb 13 '17 at 17:25
  • I could fix that, but this is a lot of work. – MaestroGlanz Feb 16 '17 at 8:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.