# Can I partially re-use a table or build it up over chapters?

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.

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}


## 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.

## 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
\protected@edef\MyTempTableTokens{#1}%
}
%%% 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}{}%
\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}}{%
}{%
%% 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}

• See my answer for an implementation of a handler of the list of rows and ranges. You can incorporate that into your code if you like. – Hood Chatham Aug 24 '18 at 10:31
• @HoodChatham: Thanks. Have updated the answer to adapt your solution to the range parsing. – Peter Grill Aug 24 '18 at 22:09

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}{}%