# Matrix of values as parameter for a macro

This is my code:

\documentclass{article}

\usepackage{polyglossia}
\usepackage{forloop}

\newcommand{\values}[2]{
\ifcase#1%
\ifcase#2%
value a%
\c%
value b%
\or%
value c%
\fi
\or%
\ifcase#2%
value d%
\or%
value e%
\or%
value f%
\fi
\fi%
}

\newcounter{ct}
\newcommand{\mytable}[1]{
\begin{tabular}{l|l|l}
First & Second & Third
\forloop{ct}{0}{\value{ct} < #1}{
\\ \hline
\values{\thect}{0} & \values{\thect}{1} & \values{\thect}{2}
}
\end{tabular}
}

\begin{document}
\mytable{2}
\mytable{3}
\end{document}


What I want to do is to define a macro \mytable, which takes the number of rows as first argument, and then a second argument which provides the content of the table. My current approach uses a second macro for providing the content. I am searching for a way to pass the values currently defined in \values to \mytable, so that the second call can have a different content. \renewcommand{\values} between the calls isn't an option in the actual code.

• Would something like \mytable{a,b,c;d,e,f} suffice? – egreg Sep 19 '14 at 15:38
• No, the call to \mytable and the definition of the values need to be at different places in my code. – flyx Sep 19 '14 at 15:39
• So \mytable{2} will just use the first two rows defined beforehand? – egreg Sep 19 '14 at 15:41
• I want to call it like \mytable{2}{\values} and then again with \mytable{3}{\othervalues}, where each builds a table with the values that have been passed as content – flyx Sep 19 '14 at 15:42
• @StevenB.Segletes: Because I need to define the values at one source file and the call to \mytables macro is in another source file. The file with the values is a customizable configuration file where the values can be changed; the call to \mytables is inside the document structure. – flyx Sep 19 '14 at 15:51

It is still not clear what flexibility you need in setting the values, but here is one possibility that may or may not suffice.

\documentclass{article}

%\usepackage{polyglossia}
\usepackage{forloop}

\newcommand{\valuesA}[2]{
\ifcase#1%
\ifcase#2%
value a%
\or%
value b%
\or%
value c%
\fi
\or%
\ifcase#2%
value d%
\or%
value e%
\or%
value f%
\fi
\fi%
}

\newcommand{\valuesB}[2]{
\ifcase#1%
\ifcase#2%
value A%
\or%
value B%
\or%
value C%
\fi
\or%
\ifcase#2%
value X%
\or%
value Y%
\or%
value Z%
\fi
\fi%
}

\newcounter{ct}
\newcommand{\mytable}[2]{
\begin{tabular}{l|l|l}
First & Second & Third
\forloop{ct}{0}{\value{ct} < #1}{
\\ \hline
#2{\thect}{0} & #2{\thect}{1} & #2{\thect}{2}
}
\end{tabular}
}

\begin{document}
\mytable{2}{\valuesA}

\bigskip
\mytable{3}{\valuesB}
\end{document}


• Well that was simple. I should have just tried that before asking. Thanks! – flyx Sep 19 '14 at 16:10
• @flyx Glad I could be of some assistance. – Steven B. Segletes Sep 19 '14 at 16:11
• The mess is in the first column. Is it desired? – wipet Sep 20 '14 at 5:19
• @wipet - Thanks. One of the \or in the first columns got scrogged in the copy/paste as \c resulting in the mess. Fixed. – Steven B. Segletes Sep 20 '14 at 22:48

With xparse and expl3 you can have a better interface for defining the matrices.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definematrix}{O{default}m}
{
\flyx_define_matrix:nn { #1 } { #2 }
}

\NewDocumentCommand{\usematrix}{O{default}m}
{
\flyx_use_matrix:nn { #1 } { #2 }
}

\NewDocumentCommand{\setmatrixformat}{mm}
{
\tl_gset:Nn \g_flyx_matrix_format_tl { #1 }
}

\seq_new:N \l_flyx_temp_rows_seq
\int_new:N \l_flyx_row_index_int
\tl_new:N \g_flyx_matrix_format_tl

\cs_new_protected:Npn \flyx_define_matrix:nn #1 #2
{
\seq_set_split:Nnn \l_flyx_temp_rows_seq { \\ } { #2 }
\int_zero:N \l_flyx_row_index_int
\seq_map_inline:Nn \l_flyx_temp_rows_seq
{
\int_incr:N \l_flyx_row_index_int
\tl_gclear_new:c { g_flyx_#1_matrix_ \int_to_roman:n { \l_flyx_row_index_int } _tl }
\tl_gset:cn
{ g_flyx_#1_matrix_ \int_to_roman:n { \l_flyx_row_index_int } _tl }
{ ##1 }
}
}

\cs_new_protected:Npn \flyx_use_matrix:nn #1 #2
{
\use:x { \exp_not:N \begin{tabular} { \exp_not:V \g_flyx_matrix_format_tl } }
\hline
\hline
\tl_clear:N \l_flyx_table_body_tl
\int_step_inline:nnnn { 1 } { 1 } { #2 }
{
\tl_put_right:Nv \l_flyx_table_body_tl { g_flyx_#1_matrix_ \int_to_roman:n { ##1 } _tl }
\tl_put_right:Nn \l_flyx_table_body_tl { \\ }
}
\tl_use:N \l_flyx_table_body_tl
\hline
\end{tabular}
}

\cs_generate_variant:Nn \tl_put_right:Nn { Nv }
\ExplSyntaxOff

\definematrix{
a & b & c \\
d & e & f \\
g & h & i
}

\definematrix[numbers]{
1 & 2 \\
3 & 4 \\
5 & 6 \\
7 & 8
}

\setmatrixformat{|l|l|l|}{First & Second & Third}

\begin{document}

\medskip

\setmatrixformat{lll}{A & B & C}

\usematrix{2}

\medskip

\setmatrixformat{cc}{A & B}

\end{document}


The \definematrix has an optional argument (a name); successive declarations with the same name (or without name) will overwrite the defined matrix.

With \setmatrixformat you set the columns and the header to be used from that point on.

With \usematrix you can specify a name (or use the default matrix) and the number of rows to use.