Joachim Breitner

Including full LaTeX documents in another LaTeX document

Published 2012-02-15 in sections English, Digital World.

Assume the following situation: You set problem sheets for a class, and at the end of the semester, you have 13 individual LaTeX files, including the preamble (the stuff from \documentclass to \begin{document}). Now you want to provide a file that contains all problems, followed by all problems with solutions. You could just concatenate the resulting PDFs, but that would waste quite a bit of paper, as most problem sheets do not fill the whole page. You could just copy’n’paste the LaTeX code, but that is not neat either.

So you want to include the 13 individual documents in one LaTeX document. LaTeX provides \include and \input commands, but these would require that the content of the individual files, i.e. the stuff between \begin{document} and \end{document}, is put in a file of its own. You cannot just \input the full problem sheet document, as there must be only one \documentclass command, and a few preamble commands are invalid within the document.

There are various solutions suggested, e.g. on Wikibooks and StackOverflow, and there are packages helping with that functionality, such as combine or subfiles. I chose a rather rough, hands-on solution that worked great in my case: The idea is to simply re-define all commands that you have in your preamble to do nothing, including the document environment, before including the other files and constraint to a group. In my case, the preambles were relatively small, as the common definitions of the problem sheets were in a file of their own. I am also using the \foreach command provided by the TikZ package for a convenient loop over all problem sheets:

\foreach \x in {0,...,13} {
  {
    \excludecomment{solution}
    
    \DeclareDocumentCommand{\documentclass}{om}{}
    \DeclareDocumentCommand{\usepackage}{om}{}
    \newcommand{\Blattnummer}[1]{}
    \DeclareDocumentCommand{\FirstDueDate}{mmm}{}
    \DeclareDocumentCommand{\ThisDueDate}{mmm}{}
    \newcommand{\SkippedWeeks}[1]{}
    \renewenvironment{document}{}{}
    \section*{Problem Sheet \x}
    \setcounter{problem}{0}
    \input{GraphTheoryProblems\x}
  }
}
\clearpage
\label{sols}
\foreach \x in {0,...,13} {
  {
    \newenvironment{solution}{
      \par\addvspace{1em}
    }{
    }
    \DeclareDocumentCommand{\documentclass}{om}{}
    \DeclareDocumentCommand{\usepackage}{om}{}
    \newcommand{\Blattnummer}[1]{}
    \DeclareDocumentCommand{\FirstDueDate}{mmm}{}
    \DeclareDocumentCommand{\ThisDueDate}{mmm}{}
    \newcommand{\SkippedWeeks}[1]{}
    \renewenvironment{document}{}{}
    \section*{Solution Sheet \x}
    \setcounter{problem}{0}
    \input{GraphTheoryProblems\x}
  }
}

To redefine commands taking optional arguments, using the xparse package is convenient. You can see how I include every file twice, first with the solution environment turned into a comment and then again with the solution environment actually showing its content. I create a section header based on the counter of the foreach loop, but I could have easily redefined \title and use that for a header, if my problem sheets had used that command (They don’t, as they calculate the problem sheet number and the due date based on the number in the filename – very convenient, and maybe worth a blog post of its own). The problem counter is reset for each file, so that the problems are numbered individually. I could have left this out, then the problems would be numbered consecutively across all included problem sheets.

The individual and resulting files can be found on the Graph Theory course website.

Comments

Have something to say? You can post a comment by sending an e-Mail to me at <mail@joachim-breitner.de>, and I will include it here.