# Using & in macro abstracting a tabular's row

I am attempting to create a macro for table rows. This will allow me to change the order of the columns in the future, without having to change the order of the columns in every single row.

I have attempted:

\newcommand\taxrow[9]{%
\def\paper{#1}%
\def\method{#2}%
\def\optobj{#3}%
\def\sla{#5}%
\def\perfpred{#6}%
\def\numofreps{#7}%
\def\faulttol{#8}%
\def\failact{#9}%
\taxrowcond
}

\newcommand\taxrowcond[1]{
\paper & \method & \optobj & \workload & \sla & \perfpred & \numofreps & \faulttol & \failact & #1
}

\begin{table}[h]
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|}
\hline
{Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection}
&  & & & & & & & & \\ \hline
\end{tabular}
\end{table}


If I remove the ampersands &, it works:

\newcommand\taxrow[9]{%
\def\paper{#1}%
\def\method{#2}%
\def\optobj{#3}%
\def\sla{#5}%
\def\perfpred{#6}%
\def\numofreps{#7}%
\def\faulttol{#8}%
\def\failact{#9}%
\taxrowcond
}

\newcommand\taxrowcond[1]{
\paper
\method
\optobj
\sla
\perfpred
\numofreps
\faulttol
\failact
#1
}

\begin{table}[h]
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|}
\hline
{Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection}
&  & & & & & & & & \\ \hline
\end{tabular}
\end{table}

-
Welcome to TeX.SX! Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem. –  cfr Aug 10 '14 at 21:51
Your code fails for two reasons: Missing  \\  at the end of \tablerowcond and it for \def being grouped –  Christian Hupfer Aug 10 '14 at 21:59
Why not use keys to set the parameters \paper, \method, etc.? –  A.Ellett Aug 10 '14 at 22:59

The code by the OP fails for two reasons

1. A missing \tabularnewline (or \\) at the end of \tablerowcond, leading to the fact, that there are more & characters than allowed (at most 9 since the table has 10 columns), such that the additional & & & & ...& would be 'added' to the current row error
2. \def within a table cell are grouped, so not visible outside of that table cell, being undefined in the next cell. Use (if really needed), a global definition \gdef instead. (Note I do not recommend this method of coding at all ...) If for some reason (not really unlikely!) \method is defined outside, the outer version would be used instead the one being set to #2!

\documentclass{article}%

\newcommand\taxrow[9]{%
\gdef\paper{#1}%
\gdef\method{#2}%
\gdef\optobj{#3}%
\gdef\sla{#5}%
\gdef\perfpred{#6}%
\gdef\numofreps{#7}%
\gdef\faulttol{#8}%
\gdef\failact{#9}%
\taxrowcond%
}

\newcommand\taxrowcond[1]{%
\paper &  \method & \optobj & \workload & \sla & \perfpred & \numofreps & \faulttol & \failact & #1  \tabularnewline
}

\begin{document}

\begin{table}[h]
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|}
\hline
{Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection}
&  & & & & & & & & \\ \hline
\end{tabular}
\end{table}

\end{document}%

-
(+1) Indeed, we did have basically the same idea! I kind of like the loop because it makes it very easy to rearrange the columns without worrying about looking &s. (The kind of thing I would do is lose track of those and then spend ages trying to figure out the error. Precautions are not necessary if you are more careful than me!) Agree about the coding style. I think it would be tidier to merge the data from another file... –  cfr Aug 10 '14 at 22:09
1) was not the primary concern of this post. The user of gdef fixed it. Since I'm using gdef, I prefixed all the of temporary definitions so that they do not pollute the namespace. –  joseph Aug 10 '14 at 22:28
@joseph: Yes, if you remove the & characters, it will compile and then all \def are within the same cell, but you won't get the table layout? –  Christian Hupfer Aug 10 '14 at 22:31

A more general abstraction, which allows for several table types.

\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{booktabs}
\usepackage{xparse}

\newcommand{\splitcell}[1]{\begin{tabular}{@{}c@{}}\strut#1\strut\end{tabular}}

\ExplSyntaxOn
\NewDocumentCommand{\definecolumns}{mm}
{
\joseph_define_columns:nn { #1 } { #2 }
}

\NewDocumentCommand{\sortcolumns}{mm}
{
\joseph_sort_columns:nn { #1 } { #2 }
}

\NewDocumentCommand{\printrow}{mm}
{
\joseph_print_row:nn { #1 } { #2 }
}
\int_new:N \l__joseph_loop_int

\cs_new_protected:Npn \joseph_define_columns:nn #1 #2
{
\seq_new:c { g_joseph_columns_#1_seq }
\seq_new:c { g_joseph_sort_#1_seq }
\prop_new:c { l_joseph_row_#1_prop }
\seq_gset_from_clist:cn { g_joseph_columns_#1_seq } { #2 }
\seq_set_eq:cc { g_joseph_sort_#1_seq } { g_joseph_columns_#1_seq }
}

\cs_new_protected:Npn \joseph_sort_columns:nn #1 #2
{
\seq_gset_from_clist:cn { g_joseph_sort_#1_seq } { #2 }
}

\cs_new_protected:Npn \joseph_print_row:nn #1 #2
{
\int_zero:N \l__joseph_loop_int
\clist_map_inline:nn { #2 }
{
\int_incr:N \l__joseph_loop_int
\prop_put:cxn { l_joseph_row_#1_prop }
{
\seq_item:cn { g_joseph_columns_#1_seq } { \l__joseph_loop_int }
}
{
##1
}
}
\seq_clear:N \l__joseph_row_seq
\seq_map_inline:cn { g_joseph_sort_#1_seq }
{
\seq_put_right:Nx \l__joseph_row_seq
{
\prop_item:cn { l_joseph_row_#1_prop } { ##1 }
}
}
\seq_use:Nn \l__joseph_row_seq { & } \\
}

\cs_generate_variant:Nn \prop_put:Nnn { cx }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{*{9}{c}}
\toprule
\printrow{tax}{
Paper,Method,\splitcell{Optimization\\Objective},
\splitcell{Num.\ of\\Reps},\splitcell{Fault\\Tolerant},\splitcell{Failover\\Action}
}
\midrule
\printrow{tax}{01,02,03,04,05,06,07,08,09}
\printrow{tax}{11,12,13,14,15,16,17,18,19}
\printrow{tax}{21,22,23,24,25,26,27,28,29}
\bottomrule
\end{tabular}

\bigskip

\begin{tabular}{*{9}{c}}
\toprule
\printrow{tax}{
Paper,Method,\splitcell{Optimization\\Objective},
\splitcell{Num.\ of\\Reps},\splitcell{Fault\\Tolerant},\splitcell{Failover\\Action}
}
\midrule
\printrow{tax}{01,02,03,04,05,06,07,08,09}
\printrow{tax}{11,12,13,14,15,16,17,18,19}
\printrow{tax}{21,22,23,24,25,26,27,28,29}
\bottomrule
\end{tabular}

\end{document}


The initial sorting order is the one resulting from the order in \definecolumns, but it can be changed at will with \sortcolumns, as shown in the example.

-

You could do this (but it probably isn't the best solution):

\documentclass{article}
\makeatletter
\newcommand\taxrow[9]{%
\gdef\taxpaper{#1}%
\gdef\method{#2}%
\gdef\optobj{#3}%
\gdef\sla{#5}%
\gdef\perfpred{#6}%
\gdef\numofreps{#7}%
\gdef\faulttol{#8}%
\gdef\failact{#9}%
\taxrowcond
}
\def\mytax#1{#1 &}
\newcommand\taxrowcond[1]{
\gdef\setthis{\taxpaper \method \optobj \workload \sla \perfpred \numofreps \faulttol \failact}%
\@for \xx:=\setthis \do{%
\mytax{\xx}}%
#1}
\makeatother
\begin{document}

\begin{table}[h]
\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|}
\hline

We had basically the same idea, but your style with the \@for loop is quite nice! –  Christian Hupfer Aug 10 '14 at 22:06
(Already +1): Yes, the reordering of 'argument' is a nice feature. With coding style I rather meant the usage of the \...def stuff inside, but I agree with you, that merging from another file would be better! –  Christian Hupfer Aug 10 '14 at 22:12