如何使用iText生成目录“TOC”?

我已经用一些Chapter创建了一个文档。

如何为此文档生成TOC?

它应该如下所示:

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

这可以通过使用PdfTemplatePdfTemplatePdfTemplate是一种占位符,您可以在之后填充。

使用Bruno的提示进行更新:

要在开始时在TOC生成,您需要为TOC中的所有页码添加一些占位符。 你在Map收集的那些PdfTemplate 。 然后,当您将Chapter添加到文档时,您可以填充这些占位符。

此示例显示如何:

 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(); } } } 

生成的PDF如下所示: TableOfContents.pdf

Christian Schneider的答案似乎有些复杂。 我也会使用页面事件,但我会使用onChapter()方法创建章节标题和页码的列表。 如果还需要Section标题,请使用onSection()方法来跟踪这些节。

获得此列表后,在文档末尾创建TOC。 如果您想将TOC移到前面,请阅读我对这个问题的回答: PDF页面使用itext重新排序