# Fill table with dynamic amount of columns

I want to fill a table with a dynamic (calculated) amount of columns. The column should be filled with a value which the user should provide comma separated. I therefore tried to use forcsvloop, but I must have made some mistakes, as I got a strange error:

Undefined control sequence ^^I\entry{5,6,7}


with example

\documentclass{article}
\usepackage{etextools}

%Create a table with a specific amount of columns
\newenvironment{vartab}[1]
{
\begin{tabular}{ |c@{} *{#1}{r|} } \hline
}{
\end{tabular}
}

\newcommand{\entry}[1]{
\forcsvloop{#1}\do{
& ##1
}\\ \hline
}

\begin{document}

\begin{vartab}{3}
& 2 & 3 & 4 \\\hline
\entry{5,6,7}
\end{vartab}

\end{document}


Do you know what the problem might be?

• Note that TeX is not “free form” and end-of-lines are significant: they're translated into spaces that may or may not appear in the output; several of your end-of-lines do appear in the output. – egreg Aug 13 '13 at 10:15
• @egreg What kind of "end-of-lines" do you mean, the manual ones ("\\") or the raw newline characters ("\n") in my example? – muffel Aug 13 '13 at 10:18
• The raw newlines. For instance, you get spaces before and after the table, which you can check with X\begin{vartab}{3}&2&3&4\\\hline\end{vartab}X – egreg Aug 13 '13 at 11:19

A simpler way to do this is using an auxillary macro, to simplify expansion:

\documentclass{article}
\usepackage{etextools}

%Create a table with a specific amount of columns
\newenvironment{vartab}[1]
{
\begin{tabular}{ |c@{} *{#1}{r|} } \hline
}{
\end{tabular}
}

\newcommand{\myformat}[1]{& #1}

\newcommand{\entry}[1]{
\edef\result{\csvloop[\myformat]{#1}}
\result \\ \hline
}

\begin{document}

\begin{vartab}{3}
& 2 & 3 & 4 \\\hline
\entry{5,6,7}
\end{vartab}

\end{document}


As a completely different approach note that tabular is built on top of the tex primitive \halign that builds tables row by row. This primitive has an vertical analogue \valign that works columnwise:

\documentclass{article}

\begin{document}

\vskip 1pt plus 1fil\hrule\cr
\noalign{\vrule}
2&5\cr
\noalign{\vrule}
3&6\cr
\noalign{\vrule}
4&7\cr
\noalign{\vrule}}

\end{document}

• Great, and much better as my approach, thank you! Anyways, just to learn from my mistakes, do you know what I did wrong? – muffel Aug 13 '13 at 8:44
• It is a problem with expansions, but I didn't get to the bottom of it. – Andrew Swann Aug 13 '13 at 9:14

You're trying to begin the loop in a cell and end it in another, which isn't possible because table cells form groups; it's like improperly nesting environments

\begin{A}
\begin{B}
...
\end{A}
\end{B}


which can't work.

Here's a way with etoolbox (I can't recommend using etextools that's buggy and unmaintained).

\documentclass{article}
\usepackage{etoolbox}

%Create a table with a specific amount of columns
\newenvironment{vartab}[1]
{\begin{tabular}{ |c@{} *{#1}{r|} } \hline}
{\end{tabular}}

\newcommand{\doentry}[1]{\appto\temp{& #1}}

\newcommand{\entry}[1]{%
\def\temp{}% initialize to empty
\appto\temp{\\ \hline}% end the row
\temp % deliver contents
}

\begin{document}

\begin{vartab}{3}
& 2 & 3 & 4 \\\hline
\entry{5,6,7}
\end{vartab}

\end{document}


The loop is completely worked out in the first cell, by adding to a temporary command that's expanded at the end.

A different solution uses xparse and expl3; note that the dummy first column is not needed any more.

\documentclass{article}
\usepackage{xparse}

%Create a table with a specific amount of columns
\newenvironment{vartab}[1]
{\begin{tabular}{ |*{#1}{r|} } \hline}
{\end{tabular}}

\ExplSyntaxOn
\NewDocumentCommand{\entry}{m}
{
\clist_set:Nn \l_muffel_row_clist { #1 }
\clist_use:Nn \l_muffel_row_clist { & }
\\
\hline
}
\clist_new:N \l_muffel_row_clist % allocate a clist variable
\ExplSyntaxOff

\begin{document}

\begin{vartab}{3}
2 & 3 & 4 \\\hline
\entry{5,6,7}
\end{vartab}

\end{document}