Marcel
Marcel

Reputation: 984

iTextSharp - Combining multiple A4 documents into double-sided A3 booklet

I have a PDF form that is 4 x A4 pages. I complete the fields using iTextSharp. All good with this part.

I then need to combine a number of these forms into one PDF document. Plan on using this approach : Using iTextSharp to generate multiple page PDF from existing PDF Form.

These A4 pages however, need to be combined into a single A3 sheet, printed in a "booklet" type configuration, i.e. front and back like below

          A3 Front    ----- turn over ---->    A3 Back
-------------------------------   -------------------------------
|              |              |   |              |              |
|              |              |   |              |              |
|              |              |   |              |              |
|     Page     |     Page     |   |     Page     |     Page     |
|       4      |      1       |   |      2       |       3      |
|              |              |   |              |              |
|              |              |   |              |              |
|              |              |   |              |              |
-------------------------------   -------------------------------

(ascii ftw)

When the A3 is then folded in half, it would read (left to right), page 1, page 2, page 3, page 4. I would then combine all my completed forms in this manner, then print the whole PDF document on A3 back-to-back.

I found this post (http://forums.asp.net/t/1692347.aspx?Merging+two+pdf+pages+into+one+using+itextsharp) that mentions putting a PdfPTable on the page, then grabbing an Image of the page, and embedding it in the table cell...

If I did it this, wouldn't the PDF file be massive, since its basically full of images? Is there a better way to achieve this?

Upvotes: 0

Views: 1848

Answers (1)

Marcel
Marcel

Reputation: 984

Figured it out... follow this approach:

using (var copyms = new MemoryStream())
{
    var document = new Document();

    using (PdfSmartCopy copy = new PdfSmartCopy(document, copyms))
    {
        document.Open();

        foreach (var item in Items)
        {
            // Read the template
            var pdfReader = new PdfReader(TemplateLocation);

            // Save the current completed template to a MemoryStream
            using (var ms = new MemoryStream())
            {
                using (PdfStamper stamper = new PdfStamper(pdfReader, ms))
                {
                    var fields = stamper.AcroFields;

                    // Set the field values here

                    stamper.FormFlattening = true;
                }

                pdfReader = new PdfReader(ms.ToArray());

                // Copy the memorystream to the main document
                copy.AddDocument(pdfReader);
            }
        }
    }

    document.CloseDocument();

    // Combine on A3 pages in new document

    var a3doc = new Document(PageSize.A3.Rotate(), 0, 0, 0, 0);

    var a3reader = new PdfReader(copyms.ToArray());
    var a3writer = PdfWriter.GetInstance(a3doc, new FileStream(outputFileLocation, FileMode.Create));

    a3doc.Open();

    var a3cb = a3writer.DirectContent;

    PdfImportedPage page;

    int totalPages = a3reader.NumberOfPages;

    for (int i = 1; i <= (int)Math.Ceiling(totalPages / 2); i++)
    {
        // Create an A3 page
        a3doc.NewPage();
        var a3size = PageSize.A3.Rotate();

        page = a3writer.GetImportedPage(a3reader, (i * 2) + 1);
        a3cb.AddTemplate(page, 0, 0);

        page = a3writer.GetImportedPage(a3reader, (i * 2) + 2);
        a3cb.AddTemplate(page, (int)(a3size.Width / 2), 0);                    
    }

    a3doc.CloseDocument();
}

So basically, keep everything in memory, and at the end use the writer's DirectContent to paste the A4 page somewhere on the A3 page. Also, use PdfSmartCopy to keep the file size low since the template page stuff isn't being added everytime you add a filled copy.

Upvotes: 1

Related Questions