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.
I'm doing the following:
Document document = newDocument();
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),
newFont(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 How to create a TOC when merging documents? | iText 5 PDF Development Guide if you want to see how to answer this question in iText 5.