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 am attempting to create a marco 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\workload{#4}%
        \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
        \taxrow{Paper}{Method}{Optimization Objective}{Workload}{SLA}{Performance Objective}
                {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\workload{#4}%
        \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
        \taxrow{Paper}{Method}{Optimization Objective}{Workload}{SLA}{Performance Objective}
                {Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection}
    &  & & & & & & & & \\ \hline
\end{tabular}
\end{table}
share|improve this question
1  
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 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 at 21:59
    
Why not use keys to set the parameters \paper, \method, etc.? –  A.Ellett Aug 10 at 22:59

3 Answers 3

up vote 5 down vote accepted

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\workload{#4}%
        \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
        \taxrow{Paper}{Method}{Optimization Objective}{Workload}{SLA}{Performance Objective}
                {Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection} 
    &  & & & & & & & & \\ \hline
\end{tabular}
\end{table}

\end{document}%
share|improve this answer
    
(+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 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 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 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

\definecolumns{tax}{paper,method,optobj,workload,sla,perfpred,numofreps,faulttol,failact}

\begin{document}

\begin{tabular}{*{9}{c}}
\toprule
\printrow{tax}{
  Paper,Method,\splitcell{Optimization\\Objective},
  Workload,SLA,\splitcell{Performance\\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

\sortcolumns{tax}{paper,method,optobj,numofreps,faulttol,failact,workload,sla,perfpred}

\begin{tabular}{*{9}{c}}
\toprule
\printrow{tax}{
  Paper,Method,\splitcell{Optimization\\Objective},
  Workload,SLA,\splitcell{Performance\\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.

enter image description here

share|improve this answer

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\workload{#4}%
    \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
      \taxrow{Paper}{Method}{Optimization Objective}{Workload}{SLA}{Performance Objective}
      {Num. of Reps}{Fault Tolerant}{Failover Action}{Overload Protection}\\
      &  & & & & & & & & \\ \hline
    \end{tabular}
  \end{table}
\end{document}
share|improve this answer
    
We had basically the same idea, but your style with the \@for loop is quite nice! –  Christian Hupfer Aug 10 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 at 22:12
    
@ChristianHupfer Oh, yes. I figured that's what you meant about the coding style. –  cfr Aug 10 at 22:16

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.