# Creating a command to fill a template table

I'm creating a style file for deliverables for a project. During the draft stage, deliverables need to have a revision history in a table (version, date, modifications, modified by).

In the style file, I define a command:

\newcommand{\makedeliverable}{ % very long template
}


In any deliverable made using the template, \newdeliverable \makedeliverable is used immediately after \begin{document} to create the cover page, table of contents, list of figures etc. (I appreciate this might not be the best way, but it works well and I was able to produce it quickly).

I'd also like this command to create the revision history table, based on revisions specified by a user in their own preamble.

So in the .sty file (as part of the \makedeliverable command} I would have:

\begin{tabular}{|p{0.2\textwidth} | p{0.3\textwidth} | p{0.3\textwidth} | p{0.2\textwidth} |}
\hline
\textbf{Version} & \textbf{Date} & \textbf{Modifications} &     \textbf{Modified by}\\
\hline
% something here to populate the table
\end{tabular}


And also a command definition along the lines of:

\newcommand{\addrevision}[4]{ %something
}


Which would be called in the preamble with (e.g.):

\addrevision{0.1, 2017-11-27, Added new stuff, J. Bloggs}


With my programming hat on, I'd have \addrevision populate an array which is then printed out in the table. But I'm unsure how to go about this in LaTeX.

The code below does what I think you want. It uses LaTeX3 to build up a token list for the revision history. The code assumes that the \addrevision{...} lines are added in "revision order". Following the recommendations in the booktabs manual, I have dropped the vertical rules as the general opinion is that tables look better without them (and it is trivial to add them back if they are required).

The code defines two commands:

• \addrevision{...}: this accepts/expects a comma separated list of the four pieces of "revision data": version, date, modifications, modifier
• \RevisionHistory: inserts the current revision history

Here is the output:

...and here is the code:

\documentclass{article}
\usepackage{expl3}
\usepackage{booktabs}

\ExplSyntaxOn
\tl_new:N \l_revisions_tl% to hold revision history
\regex_split:nnN {\,} {#1} \l_tmpa_seq% split #1 on commas
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl% don't want & before first entry
\tl_put_right:NV \l_revisions_tl \l_tmpa_tl
\seq_map_inline:Nn \l_tmpa_seq { \tl_put_right:Nn \l_revisions_tl {&##1} }
\tl_put_right:Nn \l_revisions_tl {\\}% add \\ for end of line
}
\newcommand\RevisionHistory{%
\begin{tabular}{p{0.2\textwidth}p{0.3\textwidth}p{0.3\textwidth}p{0.2\textwidth}}
\toprule
\textbf{Version} & \textbf{Date} & \textbf{Modifications} & \textbf{Modified~by}\\
\midrule
\tl_use:N \l_revisions_tl
\bottomrule
\end{tabular}
}
\ExplSyntaxOff

\begin{document}

\RevisionHistory

\end{document}


I have used the same columns widths as in the OP but, probably, columns 1,2 and 4 should all be narrowed and the modifications column should be wider. If the revision history goes on for pages then something like longtable or supertabular should be used.

EDIT

Here is a second version using expl3 sequences. This is closer in spirit to the approach suggested in the OP and the code is shorter and, arguably, easier to understand.

\documentclass{article}
\usepackage{expl3}
\usepackage{booktabs}

\ExplSyntaxOn
\seq_new:N \l_revisions_seq
\seq_put_right:Nn \l_revisions_seq {#1}
}
\newcommand\RevisionHistory{%
\begin{tabular}{p{0.2\textwidth}p{0.3\textwidth}p{0.3\textwidth}p{0.2\textwidth}}
\toprule
\textbf{Version} & \textbf{Date} & \textbf{Modifications} & \textbf{Modified~by}\\
\midrule
\seq_map_inline:Nn \l_revisions_seq {% loop over revisions
\regex_split:nnN {\,} {##1} \l_tmpa_seq% split on commas
\seq_use:Nn \l_tmpa_seq {&}% print the table row
\\
}
\\[-12pt]% \\ is necessary here but it inserts a blank line, so hack...
\bottomrule
\end{tabular}
}
\ExplSyntaxOff

\begin{document}

\RevisionHistory

\end{document}


For reasons I don't understand, I have had to use the hack \\[-12pt]\bottomrule to prevent a blank line from appearing at the bottom of the table. The output is the same as before

• +1, but you \usepackage{xparse} and code \newcommand? – TeXnician Nov 27 '17 at 15:51
• No, that's not what I meant, I just thought that including it without actually using it is a bit pointless, but your code is alright. Maybe the l3 guys would point out that this would be one more step towards the separation of code and document level, but I'm not really sure, whether this is necessary here. – TeXnician Nov 27 '17 at 16:52
• No, LaTeX3 is loaded by expl3, which is loaded by xparse. xparse itself only provides the layers like \NewDocumentCommand etc. on top. – TeXnician Nov 27 '17 at 20:23
• The first method given in this solution worked perfectly! Thanks very much. – ThetaSigma Nov 28 '17 at 13:00

The mandatory \xintFor solution.

\documentclass{article}
\usepackage{xinttools}
\usepackage{booktabs}

\newcommand\Revisions {}%

% append a new revision, the csv list being converted to braced items
\global\oodef\Revisions
% oodef = twice expand contents, second expansion will expand \Revisions
% itself; first expansion propagates to \xintcsvtolist to convert #1
% into braced items, which we will use with \xintListWithSep later on
{\expandafter\Revisions\expandafter{\romannumeral0\xintcsvtolist{#1}}}%
}

\newcommand\RevisionHistory{%
\begin{tabular}{p{0.2\textwidth}p{0.3\textwidth}p{0.3\textwidth}p{0.2\textwidth}}
\toprule
\textbf{Version} & \textbf{Date} & \textbf{Modifications} & \textbf{Modified~by}\\
\midrule
% we need to double the # here because we are inside a macro definition
\xintFor* ##1 in \Revisions
\do
{\xintListWithSep{&}{##1}\\}% one row for each revision
\bottomrule
\end{tabular}
}

\begin{document}

\RevisionHistory

\end{document}


• \xintListWithSep{&}{##1} is a bit overkill: ##1 is simply for example {0.1}{2017-11-27}{...}{...} and we only need a macro \newcommand\mymacro[4]{#1&#2&#3&#4} in this specific case and usage will be \mymacro##1 (no braces... we need \mymacro to see its four arguments...). – user4686 Nov 28 '17 at 9:49

You can let \addrevision write the table rows to a temporary file that you \input in \makedeliverable.

\documentclass{article}
\usepackage{booktabs}
%%%%% In sty-file
\newwrite\RevisionFile
\immediate\openout\RevisionFile=\jobname.Revision.txt
\immediate\write\RevisionFile{#1 & #2 & #3 & #4 \noexpand\\}
}
\newcommand\makedeliverable{%
\immediate\closeout\RevisionFile
\begin{tabular}{p{0.2\textwidth}p{0.3\textwidth}p{0.3\textwidth}p{0.2\textwidth}}
\toprule
\textbf{Version} & \textbf{Date} & \textbf{Modifications} &     \textbf{Modified by}\\\midrule
\input{\jobname.Revision.txt}
\bottomrule
\end{tabular}
}
%%%%% End of sty-file
%%%%% Revisions
%%%%%
\begin{document}
\makedeliverable

\end{document}


The file <filename>.Revision.txtis created as

0.1 & 2017-11-27 & Added new stuff & J. Bloggs \\
0.2 & 2017-11-27 & Added more new stuff & B. Smith \\


And the output: