Comment générer une table des matières “TOC” avec iText?

J’ai créé un document avec des Chapter .

Comment générer une table des matières pour ce document?

Ça devrait ressembler à ça:

 TOC: Chapter 1 3 Chapter 2 4 Chapter 3 6 Chapter 4 9 Chapter 5 10 

Ceci est possible en utilisant PdfTemplate s. PdfTemplate s sont une sorte d’espace réservé que vous pouvez remplir ultérieurement.

Mise à jour avec les astuces de Bruno:

Pour générer la table des matières au début, vous devez définir des espaces réservés pour tous les numéros de page de la table des matières. Ces PdfTemplate s que vous collectez dans une Map . Ensuite, lorsque vous ajoutez les Chapter au document, vous pouvez remplir ces espaces réservés.

Cet exemple montre comment:

 public class Main extends PdfPageEventHelper { private final Document document; private final PdfWriter writer; private final BaseFont baseFont = BaseFont.createFont(); private final Font chapterFont = FontFactory.getFont(FontFactory.HELVETICA, 24, Font.NORMAL); // table to store placeholder for all chapters and sections private final Map tocPlaceholder = new HashMap<>(); // store the chapters and sections with their title here. private final Map pageByTitle = new HashMap<>(); public static void main(final String[] args) throws Exception { final Main main = new Main(); main.document.add(new Paragraph("This is an example to generate a TOC.")); main.createTOC(10); main.createChapters(10); main.document.close(); } public Main() throws Exception { this.document = new Document(PageSize.A6); this.writer = PdfWriter.getInstance(this.document, new FileOutputStream("text.pdf")); this.writer.setPageEvent(this); this.document.open(); } @Override public void onChapter(final PdfWriter writer, final Document document, final float paragraphPosition, final Paragraph title) { this.pageByTitle.put(title.getContent(), writer.getPageNumber()); } @Override public void onSection(final PdfWriter writer, final Document document, final float paragraphPosition, final int depth, final Paragraph title) { this.pageByTitle.put(title.getContent(), writer.getPageNumber()); } private void createTOC(final int count) throws DocumentException { // add a small introduction chapter the shouldn't be counted. final Chapter intro = new Chapter(new Paragraph("This is TOC ", this.chapterFont), 0); intro.setNumberDepth(0); this.document.add(intro); for (int i = 1; i < count + 1; i++) { // Write "Chapter i" final String title = "Chapter " + i; final Chunk chunk = new Chunk(title).setLocalGoto(title); this.document.add(new Paragraph(chunk)); // Add a placeholder for the page reference this.document.add(new VerticalPositionMark() { @Override public void draw(final PdfContentByte canvas, final float llx, final float lly, final float urx, final float ury, final float y) { final PdfTemplate createTemplate = canvas.createTemplate(50, 50); Main.this.tocPlaceholder.put(title, createTemplate); canvas.addTemplate(createTemplate, urx - 50, y); } }); } } private void createChapters(final int count) throws DocumentException { for (int i = 1; i < count + 1; i++) { // append the chapter final String title = "Chapter " + i; final Chunk chunk = new Chunk(title, this.chapterFont).setLocalDestination(title); final Chapter chapter = new Chapter(new Paragraph(chunk), i); chapter.setNumberDepth(0); chapter.addSection("Foobar1"); chapter.addSection("Foobar2"); this.document.add(chapter); // When we wrote the chapter, we now the pagenumber final PdfTemplate template = this.tocPlaceholder.get(title); template.beginText(); template.setFontAndSize(this.baseFont, 12); template.setTextMatrix(50 - this.baseFont.getWidthPoint(String.valueOf(this.writer.getPageNumber()), 12), 0); template.showText(String.valueOf(this.writer.getPageNumber())); template.endText(); } } } 

Le PDF généré ressemble à ceci: TableOfContents.pdf

La réponse de Christian Schneider semble quelque peu complexe. J’utiliserais également l’événement page, mais j’utiliserais la méthode onChapter() pour créer une liste de titres de chapitre et de numéros de page. Si vous avez également besoin de titres de Section , utilisez la méthode onSection() pour suivre également les sections.

Une fois que vous avez cette liste, créez la table des matières à la fin du document. Si vous souhaitez déplacer la table des matières au premier plan, lisez ma réponse à cette question: Réorganisation de pages PDF à l’aide d’itext