Copy table row n times

The main problem is that \foreach works in a group, but it's not only that.

The simplest thing to do is to first build the table in a macro and then expand it:

\documentclass{article}
\usepackage{tikz}

\newcommand{\test}[1]{%
  \def\temp{}%
  \foreach \i in {1,...,#1}
    {%
    \expandafter\gdef\expandafter\temp\expandafter{\temp t1 & t2 \\}%
    }%
  \temp}

\begin{document}
\begin{tabular}{cc}
\test{3}
\end{tabular}
\end{document}

The \temp macro is initialized to empty and then augmented at each cycle; at the end it's expanded. The \gdef is necessary because of the implicit groups around the cycles.


With \test{3} what happens is essentially

\def\temp{}%
{\expandafter\gdef\expandafter\temp\expandafter{\temp t1 & t2 \\}}%
{\expandafter\gdef\expandafter\temp\expandafter{\temp t1 & t2 \\}}%
{\expandafter\gdef\expandafter\temp\expandafter{\temp t1 & t2 \\}}%
\temp

and everything takes place when TeX is still looking for the material in the first cell of the first row. The first line states that \temp expands to nothing; then the second line is executed: each \expandafter expands the second token after it; for the first two it's another \expandafter so we arrive at \temp. Hence the second line is equivalent to saying

{\gdef\temp{t1 & t2 \\}}

but when the same operation is performed in the third line the effect is

{\gdef\temp{t1 & t2 \\t1 & t2 \\}}

and at the fourth line it becomes

{\gdef\temp{t1 & t2 \\t1 & t2 \\t1 & t2 \\}}

The supplementary braces represent the implicit group that \foreach puts around the cycles. Thus \gdef is necessary because otherwise the redefinition of \temp would disappear at group end.

The presence of & tokens is not a problem, because TeX scans it between braces, so they aren't used for marking the end of a cell. This is an issue that, sometimes, bites someone.

At the end, \temp will produce the tokens

t1 & t2 \\t1 & t2 \\t1 & t2 \\

that will be seen properly by TeX for building the table.

A less readable definition, but which does exactly the same, would be

\makeatletter
\newcommand{\test}[1]{%
  \let\@temp\@empty
  \foreach \i in {1,...,#1}
    {%
    \g@addto@macro\@temp{t1 & t2 \\}%
    }%
  \@temp}
\makeatother

The compulsory LaTeX3 version:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\repeatrow}{mm}
 {
  \azet_repeat_row:nn { #1 } { #2 }
 }

\tl_new:N \l_azet_rows_tl
\cs_new_protected:Npn \azet_repeat_row:nn #1 #2
 {
  \tl_clear:N \l_azet_rows_tl
  \prg_replicate:nn { #1 } { \tl_put_right:Nn \l_azet_rows_tl { #2 \\ } }
  \tl_use:N \l_azet_rows_tl
 }
\ExplSyntaxOff

\begin{document}
\begin{tabular}{cc}
\repeatrow{3}{t1 & t2}
\end{tabular}
\end{document}

The working is very similar to the "classical" solution, but it uses \prg_replicate:nn instead of \foreach. The command is

\prg_replicate:nn { <integer expression> } { <code> }

and it evaluates the <integer expression> (so one might also call \repeatrow{3*5}{...}); then it repeats the <code> in the second argument as many times as specified in the first one.

This command is preceded by the analog of \def\temp{}: the token list variable \l_azet_rows_tl is cleared and the <code> is just "append the second argument to \azet_repeat_row:nn (which in turn is the "internal" version of \repeatrow). Then the contents of the token list variable is delivered for use (the analog of saying \temp in the first solution).


You don't really need a for-each macro for this, you just need to take care that your loop counter and the groups from the table cells interact correctly.

The following produces the three row table without any large (or small) package overhead.

\documentclass{article}

\newcommand{\test}[1]{%
 t1 & t2 \\
\ifnum#1>1 
  \expandafter\test\expandafter{\numexpr#1-1\expandafter\relax\expandafter}\fi
}

\begin{document}
\begin{tabular}{cc}
\test{3}
\end{tabular}
\end{document}

Here is an alternative using Latex 3,

\documentclass[letterpaper]{article}
\usepackage{expl3}

\ExplSyntaxOn
\cs_new_eq:NN \Copy \prg_replicate:nn
\ExplSyntaxOff

\begin{document}
\begin{tabular}{cc}
\Copy{4}{t1 & t2 \\}
\end{tabular}
\end{document}

Tags:

Foreach

Tables