使用 \multido 自动生成表格

使用 \multido 自动生成表格

首先:这个问题类似于使用 \multido (或类似方法)生成表中的行

考虑以下代码:

\documentclass{article}

\usepackage{siunitx}
\usepackage{multido}
\usepackage{booktabs}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\newcommand*\nederst[1]{\calc{#1*(#1+1)/2}}
\newcommand*\iAlt[1]{\calc{#1*(#1+1)*(#1+2)/6}}

\begin{document}

\makeatletter
  \newcommand*\skyIDtable{}
  \multido{\i = 1+1}{6}{%
    \protected@xdef\skyIDtable{\skyIDtable \i & \i & \i & \nederst{\i} & \iAlt{\i}\\}
  }
\makeatother

\begin{table}
\centering
  \begin{tabular}{
    *{3}{S[table-format = 1]}
    *{2}{S[table-format = 2]}
  }
   \toprule
    {Long text~A} & {Long text~B} & {Long text~C} & {Long text~D} & {Long text~E} \\
   \midrule
    \skyIDtable
   \bottomrule
  \end{tabular}
\end{table}

\end{document}

输出

我想交换列和行以获得以下内容:

通缉

我怎么做?

答案1

代码更复杂,但语法更简单:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[danish]{babel}

\usepackage{xparse,siunitx,booktabs}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\nederst}{m}
 {
  \fp_eval:n { #1 * (#1+1)/2 }
 }
\DeclareExpandableDocumentCommand{\iAlt}{m}
 {
  \fp_eval:n { #1 * ( #1 + 1 ) * ( #1 + 2 ) / 6 }
 }

\NewDocumentCommand{\printtable}{smmmm}
 {% * = transpose
  % #2 = number of iterations
  % #3 = column/row headers
  % #4 = table preamble
  % #5 = entry specs
  \svend_preparetable:nnn { #2 } { #3 } { #5 }
  \IfBooleanTF{#1}
   { \__svend_make_table_rows:nn { #3 } { #4 } }
   { \__svend_make_table_columns:nn { #3 } { #4 } }
 }

\tl_new:N \l_svend_tablebody_tl
\prop_new:N \l_svend_entries_prop
\int_new:N \l_svend_rows_int
\int_new:N \l_svend_columns_int

\cs_new:Npn \svend_prop_item:Nnn #1 #2 #3
 {
  \prop_item:Nn #1 { #2, #3 }
 }
\cs_generate_variant:Nn \svend_prop_item:Nnn { Nnf , Nfn }

\cs_new_protected:Npn \svend_preparetable:nnn #1 #2 #3
 {% #1=iterations; #2=column/row headers; #3=specs
  \int_set:Nn \l_svend_columns_int { \clist_count:n { #2 } }
  \int_set:Nn \l_svend_rows_int { #1 }
  \prop_clear:N \l_svend_entries_prop
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
   {
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
     {
      \prop_put:Nnf \l_svend_entries_prop { ##1,####1 }
       {
        \clist_item:nn { #3 } { ####1 }
       }
     }
   }
 }

\cs_generate_variant:Nn \prop_put:Nnn { Nnf }

\cs_new_protected:Npn \__svend_make_table_columns:nn #1 #2
 {
  % start making the table body
  \tl_set:Nn \l_svend_tablebody_tl
   {
    \begin{tabular}{ #2 }\toprule
   }

  % the header row
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
   {
    \tl_put_right:Nx \l_svend_tablebody_tl
     {
      \int_compare:nF { ##1 == 1 } { & }
      { \clist_item:nn { #1 } { ##1 } }
     }
   }
  \tl_put_right:Nn \l_svend_tablebody_tl { \\ \midrule } % finish the row

  % the table body proper
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
   {
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
     {
      \tl_put_right:Nx \l_svend_tablebody_tl
       {
        \int_compare:nF { ####1 == 1 } { & }
        \svend_prop_item:Nnn \l_svend_entries_prop { ##1 } { ####1 }
       }
     }
    \tl_put_right:Nn \l_svend_tablebody_tl { \\ }
   }

  % finish up the table body
  \tl_put_right:Nn \l_svend_tablebody_tl { \bottomrule \end{tabular} }

  % produce the table
  \tl_use:N \l_svend_tablebody_tl
 }

\cs_new_protected:Npn \__svend_make_table_rows:nn #1 #2
 {
  % start building the table body
  \tl_set:Nn \l_svend_tablebody_tl
   {
    \begin{tabular}{ #2 }\toprule
   }

  % the table body proper
  \int_step_inline:nnnn { 1 } { 1 } { \l_svend_columns_int }
   {
    \tl_put_right:Nx \l_svend_tablebody_tl
     {
      \clist_item:nn { #1 } { ##1 } &
     }
    \int_step_inline:nnnn { 1 } { 1 } { \l_svend_rows_int }
     {
      \tl_put_right:Nx \l_svend_tablebody_tl
       {
        \int_compare:nF { ####1 == 1 } { & }
        \svend_prop_item:Nnn \l_svend_entries_prop { ####1 } { ##1 }
       }
     }
    \tl_put_right:Nn \l_svend_tablebody_tl { \\ }
   }
  % finish up the table body
  \tl_put_right:Nn \l_svend_tablebody_tl { \bottomrule \end{tabular} }

  % produce the table
  \tl_use:N \l_svend_tablebody_tl
 }

\cs_generate_variant:Nn \prop_item:Nn { Nx }

\ExplSyntaxOff

\begin{document}

\printtable
 {6}
 { Long text A, Long text B, Long text C, Long text D, Long text E }
 { *{3}{S[table-format = 1]} *{2}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable*
 {6}
 { Opstillingsnummer, Antal lag, Antal bægre i bundes side,
   Antal bægre i nederste lag, Antal bægre i optillingen }
 { l *{6}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable
 {7}
 { Long text A, Long text B, Long text C, Long text D, Long text E }
 { *{3}{S[table-format = 1]} *{2}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\bigskip

\printtable*
 {7}
 { Opstillingsnummer, Antal lag, Antal bægre i bundes side,
   Antal bægre i nederste lag, Antal bægre i optillingen }
 { l *{7}{S[table-format = 2]} }
 { #1,#1,#1,\nederst{#1},\iAlt{#1} }

\end{document}

在此处输入图片描述

表条目经过计算并存储在属性列表中,由 索引row,column

然后按列(无*)或按行打印表,从属性列表中收集适当的索引。

第一个参数是迭代次数,第二个参数是列或行标题的逗号分隔列表(用于确定列/行的数量),第三个参数是表格前言;最后是说明符,其中#1用于当前整数。

答案2

我展示了普通的 TeX 类解决方案,但它在 LaTeX 中也有效,因为只\newcount使用了 eTeX 基元和宏。我们不需要任何 LaTeX 包。

\def\nederst#1{\the\numexpr #1*(#1+1)/2 \relax}
\def\iAlt#1{\the\numexpr #1*(#1+1)*(#1+2)/6 \relax}

\newcount\i \i=1
\def\skyIDtable{
   \the\i & \the\i & \the\i & \hbox to1em{\hss\nederst\i} & \hbox to1em{\hss\iAlt\i}
   \global\advance\i by 1
   \ifnum\i<7 \global\let\next=\skyIDtable \else \global\let\next=\empty \global\i=1 \fi
   \cr \next
}
\def\trline#1{#11 & #12 & #13 & #14 & #15 & #16 \cr}
\def\skyIDtableT{
   Opstillingsnummer            & \trline\relax  
   Antal lag                    & \trline\relax  
   Antal bægre i bundes side    & \trline\relax  
   Antal bægre i nederste lag   & \trline\nederst
   Antal bægre i optillingen    & \trline\iAlt
}

\def\toprule{\noalign{\smallskip\hrule height1pt\smallskip}}\let\botrule=\toprule
\def\midrule{\noalign{\smallskip\hrule\smallskip}}

Normal table:

\hfil\vbox{\halign{&\enspace\hfil#\unskip\hfil\enspace \cr
   \toprule
   Long text A & Long text B & Long text C & Long text D & Long text E \cr
   \midrule   
   \skyIDtable
   \botrule
}}

Transposed table:

\hfil\vbox{\halign{\enspace #\unskip\enspace\hfil&&\enspace\hfil#\unskip\enspace\cr
   \toprule
   \skyIDtableT
   \botrule
}}

\bye

答案3

转置并不那么简单。你必须逐行循环:

在此处输入图片描述

\documentclass{article}

\usepackage{siunitx,multido,booktabs}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\newcommand*\nederst[1]{\calc{#1*(#1+1)/2}}
\newcommand*\iAlt[1]{\calc{#1*(#1+1)*(#1+2)/6}}

\begin{document}

\centering

\makeatletter
\newcommand\skyIDtable{}
\multido{\i=1+1}{6}{% Construct 6 rows
  \protected@xdef\skyIDtable{\skyIDtable \i & \i & \i & \nederst{\i} & \iAlt{\i}\protect\\}%
}
\makeatother

\begin{tabular}{
  *{3}{S[table-format = 1]}
  *{2}{S[table-format = 2]}
}
 \toprule
 {Long text~A} & {Long text~B} & {Long text~C} & {Long text~D} & {Long text~E} \\
 \midrule
 \skyIDtable
 \bottomrule
\end{tabular}

\bigskip

% Transposed table

\makeatletter
\newcommand\skyIDtableT{Long text A}% First column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add first row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text B}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add second row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text C}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \i}}% Add third row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text D}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \nederst{\i}}}% Add fourth row entries
\g@addto@macro{\skyIDtableT}{\protect\\ Long text E}% Add another first column ID
\multido{\i = 1+1}{6}{\protected@xdef\skyIDtableT{\skyIDtableT & \iAlt{\i}}}% Add fifth row entries
\makeatother

\begin{tabular}{
  l
  *{6}{S[table-format = 2]}
}
 \toprule
 \skyIDtableT \\% Insert constructed table
 \bottomrule
\end{tabular}

\end{document}

相关内容