Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'd like to be able to create a TeX file that will output multiple PDF files with one compilation. I'm not even sure if this is possible. Here is the setup:

I am writing dozens of cover letters for job applications, and wish for them to all look "personalized". So I defined a function which calls multiple variables, such as the address, name of the institution, open position, etc., and outputs a "personalized" cover letter for each function call. The problem is that compilation of the TeX file outputs just one file. Since I will be submitting all of these files online eventually, I would like each letter to be in its own file. Is there a way to do this at the TeX level?

share|improve this question
8  
Another use for this kind of thing would be to have one compile command output a beamer slides pdf and a handout pdf... –  Seamus Nov 11 '10 at 20:57
    
What operating system are you on? A simple batch file or script could be made to do what you want easily enough. –  frabjous Nov 11 '10 at 21:06
8  
probably easier to write a makefile/script that regex's the necessary "personalized" parts then generates the file and compiles it to PDF. –  Mica Nov 11 '10 at 21:46
    
I use the plain letter class and pdftk. –  dmckee Nov 12 '10 at 2:52
    
This isn't TeX, so I'm not going to make it an answer, but I think using some of scripting language that does a find and replace for you then runs LaTeX on each of the resulting would be simpler. Python, perl, awk, sed, bash... Are you familiar with any of those? A simple linux script to do that would not be hard. –  Canageek Sep 28 '11 at 4:41
show 3 more comments

8 Answers

up vote 33 down vote accepted

How do you store this information? You could just have one info-file for each letter

% letter1.adr
\def\toname{Foo}

and

% letter2.adr
\def\toname{Bar}

and then have a main file

% main.tex
\documentclass[addrfield]{scrlttr2}
\input \jobname.adr

\begin{document}
\begin{letter}{\toname}
\opening{Dear \toname, }
 A nice letter.
\end{letter}
\end{document}

Then you can compile all letters from the command line with something like

for %i in (*.adr) do pdflatex -jobname=%i main.tex

The koma bundle also provides tools for more sophisticated address files.

share|improve this answer
    
I've been using essentially this trick for years, to ensure that items charged on invoices match up with the work specified in contracts. –  Charles Stewart Nov 11 '10 at 21:15
    
I do the same except I use a makefile for managing the dependencies and rebuilds. –  Pat Notz Nov 11 '10 at 21:53
    
This was just what I was looking for; thanks! –  Kristen Nov 12 '10 at 17:47
    
Typo: comile -> compile. –  Faheem Mitha Apr 1 at 9:26
add comment

The answer is no, TeX outputs one PDF file.

I'd use a tool to split the PDF files afterwards. pdfpages (TeX) pdfsam, and pdftk should do the trick.

share|improve this answer
    
If have found pdftk to be cumbersome if you want to split a PDF into k-page chunks for k>1. So, naturally, I wrote a script to do it more conveniently. –  Raphael Sep 9 '13 at 12:35
add comment

Yes it is possible if you enable \write18 (e.g. pdflatex --shell-escape with MiKTeX). Then you can call pdflatex again inside your document. An example (the code is not from me). It will generate three documents \jobname1-\jobname3:

\documentclass{article}

\ifx\conditionmacro\undefined
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname1"
    \gdef\string\conditionmacro{1}\string\input\space\jobname
  }%
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname2"
    \gdef\string\conditionmacro{2}\string\input\space\jobname
  }%
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname3"
    \gdef\string\conditionmacro{3}\string\input\space\jobname
  }%
  \expandafter\stop
\fi

\begin{document}
\ifnum\conditionmacro=1 Condition is 1\fi
\ifnum\conditionmacro=2 Condition is 2\fi
\ifnum\conditionmacro=3 Condition is 3\fi

\verb|\conditionmacro| is \texttt{\meaning\conditionmacro}.
\end{document}

Case sensitive systems

As noted in Martin Heller's comment you need to change this code for case sensitive operating systems to:

\documentclass{article}

\ifx\conditionmacro\undefined
  \immediate\write18{%
    pdflatex --jobname="\jobname1"
    "\gdef\string\conditionmacro{1}\string\input\space\jobname"
  }%
  \immediate\write18{%
    pdflatex --jobname="\jobname2"
    "\gdef\string\conditionmacro{2}\string\input\space\jobname"
  }%
  \immediate\write18{%
    pdflatex --jobname="\jobname3"
    "\gdef\string\conditionmacro{3}\string\input\space\jobname"
  }%
  \expandafter\stop
\fi

\begin{document}

\ifnum\conditionmacro=1 Condition is 1\fi 

\ifnum\conditionmacro=2 Condition is 2\fi

\ifnum\conditionmacro=3 Condition is 3\fi

\verb|\conditionmacro| is \texttt{\meaning\conditionmacro}.

\end{document}
share|improve this answer
1  
Very nice. On case sensitive systems you need to use lowercase for the call to pdflatex. I also had to add quotes around the \gdef.... –  Martin Heller Nov 12 '10 at 22:47
    
I know it's old but --- thanks. I use to prepare multiple versions of tests and exams and this helps me a lot. Now I will try to search how to make this work with latexmk.... –  Rmano Apr 4 at 15:37
add comment

You can do as Patrick says, or you can generate TeX files from a script language (say, Perl + Template Toolkit) and then use environment variables to pass the parameters.

E.g. on Linux with bash, you can do $ PARAM1=VALUE1 PARAM2=VALUE2 perl ./compile.pl

share|improve this answer
    
+1 for Perl + TT (search.cpan.org/~abw/Template-Toolkit-2.22/lib/Template.pm), but why pass parameters on env variables? In the script that will do the compiling just have a hash of the data needed and foreach of the keys do a replace/compile –  Joel Berger Nov 12 '10 at 13:44
1  
Wouldn't it be easier to use something along the lines of awk or sed to do a replacement? –  Canageek Sep 28 '11 at 4:38
    
@Canageek, it's just my prejudice against editing the code when I can use inputs :) –  Alexei Averchenko Sep 28 '11 at 7:44
add comment

I don't think you can make a single .tex file produce multiple .PDFs, however you could create some very simple .tex files (one per PDF you want to create), which simply set up a few macros (your personalised variables) and then \input (or \include) the common .tex file.

Running pdflatex (or whatever TeX-to-xxx converter/compiler you like best) on each of the small files will produce all your PDFs.

(Probably worth writing a little script to compile each one if the differing elements are more than very simple macro replacements)

share|improve this answer
add comment

Expanding on my comment to Alexei, If you make a file test.tex with:

\documentclass{article}

\begin{document}

Hello [% name %]

\end{document}

and a test.pl with:

#!/usr/bin/env perl

use strict;
use warnings;

use Template;

my $tt = Template->new(); 

my @names = ('john','sally');
my $infile = 'test.tex';

foreach my $name (@names) {
  my %data;
  my $outname = $name . 'tex';
  $data{'name'} = $name;
  $tt->process($infile,\%data, $outname);
  system("latexmk -pdf $outname");
  system("latexmk -c");
}

when you execute test.pl you should get a john.tex and a john.pdf, etc in the same folder. Its a simple example but I'm sure you can extend it to what you need. PS if you don't know latexmk, check it out!

share|improve this answer
add comment

You should be able to do this with the letter options in KOMA script, it's briefly in the manual although I haven't personally experimented with it.

share|improve this answer
add comment

Since cover letter usually does not exceed 1 page, it is possible to extract given range of pages from Adobe Acrobat using Tools | Pages | Extract | Extract Pages As Separate Files.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.