views:

69

answers:

3

This was asked in 2008. Hopefully there's a better answer now.

How can you combine PDFs in ruby?

I'm using the pdf-stamper gem to fill out a form in a PDF. I'd like to take n PDFs, fill out a form in each of them, and save the result as an n-page document.

Can you do this with a native library like prawn? Can you do this with rjb and iText? pdf-stamper is a wrapper on iText.

I'd like to avoid using two libraries (i.e. pdftk and iText), if possible.

A: 

We're closer than we were in 2008, but not quite there yet.

The latest dev version of Prawn lets you use an existing PDF as a template, but not use a template over and over as you add more pages.

James Healy
A: 

Via iText, this will work... though you should flatten the forms before you merge them to avoid field name conflicts. That or rename the fields one page at a time.

Within PDF, fields with the same name share a value. This is usually not the desired behavior, though it comes in handy from time to time.

Something along the lines of (in java):

PdfCopy mergedPDF = new PdfCopy( new Document(), new FileOutputStream( outPath );

for (String path : paths ) {
  PdfReader reader = new PdfReader( path );
  ByteArrayOutputStream curFormOut = new ByteArrayOutputStream();
  PdfStamper stamper = new PdfStamper( reader, curFormOut );

  stamper.setField( name, value ); // ad nauseum

  stamper.setFlattening(true); // flattening setting only takes effect during close()
  stamper.close();

  byte curFormBytes = curFormOut.toByteArray();
  PdfReader combineMe = new PdfReader( curFormBytes );

  int pages = combineMe .getNumberOfPages();
  for (int i = 1; i <= pages; ++i) { // "1" is the first page
    mergedForms.addPage( mergedForms.getImportedPage( combineMe, i );
  }
}

mergedForms.close();
Mark Storer
There's a much simpler way to do this — you can usePdfCopyFields and addDocument. See the gem I made.
Paul Schreiber
Granted, but PdfCopyFields won't rename fields... and given the "same name == same value" thing, I thought flattening to be the best route. I'd think field renaming would be right up CopyField's alley, but I don't see anything in the API ref: http://api.itextpdf.com/. PdfStamper can change field names, but won't handle the importing for you. Sadly iText has this sort of "can't walk and chew gum" type problem fairly often, requiring that you create, 'save', and read the same PDF to apply it to some other thing. Not terribly efficient, but it works, and its hard to be the price.
Mark Storer
+1  A: 

I wrote a ruby gem to do this — PDF::Merger. It uses iText. Here's how you use it:

pdf = PDF::Merger.new
pdf.add_file "foo.pdf"
pdf.add_file "bar.pdf"
pdf.save_as "combined.pdf"
Paul Schreiber