表格环境中的列上的循环

表格环境中的列上的循环

在环境中使用循环的正确方法是什么tabular

我的问题背景是使用datatool包生成表格。我需要以下功能:

  1. 在每一行中,我想使用循环生成单元格
  2. 在每个单元格内,我应该能够:
    • 能够使用\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扩展地替换标记(这里我们使用#插入列号;如果您#出于任何原因需要在循环列中使用,则可以使用另一个带有tokent键的单个标记)。

\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}

相关内容