How to create a TOC when merging documents?

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.

31st May 2016
admin-marketing

I'm doing the following:

 

Document document = new Document();
PdfCopy copy = new PdfCopy(document, outputStream);
PdfCopy.PageStamp stamp;
document.open();
PdfReader reader;
ListInputStream> pdfs = streamOfPDFFiles;
ListPdfReader> readers = new ArrayListPdfReader>();
IteratorInputStream> iteratorPDFs = pdfs.iterator();
for (; iteratorPDFs.hasNext(); pdfCounter++) {
    InputStream pdf = iteratorPDFs.next();
    reader = new PdfReader(pdf);
    readers.add(reader);
    pdf.close();
}
int currentPageNumber = 0;
IteratorPdfReader> readerIterator = readers.iterator();
PdfImportedPage page;
int count = 1;
while (readerIterator.hasNext()) {
    reader = readerIterator.next();
    count++;
    int number_of_pages = reader.getNumberOfPages();
    for (int pageNum = 0; pageNum  number_of_pages;) {
        currentPageNumber++;
        page = copy.getImportedPage(reader, ++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();
        copy.addPage(page);
    }
}
document.close();

 

Posted on StackOverflow on Feb 4, 2014 by Butani Vijay

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:

Text text = new Text(String.format("Page %d", pageNo));
entry.getValue().copyPagesTo(i, i, pdfDoc);
if (i == 1) {
    text.setDestination("p" + pageNo);
}
doc.add(new Paragraph(text).setFixedPosition(pageNo, 549, 810, 40));

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:

PdfDocument tocDoc = new PdfDocument(new PdfReader(src3));
tocDoc.copyPagesTo(1, 1, pdfDoc);
tocDoc.close();
float y = 770;
for (Map.Entry entry : toc.entrySet()) {
    Paragraph p = new Paragraph();
    p.addTabStops(new TabStop(500, TabAlignment.LEFT, new DashedLine()));
    p.add(entry.getValue());
    p.add(new Tab());
    p.add(String.valueOf(entry.getKey()));
    p.setAction(PdfAction.createGoTo("p" + entry.getKey()));
    doc.add(p.setFixedPosition(pdfDoc.getNumberOfPages(), 36, y, 595 - 72));
    y -= 20;
}
for (PdfDocument srcDoc : filesToMerge.values()) {
    srcDoc.close();
}

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.

Click this link if you want to see how to answer this question in iText 5.



Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now