java - 如何使用 OpenPDF 添加目录

标签 java openpdf

我正在开发一个工具,用于生成代表评估结果的 PDF 文档。这些文档的结构以及一些文本和图像是由非技术用户定义的(这就是为什么不选择 Apache FOP 和 XSL 的原因之一)。

OpenPDF 似乎是一个很有前途的库(除了 Apache PDFBox,它的级别太低)。但是,生成的文档必须包含目录。
预期的文档结构是这样的:

 1. Cover
 2. Abstract
 3. Table of Contents
 4. Chapter 1 .. n

由于我不知道文档最终将有多少页或不同章节将在哪些页上开始,因此我无法在将每一章添加到文档之前定义目录。
由于 OpenPDF 直接将元素写入文档,因此似乎不可能保留示例性目录元素的引用并在添加所有章节后添加其内容。

最佳答案

我通过使用 com.lowagie.text.pdf.PdfWriterreorderPages(int[]) 方法找到了一种适用于预期结构的解决方案:

首先,我保留预期的目录第一页(摘要后的第一页):

int intendedTocFirstPage = pdfWriter.getCurrentPageNumber() - 1; // - 1 because of a necessary `document.newPage();` before that

将所有章节添加到文档后,我最后添加目录并保留第一页和最后一页(因为可能需要多个页面,具体取决于章节和子章节的数量):

int tocFirstPage = pdfWriter.getCurrentPageNumber();
document.add(new Paragraph("TBA: Actual Table of Contents")); // TODO replace with the table of contents based on the existing chapters and sections
document.newPage();
int tocLastpage = pdfWriter.getCurrentPageNumber();

然后我创建一个数组,它基于三个 int 变量来表示页面的新顺序:

private int[] getReorderedPagesForTableOfContents(int intendedTocFirstPage, int tocFirstPage, int tocLastpage) {
    int[] pages = IntStream
            .range(1, tocLastpage)
            .toArray();

    /*
     * Reorder the pages array by placing the toc page numbers at
     * the indexes starting from targetedTocFirstPage (should be
     * the page directly after the summary)
     */
    int numberOfTocPages = tocLastpage - tocFirstPage;
    if (numberOfTocPages >= 0) {
        System.arraycopy(pages, tocFirstPage - 1, pages, intendedTocFirstPage, numberOfTocPages);
    }

    /* Shift the page numbers of all pages after the last toc page */
    for (int i = intendedTocFirstPage + numberOfTocPages; i < pages.length; i++) {
        pages[i] = i - numberOfTocPages + 1; // `+ 1` because page numbers start with 1 not 0
    }

    return pages;
}

最后,我对文档的页面进行重新排序:

int[] reorderedPages = getReorderedPagesForTableOfContents(targetedTocFirstPage, tocFirstPage, tocLastpage);
pdfWriter.reorderPages(reorderedPages);

这可行,但会产生另一个问题:
使用页脚显示页码将不再正常工作,因为重新排序之前的页码将被保留。
一个可能的解决方案是首先创建完整的文档,包括页面的重新排序,然后使用 PdfReader 添加页码,如本答案所述:https://stackoverflow.com/a/759972/10551549

如果有人有更好的解决方案,我会很高兴听到它(因为在我看来,这个有点困惑)。 :)

关于java - 如何使用 OpenPDF 添加目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61815826/

相关文章:

java - 正在运行的 Ruby 和 Java 程序之间进行通信

java - DSSException : Revocation data is missing

java - WindowBuilder 与 JavaFX Scenebuilder 按钮操作?

java - 如何使用 OpenPdf 将 HTML 转换为 Pdf

java - 在 Java 中使用 OpenPDF 居中/对齐表格单元格中的文本

java - 使用 openpdf 的 FlyingSaucer 无法正确渲染弹性框

java - 即使应用程序未运行,也处理 onMessageReceived() 和 onTokenRefresh()

java - 棕地 |听诊器 | ":com.facebook.stetho:stetho-okhttp:1.2.0' 依赖于一个或多个 Android 库但是是一个 jar”

java - Eclipse 无法正确处理子包