循环将内容输入表格中

循环将内容输入表格中

tabular我正在尝试使用循环将代表表行的文件输入到环境中,但在使用时遇到了麻烦input

这是我的代码的 MWE,没有使用循环。我有一些包含表格行的文件,我可以使用数字循环这些行,并且我\tables使用存储这些表格的文件夹的路径定义命令。我使用csnamewith来避免不可扩展的input问题(当我以正常方式输入表格后立即添加时会导致一些问题)。input\midrule

\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs} 
\newcommand{\tables}{Folder} %Path for tables

\begin{document}

\begin{tabular}{cc}
\toprule
\csname @@input\endcsname "\tables/r_1.tex"
\midrule
\csname @@input\endcsname "\tables/r_2.tex"
\bottomrule
\end{tabular}

\end{document}

我曾尝试使用 和 来实现这一点pgfforforloop但都无济于事。以下是我尝试使用 实现的效果pgffor

\begin{tabular}{cc}
\midrule
\foreach \x in {1,...,2}{
    \csname @@input\endcsname "\tables/r_\x.tex"
    \midrule
}
\end{tabular}

上一个表无法编译。我尝试了一个更简单的版本,其中有常规的input和,但没有使用booktabs,但它也不起作用,即使代码在循环之外运行良好。

\begin{tabular}{cc}
\foreach \x in {1,...,2}{
    \input{\tables/r_\x.tex}
}
\end{tabular}

有什么想法我可以做些什么来解决这个问题?

答案1

每个表格单元格本身都是一个范围。

并且每次迭代\foreach都会打开其自己的本地范围。(pgfmanual.pdf,“88 重复的事情:Foreach 语句”部分说:“请注意,在每次执行 ⟨commands⟩ 时,⟨commands⟩ 都会放入一个 TeX 组中。”)

因此,表格单元格的作用域和迭代的作用域\foreach会产生严重干扰:

\begin{tabular}{cc}
\midrule
\foreach \x in {1,...,2}{
    \csname @@input\endcsname "\tables/r_\x.tex"
    \midrule
}
\end{tabular}

就好像

\begin{tabular}{cc}
% Begin of scope of 1st table cell in 1st row
% Begin of scope of 1st foreach-iteration
A 
% End of scope of 1st table cell  in 1st row
& 
[...]

您可以看到,例如,已找到第一行第一个表格单元格的范围结束,但第一个 foreach 迭代的范围尚未关闭。

您可以使用\foreach-loop 来收集令牌寄存器中的内容:

\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs, pgffor} 
\newcommand{\tables}{Folder} %Path for tables
\newtoks\scratchtoks
\newcommand\globaladdtoscratchtoks[1]{%
  \global\scratchtoks=\expandafter{\the\scratchtoks#1}%
}%

\begin{document}

\global\scratchtoks={}
\foreach \x in {1,...,2}{
  \ifnum\x=1 \globaladdtoscratchtoks{\toprule}\fi
  \expandafter\globaladdtoscratchtoks\expandafter{%
    \csname @@input%
    \expandafter \expandafter 
    \expandafter              \endcsname
    \expandafter \expandafter
    \expandafter "%
    \expandafter \tables
    \expandafter /%
    \expandafter r%
    \expandafter_%
    \x.tex"%
  }%
  \ifnum\x=2 %
    \globaladdtoscratchtoks{\bottomrule}%
  \else
    \globaladdtoscratchtoks{\midrule}%
  \fi
}%
%\showthe\scratchtoks

\begin{tabular}{cc}\the\scratchtoks\end{tabular}

\end{document}

如果您不愿意坚持使用 pgf \foreach,而是定义自己的尾部递归循环(例如使用)\numexpr,您可以执行以下操作:

\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs} 
\newcommand{\tables}{Folder} %Path for tables


\newcommand\inputloop[2]{%
  \csname @\ifnum\numexpr(#1)\relax>\numexpr(#2)\relax 
  gobble\else firstofone\fi\endcsname{%
    \csname @@input\endcsname "\tables/r_\the\numexpr(#1)\relax.tex"
    \ifnum\numexpr(#1)\relax<\numexpr(#2)\relax \midrule \fi
    \expandafter\inputloop\expandafter{\the\numexpr((#1)+1)\relax}{#2}%
  }%
}%

\begin{document}

\begin{tabular}{cc}
\toprule
\inputloop{1}{2}%
\bottomrule
\end{tabular}

\end{document}

\inputloop如果愿意,您可以按如下方式更改参数模式:

\inputloop{⟨lower bound for number-components of filenames⟩}
          {⟨upper bound for number-components of filenames⟩}
          {⟨file-path and/or filename-component at the left of the filename's number-component⟩}
          {⟨filename-component at the right of the filename's number-component⟩}
          {⟨tokens between \input-commands⟩}%
\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs} 
\newcommand{\tables}{Folder} %Path for tables


\newcommand\inputloop[5]{%
  \csname @\ifnum\numexpr(#1)\relax>\numexpr(#2)\relax 
  gobble\else firstofone\fi\endcsname{%
    \csname @@input\endcsname "#3\the\numexpr(#1)\relax#4"
    \csname @\ifnum\numexpr(#1)\relax<\numexpr(#2)\relax
    firstofone\else gobble\fi\endcsname{#5}%
    \expandafter\inputloop\expandafter{\the\numexpr((#1)+1)\relax}{#2}{#3}{#4}{#5}%
  }%
}%


\begin{document}

\begin{tabular}{cc}
\toprule
\inputloop{1}{2}{\tables/r_}{.tex}{\midrule}%
\bottomrule
\end{tabular}

\end{document}

答案2

这里我使用 的方法readarray。请注意,为了方便起见,我更改了文件名以仅保留在工作目录中。

在这里,我展示如何循环遍历由

% LIST OF FILE IDENTIFIERS
\def\filelist{1,2,X}

在这种情况下,由于文件中已经包含表格格式,我只需要将文件内容读入\def.

以下是 MWE:

\begin{filecontents*}[overwrite]{r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{r_X.tex}
\today & ZZ \\
P & Q \\
\end{filecontents*}

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, readarray,listofitems} 
\newtoks\mytoks
\newcommand\addtotoks[1]{\global\mytoks\expandafter{\the\mytoks#1}}
\newcommand\xaddtotoks[1]{\expandafter\addtotoks\expandafter{#1}}
\readarraysepchar{}
\newcommand{\tables}{Folder} %Path for tables

% LIST OF FILE IDENTIFIERS
\def\filelist{1,2,X}
% READ FILE CONTENTS INTO VARIABLES NAMED \r_<identifier>
\readlist\myfiles{\filelist}
\foreachitem\z\in\myfiles[]{%
  \def\tmp{\readdef{r_\z.tex}}
  \expandafter\tmp\expandafter{\csname r_\z\endcsname}
}
\begin{document}
\begin{tabular}{cc}
\toprule
% ACCUMULATE TYPESET ARRAY TOKENS
\foreachitem\z\in\myfiles[]{%
  \ifnum\zcnt=1\else\addtotoks{\midrule}\fi
  \xaddtotoks{\csname r_\z\endcsname}%
}%
% SET THE TOKENS IN THE TABULAR
\the\mytoks
\bottomrule
\end{tabular}

\end{document}

在此处输入图片描述

如果希望避免将&\\格式置于数据文件本身中,readarray也可以处理这种情况。但是,在这种情况下,必须将文件信息读入二维数组,以便通过适当重新定义\typesetrowsepchar和在单元格之间添加表格格式\typesetcolsepchar

\begin{filecontents*}[overwrite]{r_1.tex}
A, B
C, D
\end{filecontents*}
\begin{filecontents*}[overwrite]{r_2.tex}
1, 2
3, 4
\end{filecontents*}
\begin{filecontents*}[overwrite]{r_X.tex}
\today, ZZ
P, Q
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs, readarray,listofitems} 
\newtoks\mytoks
\newcommand\addtotoks[1]{\global\mytoks\expandafter{\the\mytoks#1}}
\newcommand\xaddtotoks[1]{\expandafter\addtotoks\expandafter{#1}}
\readarraysepchar{,}
\renewcommand\typesetrowsepchar{\\}
\renewcommand\typesetcolsepchar{&}
\newcommand{\tables}{Folder} %Path for tables

% LIST OF FILE IDENTIFIERS
\def\filelist{1,2,X}
% READ FILE CONTENTS INTO ARRAYS NAMED 
%   \myarray_<identifier>[<row>,<column>]
\readlist\myfiles{\filelist}
\foreachitem\z\in\myfiles[]{%
  \def\tmp{\readdef{r_\z.tex}}
  \expandafter\tmp\expandafter{\csname r_\z\endcsname}
  \expandafter\readarray\csname r_\z\expandafter\endcsname
    \csname myarray\z\endcsname[-,\ncols]
}
\begin{document}
\begin{tabular}{cc}
\toprule
% ACCUMULATE TYPESET ARRAY TOKENS
\foreachitem\z\in\myfiles[]{%
  \ifnum\zcnt=1\else\addtotoks{\\\midrule}\fi
  \addtotoks{\expandafter\typesetarray\csname myarray}%
  \xaddtotoks{\z\endcsname}%
}%
% SET THE TOKENS IN THE TABULAR
\the\mytoks\\
\bottomrule
\end{tabular}

\end{document}

答案3

使用 OpTeX 时没有问题,因为OpTeX 独立于 TeX 组运行并且它们是可扩展的\fornum\foreach

\createfile {r_1.tex}
A & B \cr
C & D \cr
\endfile

\createfile {r_2.tex}
1 & 2 \cr
3 & 4 \cr
\endfile


\def\toprule{\crcr\noalign{\hrule height1pt}}
\let\bottomrule=\toprule
\def\midrule{\crcr\noalign{\hrule}}

\table{cc}{
   \toprule
   \fornum 1..2 \do{\input r_#1 \ifnum#1<2 \midrule \else \bottomrule \fi}
}
\bye

答案4

将文件加载到变量中,将它们放在一起并立即传送,并\midrule在它们之间进行。

文件加载已经完成,\file_get:nnNTF因此我们也可以防止文件丢失。

\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs} 

\ExplSyntaxOn

\NewDocumentCommand{\maketablefromfiles}{O{.}m}
 {% #1 = optional path, #2 = list of file names
  \suarez_maketable:nn { #1 } { #2 }
 }

\seq_new:N \l__suarez_maketable_body_seq
\tl_new:N \l__suarez_maketable_tmp_tl

\cs_new_protected:Nn \suarez_maketable:nn
 {
  \seq_clear:N \l__suarez_maketable_body_seq
  \clist_map_inline:nn { #2 }
   {
    \file_get:nnNTF { #1/##1 } {} \l__suarez_maketable_tmp_tl
     {% file exists
      \seq_put_right:NV \l__suarez_maketable_body_seq \l__suarez_maketable_tmp_tl
     }
     {% file doesn't exist
      \msg_error:nnn { suarez/maketable } { file-not-exist } { ##1 }
      \seq_put_right:Nn \l__suarez_maketable_body_seq { \\ }
     }
   }
  \seq_use:Nn \l__suarez_maketable_body_seq { \midrule }
 }

\msg_new:nnnn { suarez/maketable } { file-not-exist }
 {
  Non~existing~file~#1
 }
 {
  The~file~you~requested~doesn't~exist.~Added~\tl_to_str:n { \\ }~to~avoid~errors
 }

\ExplSyntaxOff

\newcommand{\tables}{Folder}

\begin{document}

% with the explicit path
\begin{tabular}{cc}
\toprule
\maketablefromfiles[Folder]{r_1,r_2}
\bottomrule
\end{tabular}

\bigskip

% with the macro for the path; also error shown
\begin{tabular}{cc}
\toprule
\maketablefromfiles[\tables]{r_1,r_2,r_3}
\bottomrule
\end{tabular}

\end{document}

第二个示例显示您可以在“path”参数中使用宏。我还展示了如果您请求不存在的文件会发生什么。当然,如果您r_3在第二个参数中删除,则输出与第一个示例相同。

在此处输入图片描述

控制台上显示的错误:

! Package suarez/maketable Error: Non existing file r_3

For immediate help type H <return>.
 ...

l.66 \maketablefromfiles[\tables]{r_1,r_2,r_3}

? h

The file you requested doesn't exist. Added \\ to avoid errors

?

略有不同的版本,其中各部分之间的分离是可选的(默认\midrule)。

\begin{filecontents*}[overwrite]{Folder/r_1.tex}
A & B \\
C & D \\
\end{filecontents*}
\begin{filecontents*}[overwrite]{Folder/r_2.tex}
1 & 2 \\
3 & 4 \\
\end{filecontents*}

\documentclass{article}
\usepackage{booktabs} 

\ExplSyntaxOn

\NewDocumentCommand{\maketablefromfiles}{O{.}mO{\midrule}}
 {% #1 = optional path, #2 = list of file names, #3 = optional separator
  \suarez_maketable:nnn { #1 } { #2 } { #3 }
 }

\seq_new:N \l__suarez_maketable_body_seq
\tl_new:N \l__suarez_maketable_tmp_tl

\cs_new_protected:Nn \suarez_maketable:nnn
 {
  \seq_clear:N \l__suarez_maketable_body_seq
  \clist_map_inline:nn { #2 }
   {
    \file_get:nnNTF { #1/##1 } {} \l__suarez_maketable_tmp_tl
     {% file exists
      \seq_put_right:NV \l__suarez_maketable_body_seq \l__suarez_maketable_tmp_tl
     }
     {% file doesn't exist
      \msg_error:nnn { suarez/maketable } { file-not-exist } { ##1 }
      \seq_put_right:Nn \l__suarez_maketable_body_seq { \\ }
     }
   }
  \seq_use:Nn \l__suarez_maketable_body_seq { #3 }
 }

\msg_new:nnnn { suarez/maketable } { file-not-exist }
 {
  Non~existing~file~#1
 }
 {
  The~file~you~requested~doesn't~exist.~Added~\tl_to_str:n { \\ }~to~avoid~errors
 }

\ExplSyntaxOff

\newcommand{\tables}{Folder}

\begin{document}

% with the explicit path
\begin{tabular}{cc}
\toprule
\maketablefromfiles[Folder]{r_1,r_2}
\bottomrule
\end{tabular}

\bigskip

% with the macro for the path
\begin{tabular}{cc}
\toprule
\maketablefromfiles[\tables]{r_1,r_2}[\addlinespace]
\bottomrule
\end{tabular}

\end{document}

在此处输入图片描述

相关内容