3

In my thesis I have a table that I want to build up over the course of a chapter. Specifically, I am presenting statistics about different datasets, including one that I created myself to address issues in the existing data.

Ideally I would write the table+tabular code once and then refer to that code everywhere the table needs to be repeated, just revealing or hiding different parts of it.

So I might write:

   \begin{table}
     \caption{Sample Table}
     \label{tab:sample-table}
     \begin{tabular}{lr}
       dataset & some numbers\\
       \hline
       A & 10\\
       B & 11\\
       C & 12\\
       \hline
       D & 48\\
       E & 144\\
     \end{tabular}
   \end{table}

And then in one place use some command like:

   \inserttable[1-4]{tab:sample-table}

to insert the header & rows A-C, and in another place write:

   \inserttable{tab:sample-table}

in order to insert the whole table.

Is there any package or set of macros for doing this or do I have to repeat the table every place that I want to reference it?

My table is quite a bit larger and more complex than this, and my concern is that if I have to update some of the values I might update them in one place and forget the others if I have to duplicate the code.

dmh
  • 133

2 Answers2

3

Here is one way to do this. First define the entries of the entire table:

\newcommand*{\MyTabularEntries}{%
   Row & dataset & some numbers \\,
   \unexpanded{\cmidrule(r){1-1}\cmidrule(lr){2-2}\cmidrule(l){3-3}},
   3 & A & 10 \\,
   4 & B & 11 \\,
   5 & C & 12 \\,
   \unexpanded{\cmidrule{1-3}},
   7 & D & 48 \\,
   8 & E & 144 \\,
}%

and then build the table with only the dried rows by invoking

\InsertTable[<csv list of rows>]{<title>}{\MyTabularEntries}

enter image description here

Notes:

  • I added a row number to make it easier to see that this solution is working correctly. The header and cmidrule are counted.
  • I also used the booktabs package as that produces better tables.

References

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{xparse}
\usepackage{tikz}

\newcommand{\MyTempTableTokens}{}% \makeatletter \newtoks@tabtoks %%% assignments to @tabtoks must be global, because they are done in \foreach \newcommand\AddTableTokens[1]{\global@tabtoks\expandafter{\the@tabtoks#1}} \newcommand\eAddTableTokens[1]{% \protected@edef\MyTempTableTokens{#1}% \expandafter\AddTableTokens\expandafter{\MyTempTableTokens}% } %%% variable should always be operated on always locally or always globally \newcommand\ResetTableTokens{\global@tabtoks{}} \newcommand*\PrintTableTokens{\the@tabtoks}

%% \processlist is based on a contribution by Hood Chatham \newcount\tempcount \newcommand*{\MacroToExecute}{}% \def\processlist#1#2{\def\MacroToExecute{#1}\processlist@#2,@nil} \def\processlist@#1,{% \in@-{#1}% \ifin@ \processrange#1@nil \else \MacroToExecute{Row #1}{}% \fi @ifnextchar@nil{@gobble}{\processlist@}% }

\def\processrange#1-#2@nil{% \tempcount=#1\relax \loop \MacroToExecute{Row \the\tempcount}{}% \advance\tempcount1\relax \unless\ifnum\tempcount>#2\repeat } \makeatother

\newcommand*{\MyTabularEntries}{% Row & dataset & some numbers \, \unexpanded{\cmidrule(r){1-1}\cmidrule(lr){2-2}\cmidrule(l){3-3}}, 3 & A & 10 \, 4 & B & 11 \, 5 & C & 12 \, \unexpanded{\cmidrule{1-3}}, 7 & D & 48 \, 8 & E & 144 \, }%

\newcounter{RowNumber} \NewDocumentCommand{\InsertTable}{% O{1-10}% #1 = range of lines to print, defaults to all lines from 1-99 m% #2 = table title m% #3 = list of entries (terminated by comma). }{% \processlist{\csdef}{#1}% \ResetTableTokens% \setcounter{RowNumber}{0}% \foreach \Entry in #3 {% \stepcounter{RowNumber}% \ifcsdef{Row \arabic{RowNumber}}{% \eAddTableTokens{\Entry}% }{% %% This row number was not requested so skip it }% }% \begin{tabular}{lll} \toprule \multicolumn{3}{c}{#2} \ \PrintTableTokens \bottomrule \end{tabular}% % Clear the desired rows list \processlist{\csundef}{#1}% }

\begin{document}

\InsertTable{All Rows}{\MyTabularEntries}%

\par\medskip
\InsertTable[1-5]{Rows 1-5}{\MyTabularEntries}%

\par\medskip
\InsertTable[1,2,4,6-10]{Rows 1,2,4,6-10}{\MyTabularEntries}%

\end{document}

Peter Grill
  • 223,288
3

This isn't a complete answer answer because I think Peter Grill's answer is pretty good. I am just providing here a macro to process a list of individual rows and ranges to work with Peter's code.

\newcount\tempcount
\def\processlist#1{\processlist@#1,\@nil}
\def\processlist@#1,{%
    \in@-{#1}%
    \ifin@
        \processrange#1\@nil
    \else
        \csgdef{Row #1}{}%
    \fi
    \@ifnextchar\@nil{\@gobble}{\processlist@}%
}

\def\processrange#1-#2\@nil{%
    \tempcount=#1\relax
    \loop
        \csgdef{Row \the\tempcount}{}%
        \advance\tempcount1\relax
    \unless\ifnum\tempcount>#2\repeat
}
Hood Chatham
  • 5,467