尝试基于字符串数组构建表格时,我遵循了 的思路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}