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

时间:2014-02-28 23:58:11

标签: java itext

我创建了一个包含Chapter个文件的文档。

如何为此文档生成TOC?

它应该是这样的:

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

2 个答案:

答案 0 :(得分:12)

使用PdfTemplate可以做到这一点。 PdfTemplate是一种占位符,您可以在之后填写。

使用Bruno的提示进行更新:

要在开头的TOC生成,您需要为TOC中的所有页码添加一些占位符。您在PdfTemplate中收集的Map。然后,当您将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<String, PdfTemplate> tocPlaceholder = new HashMap<>();

    // store the chapters and sections with their title here.
    private final Map<String, Integer>     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

答案 1 :(得分:2)

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

获得此列表后,在文档末尾创建TOC。如果您想将TOC移到前面,请阅读我对这个问题的回答:PDF Page re-ordering using itext