我想创建一个宏,从列表创建一个表,并将第一列合并。我仍然有两个问题,第一个是获取列表的大小,目前我得到的是 size + 1 ;(,第二个是将结果用于 \multirow 的第一个参数。我考虑过类似 \multirow{\sizeList}{*}{some data} 的东西...但它不起作用。
\documentclass{article}
\usepackage{float}
\usepackage{etoolbox}
\usepackage{multirow}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \countItems {m}{\clist_count:N #1}
\newcommand\mylist{}
\newcommand{\addRow}[2]{
\def\delim{&}
\listadd{\mylist}{ \delim#1,#2}
}
\newcommand{\makerow}[1]{%
\def\delim{ & }%
\renewcommand*{\do}[1]{##1 \delim}%
\docsvlist{#1}%
}
\newcommand{\dorow}[1]{\makerow{#1} \\ \cline{2-3}}
\newcommand{\makeTable}{
\begin{table}[H]
\begin{tabular}{|c|c|c|}
\hline
Uppercase & Number & Lowercase \\ \hline
\multirow{4}{*}{some item} \forlistloop{\dorow}{\mylist} %\multirow{\countItems{\mylist}-1{*}{some item}
\hline
\end{tabular}
\end{table}
}
\ExplSyntaxOff
\begin{document}
\addRow{A}{1}
\addRow{B}{2}
\addRow{C}{3}
\addRow{D}{4}
\makeTable
This list has \countItems{\mylist} elements. %>>>> does not get the right length
\end{document}
答案1
我添加了\show\mylist
您的代码。(就在说明有多少个项目的语句之前。)这在我的终端上显示以下内容:
> \mylist=macro:
->\delim A,1|\delim B,2|\delim C,3|\delim D,4|
您可以看到,此列表中确实有 5 个项目。有 4 个逗号和 5 个项目,因为每个逗号都\addRow
添加了<content before>,<content after>
。因此,添加第一个项目后,列表包含 2 个,添加第二个项目后,列表包含 3 个,依此类推。
您还使用了 LaTeX 2e 和 TeX 的混合版本。虽然现在expl3
很难(不可能?)完全使用,但这可能会更简洁一些。expl3
对于计数,在我看来,你至少有两个选择。你可以直接扣除 1,因为你的代码在设计上添加了 n+1 个项目。或者,你可以保留一个单独的计数。或者你可以重组事物。哪一个最合理可能取决于你的上下文的进一步特征。
接下来我采用重构路线。我将给出的两个参数存储\addRow
在两个序列中,然后简单地将它们两两地输入到函数中以创建行。然后任一序列的计数都会给出行数。我们可以\mutlirow
通过使用expl3
函数变体将其直接输入,以便在函数看到它之前完成计数。
由于带有垂直线和较小间距的表格通常被认为是次优的,因此我还提供了一个booktabs
版本。此版本不使用,H
因为H
这不是个好主意。最好避免使用非浮动浮动。相反,我使用从包中center
提供一些间距和,因为对标题的需求通常会激发人们对非浮动浮动的渴望。\captionof
caption
\documentclass{article}
\usepackage{float}
\usepackage{multirow}
\usepackage{booktabs}
\usepackage{caption}
% not needed with recent LaTeX kernels
% uncomment one or both if you have an older install
% \usepackage{expl3}
% \usepackage{xparse}
\ExplSyntaxOn
% use two sequences and forget storing commas
\seq_new:N \l_francoisfem_itemsa_seq
\seq_new:N \l_francoisfem_itemsb_seq
\NewDocumentCommand \countItems {m}
{
\seq_count:c { l_francoisfem_#1_seq }
}
\NewDocumentCommand {\addRow} {mm}{ % just store the arguments pairwise
\seq_put_right:Nn \l_francoisfem_itemsa_seq { #1 }
\seq_put_right:Nn \l_francoisfem_itemsb_seq { #2 }
}
\cs_new_protected_nopar:Nn \francoisfem_make_row:nn
{ % we add the alignment and row endings etc. here
& #1 & #2 \\ \cline{2-3}
}
\cs_new_protected_nopar:Nn \francoisfem_makenicer_row:nn
{ % for booktabs version
& #1 & #2 \\
}
\cs_new_protected_nopar:Nn \francoisfem_multirow:nnn
{ % make expansion easy for multirow
\multirow {#1} {#2} {#3}
}
% generate a version of multirow which expands its first argument once, so we get the result of the count
\cs_generate_variant:Nn \francoisfem_multirow:nnn { onn }
\NewDocumentCommand{\makeTable}{ O {*} D () { some ~ item } }
{ % two optional arguments: square brackets (defaults to *); parentheses (defaults to 'some item'')
\begin{table}[H] % note that H is Really Not A Good Idea
\centering
\caption{Usually ~ why ~ people ~ want ~ non-floating ~ floats}
\begin{tabular}{|c|c|c|} % note that vertical rules and standard spacing don't make for professional-looking results (see e.g. booktabs)
\hline
Uppercase & Number & Lowercase \\ \hline
\francoisfem_multirow:onn % the o means the first argument gets expanded *before* multirow sees it
{
\seq_count:N \l_francoisfem_itemsa_seq
}{#1}{#2}
% Noah's ark : we feed the contents of the sequences in two-by-two to our row-maker function
\seq_map_pairwise_function:NNN \l_francoisfem_itemsa_seq \l_francoisfem_itemsb_seq \francoisfem_make_row:nn
\hline
\end{tabular}
\end{table}
}
\NewDocumentCommand \makenicerTable { O {*} D () { some ~ item } }
{ % booktabs version
\begin{center} % don't use a float if we don't want it to move
\captionof{table}{If ~ we ~ want ~ a ~ caption}
\begin{tabular}{ccc} % no vertical rules
\toprule
Uppercase & Number & Lowercase \\ \midrule
\francoisfem_multirow:onn
{
\seq_count:N \l_francoisfem_itemsa_seq
}{#1}{#2}
\seq_map_pairwise_function:NNN \l_francoisfem_itemsa_seq \l_francoisfem_itemsb_seq \francoisfem_makenicer_row:nn
\bottomrule
\end{tabular}
\end{center}
}
\ExplSyntaxOff
\begin{document}
\addRow{A}{1}
\addRow{B}{2}
\addRow{C}{3}
\addRow{D}{4}
\makeTable
This list has \countItems {itemsa} elements.
\makenicerTable
\end{document}
答案2
睡了一晚后,可能的解决方案是:):
\documentclass{article}
\usepackage{float}
\usepackage{etoolbox}
\usepackage{multirow}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \countItems {m}{\clist_count:N #1}
\newcommand\mylist{}
\newcounter{lenList} %<<<<<< creating a counter
\newcommand{\addRow}[2]{
\addtocounter{lenList}{1} %<<<<<< when add a row add 1 to the counter
\def\delim{&}
\listadd{\mylist}{ \delim#1,#2}
}
\newcommand{\makerow}[1]{%
\def\delim{ & }%
\renewcommand*{\do}[1]{##1 \delim}%
\docsvlist{#1}%
}
\newcommand{\dorow}[1]{\makerow{#1} \\ \cline{2-3}}
\newcommand{\makeTable}{
\begin{table}[H]
\begin{tabular}{|c|c|c|}
\hline
Uppercase & Number & Lowercase \\ \hline
\multirow{\thelenList}{*}{some item} \forlistloop{\dorow}{\mylist} %<<<< using the counter ...
\hline
\end{tabular}
\end{table}
}
\ExplSyntaxOff
\begin{document}
\addRow{A}{1}
\addRow{B}{2}
\addRow{C}{3}
\addRow{D}{4}
\makeTable
This list has \countItems{\mylist} elements.
\end{document}
答案3
不要混淆expl3
。etoolbox
你只需要设置二您可以协调使用的数据集。
如果您需要两列以上的数据,则会稍微复杂一些。
\documentclass{article}
\usepackage{etoolbox}
\usepackage{multirow}
\ExplSyntaxOn
\seq_new:N \l__francois_table_a_seq
\seq_new:N \l__francois_table_b_seq
\tl_new:N \l__francois_table_alast_tl
\tl_new:N \l__francois_table_blast_tl
\NewDocumentCommand{\clearRows}{}
{
\seq_clear:N \l__francois_table_a_seq
\seq_clear:N \l__francois_table_b_seq
}
\NewDocumentCommand{\addRow}{mm}
{
\seq_put_right:Nn \l__francois_table_a_seq { #1 }
\seq_put_right:Nn \l__francois_table_b_seq { #2 }
}
\NewDocumentCommand{\makeTable}{}
{
% last row is special
\seq_pop_right:NN \l__francois_table_a_seq \l__francois_table_alast_tl
\seq_pop_right:NN \l__francois_table_b_seq \l__francois_table_blast_tl
% make the tabular
\begin{tabular}{|c|c|c|}
\hline
% headers
Uppercase & Number & Lowercase \\ \hline
% start with \multirow
\multirow{\int_eval:n { \seq_count:N \l__francois_table_a_seq + 1 }}{*}{some~item}
\seq_map_pairwise_function:NNN
\l__francois_table_a_seq % first sequence
\l__francois_table_b_seq % second sequence
\__francois_table_make:nn % what to do
% last row, no \cline
& \l__francois_table_alast_tl & \l__francois_table_blast_tl \\
\hline
\end{tabular}
}
\cs_new_protected:Nn \__francois_table_make:nn
{
& #1 & #2 \\ \cline{2-3}
}
\ExplSyntaxOff
\begin{document}
\clearRows
\addRow{A}{1}
\addRow{B}{2}
\addRow{C}{3}
\addRow{D}{4}
\begin{table}[htp]
\centering
\makeTable
\caption{A table with some data}
\end{table}
\end{document}
切勿使用
[H]
如果不需要标题,那么使用
table
环境就没有意义了。仔细看看结果:你真的认为这
\multirow
有帮助吗?“某些项目”部分实际上不是表格的一部分,对吗?垂直规则也无济于事。