在环境中使用循环的正确方法是什么tabular
?
我的问题背景是使用datatool
包生成表格。我需要以下功能:
- 在每一行中,我想使用循环生成单元格
- 在每个单元格内,我应该能够:
- 能够使用
\multicolumn{1}{c}
宏来更改列格式 - 使用循环计数器的值,例如在
if/then
语句内部以及获取某些数据工具值
- 能够使用
我不知道该怎么做这三件事。以下此条目,我尝试了几种方法,总结如下:
\def\tand{&}
\newcounter{k}
% attepmt 1a
\def\firstattempta{
\setcounter{k}{1}
\whiledo{\thek < 3}{
header\ \thek
%\multicolumn{1}{c}{header \thek} % multicolumn not accepted
\tand
\stepcounter{k}
}
header\ \thek
}
% attempt 1b
\makeatletter
\def\xwhilenum #1\do{\@whilesw{\ifnum #1}\fi }
\makeatother
\def\firstattemptb{
\setcounter{k}{1}
\xwhilenum{\thek < 3}\do{%
header\ \thek
%\multicolumn{1}{c}{header \thek} % multicolumn not accepted
\stepcounter{k}
&
}
header\ \thek
}
% attempt 2
\setcounter{k}{1}
\def\secondattempt{}
\whiledo{\thek < 3}{%
\expandafter\def\expandafter\secondattempt\expandafter{%
\secondattempt
\multicolumn{1}{c|}{header \thek}
\ifnum\thek<4 \tand \fi % 4 should be any other but it doesn't work
}
\stepcounter{k}%
}
\expandafter\def\expandafter\secondattempt\expandafter{
\secondattempt\multicolumn{1}{c|}{header \thek}} % (*)
\begin{document}
\begin{tabular}{*{3}{|D{.}{,}{-1}}|}
\hline
\firstattempta \\
\hline
\firstattemptb \\
\hline
\secondattempt \\
\hline
\end{tabular}
\end{document}
答案1
以下是循环遍历 n 列。它必须用作行的第一个元素,因此您只能使用它来循环遍历整行或行的前 n 列。 的第一个参数\colloop
是它应该循环的列数,第二个参数是每个单元格的内容,用#1
列号替换。
\documentclass[border=3.14]{standalone}
\newcounter{col}
\makeatletter
\newcommand\colloop@add[2]
{%
\expandafter\g@addto@macro\expandafter\colloop@\expandafter
{\colloop@@{#1}}%
\ifnum#2>\value{col}
\g@addto@macro\colloop@{&}%
\fi
}
\newcommand\colloop[2]
{%
\noalign
{%
\setcounter{col}{0}%
\gdef\colloop@{}%
\gdef\colloop@@##1{#2}%
\loop\ifnum#1>\value{col}
\stepcounter{col}%
\expandafter\colloop@add\expandafter{\the\value{col}}{#1}%
\repeat
}%
\colloop@
}
\makeatletter
\begin{document}
\begin{tabular}[]{llll}
\colloop{4}{column #1} \\
\colloop{4}{\multicolumn{1}{c}{c#1}} \\
\colloop{4}{\multicolumn{1}{r}{col#1}} \\
\end{tabular}
\end{document}
编辑:另一种方法分为可扩展部分和不可扩展部分。使用\Setupexpcolloop
和,\setupexpcolloop
您可以定义\expcolloop
应扩展为的内容(再次使用#1
当前列)。两个定义宏之间的区别在于,可以\setupexpcolloop
在任何地方使用,而\Setupexpcolloop
只能在行的开头使用。但是如果您使用,则\setupexpcolloop
不能\multicolumn
在同一个单元格中使用或类似(因此请在表格环境之外使用它,或者在已经填充内容的单元格末尾使用它)。这种方法的优点是,您不必循环遍历整行或仅循环前 n 列。
\documentclass[border=3.14]{standalone}
\makeatletter
\long\def\myfi@b\fi#1#2{\fi#2}
\newcommand\setupexpcolloop[1]
{%
\gdef\expcolloop@##1{#1}%
}
\newcommand\Setupexpcolloop[1]
{%
\noalign{\setupexpcolloop{#1}}%
}
\newcommand\expcolloop[2]
{%
\expcolloop@{#1}%
\ifnum#1<#2
\myfi@b
\fi
\@gobble
{&\expandafter\expcolloop\expandafter{\the\numexpr#1+1\relax}{#2}}%
}
\makeatletter
\begin{document}
\begin{tabular}[]{|l|l|l|l|l|l|}
\Setupexpcolloop{column #1}
\expcolloop{1}{6} \\
\Setupexpcolloop{\multicolumn{1}{c|}{c#1}}
col1 & \expcolloop{2}{6} \\
\Setupexpcolloop
{%
\ifnum#1=1
\multicolumn{1}{|c|}{hihi1}%
\else
\multicolumn{#1}{c|}{hihi#1}%
\fi
}%
\expcolloop{1}{3} \\
\Setupexpcolloop{c#1}
\expcolloop{1}{2}\setupexpcolloop{Cc#1} & \expcolloop{3}{6} \\
\end{tabular}
\end{document}
免责声明:我不赞同在表格中使用垂直规则,这只是为了展示\multicolumn
用法的效果。
正因为有可能,这里还有另一种完全可扩展且不需要拆分的变体。这利用了expkv-cs
可扩展地解析 key=value 列表,以及可etl
扩展地替换标记(这里我们使用#
插入列号;如果您#
出于任何原因需要在循环列中使用,则可以使用另一个带有token
或t
键的单个标记)。
\documentclass[border=3.14]{standalone}
\usepackage{etl}
\usepackage{expkv-cs}
\ExplSyntaxOn
\NewExpandableDocumentCommand \colloop { O{} m m }
{
\exp_args:Ne \exp_not:o
{
\exp_not:N \use_none:n
\__emoro_colloop:nnn {#1} {#2} { & #3 }
}
}
\ekvcSplitAndForward \__emoro_colloop:nnn \__emoro_colloop:nnNnn % define keys
{
long ~ start = 1
,long ~ step = 1
,long ~ token = #
}
\ekvcSecondaryKeys \__emoro_colloop:nnn % define shortcut names for keys
{
alias ~ s = step
,alias ~ t = token
}
\NewDocumentCommand \colloopsetup { m }
{ \ekvcChange \__emoro_colloop:nnn {#1} }
\makeatletter
\cs_if_exist:NF \ekvletunknownNoVal
{
\cs_new_protected:Npn \ekvletunknownNoVal #1
{\expandafter\let\csname\ekv@name{#1}{}uN\endcsname}
}
\exp_args:Nnc \ekvletunknownNoVal
{ \token_to_str:N \__emoro_colloop:nnn }
{ \ekv@name { \token_to_str:N \__emoro_colloop:nnn } { start } }
\makeatother
\cs_new:Npn \__emoro_colloop:nnNnn #1#2#3#4#5
{
\emoro_int_step_tokens:nnnn {#1} {#2} {#4}
{ \etl_token_replace_all_deep:nNn {#5} #3 }
}
\msg_new:nnn { emoro } { zero-step } { Zero~ step~ size }
\cs_new:Npn \emoro_int_step_tokens:nnnn #1#2#3#4
{
\int_compare:nNnTF {#2} > \c_zero_int
{ \__emoro_int_step_tokens:Nfffn > }
{
\int_compare:nNnTF {#2} = \c_zero_int
{ \msg_expandable_error:nn { emoro } { zero-step } \prg_break: }
{ \__emoro_int_step_tokens:Nfffn < }
}
{ \int_eval:n {#1} }
{ \int_eval:n {#2} }
{ \int_eval:n {#3} }
{#4}
\prg_break_point:
}
\cs_new:Npn \__emoro_int_step_tokens:Nnnnn #1#2#3#4#5
{
\if_int_compare:w #2 #1 #4 \exp_stop_f: \prg_break:n \fi:
\use:n {#5} {#2}
\exp_args:NNf \__emoro_int_step_tokens:Nnnnn #1
{ \int_eval:n { #2 + #3 } }
{#3}
{#4}
{#5}
}
\cs_generate_variant:Nn \__emoro_int_step_tokens:Nnnnn { Nfff }
\ExplSyntaxOff
\begin{document}
\begin{tabular}{lllll}
\colloop{5}{column #} \\
\colloop[11]{15}{\multicolumn{1}{c}{c#}} \\
\colloop[s=2]{5}
{%
\ifnum#=1
\multicolumn{1}{r}{hihi1}%
\else
\multicolumn{2}{r}{hihi#}%
\fi
} \\
\colloop[5,s=-1]{1}{and #}
\end{tabular}
\end{document}