Как создать Оглавление " TOC " с помощью iText?

Я создал документ с какими-то Chapters.

Как создать TOC для этого документа?

Это должно выглядеть так:

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

2 ответов


это возможно с помощью PdfTemplates. PdfTemplates-это своего рода заполнитель, который вы можете заполнить позже.

обновление с подсказками от Бруно:

чтобы сгенерировать в TOC в начале, вам нужно поместить некоторые заполнители для всех номеров страниц в TOC. Те PdfTemplates вы собираете в Map. Затем, когда вы добавляете Chapters в документ, вы можете заполнить эти заполнители.

этот пример показывает, как:

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


ответ Кристиана Шнайдера кажется несколько сложным. Я бы также использовал событие page, но я бы использовал onChapter() метод для создания списка заголовков глав и номеров страниц. Если вам также нужно Section titles, используйте onSection() метод, чтобы отслеживать разделы тоже.

как только у вас есть этот список, создайте TOC в конце документа. Если вы хотите переместить TOC вперед, прочитайте мой ответ на этот вопрос:страница PDF повторный заказ с использованием itext