我正在尝试使用 pdflatex 制作一个自动会议日志生成器。我想创建一个包含 n 行的表格,并用逗号分隔的 typein 输入填充它们。我myTable
从这个答案,如果我直接在文本中写入,它就可以正常工作。 (1)但是如果我使用\def\variable
或\typein[\variable]{variable}
(2),它会失败并出现以下错误。
据我所知,我可能应该\expandafter
以某种方式使用某个地方,但我自己无法弄清楚。
\documentclass[a4paper,11pt]{article}
\usepackage{etoolbox}
\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}
\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{
\renewcommand*\do[1]{\addtablerow##1!}
\begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} | p{0.2\textwidth}|}
\hline
Name & Role & Presence & Present \\ \hline
\docsvlist{#1} \hline
\end{tabular}
}
\begin{document}
% 1
\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
% 2
\myTable{\variable}
\end{document}
完整错误:
\variable !\etb@lst@docsvlist \@nil \etb@lst@q@end ,& \hline \end {ta\ETC.
! File ended while scanning use of \addtablerow.
<inserted text>
\par
<*> test.tex
! Emergency stop.
<*> test.tex
答案1
该调用\myTable{\variable}
传递一个长度为 1 的列表。您需要访问价值之前\variable
完成\myTable
其工作。
因此,正如另一个答案所暗示的是正确的,尽管没有必要\expandafter
在前面添加\addtablerow
。
我建议采用一种不同的方法,即使用命名空间的模拟expl3
来避免污染代码。\def
如果您想使用先前定义的列表,则宏\printlist
将采用。*
如果您需要的所有列表都是这样的,您可以避免这种*
变体,更改代码应该很容易。
其工作原理与 非常相似\docsvlist
,但有一些优势:例如,逗号分隔符周围的空格会被忽略。这里的\clist_map_inline:nN
作用类似于\docsvlist
,您无需重新定义,而是\do
定义一组两个宏,其中第一个宏与 类似\addtablerow
,但必须将其拆分为外部部分和内部部分。
表格前言已经修复,以避免过满:您的表格比文本宽度长,因为您没有考虑列间空间。
\documentclass[a4paper,11pt]{article}
\ExplSyntaxOn
\NewDocumentCommand{\definelist}{mm}
{
\clist_clear_new:c { l_fauszt_list_#1_clist }
\clist_set:cn { l_fauszt_list_#1_clist } { #2 }
}
\NewDocumentCommand{\printlist}{sm}
{% the star variant uses a list name
% otherwise a full list is passed
\IfBooleanTF{#1}
{
\fauszt_list_print:v { l_fauszt_list_#2_clist }
}
{
\fauszt_list_print:n { #2 }
}
}
\cs_new_protected:Nn \fauszt_list_print:n
{
\begin{tabular}{
|p{\dimexpr0.4\textwidth-2\tabcolsep}
|p{\dimexpr0.2\textwidth-2\tabcolsep}
|p{\dimexpr0.2\textwidth-2\tabcolsep}
|p{\dimexpr0.2\textwidth-2\tabcolsep}|
}
\hline
Name & Role & Presence & Present \\
\hline
\clist_map_function:nN { #1 } \__fauszst_list_print_row:n
\end{tabular}
}
\cs_generate_variant:Nn \fauszt_list_print:n { v }
\cs_new_protected:Nn \__fauszst_list_print_row:n
{
\__fauszt_list_print_row:w #1 \q_stop
}
\cs_new_protected:Npn \__fauszt_list_print_row:w #1 / #2 / #3 / #4 \q_stop
{
\textbf{#1} & #2 & #3 & #4 \\ \hline
}
\ExplSyntaxOff
\definelist{variable}{
Person 1/Active/Online/X,
Person 2/Active/-/-,
Person 3/Intern/Office/X
}
\begin{document}
\noindent
\printlist{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
\bigskip
\noindent
\printlist*{variable}
\end{document}
可以进行进一步的概括。
为了完整起见,我将证明我的说法,在提出的解决方案中用户237299\expandafter
,中的标记\expandafter\addtablerow##1
可以被删除,因为它没有任何用处(并且它甚至可能在极端情况下做坏事)。
让我们按照扩展来做。当\variable
定义为问题中所述时,调用为
\noindent\expandafter\myTable\expandafter{\variable}
(第一个提出的解决方案),这与调用
\noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
然后\docsvlist
将确定第一项并将其作为括号参数传递给\do
,因此循环中的第一个循环将执行
\do{Person 1/Developer/Online/X}
这将成为
\expandafter\addtablerow Person 1/Developer/Online/X!
并且\expandafter
显然是无用的。
在第二个解决方案中,调用的是\myTable{\variable}
,然后主要部分是
\expandafter\docsvlist\expandafter{\variable}
但它只是第一个的变体,其工作原理完全相同。
然后 user237299 声称\expandafter
我指的将在呼叫发生时有用\myTable{\variableTwo}
,其中已经发生
\def\variableTwo{\variable}
不幸的是,事实并非如此。事实上,使用第一个解决方案(但使用第二个解决方案完全相同),
\expandafter\myTable\expandafter{\variableTwo}
即成为
\myTable{\variable}
调用\docsvlist{\variable}
。参数没有逗号,因此执行单个循环,调用变为
\expandafter\addtablerow\variable
没什么用,因为我们会得到
\addtablerow Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X!
当然,\def\variableTwo{\variable}
在这种情况下,这样做毫无意义。如果想要为 指定别名\variable
,也许是为了在保留先前列表的情况下对其进行扩充,则应该执行\let\variableTwo=\variable
。
答案2
你只需要一些\expandafter
s。
\documentclass[a4paper,11pt]{article}
\usepackage{etoolbox}
\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}
\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{
\renewcommand*\do[1]{\expandafter\addtablerow##1!}
\begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} | p{0.2\textwidth}|}
\hline
Name & Role & Presence & Present \\ \hline
\docsvlist{#1} \hline
\end{tabular}
}
\begin{document}
% 1
\noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
% 2
\par
\noindent\expandafter\myTable\expandafter{\variable}
\end{document}
或者
\documentclass[a4paper,11pt]{article}
\usepackage{etoolbox}
\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}
\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{%
\renewcommand*\do[1]{\expandafter\addtablerow##1!}
\begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} | p{0.2\textwidth}|}
\hline
Name & Role & Presence & Present \\ \hline
\expandafter\docsvlist\expandafter{#1} \hline
\end{tabular}
}
\begin{document}
% 1
\noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
% 2
\par
\noindent\myTable{\variable}
\end{document}