# Automatically creating a table from datatool using references in the text

This question is based on Peter Grill's answer to "Table including rows of a master table"..

The function \PrintDTLTable takes an optional list of rowIDs (first row of the data file) as its first argument, and makes a table containing only those rows. The rowIDs are also used as labels.

BibTeX is usually used so that it only lists those papers that are cited in the bibligraphy. I don't know how this mechanism works, but I was wondering if can be adapted to this situation. I.e., if I reference some rows by label in the text, then is there some way to automatically generate a table containing only the rows corresponding to the labels appearing in the text?

\documentclass{article}
\usepackage{array}
\usepackage{multirow}
\usepackage{datatool}
\usepackage{longtable}
\usepackage{etoolbox}
\usepackage{filecontents}
\newcounter{tabenum}\setcounter{tabenum}{0}
\newcommand{\nextnuml}[1]{\refstepcounter{tabenum}\thetabenum.\label{#1}}

\begin{filecontents*}{foo.dat}
Hammer001,   Hammer,    1 ,  0 , 1 , 10 , 1 , \multirow{2}{2in}{light (add some words here to wrap around)}\\
Hammer002,   Hammer,    2 ,  0 , 1 , 10 , 1 , heavy
Hammer003,   Hammer,    3 ,  0 , 1 , 10 , 1 , really heavy
Longsword001,Longsword, 1 , -1 , 2 , 75 , 2 , one-handed
Longsword002,Longsword, 2 , -1 , 2 , 75 , 2 , two-handed
Longsword003,Longsword, 3 , -1 , 2 , 75 , 2 , three-handed
\end{filecontents*}

\newcommand{\PrintDTLTable}[2][]{%
% #1 = list of rowIDs
% #2 = database to search
\begin{longtable}{l l l l l l l l}
\DTLforeach
[\ifblank{#1}{\boolean{true}}{\DTLisSubString{#1}{\RowID}}]
{#2}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{longtable}
}%

\begin{document}
% \DTLsetseparator{&}% Define separator of the data

% \DTLdisplaydb{myDB}% Useful for debugging.

\PrintDTLTable[Hammer001,Hammer003,Longsword003]{myDB}
\PrintDTLTable{myDB}

This is a reference to ~\ref{Hammer003}.

\end{document}


The tables produced by the code should be as follows: In the case of

\PrintDTLTable[Hammer001,Hammer003,Longsword003]{myDB}


the table by default consists of the three rows

Hammer001,Hammer003,Longsword003


Since the only reference is to Hammer003, the table produced should only contain the Hammer003 row.

Similarly, in the case of \PrintDTLTable{myDB}, the table by default consists of all 6 rows. Again, since the only reference is to Hammer003, the table produced should only contain the Hammer003 row.

Maybe this is what you want:

\begin{filecontents*}{\jobname.dat}
Hammer001,   Hammer,    1 ,  0 , 1 , 10 , 1 , light (add some words here to wrap around)
Hammer002,   Hammer,    2 ,  0 , 1 , 10 , 1 , heavy
Hammer003,   Hammer,    3 ,  0 , 1 , 10 , 1 , really heavy
Longsword001,Longsword, 1 , -1 , 2 , 75 , 2 , one-handed
Longsword002,Longsword, 2 , -1 , 2 , 75 , 2 , two-handed
Longsword003,Longsword, 3 , -1 , 2 , 75 , 2 , three-handed
\end{filecontents*}

\documentclass{article}
\usepackage{array}
\usepackage{datatool}
\usepackage{longtable}
\usepackage{etoolbox}

\newcounter{tabenum}\setcounter{tabenum}{0}
\newcommand{\nextnuml}[1]{%
\refstepcounter{tabenum}\thetabenum.\label{#1}%
}

\newcommand{\PrintDTLTable}[2][]{%
% #1 = list of rowIDs
% #2 = database to search
\begin{longtable}{l l l l l l l m{2in}}
\hline
\DTLforeach
[%
$$\equal{#1}{}\AND\DTLisSubString{\ReferencedIDs}{\RowID}$$
\OR
$$\DTLisSubString{#1}{\RowID}\AND\DTLisSubString{\ReferencedIDs}{\RowID}$$%
]
{#2}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{longtable}
}

\makeatletter
\let\oldref\ref
\def\ref#1{%
\immediate\write\@auxout{%
\string\gappto\string\ReferencedIDs{#1,}%
}%
\oldref{#1}%
}
\def\ReferencedIDs{}
\makeatother

\begin{document}

% \DTLsetseparator{&}% Define separator of the data

% \DTLdisplaydb{myDB}% Useful for debugging.

\PrintDTLTable[Hammer001,Hammer003,Longsword003]{myDB}

\PrintDTLTable[Hammer002,Longsword002]{myDB}

This is a reference to ~\ref{Hammer003}.

This is a reference to ~\ref{Longsword002}.

\end{document}


The macro \ref is redefined to write in the .aux file also

\gappto\ReferencedIDs{Hammer003,}
\gappto\ReferencedIDs{Longsword002,}


assuming that \ref{Hammer003} and \ref{Longsword002} appear in the text.

The macro \ReferencedIDs is initialized to empty at the start of the job. At the next run, when LaTeX reads the .aux file, it will see those instructions, so at begin document the value of \ReferencedIDs would be equivalent to having said

\def\ReferencedIDs{Hammer003,Longsword002,}


because of how \gappto works.

When \DTLforeach is called, we check the optional argument. If it's empty, the current ID is matched only with \ReferencedIDs. Otherwise, the current ID is matched against both the optional argument and \ReferencedIDs; if the current ID is present in both lists, the row is printed, otherwise it's omitted.

\documentclass{article}
\usepackage{array}
\usepackage{longtable}
\makeatletter
\let\oldref\ref
\def\ref#1{\immediate\write\@auxout{\string\expandafter\gdef\noexpand\csname REF:#1\string\endcsname{}}%
\oldref{#1}}

\def\zz#1#2{\noalign{%
\expandafter\ifx\csname REF:#1\endcsname\@empty
\def\@currentlabel{#2}\label{#1}%
\else
\aftergroup\zzapline
\fi}#2}

\long\def\zzapline#1\\{}
\makeatother

\begin{document}

\begin{longtable}{l l l l l l p{2in}}
\zz{Hammer001}{Hammer}&    1 &  0 & 1 & 10 & 1 & light (add some words here to wrap around)\\
\zz{Hammer002}{Hammer}&    2 &  0 & 1 & 10 & 1 & heavy\\
\zz{Hammer003}{Hammer}&    3 &  0 & 1 & 10 & 1 & really heavy\\
\zz{Longsword001}{Longsword}& 1 & -1 & 2 & 75 & 2 & one-handed\\
\zz{Longsword002}{Longsword}& 2 & -1 & 2 & 75 & 2 & two-handed\\
\zz{Longsword003}{Longsword}& 3 & -1 & 2 & 75 & 2 & three-handed\\% don't miss this out
\end{longtable}

This is a reference to ~\ref{Hammer003} or  ~\ref{Longsword002}.

\end{document}