4

I am using iText to create a single PDF by merging a number of PDFs using PDFCopy. I need to create a TOC (not bookmarks) at the beginning of this document with clickable links to the first pages of each of the source PDFs.

Code to merge pdf

Document PDFJoinInJava = new Document();
PdfCopy PDFCombiner = new PdfCopy(PDFJoinInJava, outputStream);
PdfCopy.PageStamp stamp;
PDFJoinInJava.open();
PdfReader ReadInputPDF;

List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
for (; iteratorPDFs.hasNext(); pdfCounter++) {
    InputStream pdf = iteratorPDFs.next();
    PdfReader pdfReader = new PdfReader(pdf);
    readers.add(pdfReader);
    totalPages += pdfReader.getNumberOfPages();
    pdf.close();
}
int number_of_pages;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();

PdfImportedPage page;
// Loop through the PDF files and add to the output.
int count = 1;

while (iteratorPDFReader.hasNext()) {
    PdfReader pdfReader = iteratorPDFReader.next();
    count++;
    number_of_pages = pdfReader.getNumberOfPages();

    // Create a new page in the target for each source page.
    for (int pageNum = 0; pageNum < number_of_pages;) {
        currentPageNumber++;
        pageOfCurrentReaderPDF++;
        page = PDFCombiner.getImportedPage(pdfReader, ++pageNum);
        ColumnText.showTextAligned(stamp.getUnderContent(),
                        Element.ALIGN_RIGHT, new Phrase(String
                                .format("%d", currentPageNumber),new Font(FontFamily.TIMES_ROMAN,3)),
                        50, 50, 0);
            stamp.alterContents();

        PDFCombiner.addPage(page);
    }
}
PDFJoinInJava.close();
Butani Vijay
  • 4,181
  • 2
  • 29
  • 61

1 Answers1

4

You're asking for something that should be trivial, but that isn't. Please take a look at the MergeWithToc example. You'll see that your code to merge PDFs is correct, but in my example, I added one extra feature:

chunk = new Chunk(String.format("Page %d", pageNo));
if (i == 1)
    chunk.setLocalDestination("p" + pageNo);
ColumnText.showTextAligned(stamp.getUnderContent(),
    Element.ALIGN_RIGHT, new Phrase(chunk), 559, 810, 0);

For every first page, I define a named destination as a local destination. We use p followed by the page number as its name.

We'll use these named destinations in an extra page that will serve as a TOC:

PdfReader reader = new PdfReader(SRC3);
page = copy.getImportedPage(reader, 1);
stamp = copy.createPageStamp(page);
Paragraph p;
PdfAction action;
PdfAnnotation link;
float y = 770;
ColumnText ct = new ColumnText(stamp.getOverContent());
ct.setSimpleColumn(36, 36, 559, y);
for (Map.Entry<Integer, String> entry : toc.entrySet()) {
    p = new Paragraph(entry.getValue());
    p.add(new Chunk(new DottedLineSeparator()));
    p.add(String.valueOf(entry.getKey()));
    ct.addElement(p);
    ct.go();
    action = PdfAction.gotoLocalPage("p" + entry.getKey(), false);
    link = new PdfAnnotation(copy, 36, ct.getYLine(), 559, y, action);
    stamp.addAnnotation(link);
    y = ct.getYLine();
}
ct.go();
stamp.alterContents();
copy.addPage(page);

In my example, I assume that the TOC fits on a single page. You'll have to keep track of the y value and create a new page if its value is lower than the bottom margin.

If you want the TOC to be the first page, you need to reorder the pages in a second go. This is shown in the MergeWithToc2 example:

reader = new PdfReader(baos.toByteArray());
n = reader.getNumberOfPages();
reader.selectPages(String.format("%d, 1-%d", n, n-1));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filename));
stamper.close();
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • Thanks it working fine but toc generate at last. can i add toc at beginning of the pdf? – Butani Vijay Feb 05 '14 at 13:02
  • I've created a new example to my answer that reorders the pages after the PDF is created. – Bruno Lowagie Feb 05 '14 at 13:14
  • Thank you very much for creating full example.can you provide link where i read more about page reordering because may i need to reorder multiple pages(when more than one index page). – Butani Vijay Feb 06 '14 at 04:05
  • Post a new question and I'll answer with the syntax for page reordering with `PdfStamper`. – Bruno Lowagie Feb 06 '14 at 07:52
  • Hello Bruno please refer this link http://stackoverflow.com/questions/21600040/page-re-ordering-using-itext – Butani Vijay Feb 06 '14 at 10:22
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46917/discussion-between-bruno-lowagie-and-butani-vijay) – Bruno Lowagie Feb 06 '14 at 10:50
  • @BrunoLowagie This article really helped, I am trying to add toc having multiple pages. I have written code like if(y<=50){ copy.addPage(PageSize.A4, 0); y = 770; ct = new ColumnText(stamp.getOverContent()); ct.setSimpleColumn(36, 36, 559, y); } but it gets overlaping can you please help here ? – Hemant Metalia Feb 21 '17 at 14:20
  • @BrunoLowagie also I want to add one page with title before each pdf and the toc will redirect to that page. can you please provide me sample to add page with title in columntext or something we can integrate in this demo provided ? – Hemant Metalia Feb 21 '17 at 14:57