5

I want to use subfile within a loop to add new pages to a document, depending on the number of lines in a .txt file.
The .txt may look like this:

0001
0002
0003

The .tex Subfiles are A0001.tex, A0002.tex A0003.tex

My code:

\documentclass{article}
\usepackage{subfiles}
\usepackage{forloop}

\begin{document}%
%
\newread\file%
    \openin\file=mytextfile.txt%
        \loop\unless\ifeof\file%
            \read\file to\linecontent%
            \subfile{A\linecontent}
            \newpage%
        \repeat%
    \closein\file%
\end{document}

I get this error messages for codeline 22 (\repeat), despite that the .pdf is created and looks correct.

Paragraph ended before @iinput was complete.

Extra }, or forgotten \endgroup. @import ...er #1\expandafter {\import@path@file }

If i change the subfile input to only one subfile (A0001), there is no error but it adds 4 ! new pages as if there where 4 lines in the .txt file.

\subfile{A0001}

I think im missing some small detail, but i really dont know what.

2
  • Welcome to TeX.SX! I get an error, because a space is added after each line that is read in, so that \subfile for example looks for A0001 .tex, which is not available. I am currently looking for a solution for this problem. Nov 11, 2021 at 9:53
  • This problem is not related to the subfiles package. Replacing \subfiles by \input shows the same issue, which is related to the loop not terminating properly.
    – gernot
    Nov 11, 2021 at 10:15

2 Answers 2

4

The main problem is that the contents of \linecontent ends with a space that should be trimmed off.

Here's a simpler implementation with a predefined expl3 loop (avoid reinventing the wheel):

\documentclass{article}
\usepackage{subfiles}

\ExplSyntaxOn

\NewDocumentCommand{\batchsubfiles}{m +O{}}
 {% #1 = file name, #2 = code to execute after each \subfile command
  \patrix_batchsubfiles:nn { #1 } { #2 }
 }

\ior_new:N \g_patrix_batchsubfiles_ior

\cs_new_protected:Nn \patrix_batchsubfiles:nn
 {
  \ior_open:Nn \g_patrix_batchsubfiles_ior { #1 }
  \ior_map_inline:Nn \g_patrix_batchsubfiles_ior
   {
    \subfile{A##1}
    #2
   }
 }

\ExplSyntaxOff

\begin{document}

\textbf{Nothing in between}

\batchsubfiles{subfiles.txt}

\bigskip

\textbf{With paragraph break after subfiles}

\batchsubfiles{subfiles.txt}[\par]

\end{document}

The subfiles.txt file is

0001
0002
0003

and the subfiles contain what's evident from the output below.

enter image description here

Some explanations

  1. \ior_new:N \g_patrix_batchsubfiles_ior is the analog of \newread\file

  2. \ior_open:N \g_patrix_batchsubfiles_ior { filename } is the analog of \openin\file=filename; here the file name is passed as the mandatory argument to \batchsubfiles, via the internal function \patrix_batchsubfiles:nn

  3. \ior_map_inline:Nn is the analog of the \loop construction you use, with several advantages over it:

    • one doesn't need to test for \ifeof
    • the implicit empty line at the end of the file is automatically ignored
    • there is no need to use a control sequence to store the contents of the current line, one just uses #1 instead; here ##1 because we're inside a definition
    • the implicit space at the end of lines is automatically ignored
  4. the mapping is done on one line at the time

  5. one can also do a test in the body of the loop and break it, if some condition is satisfied; for instance one could test for an empty line and break if found with

    \tl_if_empty:nT { ##1 } { \ior_map_break: }
    
2
  • Thanks for you help, your sample works flawless for my use. Now i need to understand expl3 x). But for now im good.
    – Patrix
    Nov 11, 2021 at 13:25
  • 1
    @Patrix I added some words of explanation
    – egreg
    Nov 11, 2021 at 13:34
4

Welcome to TeX.SX! I got a different error from yours, which was due to the fact that TeX inserts a space after each line that is read from another file by default (see also here). The code would then look for a file named, for example, A0001 .tex, that does not exist and which eventually raises this error. Therefore, I inserted \endlinechar=-1 to your code, which suppresses this trailing space. I assume this is also the solution four your problem, although you got a different error.

I further added an \if clause that tests whether \linecontets contains any characters at all, since the end of the file will be considered an additional empty line when read in. This is also the reason why you got four pages although your .txt file only contains three lines.

\documentclass{article}
\usepackage{subfiles}
\usepackage{forloop}

\begin{document}%
%
\newread\file%
    \openin\file=mytextfile.txt%
    \begingroup\endlinechar=-1 %
        \loop\unless\ifeof\file%
            \read\file to \linecontent%
            \ifx\linecontent\empty\else%
                \subfile{A\linecontent}
            \fi%
            \newpage%
        \repeat%
    \endgroup%
    \closein\file%
\end{document}
1
  • 1
    Thank you for your answer, it was definitely usefull but i think i had some more problems with the loop and the subfile i used (and the packages for its content). Anyway with the code of egreg and some changes its running perfect!
    – Patrix
    Nov 11, 2021 at 13:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .