在主题的代码中我想创建一个新的命令来制作表格,命令中的参数将填充表格
分隔符是逗号:
\cards{3,1,6,1,2,2,3,2,4,3,4,3,5,7,5,4}
但在我的数据中,有很多条目包含逗号:例如“红色,蓝色T恤”
我怎样才能将分隔符更改为管道符|
,以便可以输入以下内容?
\cards{3|1|6|1|2|2|3|2|4|3|4|3|5|7|5|4}
最小代码:
\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\cards}{ m }
{
\arne_card_distribution:n { #1 }
}
\cs_new_protected:Nn \arne_card_distribution:n
{
\begin{tabular}{ *{5}{c} }
\toprule
& lente & zomer & herfst & winter \\
\cmidrule{2-5}
B & \clist_item:nn { #1 } { 1 }
& \clist_item:nn { #1 } { 2 }
& \clist_item:nn { #1 } { 3 }
& \clist_item:nn { #1 } { 4 } \\
G & \clist_item:nn { #1 } { 5 }
& \clist_item:nn { #1 } { 6 }
& \clist_item:nn { #1 } { 7 }
& \clist_item:nn { #1 } { 8 } \\
D & \clist_item:nn { #1 } { 9 }
& \clist_item:nn { #1 } { 10 }
& \clist_item:nn { #1 } { 11 }
& \clist_item:nn { #1 } { 12 } \\
S & \clist_item:nn { #1 } { 13 }
& \clist_item:nn { #1 } { 14 }
& \clist_item:nn { #1 } { 15 }
& \clist_item:nn { #1 } { 16 } \\
\bottomrule
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\cards{3,1,6,1,2,2,3,2,4,3,4,3,5,7,5,4}
\end{document}
答案1
这是表格的一个略微(过度?)修改过的版本。我让它在行数和列数方面更加灵活。
该\cards
命令现在接受一个可选参数和三个强制参数:
\cards[<key-val>]{<header row>}{<first column>}{<table body>}
可选参数允许您使用sep=<sep>
(默认为) 设置分隔符并使用(默认为) 设置sep=|
表格单元格的对齐方式。是一个以 分隔的项目列表,将排版在表格顶部,前面有一个空单元格。也是一个以 分隔的项目列表,将排版在表格的每一行,从第二行开始。align=<token>
align=c
<header row>
<sep>
<first column>
<sep>
是<table body>
一个<sep>
以 - 分隔的列表M×N
项目 (M
和N
<header row>
是和列表中的项目数<first column>
),这些项目将按行主顺序逐个添加到表中(即第一个M
项目放在第一行,下一行M
物品放在第二行,依此类推。
您问题中的表格可以这样排版(为清楚起见添加了换行符;项目周围的空格被修剪):
\cards{ lente | zomer | herfst | winter }
{ B | G | D | S }
{3|1|6|1|
2|2|3|2|
4|3|4|3|
5|7|5|4}
使用选项的示例:
\cards[sep = /, align = l]
{ foo / bar / baz }
{ F / B / B }
{1/2/3/
4/5/6/
7/8/9}
输出:
代码:
\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__forti_table_sep_tl
\tl_new:N \l__forti_table_align_tl
\tl_new:N \l__forti_table_temp_tl
\int_new:N \l__forti_table_ncols_int
\seq_new:N \g__forti_table_body_seq
\seq_new:N \g__forti_table_header_seq
\seq_new:N \g__forti_table_column_seq
\cs_generate_variant:Nn \seq_gset_split:Nnn { Nx }
\keys_define:nn { forti }
{
, sep .tl_set:N = \l__forti_table_sep_tl
, sep .initial:n = { | }
, sep .value_required:n = true
, align .tl_set:N = \l__forti_table_align_tl
, align .initial:n = { c }
, align .value_required:n = true
}
\NewDocumentCommand { \cards } { o m m m }
{
\group_begin:
\IfValueT {#1} { \keys_set:nn { forti } {#1} }
\forti_card_distribution:nnn {#2} {#3} {#4}
\group_end:
}
\cs_new_protected:Npn \forti_card_distribution:nnn #1 #2 #3
{
\__forti_seq_gset_split:Nn \g__forti_table_header_seq {#1}
\__forti_seq_gset_split:Nn \g__forti_table_column_seq {#2}
\__forti_seq_gset_split:Nn \g__forti_table_body_seq {#3}
\__forti_card_distribution_check_do:nnnN
{ \seq_count:N \g__forti_table_header_seq }
{ \seq_count:N \g__forti_table_column_seq }
{ \seq_count:N \g__forti_table_body_seq }
\__forti_card_distribution:nn
}
\cs_new_protected:Npn \__forti_seq_gset_split:Nn #1 #2
{ \seq_gset_split:Nxn #1 { \tl_use:N \l__forti_table_sep_tl } {#2} }
\cs_new_protected:Npn \__forti_card_distribution_check_do:nnnN #1 #2 #3 #4
{
\int_compare:nNnTF {#1*#2} = {#3}
{ #4 {#1} {#2} }
{
\msg_error:nnxx { forti } { wrong-number-of-items }
{ \int_eval:n {#1*#2} } {#3}
}
}
\cs_new_protected:Npn \__forti_card_distribution:nn #1 #2
{
\int_set:Nn \l__forti_table_ncols_int {#1}
\use:x
{
\exp_not:N \begin{tabular}
{ * { \int_eval:n {#1 + 1} } { \tl_use:N \l__forti_table_align_tl } }
}
\toprule
\c_alignment_token
\seq_use:Nn \g__forti_table_header_seq { \c_alignment_token } \\
\cmidrule { 2 - \int_eval:n {#1 + 1} }
\int_step_function:nN { #2 }
\__forti_typeset_table_row:n
\bottomrule
\end{tabular}
}
\cs_new_protected:Npn \__forti_typeset_table_row:n #1
{
\seq_gpop:NN \g__forti_table_column_seq \l__forti_table_temp_tl
\tl_use:N \l__forti_table_temp_tl
\int_step_function:nN { \int_use:N \l__forti_table_ncols_int }
\__forti_typeset_table_item:n
\\
}
\cs_new_protected:Npn \__forti_typeset_table_item:n #1
{
\seq_gpop:NN \g__forti_table_body_seq \l__forti_table_temp_tl
\use:x { \c_alignment_token \exp_not:V \l__forti_table_temp_tl }
}
\msg_new:nnn { forti } { wrong-number-of-items }
{ Wrong~number~of~items~`#2'.~The~table~has~`#1'~cells. }
\ExplSyntaxOff
\begin{document}
\cards{ lente | zomer | herfst | winter }
{ B | G | D | S }
{3|1|6|1|
2|2|3|2|
4|3|4|3|
5|7|5|4}
\cards[sep = /, align = l]
{ foo / bar / baz }
{ F / B / B }
{1/2/3/
4/5/6/
7/8/9}
\end{document}
根据要求,这是一个没有第一列的版本:
\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__forti_table_sep_tl
\tl_new:N \l__forti_table_align_tl
\tl_new:N \l__forti_table_temp_tl
\int_new:N \l__forti_table_ncols_int
\seq_new:N \g__forti_table_body_seq
\seq_new:N \g__forti_table_header_seq
\cs_generate_variant:Nn \seq_gset_split:Nnn { Nx }
\keys_define:nn { forti }
{
, sep .tl_set:N = \l__forti_table_sep_tl
, sep .initial:n = { | }
, sep .value_required:n = true
, align .tl_set:N = \l__forti_table_align_tl
, align .initial:n = { c }
, align .value_required:n = true
}
\NewDocumentCommand { \cards } { o m m }
{
\group_begin:
\IfValueT {#1} { \keys_set:nn { forti } {#1} }
\forti_card_distribution:nn {#2} {#3}
\group_end:
}
\cs_new_protected:Npn \forti_card_distribution:nn #1 #2
{
\__forti_seq_gset_split:Nn \g__forti_table_header_seq {#1}
\__forti_seq_gset_split:Nn \g__forti_table_body_seq {#2}
\__forti_card_distribution_check_do:nnN
{ \seq_count:N \g__forti_table_header_seq }
{ \seq_count:N \g__forti_table_body_seq }
\__forti_card_distribution:nn
}
\cs_new_protected:Npn \__forti_seq_gset_split:Nn #1 #2
{ \seq_gset_split:Nxn #1 { \tl_use:N \l__forti_table_sep_tl } {#2} }
\cs_new_protected:Npn \__forti_card_distribution_check_do:nnN #1 #2 #3
{
\int_compare:nNnTF { \int_mod:nn {#2}{#1} } = { 0 }
{ #3 {#1} {#2} }
{ \msg_error:nnxx { forti } { wrong-number-of-items } {#1} {#2} }
}
\cs_new_protected:Npn \__forti_card_distribution:nn #1 #2
{
\int_set:Nn \l__forti_table_ncols_int {#1}
\use:x
{
\exp_not:N \begin{tabular}
{ * { \int_eval:n {#1} } { \tl_use:N \l__forti_table_align_tl } }
}
\toprule
\seq_use:Nn \g__forti_table_header_seq { \c_alignment_token } \\
\midrule
\int_step_function:nN { #2/#1 }
\__forti_typeset_table_row:n
\bottomrule
\end{tabular}
}
\cs_new_protected:Npn \__forti_typeset_table_row:n #1
{
\int_step_function:nN { \l__forti_table_ncols_int }
\__forti_typeset_table_item:n
\\
}
\cs_new_protected:Npn \__forti_typeset_table_item:n #1
{
\seq_gpop:NN \g__forti_table_body_seq \l__forti_table_temp_tl
\use:x
{
\int_compare:nNnT {#1} > { 1 } { \c_alignment_token }
\exp_not:V \l__forti_table_temp_tl
}
}
\msg_new:nnn { forti } { wrong-number-of-items }
{ Wrong~number~of~items~`#2'.~The~table~has~`#1'~cells. }
\ExplSyntaxOff
\begin{document}
\cards{ lente | zomer | herfst | winter }
{3|1|6|1|
2|2|3|2|
4|3|4|3|
5|7|5|4}
\cards[sep = /, align = l]
{ foo / bar / baz }
{1/2/3/
4/5/6/
7/8/9}
\end{document}