![使用宏定义表格主体 / & 分隔符问题](https://linux22.com/image/290605/%E4%BD%BF%E7%94%A8%E5%AE%8F%E5%AE%9A%E4%B9%89%E8%A1%A8%E6%A0%BC%E4%B8%BB%E4%BD%93%20%2F%20%26%20%E5%88%86%E9%9A%94%E7%AC%A6%E9%97%AE%E9%A2%98.png)
我想创建一个宏,它可以创建并填充一个多行表格,每行有 4 个条目,其中\bidding{3H,4S,5C,X,XX,-}
条目数当然是动态的。
我尝试了不同的方法,但无法解决问题,让乳胶&
正确解释分隔符。
我总是以 & 根本不被解释或以
Misplaced alignment tab character &.
错误消息。尝试从此处找到的另一个执行递归部分的解决方案中得出此结论,最新的失败(以错误消息结尾)如下所示:
\documentclass{article}
\usepackage{kvsetkeys}
\usepackage{etexcmds}
\makeatletter
\newcommand*{\commut}[2]{{#1}&{#2}}
\newcommand*{\qcommut}[1]{%
\let\commut@list\relax
\comma@parse{#1}\@qcommut
\typeout{\meaning\commut@list}% for debugging
\expandafter\commut@list
}
\def\@qcommut#1{%
\ifx\commut@list\relax
\def\commut@list{#1}%
\else
\edef\commut@list{%
\noexpand\commut{%
\etex@unexpanded\expandafter{\commut@list}%
}{#1}%
}%
\fi
}
\makeatother
\begin{document}
\begin{tabular}{ccccc}
\qcommut{A,B,C,D,E}
\end{tabular}
\end{document}
这不会为我提供每行 4 组,但我只是渴望解决这个&
问题,剩下的就很容易了...任何帮助都值得赞赏。
答案1
我不明白为什么这么简单的任务会产生这么多代码。我的意思是下面的代码是成功的。
\documentclass{文章} \def\tabline{} \def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}} \def\qcommut#1{\qcommutA#1,,\tabline\cr} \def\qcommutA#1,{% \如果^#1^\否则 \ifx\tabline\empty \else\addto\tabline{&}\fi \addto\tabline{#1}\expandafter\qcommutA \fi } \开始{文档} \开始{表格}{ccccc} \qcommut{A,B,C,D,E} \qcommut{A,B} \qcommut{A,B,C} \end{表格} \结束{文档}
答案2
如果编程环境不一定是你习惯的,可以采用以下方法expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\qtabular}{ O{4} m }
{
\peter_qtabular:nn { #1 } { #2 }
}
\tl_new:N \l__peter_qtabular_body_tl
\seq_new:N \l__peter_qtabular_input_seq
\int_new:N \l__peter_qtabular_cols_int
\cs_new_protected:Npn \peter_qtabular:nn #1 #2
{
\tl_clear:N \l__peter_qtabular_body_tl
\int_zero:N \l__peter_qtabular_cols_int
\seq_set_split:Nnn \l__peter_qtabular_input_seq { , } { #2 }
\seq_map_inline:Nn \l__peter_qtabular_input_seq
{
\tl_put_right:Nn \l__peter_qtabular_body_tl { ##1 }
\int_incr:N \l__peter_qtabular_cols_int
\int_compare:nTF { \l__peter_qtabular_cols_int = #1 }
{
\tl_put_right:Nn \l__peter_qtabular_body_tl { \\ }
\int_zero:N \l__peter_qtabular_cols_int
}
{
\tl_put_right:Nn \l__peter_qtabular_body_tl { & }
}
}
\begin{tabular}{*{#1}{c}}
\tl_use:N \l__peter_qtabular_body_tl
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\qtabular{A,B,C,D,E,F,G,H,I,J}
\qtabular[3]{A,B,C,D,E,F,G,H,I,J}
\end{document}
桌子的主体是预先准备好的,然后在环境中运送tabular
。
进行一个小的修改来填充最后一行(空单元格)以便能够使用\hline
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\qtabular}{ O{4} m }
{
\peter_qtabular:nn { #1 } { #2 }
}
\tl_new:N \l__peter_qtabular_body_tl
\seq_new:N \l__peter_qtabular_input_seq
\int_new:N \l__peter_qtabular_cols_int
\cs_new_protected:Npn \peter_qtabular:nn #1 #2
{
% clear the token list that will contain the body
\tl_clear:N \l__peter_qtabular_body_tl
% this counter tells us what column we're at
\int_zero:N \l__peter_qtabular_cols_int
% split the input into items at commas
\seq_set_split:Nnn \l__peter_qtabular_input_seq { , } { #2 }
% do a mapping
\seq_map_inline:Nn \l__peter_qtabular_input_seq
{% add the current item to the body and increment the counter
\tl_put_right:Nn \l__peter_qtabular_body_tl { ##1 }
\int_incr:N \l__peter_qtabular_cols_int
% if the counter equals the number of columns, add \\, else &
\int_compare:nTF { \l__peter_qtabular_cols_int = #1 }
{
\tl_put_right:Nn \l__peter_qtabular_body_tl { \\ }
\int_zero:N \l__peter_qtabular_cols_int
}
{
\tl_put_right:Nn \l__peter_qtabular_body_tl { & }
}
}
% now fill the last row, if necessary; it isn't if the counter is 0
\int_compare:nF { \l__peter_qtabular_cols_int == 0 }
{% add as many & as necessary
\prg_replicate:nn { #1 - \l__peter_qtabular_cols_int - 1 }
{ \tl_put_right:Nn \l__peter_qtabular_body_tl { & } }
% add the final \\
\tl_put_right:Nn \l__peter_qtabular_body_tl { \\ }
}
% deliver the table
\begin{tabular}{*{#1}{c}}
\hline
\tl_use:N \l__peter_qtabular_body_tl
\hline
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\qtabular{A,B,C,D,E,F,G,H,I,J}
\qtabular[3]{A,B,C,D,E,F,G,H,I,J}
\qtabular[5]{A,B,C,D,E,F,G,H,I,J}
\end{document}
答案3
一种无需封装的方法。
更新:
- 这些宏是
\long
为了允许一些特殊情况,例如
这
\qtabular[3]{A,
\begin{minipage}{2cm}
ABC\par DEF
\end{minipage},
Z}
- 定义了一个新的宏
\qtabularnewline
,允许\\
在任意位置插入 以及\hline
或甚至\noalign
材料。使用基于首先构建整个表格材料的方法实现相同功能可能会有点复杂。
代码:
\documentclass{article}
\makeatletter
% the update is a bit more clever and has less macros for more effects
\newcommand{\qtabular}[2][4]{% optional argument=nb of columns
\begin{tabular}{*{#1}{c}}
\qtabular@a {1}{#1}#2\qtabular@end,%
\end{tabular}}
% The update makes the macros \long, to be compatible with \par tokens
\long\def\qtabular@a #1#2#3,{#3%
\expandafter\qtabular@e\expandafter{\the\numexpr #1+1}{#2}}
% Use of \tabularnewline for extra-safety, but quasi unnecessary I guess.
\long\def\qtabular@e #1#2{\ifnum #2<#1
\expandafter\@firstoftwo
\else\expandafter\@secondoftwo
\fi
{\tabularnewline\qtabular@a {1}{#2}}%
{&\qtabular@a {#1}{#2}}%
}
\def\qtabular@end\expandafter\qtabular@e\expandafter #1#2{}
\long\def\qtabularnewline #1\expandafter\qtabular@e\expandafter #2#3{%
\ifnum #2=2 \else \expandafter\tabularnewline\fi
\qtabular@a {1}{#3}#1,}
% minor remark: if the #1 from what followed \qtabularnewline in the
% input was braced, one level will be removed, but this
% has quasi nil importance, any how the new cell is a group, and #1 will
% occupy it entirely.
\makeatother
\begin{document}
\qtabular[3]{A,
\begin{minipage}{2cm}
ABC\par DEF
\end{minipage},
Z}
\medskip
Using \verb|\fbox|es to check for spurious empty lines:
\medskip
\fbox{\qtabular[3]{\hline A,B,C\qtabularnewline\hline}}
=\fbox{\qtabular[3]{\hline A,B,C,\qtabularnewline\hline}}
=\fbox{\qtabular[3]{\hline A,B,C\\\hline}}
$\neq$\fbox{\qtabular[3]{\hline A,B,C,\\\hline}}
\fbox{\qtabular[3]{\hline A,B,C\qtabularnewline D}}
$\neq$
% a , after \qtabularnewline is like & after \\
\fbox{\qtabular[3]{\hline A,B,C\qtabularnewline, D}}
\fbox{\qtabular[12]{\hline\hline A,B,C\qtabularnewline\hline
D,E,F,G,H,I,J,A,B,\qtabularnewline % a comma
% before\qtabularnewline is authorized and non-significant
C,D,E,F,\qtabularnewline \hline
G,H,I,J,A,B,C,D,E,F,G,H,I,J\qtabularnewline
\noalign{\hbox{DEMONSTRATING THE APPROACH FLEXIBILITY}}
A,B,C,D,E,F,G,H,I,A,B,C,D,E,F,G,H,I,J\\\hline\hline}}
\fbox{\qtabular[1]{A,B,C,\qtabularnewline}}% checking it is ok also at
% the end
\fbox{\qtabular[1]{\qtabularnewline\hline A,\qtabularnewline\hline}}
and
\fbox{\qtabular[1]{\hline A\\\hline}}
and
\fbox{\begin{tabular}{c}
\hline A\\\hline
\end{tabular}}
\end{document}
第一个版本:
代码:
\documentclass{article}
\makeatletter
\newcommand{\qtabular}[2][4]{% optional argument=nb of columns
\begin{tabular}{*{#1}{c}}
\qtabular@a 1{#1}#2,\qtabular@a,%
\end{tabular}}
\def\qtabular@a #1#2#3,{%
\qtabular@b #3\qtabular@c\qtabular@a\qtabular@d
{#1}{#2}{#3}}
\def\qtabular@b #1\qtabular@a {}
\def\qtabular@c\qtabular@a\qtabular@d #1#2#3{}
\def\qtabular@d #1#2#3{#3%
\expandafter\qtabular@e\expandafter{\the\numexpr #1+1}{#2}}
\def\qtabular@e #1#2{\ifnum #2<#1
\expandafter\@firstoftwo
\else\expandafter\@secondoftwo
\fi
{\\\qtabular@a {1}{#2}}%
{&\qtabular@a {#1}{#2}}%
}
\makeatother
\begin{document}
\hrule
\qtabular{A,B,C,D,E,F,G,H,I,J}
\hrule
\qtabular[3]{A,B,C,D,E,F,G,H,I,J}
\hrule
\qtabular[12]{A,B,C,D,E,F,G,H,I,J,A,B,C,D,E,F,G,H,I,J,A,B,C,D,E,F,G,H,I,J,A,B,C,D,E,F,G,H,I,J,A,B,C,D,E,F,G,H,I,J}
\hrule
\qtabular[5]{A,B,C,D,E,F,G,H,I,J}
\hrule
\qtabular[1]{A} and \qtabular[1]{A,B}
\hrule
\end{document}