在电子表格中输入多个 \input 时超出 TeX 容量

在电子表格中输入多个 \input 时超出 TeX 容量

我使用\input几个spreadtab来自这个答案在我的文档中直到我收到此错误:

TeX capacity exceeded, sorry [text input levels=15].

我在网上看到,我可以通过将这个参数从 更改为 来解决这个max_in_open = 15问题max_in_open = 30

问题是我不知道在哪里可以找到进行更改的数据。我在 Mac 上使用 TeXStudio。

我正在寻找可以使我的文档正常工作的设置。

\documentclass{article}
\usepackage[a4paper,left=2.5cm,right=2.5cm,bottom=2.8cm,top=2.8cm]{geometry} 
\usepackage{longtable,tabu}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{datetime}
\usepackage{siunitx}
\usepackage{multirow}
\usepackage[sc]{mathpazo}
\usepackage{datatool}
\usepackage{spreadtab,booktabs,xpatch}
\usepackage[]{numprint}
\usepackage[]{eurosym}
\usepackage{fp}
\usepackage{booktabs}
\usepackage{tabularx,siunitx}
\usepackage{numprint}
}%=========================



\makeatletter
\def\spreadtab@ii{\IfSubStr\ST@tab{\noexpand\input}{\expandafter\spreadtab@iii\ST@tab\@nil}\relax}
\def\spreadtab@iii#1\input#2#3\@nil{%
    \long\def\spreadtab@iv##1\spreadtab@iv{\endgroup\def\ST@tab{#1##1#3}\spreadtab@ii}%
    \begingroup
    \everyeof{\spreadtab@iv\noexpand}%
    \expandafter\spreadtab@iv\@@input#2
}
\xpretocmd\spreadtab@i\spreadtab@ii{}{}
\makeatother    

\subsection*{B}
    \begin{spreadtab}{{tabular}{@{\hskip1pt}r@{\hskip7pt}p{2.7cm}crrr}}
    \toprule
    &@ Ku& @ Re & @ Ne & @ Me & @ Br \\
        \midrule
        \input{Bu1.txt}
        \input{Bu2.txt}
        \input{Bu3.txt}
        \input{Bu4.txt}
        \input{Bu5.txt}
        \input{Bu6.txt}
        \input{Bu7.txt}
        \input{Bu8.txt}
        \input{Bu9.txt}
        \input{Bu10.txt}
        \input{Bu11.txt}
        \input{Bu12.txt}
        \input{Bu13.txt}
        \input{Bu14.txt}
        \input{Bu15.txt}
        \midrule
        &@ To & @\thefo &(sum(d2:[0,-1]))tag(BN) & sum(e2:[0,-1])tag(BM)& sum(f2:[0,-1])tag(BB)\\
        \bottomrule
    \end{spreadtab}

样本内容Bu1.txt

@\thefoo&@BU1& @513& 270.00& 551.30& 3231.30\\

其余的*.txt看上去也类似。

答案1

正如 David 在评论中指出的那样,代码\everyeof{\spreadtab@iv\noexpand} \expandafter\spreadtab@iv\@@input#2导致每个代码在完成之前\input都启动另一个代码\input,就 TeX 而言,这有效地嵌套了输入。

我真的不知道spreadtab,所以我没有一个好的解决方案。相反,这是一个非常非常非常非常非常非常非常,非常非常使文档正常工作的糟糕方法。新spreadtabwithinput环境将用 的内容替换\input{<file>}其主体中的每个命令<file>,然后将所有内容传回spreadtab。您可以\input在其中放置任意多个命令。

继续需要您自担风险。

% \newwrite\wrt
% \def\x#1;{\immediate\openout\wrt"Bu#1.txt"
%   \immediate\write\wrt{@\noexpand\thefoo
%     &@BU#1& @513& 270.00& 551.30& 3231.30\noexpand\\}%
%   \immediate\closeout\wrt
%   \ifnum#1<15 \expandafter\x\number\numexpr#1+1\expandafter;\fi}\x1;

\documentclass{article}
\usepackage{spreadtab,booktabs}

% HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK %
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__ihpro_spreadtab_hack_tl
\tl_new:N \l__ihpro_tmpa_tl
\NewDocumentEnvironment { spreadtabwithinput } { +b }
  {
    \tl_clear:N \l__ihpro_spreadtab_hack_tl
    \__ihpro_spreadtab_loop:w \prg_do_nothing: #1
      \input \q_recursion_tail \q_recursion_stop
    \exp_last_unbraced:Nno
    \begin{spreadtab}
      \l__ihpro_spreadtab_hack_tl
    \end{spreadtab}
  } { }
\cs_new_protected:Npn \__ihpro_spreadtab_loop:w #1 \input #2
  {
    \tl_put_right:No \l__ihpro_spreadtab_hack_tl {#1}
    \quark_if_recursion_tail_stop:n {#2}
    \file_get:nnNF {#2} { } \l__ihpro_tmpa_tl
      {
        \msg_error:nnn { ihpro } { file-not-found } {#2}
        \tl_clear:N \l__ihpro_tmpa_tl
      }
    \exp_last_unbraced:NNo
    \__ihpro_spreadtab_loop:w \prg_do_nothing: \l__ihpro_tmpa_tl
  }
\msg_new:nnn { ihpro } { file-not-found } { File~'#1'~not~found. }
\ExplSyntaxOff
% HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK % HACK %

\newcounter{foo}

\begin{document}
\subsection*{B}
    \begin{spreadtabwithinput}{{tabular}{@{\hskip1pt}r@{\hskip7pt}p{2.7cm}crrr}}
    \toprule
    &@ Ku& @ Re & @ Ne & @ Me & @ Br \\
        \midrule
        \input{Bu1.txt}
        \input{Bu2.txt}
        \input{Bu3.txt}
        \input{Bu4.txt}
        \input{Bu5.txt}
        \input{Bu6.txt}
        \input{Bu7.txt}
        \input{Bu8.txt}
        \input{Bu9.txt}
        \input{Bu10.txt}
        \input{Bu11.txt}
        \input{Bu12.txt}
        \input{Bu13.txt}
        \input{Bu14.txt}
        \input{Bu15.txt}
        \midrule
        &@ To & @\thefoo &(sum(d2:[0,-1]))tag(BN) & sum(e2:[0,-1])tag(BM)& sum(f2:[0,-1])tag(BB)\\
        \bottomrule
    \end{spreadtabwithinput}
\end{document}

答案2

Heiko Oberdiek 即兴创作的包装捕获文件我想到的是。

您可以使用此包的宏从文件内容中定义宏。

我可以提供例行

\CatchFilesForScantokens{⟨comma-separated file list⟩}{⟨preamble code⟩}{⟨postamble code⟩}

它读取并收集⟨前导码⟩以及每个文件的内容⟨逗号分隔的文件列表⟩⟨邮寄代码⟩在 verbatim-catcode-regime 中,然后将收集/积累的东西传递到,以便\scantokens在逐字材料被重新标记时正常的 catcode-régime 生效。

您可以使用此例程作为

\CatchFilesForScantokens{⟨comma-separated file list⟩}%
                        {⟨stuff for initiating spreadtab-environment}%
                        {⟨stuff for ending the spreadtab-environment⟩}

(每个文件内部都有⟨逗号分隔的文件列表⟩该例程使用\CatchFileDef包的宏捕获文件用于从该文件的内容中(重新)定义临时宏 A,以 verbatim-catcode/category-12-régime 进行标记,然后将该临时宏 A 的扩展附加到另一个临时宏 B 的定义中。⟨前导码⟩⟨邮寄代码⟩也转到另一个临时宏 B。因此,所有内容都累积在另一个临时宏 B 中,其扩展可以\scantokens在正常的 catcode 制度下传递到该临时宏 B 进行重新标记。

我很懒,所以我使用 expl3 的函数\clist_map_inline:nn来解析⟨逗号分隔的文件列表⟩

以下是示例:

% Create  15 MyBu<X>.txt-files
% ==========================
\begin{filecontents*}{MyBu1.txt}
[0,-1]+1&@BU1& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu2.txt}
[0,-1]+1&@BU2& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu3.txt}
[0,-1]+1&@BU3& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu4.txt}
[0,-1]+1&@BU4& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu5.txt}
[0,-1]+1&@BU5& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu6.txt}
[0,-1]+1&@BU6& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu7.txt}
[0,-1]+1&@BU7& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu8.txt}
[0,-1]+1&@BU8& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu9.txt}
[0,-1]+1&@BU9& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu10.txt}
[0,-1]+1&@BU10& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu11.txt}
[0,-1]+1&@BU11& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu12.txt}
[0,-1]+1&@BU12& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu13.txt}
[0,-1]+1&@BU13& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu14.txt}
[0,-1]+1&@BU14& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}
\begin{filecontents*}{MyBu15.txt}
[0,-1]+1&@BU15& @513& 270.00& 551.30& 3231.30\\
\end{filecontents*}


% ==========================================================================================
% Define macro 
%
%   \CatchFilesForScantokens{<comma-separated file list>}{<preamble code>}{<postamble code>}
%
% to read and collect <preamble-code> and each file of <comma-separated file list> and 
% <postamble code> in verbatim-catcode-regime and to pass collected things to \scantokens:
% ==========================================================================================
\RequirePackage{catchfile}
\newcommand\MyScratchmacroA{}%
\newcommand\MyScratchmacroB{}%

% Within a local scope temporarily change the catcode-régime:
\begingroup
%
\makeatletter
\ExplSyntaxOn
%
% We won't need \makeatother / \ExplSyntaxOff as -- like the other changes to the
% catcode-régime -- the effects of  \makeatletter and \ExplSyntaxOn will be gone
% when the local scope is closed by \@firstofone.
%
% Use the SOH(=Start Of Heading)-character, code-point-number 1 in ASCII, accessible
% as ^^A in TeX's ^^-notation, for commenting:
\catcode`\^^A=14 %
% Make the CR(=Carriage-Return)-character, code-point-number 13 in ASCII, accessible
% as ^^M in TeX's ^^-notation, an ordinary character --- every line must end by something
% that is taken for a comment-character by TeX as long as this setting is in effect :
\catcode`\^^M=12\relax%
% Make % an ordinary character:
\catcode`\%=12\relax^^A
^^A
\@firstofone{^^A
  ^^A the first thing \@firstofone shall do is close the local scope where the
  ^^A catcode-régime is changed:
  \endgroup^^A
  ^^A=============================================================================
  ^^A PARAPHERNALIA:
  ^^A \UD@firstoftwo, \UD@secondoftwo, \UD@stopromannumeral, \UD@CheckWhetherNull,
  ^^A=============================================================================
  \newcommand\UD@firstoftwo[2]{#1}^^A
  \newcommand\UD@secondoftwo[2]{#2}^^A
  \@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}^^A
  ^^A-----------------------------------------------------------------------------
  ^^A Check whether argument is empty:
  ^^A.............................................................................
  ^^A \UD@CheckWhetherNull{<Argument which is to be checked>}%
  ^^A                     {<Tokens to be delivered in case that argument
  ^^A                       which is to be checked is empty>}%
  ^^A                     {<Tokens to be delivered in case that argument
  ^^A                       which is to be checked is not empty>}%
  ^^A
  ^^A The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
  ^^A <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
  \newcommand\UD@CheckWhetherNull[1]{^^A
    \romannumeral\expandafter\UD@secondoftwo\string{\expandafter^^A
    \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter^^A
    \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter^^A
    \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{^^A
    \expandafter\UD@stopromannumeral\UD@firstoftwo}^^A
  }^^A
  ^^A-----------------------------------------------------------------------------
  ^^A Check whether_verbatimized_ argument has a trailing explicit 
  ^^A <carriage-return>-character-token of catcode 12(other):
  ^^A-----------------------------------------------------------------------------
  ^^A \UD@CheckWhetherTrailingCarriageReturn{<Argument which is to be checked>}%
  ^^A                                      {<Tokens to be delivered in case
  ^^A                                       <argument which is to be checked>'s
  ^^A                                       last token is an explicit <carriage-
  ^^A                                       return>-character-token of 
  ^^A                                       catcode 12(other)>}%
  ^^A                                      {<Tokens to be delivered in case
  ^^A                                       <argument which is to be checked>'s
  ^^A                                       last token is not an explicit
  ^^A                                       <carriage-return>-character-token of 
  ^^A                                       catcode 12(other)>}%
  \newcommand\UD@CheckWhetherTrailingCarriageReturn[1]{^^A
    \UD@@CheckWhetherTrailingCarriageReturn#1\UD@SelDom^^M\UD@SelDom\UD@@SelDom^^A
  }^^A
  \@ifdefinable\UD@@CheckWhetherTrailingCarriageReturn{^^A
    \long\def\UD@@CheckWhetherTrailingCarriageReturn#1^^M\UD@SelDom#2\UD@@SelDom{^^A
      \UD@CheckWhetherNull{#2}{\UD@secondoftwo}{\UD@firstoftwo}^^A
    }^^A
  }^^A
  ^^A=============================================================================
  \NewDocumentCommand\CatchFilesForScantokens{m}{^^A
    \begingroup^^A
    \let\do\@makeother^^A
    \do\^^I^^A
    \CatchFilesForScantokensInner{#1}^^A
  }^^A
  \newcommand\verbatimregime{^^A
    \let\do\@makeother^^A
    \dospecials^^A
    \do\^^I^^A
    \do\^^M^^A
    \endlinechar=`\^^M\relax^^A
    \newlinechar=\endlinechar^^A
  }^^A
  \NewDocumentCommand\CatchFilesForScantokensInner{m+v+v}{^^A
    \endgroup^^A
    \begingroup^^A
    \edef\MyScratchmacroB{^^A
      \expandafter\UD@CheckWhetherTrailingCarriageReturn\expandafter{\detokenize{#2}}^^A
        {\unexpanded\expandafter{\detokenize{#2}}}^^A
        {\unexpanded\expandafter{\detokenize{#2^^M}}}^^A
    }^^A
    \clist_map_inline:nn{#1}{^^A
      ^^A\message{##1^^J}^^A
      \CatchFileDef{\MyScratchmacroA}{##1}{\verbatimregime}^^A
      \edef\MyScratchmacroB{^^A
        \unexpanded\expandafter\expandafter\expandafter{\expandafter\MyScratchmacroB\detokenize\expandafter{\MyScratchmacroA}}^^A
      }^^A
    }^^A
    \edef\MyScratchmacroB{^^A
      \unexpanded\expandafter\expandafter\expandafter{\expandafter\MyScratchmacroB\detokenize{#3}%}^^A
    }^^A
    \newlinechar=\endlinechar^^A
    ^^A=======================================================================
    ^^A If you want to see on connsole what \scantokens gets as spreadtab,
    ^^A then enable the next but one line by removing the leading ^^A
    ^^A=======================================================================
    ^^A\show\MyScratchmacroB^^A
    \scantokens\expandafter{\expandafter\endgroup\MyScratchmacroB}^^A
  }^^A
}%


% Create  document:
% =================
\documentclass{article}
\usepackage[a4paper,left=2.5cm,right=2.5cm,bottom=2.8cm,top=2.8cm]{geometry} 
\usepackage{longtable,tabu}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{datetime}
\usepackage{siunitx}
\usepackage{multirow}
\usepackage[sc]{mathpazo}
\usepackage{datatool}
\usepackage{spreadtab,booktabs,xpatch}
\usepackage[]{numprint}
\usepackage[]{eurosym}
\usepackage{fp}
\usepackage{booktabs}
\usepackage{tabularx,siunitx}
\usepackage{numprint}

\begin{document}

\CatchFilesForScantokens{%
  MyBu1.txt, 
  MyBu2.txt,
  MyBu3.txt,
  MyBu4.txt, 
  MyBu5.txt,
  MyBu6.txt,
  MyBu7.txt, 
  MyBu8.txt, 
  MyBu9.txt, 
  MyBu10.txt,
  MyBu11.txt,
  MyBu12.txt, 
  MyBu13.txt, 
  MyBu14.txt, 
  MyBu15.txt
}%
{%
  \begin{spreadtab}{{tabular}{@{\hskip1pt }r@{\hskip7pt }p{2.7cm }crrr}}
  \toprule
  &@ Ku& @ Re & @ Ne & @ Me & @ Br \\ % <- This is row 1.
  \midrule
  \SThiderow 0&&&&&\\ % <- This is row 2 and it is invisible and used for initial values.
}%
{%
  \midrule
  &@To & [-2,-1] &(sum(d3:[0,-1]))tag(BN) & sum(e3:[0,-1])tag(BM)& sum(f3:[0,-1])tag(BB)\\
  \bottomrule
  \end{spreadtab}
}%

\end{document}

在此处输入图片描述

!!! 这种方法基于逐字分类代码机制读取/标记文件。因此,\input⟨逗号分隔的文件列表⟩将不会执行。即,\input无法嵌套。您所能做的就是提供文件列表。!!!

!!! 它也依赖于读取和标记⟨前导码⟩⟨邮寄代码⟩在逐字分类代码制度中。这反过来意味着\CatchFilesForScantokens

  • 不能隐藏在任何宏的定义中,并且
  • 不能在宏参数中使用,即
  • 必须以这样的方式使用,确保在临时引入的类别代码制度的变化\CatchFilesForScantokens生效时,通过从 .tex 输入文件中读取和标记内容来获取参数。

!!!

答案3

在许多 TeX 发行版中,存在一个名为 texmf.cnf 的文件。它通常位于texmf/web2c并包含上述参数。通常不建议乱用这种配置文件。但是,如果您的 TeX 支持此选项,则可以在命令行中使用开关进行设置--cnf-line='max_in_open=30',例如:

lualatex --cnf-line='max_in_open=30' some-file.tex

许多编辑器支持针对项目或单个 TeX 文件的特殊命令行。例如,GNU Emacs 支持添加名为的文件局部变量,TeX-command-extra-options: "--cnf-line='max_in_open=30'"这样 TeX 文件的结尾可能如下所示:

% mode: latex
% TeX-master: t
% TeX-command-extra-options: "--cnf-line='max_in_open=30'"
% End:

相关内容