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.

For the following MWE

\documentclass{article}

\newcommand{\cmd}[5]{%
  \def\tA{#1}%
  \def\tB{#2}%
  \def\tC{#3}%
  \def\tD{#4}%
  \def\tE{#5}%

  \tA & \tB & \tC & \tD & \tE \\
}

\begin{document}
\begin{tabular}{ccccc}
  \cmd{1}{2}{3}{4}{5}
\end{tabular}
\end{document}

I keep getting the following error:

! Undefined control sequence.
\cmd ...}\def \tD {#4}\def \tE {#5}\par \tA & \tB 
                                                  & \tC & \tD & \tE \\ 
l.15   \cmd{1}{2}{3}{4}{5}

Why doesn't it work?

PS. The reason for using \def is that in my document I need to handle more than 9 parameters to the command, and thus apply this method.

share|improve this question
    
Can you show a real world example? Using more than nine arguments should be the very last resort; perhaps we can find a better way to input your text. –  egreg Apr 7 at 16:21
    
It's for a paper where we have a table with over 9 columns. We haven't decided upon the exact order of the columns, but we don't want to have to rearrange all the arguments for every row. So that's why we're using a macro which takes all these column values as arguments. –  gablin Apr 7 at 20:31
    
I said you that a better solution can be found. ;-) –  egreg Apr 7 at 21:08

2 Answers 2

up vote 12 down vote accepted

Cells inside a tabular form groups, so in your example the commands defined by \cmd are not available starting with the second cell. Solution: Use \gdef instead of \def in the definition of \cmd.

\documentclass{article}

\newcommand{\cmd}[5]{%
  \gdef\tA{#1}%
  \gdef\tB{#2}%
  \gdef\tC{#3}%
  \gdef\tD{#4}%
  \gdef\tE{#5}%

  \tA & \tB & \tC & \tD & \tE \\
}

\begin{document}
\begin{tabular}{ccccc}
  \cmd{1}{2}{3}{4}{5}
\end{tabular}
\end{document}
share|improve this answer

You can avoid using many arguments. Here's an implementation of your \cmd where you specify the arguments as a comma separated list; with \selectorder you can decide what order is used in the output.

Note that \cmd will happily accept any number of items in the list; all you need is to specify the correct number of columns in the tabular and precede it with the suitable \selectorder command. I demonstrated this with two tables with four and five columns respectively.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\cmd}{m}
 {
  \gablin_cmd:n { #1 }
 }

\NewDocumentCommand{\selectorder}{m}
 {
  \seq_gset_split:Nnn \g_gablin_order_seq { , } { #1 }
 }

\prop_new:N \l_gablin_arg_prop
\seq_new:N \l_gablin_output_seq
\seq_new:N \g_gablin_order_seq
\int_new:N \l_gablin_input_int

\cs_new_protected:Npn \gablin_cmd:n #1
 {
  % clear the variables' contents (it isn't really necessary)
  \prop_clear:N \l_gablin_arg_prop
  \seq_clear:N \l_gablin_output_seq
  \int_zero:N \l_gablin_input_int
  % map through the items in the argument
  \clist_map_inline:nn { #1 }
   {
    % the integer variable is used to number the items
    \int_incr:N \l_gablin_input_int
    % items are stored in a property list
    \prop_put:Nfn \l_gablin_arg_prop { \int_to_arabic:n { \l_gablin_input_int } } { ##1 }
   }
  % map through the items stating the order of items in columns
  \seq_map_inline:Nn \g_gablin_order_seq
   {
    % put the items in a new sequence
    \seq_put_right:Nx \l_gablin_output_seq
     {
      \prop_get:Nn \l_gablin_arg_prop { ##1 }
     }
   }
  % use the sequence, separating arguments with &
  \seq_use:Nn \l_gablin_output_seq { & }
 }

% we need a variant of \prop_put:Nnn store a number in the key
\cs_generate_variant:Nn \prop_put:Nnn { Nf }

\ExplSyntaxOff

\begin{document}

\selectorder{1,2,3,4}

\begin{tabular}{*{4}{c}}
\cmd{aa,ab,ac,ad} \\
\cmd{ba,bb,bc,bd} \\
\cmd{ca,cb,cc,cd} \\
\end{tabular}

\bigskip

\selectorder{5,4,3,2,1}

\begin{tabular}{*{5}{c}}
\cmd{aa,ab,ac,ad,ae} \\
\cmd{ba,bb,bc,bd,be} \\
\cmd{ca,cb,cc,cd,ce} \\
\end{tabular}

\end{document}

The setting defined by \selectorder will remain valid until countermanded by another choice and is global, so it doesn't matter if it's issued in a table environment. So this code is very flexible.

enter image description here

share|improve this answer

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.