使用 forarray 包的 \ForEachX 构建表格

使用 forarray 包的 \ForEachX 构建表格

尝试基于字符串数组构建表格时,我遵循了 的思路http://tex.stackexchange.com/questions/62177,其中构建了一个重复文字行的表格。
但是,我想要的不是文字行,而是取决于数组中的字符串的行。这就是我所拥有的:

\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}

但它会产生一个错误消息:

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

我该如何修复这个问题?
或者有更好的方法吗?

答案1

首先,这个名字\array选得很糟糕;绝不\def除非您确切知道要定义的宏名不会冲突,否则不要使用。

但是,这并不是造成您遇到麻烦的原因,而是您将内容存储\thislevelitem在定义主体中,而不是其扩展中;因此,当\body扩展时,已经太晚了,因为\ForEachX已经完成了其工作并被\thislevelitem重新设置为\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}

(我添加规则只是为了显示最后没有添加虚假行。)

在此处输入图片描述

还有更好的方法吗?当然有!

\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}

在此处输入图片描述

相关内容