1

Trying to build a tabular, based on an array of strings, I followed the lines of http://tex.stackexchange.com/questions/62177, where a table of repeating literal rows was built.
However, instead of literal rows, I want rows depending on the strings in the array. This is what I have:

\documentclass{article}
\usepackage{forarray}

\def\array{bank;acno;name}

% item's name for column 1   item's value for column 2
\def\bankkey{Bank}           \def\bank{Lehmann Brothers}
\def\acnokey{Account no.}    \def\acno{123456789}
\def\namekey{In the name of} \def\name{John Doe}

\newcommand{\tablebody}{%
  \def\body{}%
  \ForEachX{;}{%
    \expandafter\gdef\expandafter\body\expandafter{\body%
       \csname\thislevelitem key\endcsname &
       \csname\thislevelitem\endcsname \\
    }%
  }{\array}%
  \body%
}

\begin{document}

% I want the following tabular to be equivalent to:
% \begin{tabular}{rl}
%     \bankkey & \bank \\
%     \acnokey & \acno \\
%     \namekey & \name \\
% \end{tabular}

\begin{tabular}{rl}
  \tablebody
\end{tabular}

\end{document}

But it produces an error message:

! Missing \endcsname inserted.
<to be read again> 
                   \thislevelitem 
l.32       \tablebody

How can I repair this?
Or are there better ways to do this?

  • To begin with, the name \array is very badly chosen. Never use \def unless you know precisely that the macro you're going to define has a name that won't cause conflicts. – egreg Dec 9 '15 at 12:45
0

To begin with, the name \array is very badly chosen; never use \def unless you know precisely that the macro name you want to define won't conflict.

However, this is not the cause for your troubles, but rather that you're storing \thislevelitem in the body of the definition, not its expansion; so when \body is expanded, it's too late because \ForEachX has already finished its work and \thislevelitem is set back to mean \relax.

\documentclass{article}
\usepackage{forarray}

\def\myarray{bank;acno;name}

% item's name for column 1   item's value for column 2
\def\bankkey{Bank}           \def\bank{Lehmann Brothers}
\def\acnokey{Account no.}    \def\acno{123456789}
\def\namekey{In the name of} \def\name{John Doe}

\makeatletter
\newcommand{\tablebody}{%
  \gdef\body{}%
  \ForEachX{;}{%
    \protected@xdef\body{%
       \body
       \csname\thislevelitem key\endcsname &
       \csname\thislevelitem\endcsname \protect\\
    }%
  }{\myarray}%
  \body%
}
\makeatother

\begin{document}

\begin{tabular}{|r|l|}
  \tablebody
\end{tabular}

\end{document}

(I added rules just to show that no spurious row is added at the end.)

enter image description here

Are there better ways? Sure!

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\makearray}{O{default}m}
 {
  \tl_gset:Nn \g_wybo_array_name_tl { #1 }
  \seq_gclear_new:c { g_wybo_array_#1_seq }
  \prop_gclear_new:c { g_wybo_array_#1_prop }
  \keys_set:nn { wybo/array } { #2 }
 }

\NewDocumentCommand{\usearray}{O{default}}
 {
  \tl_clear:N \l_wybo_array_body_tl
  \seq_map_inline:cn { g_wybo_array_#1_seq }
   {
    \tl_put_right:Nx \l_wybo_array_body_tl
     {
      \prop_item:cn { g_wybo_array_#1_prop } { ##1-A }
      &
      \prop_item:cn { g_wybo_array_#1_prop } { ##1-B }
      \exp_not:N \\
     }
   }
  \tl_use:N \l_wybo_array_body_tl
 }

\keys_define:nn { wybo/array }
 {
  unknown .code:n = \wybo_array_entry:VVnn \g_wybo_array_name_tl \l_keys_key_tl #1,
 }

\cs_new_protected:Nn \wybo_array_entry:nnnn
 {
  \seq_gput_right:cn { g_wybo_array_#1_seq } { #2 } % the entry name
  \prop_gput:cnn { g_wybo_array_#1_prop } { #2-A } { #3 } % first col
  \prop_gput:cnn { g_wybo_array_#1_prop } { #2-B } { #4 } % second col
 }
\cs_generate_variant:Nn \wybo_array_entry:nnnn { VV }
\ExplSyntaxOff

\makearray{
  bank={Bank}{Lehmann Brothers},
  acno={Account no.}{123456789},
  name={In the name of}{John Doe},
}

\makearray[another]{
  a={x}{y},
  b={xx}{yy},
  c={xxx}{yyy},
}

\begin{document}

\begin{tabular}{|r|l|}
  \usearray
\end{tabular}

\begin{tabular}{|r|l|}
  \usearray[another]
\end{tabular}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.