Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am trying to build a table, and inside the tabularx environment I would like to have a loop, something like (here is a MWE):

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\begin{document}


\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
    \foreach \r in {1,...,\nRows}{  % https://stackoverflow.com/questions/2561791/iteration-in-latex
        \textbf{column1} & two & three & four & five 
    }
\end{tabularx}

\end{document}

This doesn't work, because the ampersands (&) are causing problems. If I escape the &s, then the entire line gets printed in the first column, along with the literal ampersands, kind of like:

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\begin{document}


\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
    \foreach \r in {1,...,\nRows}{  % https://stackoverflow.com/questions/2561791/iteration-in-latex
        \textbf{column1} \& two \& three \& four \& five 
    }
\end{tabularx}

\end{document}

This yields:

|column1 &      | | | |
| two & three & | | | |
| four & five   | | | |

Whereas what I want is:

|column 1 | two | three | four | five |
|column 1 | two | three | four | five |
|column 1 | two | three | four | five |

....

Any ideas on how I can achieve this? I'm actually NOT looking to make identical rows - the rows will be different. This is just a MWE. Thanks!

Edit: I have tried implementing Herbert's answer as recommended in the comments section. It results in no output - just a blank PDF. Here is how I implemented it:

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}

\makeatletter
\newtoks\@tabtoks
\newcommand\addtabtoks[1]{\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand*\resettabtoks{\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother

\begin{document}

    \resettabtoks
    \foreach \r in {1,...,\nRows}{  % https://stackoverflow.com/questions/2561791/iteration-in-latex
        % \textbf{column1} \& two \& three \& four \& five 
        \addtabtoks{\textbf{column1} & two & three & four & five \\\hline}%
    }

\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
\printtabtoks
\end{tabularx}

\end{document}

Any ideas on what I am doing wrong? Thanks!

share|improve this question
1  
Herbert's answer at tex.stackexchange.com/questions/7590/… is very much related. –  Steven B. Segletes Mar 12 at 14:39
    
Welcome to TeX.SX! Please help us to help you and add a minimal working example (MWE) that illustrates your problem. It will be much easier for us to reproduce your situation and find out what the issue is when we see compilable code, starting with \documentclass{...} and ending with \end{document}. –  Christian Hupfer Mar 12 at 14:59
2  
Also you need \raggedright\arraybackslash in your preamble. –  Andrew Swann Mar 12 at 16:43
2  
You have to use \global\@tabtoks, because \foreach executes each cycle in a group. Related: tex.stackexchange.com/questions/62177/copy-table-row-n-times –  egreg Mar 12 at 16:44
1  
You are also missing \arraybackslash after \raggedright in the last column specification. –  egreg Mar 12 at 16:51
show 2 more comments

3 Answers 3

up vote 9 down vote accepted

Presumably you are doing this because you want the rows of the table to depend on the counter in the loop. In this case you will need a way to add expanded objects to the list of tokens. Here I add an \eaddtabtoks macro in addition to egreg's corrections to the global assignments.

Sample output

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx,etoolbox}
\usepackage{tikz}
\newcommand{\nRows}{5}

\makeatletter
\newtoks\@tabtoks
\newcommand\addtabtoks[1]{\global\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand\eaddtabtoks[1]{\edef\mytmp{#1}\expandafter\addtabtoks\expandafter{\mytmp}}
\newcommand*\resettabtoks{\global\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother

\begin{document}

\resettabtoks
\foreach \r in {1,...,\nRows}{
  \addtabtoks{\textbf{column 1} &}
  \eaddtabtoks{row \r}
  \addtabtoks{ & three & four & five \\}%
}

\begin{tabularx}{\textwidth}{@{}>{\raggedright\arraybackslash}p{2.2cm}*{4}{@{}>{\raggedright\arraybackslash}X}@{}}
\printtabtoks
\end{tabularx}%

\end{document}
share|improve this answer
add comment

You're missing the fact that \foreach executes each cycle in a group, so when finishing it the change to \@tabtoks is undone.

Add \global in the relevant places (and also \arraybackslash in the specification for the last column, but this is another problem).

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}

\makeatletter
\newtoks\@tabtoks
%%% assignments to \@tabtoks must be global, because they are done in \foreach
\newcommand\addtabtoks[1]{\global\@tabtoks\expandafter{\the\@tabtoks#1}}
%%% variable should always be operated on always locally or always globally
\newcommand*\resettabtoks{\global\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother

\begin{document}
\resettabtoks
\foreach \r in {1,...,\nRows}{
  \addtabtoks{\textbf{column1} & two & three & four & five \\\hline}%
}
\noindent\begin{tabularx}{\textwidth}{
  @{}>{\raggedright}p{2.2cm}
  @{}>{\raggedright}X
  @{}>{\raggedright}X
  @{}>{\raggedright}X
  @{}>{\raggedright\arraybackslash}X
  @{}
}
\printtabtoks
\end{tabularx}

\end{document}
share|improve this answer
    
Thanks everyone! All responses were helpful. I have posted a related question here: [link]tex.stackexchange.com/questions/165208/… would be grateful for additional help. Cheers. –  Shafique Jamal Mar 12 at 21:28
add comment

If your are open to using (here) another loop than \foreach then there are options, like \xintFor from package xinttools. The syntax is a bit different, and using \xintFor at this place does not exclude using \foreach at others...

Update adds a second method for people loving the bleeding edge.

tabularx loop

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\usepackage{xinttools}
\newcommand{\nRows}{5}
% \usepackage{tabu} % alternative to tabularx
\begin{document}

\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright\arraybackslash}X@{}}
    \xintFor* #1 in {\xintSeq {1}{\nRows}}
    \do
    {(\textsl{row #1}) \textbf{column1} & two & three & four & five
    \\ }
\end{tabularx}


% Note with a tabu environment of package tabu, \arraybackslash is not needed
% \begin{tabu} to \textwidth{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
%     \xintFor* #1 in {\xintSeq {1}{\nRows}}
%     \do
%     {(\textsl{row #1}) \textbf{column1} & two & three & four & five
%     \\ }
% \end{tabu}

\end{document}

Here is an idiosyncratic way which relies on an expandable loop (\xintFor is not expandable despite the fact it enjoys tabulars), and without counters! (\xintFor does not use counters either). \xintiloopindex can not be within braces; and in this example we need to hide the tabulations, for the \xintiloopindex mechanism to work, because non-expandable material is encountered before.

\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\usepackage{xinttools}
\newcommand{\nRows}{5}
\def\TAB{&}
\begin{document}

\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright\arraybackslash}X@{}}
    \xintiloop [1+1]
    (\bgroup\slshape row \xintiloopindex\egroup )% \xintiloopindex can not be
                                % within braces...
            \textbf{column1} \TAB two \TAB three \TAB four \TAB five \\
    \ifnum\nRows>\xintiloopindex\space
    \repeat
\end{tabularx}

\end{document}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.