# Produce a table with numbers given by another macro

I want to create a table with the numbers added by latex itself and the terms are left aligned. First I ask a question about how to produced a multiplication table. And I try to use \newenvironment to deal with it, something like this

\newenvironment{boxed}
{\begin{center}
\begin{tabular*}{llllllll}
\hline\\
}
{
\\\\\hline
\end{tabular}
\end{center}
}
%--------------------------------------------------


but it seems that I am not able to insert my own macro into the definition of boxed. How can I define the environment so that I can use it to produce a formated multiplication table by

\begin{boxed}
\nineij
\end{boxed}


where \nineij is defined in my format.tex:

\documentclass{article}
\usepackage{geometry}
\geometry{a4paper,scale=0.8}

\newcount\loopi \newcount\loopj \newcount\ans
\newcount\nn
\nn=9
\def\nineij{
\vskip 6mm
}

\def\ninej{
\loopj=1
\par
}
\def\printij{
\ans=1
\multiply\ans by \loopi
\multiply\ans by \loopj
\number\loopj$\times$\number\loopi = \number\ans$\,$
}

\begin{document}

\nineij

\begin{tabular}{lllllllll}
1$\times$ 1 = 1\\
1$\times$ 2 = 2 & 2$\times$ 2 = 4\\
1$\times$ 3 = 3 & 2$\times$ 3 = 6 & 3$\times$ 3 = 9\\
1$\times$ 4 = 4 & 2$\times$ 4 = 8 & 3$\times$ 4 = 12 & 4$\times$ 4 = 16\\
1$\times$ 5 = 5 & 2$\times$ 5 = 10 & 3$\times$ 5 = 15 & 4$\times$ 5 = 20 & 5$\times$ 5 = 25\\
1$\times$ 6 = 6 & 2$\times$ 6 = 12 & 3$\times$ 6 = 18 & 4$\times$ 6 = 24 & 5$\times$ 6 = 30 & 6$\times$ 6= 36\\
1$\times$ 7 = 7 & 2$\times$ 7 = 14 & 3$\times$ 7 = 21 & 4$\times$ 7 = 28 & 5$\times$ 7 = 35 & 6$\times$ 7 = 42 & 7$\times$ 7 = 49\\
1$\times$ 8 = 8 & 2$\times$ 8 = 16 & 3$\times$ 8 = 24 & 4$\times$ 8 = 32 & 5$\times$ 8 = 40 & 6$\times$ 8 = 48 & 7$\times$ 8 = 56 & 8\times 8 = 56\\
1$\times$ 9 = 9 & 2$\times$ 9 = 18 & 3$\times$ 9 = 27 & 4$\times$ 9 = 36 & 5$\times$ 9 = 45 & 6$\times$ 9 = 54 & 7$\times$ 9 = 63 & 8$\times$ 9 = 72 & 9$\times$ 9 = 81\\
\end{tabular}

\end{document}


Any kind of solutions are appreciated.

Here's a more generic macro using expl3. First we build the table and then output it in one swoop: it's usually complicated to have loops in table cells.

\documentclass{article}
\usepackage[landscape]{geometry}
\usepackage{amsmath,xparse,xfp}

\ExplSyntaxOn
\NewDocumentCommand{\lowertriangular}{mm}
{
\group_begin:
\brooks_lowertriangular:nn { #1 } { #2 }
}

\tl_new:N \l__brooks_body_tl

\cs_new_protected:Nn \brooks_lowertriangular:nn
{
% a temporary function for massaging the entries
\cs_set:Nn \__brooks_inner:nn { #2 }
% clear the table body
\tl_clear:N \l__brooks_body_tl
% outer cycle, #1 rows
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
% inner cycle, ##1 columns
\int_step_inline:nnnn { 1 } { 1 } { ##1 }
{
% add the entry for row ##1 (outer cycle) and column ####1 (inner)
\tl_put_right:Nn \l__brooks_body_tl
{ \__brooks_inner:nn { ##1 } { ####1 } }
% if ##1 = ####1 end the row, otherwise end the cell
\tl_put_right:Nx \l__brooks_body_tl
{ \int_compare:nTF { ##1 = ####1 } { \exp_not:N \\ } { & } }
}
}
% output the table
\begin{array}{*{#1}{c}} \l__brooks_body_tl \end{array}
\group_end:
}
\ExplSyntaxOff

\begin{document}

$\lowertriangular{9}{#1\times #2}$

$\lowertriangular{9}{#1\times #2=\inteval{#1*#2}}$

$\begin{bmatrix} \lowertriangular{5}{a_{#1#2}} \end{bmatrix}$

\end{document}


You can use an expandable loop from the LaTeX kernel.

\documentclass{article}
\usepackage{geometry}
\geometry{a4paper,scale=0.8}

\newcount\loopi \newcount\loopj \newcount\ans

\begin{document}\thispagestyle{empty}

\makeatletter

\global\loopi 0
\global\loopj 0

$\begin{array}{*{9}{l}} \@whilesw{\ifnum\loopi<9 }\fi {\global\advance\loopi 1 \global\loopj 0 \@whilesw{\ifnum\loopj<\loopi}\fi {\global\advance\loopj 1 % \ifnum\loopj>1 \@firstofone{&}\fi \ans=1 \multiply\ans by \loopi \multiply\ans by \loopj \number\loopj\times\number\loopi = \number\ans % }\\ } \end{array}$

\makeatother

\end{document}


• one of the reasons you can't use easily your original approach in a tabular is that the cells form groups and the \loop makes a definition which is not global. The expandable loops like \@whilesw make no definition so they don't have this problem at least that something gets lost after a & or \\ . – user4686 Jun 7 '18 at 7:25
• the reason for the \@firstofone{&} is that non-expandable stuff was already executed (\global\advance..) and the & must then be hidden from TeX else an infamous \endtemplate would make the \ifnum incomplete. – user4686 Jun 7 '18 at 7:29