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 need to construct a table that looks like:

\begin{tabular}{ccc}
a(1,1) & a(1,2) & a(1,3)\\   % <---
a(2,1) & a(2,2) & a(2,3)\\   % <---  I need this
a(3,1) & a(3,2) & a(3,3)\\   % <---
\end{tabular}

for any given number of colums or rows. In fact I only need the part that has arrow next to it, because I would like to be able to put it in different kinds of environments.

I need it to come like some sort of macro, so I can do

\begin{tabular}{ccc}
\generate{a}{3}{3}
\end{tabular}

to get the above table. I've tried:

\newcommand\makerow[3]{
    \foreach \n [count=\ni] in {1,...,#3}{%
        \ifnum\ni=1
            #1(#2,\n)
        \else
            & #1(#2,\n)
        \fi
    }%
}%


\newcommand\makematrix[3]{
    \foreach \m [count=\mi] in {1,...,#2}{%
        \ifnum\mi=#2
            \makerow{#1}{\m}{#3}
        \else
            \makerow{#1}{\m}{#3}\\
        \fi
    }%
}%


\begin{tabular}{ccc}
\makematrix{a}{3}{3}
\end{tabular}

Yet I get this error:

Incomplete \ifnum; All text was ignored after line 81.
Missing \endgoup inserted.
....

What I need

I need a macro to quickly build tabular environments that have a variable number of colums and rows, yet I want to be able to use the tabular as I would do every day:

\begin{tabular}{cc|cc}
\hline
header 1 & header 2 & header 3\\
\hline
foo & bar & baz \\
\makematrix{a}{4}{3}    % <-- makes the rest of the table as described below
\hline    
bar & baz &baz\\
\end{tabular}

etc. So The macro must be just inputted into the tabular environment, and behave as if

a(1,1) & a(1,2) & a(1,3)\\
a(2,1) & a(2,2) & a(2,3)\\
...

were inputted at that spot. Similarly, I would like to be able to define the colums of the tabular environment myself because I'd like to be able tu use > {...} on the columns.

share|improve this question
    
You can try independently to use pgffor package and nest two foreach loops to run over all rows and columns. –  percusse Jan 6 '12 at 12:34
    
yes but I can't get the &'s to be inserted without pgf giving an error –  romeovs Jan 6 '12 at 12:40
1  
TeX conditionals cannot start in a table cell and end in another one. –  egreg Jan 6 '12 at 14:01
    
@egreg so it cannot be done? –  romeovs Jan 6 '12 at 14:22
1  
@romeovs Yes, in many ways. –  egreg Jan 6 '12 at 14:30

1 Answer 1

up vote 6 down vote accepted

This is a possible implementation.

\documentclass{article}

\newtoks\romeotoks
\makeatletter
\newcommand{\makematrix}[4][]{%
  {\global\romeotoks={}%
  \@tempcnta=\z@ \@tempcntb=\z@
  \loop\ifnum\@tempcnta<#3
    \advance\@tempcnta\@ne
    {\loop\ifnum\@tempcntb<#4
       \advance\@tempcntb\@ne
       \edef\next{%
         \ifnum\@tempcntb=\@ne\else&\fi
         \unexpanded{#2}(\number\@tempcnta,\number\@tempcntb)}%
       \global\romeotoks=\expandafter{\the\expandafter\romeotoks\next}%
     \repeat}%
    \@tempcntb=\z@
    \global\romeotoks=\expandafter{\the\romeotoks \\ #1}%
  \repeat}%
  \the\romeotoks}
\makeatother


\begin{document}

\begin{tabular}{cc|c}
\hline
header 1 & header 2 & header 3\\
\hline
foo & bar & baz \\
\makematrix{a}{4}{3}
\hline    
bar & baz &baz\\
\hline
\end{tabular}

\end{document}

The optional argument to \makematrix is something to be put at the end of each row, for example

\makematrix[\hline]{a}{4}{3}

enter image description here

\makematrix has a first optional argument that contains what you want to put after the \\ on each row (for instance, \hline).

EDIT

Here's a LaTeX3 version:

\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_romeo_cells_tl
\int_new:N \l_romeo_row_int
\int_new:N \l_romeo_col_int
\NewDocumentCommand { \preparematrix } { O{} m m m }
  {
   \tl_set:Nn \l_romeo_cells_tl { }
   \int_set:Nn \l_romeo_row_int { #3 }
   \int_set:Nn \l_romeo_col_int { #4 }
   \prg_stepwise_inline:nnnn { 1 } { 1 } { \l_romeo_row_int }
     {
      \prg_stepwise_inline:nnnn { 1 } { 1 } { \l_romeo_col_int }
        {
         \int_compare:nF { ####1 = 1 } { \tl_put_right:Nn \l_romeo_cells_tl { & } }
         \tl_put_right:Nn \l_romeo_cells_tl
           { #2 ( ##1 , ####1 ) }
        }
      \tl_put_right:Nn \l_romeo_cells_tl { \\ #1 }
     }
  }
\DeclareExpandableDocumentCommand{ \usematrix } { }
  { \tl_use:N \l_romeo_cells_tl }
\NewDocumentCommand{ \makematrix } { O{} m m m }
  { \preparematrix[#1]{#2}{#3}{#4}\usematrix }

\ExplSyntaxOff

The usage is exactly the same. However I've split the business into two parts, so one can say also

\preparematrix{a}{4}{3}
\begin{tabular}{cc|c}
\hline
header 1 & header 2 & header 3\\
\hline
foo & bar & baz \\
\usematrix
\hline    
bar & baz &baz\\
\hline
\end{tabular}

in case one has to make special adjustments in the first column with \collectcell.

share|improve this answer
1  
@romeovs The problem is exactly that you can't (easily) do that inside a tabular. Try and show a real example of what you need. –  egreg Jan 6 '12 at 15:38
1  
@romeovs See edited answer –  egreg Jan 6 '12 at 16:43
1  
@romeovs I've added a LaTeX3 version and tried a simple collcell setting, it worked. But also the old version did. –  egreg Feb 10 '12 at 22:51
1  
@romeovs With this implementation the entire submatrix is built when LaTeX is already in the first cell of a row, so it cannot work when the first column is given special treatment with \collectcell. –  egreg Feb 11 '12 at 9:29
1  
@romeovs I added the version that can prepare the matrix outside the tabular and then use it inside. –  egreg Feb 11 '12 at 13:46

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.