1

What is the proper way to use loops inside the tabular environment?

The context of my question is generating tables using the datatool package. I need the following features:

  1. In each row, I want to generate the cells using a loop
  2. Inside each cell, I should be able to:
    • Be able to use the \multicolumn{1}{c} macro to change the column format
    • Use the value of the loop counter, for example inside if/then statements and to get certain datatool values

I was not able to work out how to do these three things. Following this entry, I have tried several approaches, which are summarised by:

\def\tand{&}
\newcounter{k}

% attepmt 1a
\def\firstattempta{
\setcounter{k}{1}
\whiledo{\thek < 3}{
    header\ \thek
    %\multicolumn{1}{c}{header \thek} % multicolumn not accepted
    \tand
    \stepcounter{k}
    }
header\ \thek
}

% attempt 1b
\makeatletter
  \def\xwhilenum #1\do{\@whilesw{\ifnum #1}\fi }
\makeatother

\def\firstattemptb{
\setcounter{k}{1}
\xwhilenum{\thek < 3}\do{%
    header\ \thek
    %\multicolumn{1}{c}{header \thek} % multicolumn not accepted
    \stepcounter{k}
    &    
    }
header\ \thek
}

% attempt 2
\setcounter{k}{1}
\def\secondattempt{}
    \whiledo{\thek < 3}{%
        \expandafter\def\expandafter\secondattempt\expandafter{%
        \secondattempt
        \multicolumn{1}{c|}{header \thek}
        \ifnum\thek<4 \tand \fi % 4 should be any other but it doesn't work
        }
        \stepcounter{k}%
        }
\expandafter\def\expandafter\secondattempt\expandafter{
    \secondattempt\multicolumn{1}{c|}{header \thek}} % (*)

\begin{document}

\begin{tabular}{*{3}{|D{.}{,}{-1}}|}
\hline
\firstattempta \\
\hline
\firstattemptb \\
\hline
\secondattempt \\
\hline
\end{tabular}

\end{document} 

enter image description here

  • The way to do this is to build up the complete row inside a loop and then use the stored row at once. (not sure how to describe this better) – Skillmon May 8 at 8:37
  • By the way: Welcome to TeX.SX! – Skillmon May 8 at 11:21
  • The \DTLforeachkeyinrow (datatool package) command doesn't allow \multicolumn inside neither. – e_moro May 12 at 11:55
4

The following is a loop over n columns. It has to be used as the first element of a row so you can only use it to loop over a whole row or the first n columns of a row. The first argument of \colloop is the number of columns it should loop over, the second is contents of each cell, with #1 being replaced by the column number.

\documentclass[border=3.14]{standalone}

\newcounter{col}

\makeatletter
\newcommand\colloop@add[2]
  {%
    \expandafter\g@addto@macro\expandafter\colloop@\expandafter
      {\colloop@@{#1}}%
    \ifnum#2>\value{col}
      \g@addto@macro\colloop@{&}%
    \fi
  }
\newcommand\colloop[2]
  {%
    \noalign
      {%
        \setcounter{col}{0}%
        \gdef\colloop@{}%
        \gdef\colloop@@##1{#2}%
        \loop\ifnum#1>\value{col}
          \stepcounter{col}%
          \expandafter\colloop@add\expandafter{\the\value{col}}{#1}%
        \repeat
      }%
    \colloop@
  }
\makeatletter

\begin{document}
\begin{tabular}[]{llll}
  \colloop{4}{column #1} \\
  \colloop{4}{\multicolumn{1}{c}{c#1}} \\
  \colloop{4}{\multicolumn{1}{r}{col#1}} \\
\end{tabular}
\end{document}

enter image description here

EDIT: Alternative approach which is split in an expandable and an unexpandable part. With \Setupexpcolloop and \setupexpcolloop you can define what \expcolloop should expand to (again using #1 for the current column). The difference between the two defining macros is, that \setupexpcolloop can be used anywhere while \Setupexpcolloop can be used only at the start of a row. But if you use \setupexpcolloop you can't use \multicolumn or similar in the same cell (so use it outside of the tabular environment, or at the end of a cell which is already filled with contents). The advantage of this approach is, that you don't have to loop over an entire row or only the first n columns.

\documentclass[border=3.14]{standalone}

\makeatletter
\long\def\myfi@b\fi#1#2{\fi#2}
\newcommand\setupexpcolloop[1]
  {%
    \gdef\expcolloop@##1{#1}%
  }
\newcommand\Setupexpcolloop[1]
  {%
    \noalign{\setupexpcolloop{#1}}%
  }
\newcommand\expcolloop[2]
  {%
    \expcolloop@{#1}%
    \ifnum#1<#2
      \myfi@b
    \fi
    \@gobble
    {&\expandafter\expcolloop\expandafter{\the\numexpr#1+1\relax}{#2}}%
  }
\makeatletter

\begin{document}
\begin{tabular}[]{|l|l|l|l|l|l|}
  \Setupexpcolloop{column #1}
  \expcolloop{1}{6} \\
  \Setupexpcolloop{\multicolumn{1}{c|}{c#1}}
  col1 & \expcolloop{2}{6} \\
  \Setupexpcolloop
    {%
      \ifnum#1=1
        \multicolumn{1}{|c|}{hihi1}%
      \else
        \multicolumn{#1}{c|}{hihi#1}%
      \fi
    }%
  \expcolloop{1}{3} \\
  \Setupexpcolloop{c#1}
  \expcolloop{1}{2}\setupexpcolloop{Cc#1} & \expcolloop{3}{6} \\
\end{tabular}
\end{document}

enter image description here

Disclaimer: I do not endorse the usage of vertical rules in tables, this is just to show the effects of the \multicolumn usages.

  • So, like I could suppose, the paradigm I explored was finished. Your new point of view, colloop comand and their extensions work fine! I also take note of your beer-licence ;) – e_moro May 12 at 11:47
  • @e_moro the beerware license is primarily for code that gets published in packages or the like (the whole relicense thread is primarily for that). If you use it in your document and don't publish the code you don't have to strictly follow that license. Of course I wouldn't say no to a beer :) – Skillmon May 12 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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