【问题标题】:How to add a "Page X of Y" footer in iText 7如何在 iText 7 中添加“Y 页 X”页脚
【发布时间】:2016-11-30 00:46:38
【问题描述】:

我正在尝试弄清楚如何在我使用 iText 7 生成的 PDF 文档的每一页中添加“Page X of Y”页脚。

使用 IEventHandler 生成“Page X”部分似乎相当简单——这是我正在努力解决的“Y”位。我想避免生成整个文档两次以找出它有多少页,因为这会严重影响性能!

我在 iText 5 中找到了解决方案:PDF Page Numbering in Java & iText,但 iText 7 是对 iText 的完全重写,具有完全不同的界面,因此到目前为止,我一直找不到任何类似的 iText 7 示例。

【问题讨论】:

  • 有人可以创建一个“iText7”标签,我可以添加到这个标签中,因为我没有足够的声誉! :-( 在搜索 iText7 问题和答案时,“iText”标签并不是特别有用,因为 iText 5 和 iText 7 是完全不同的野兽!
  • 根据meta.stackexchange.com/questions/85358/…meta.stackoverflow.com/questions/299598/…itext7 标签可能有用。我不反对。但是,StackOverflow 版主会非常迅速地压制这样的标签,而无需了解细节。
  • 我刚刚创建了标签,让我们看看它的寿命。老实说,我并不乐观。
  • 感谢@AmedeeVanGasse!您发布的第一个链接在正确答案中有这个:“我只会在问题内容不可撤销地与某物的特定版本相关联并且永远不会与早期版本或更高版本相关时使用版本标签” - 这绝对适用于此iText 5 和 7 的情况完全不同。另一个问题也有类似的答案。所以这里的希望......! :-)
  • 我希望 iText7 标签持续存在!新版本不仅功能强大得多,而且使用起来也大不相同。人们会有很多关于它的问题(我知道我有!)

标签: itext itext7


【解决方案1】:

answer you found for iText 5 引用了 MovieCountries1 示例。此示例已针对 iText 7 重写为 Listing_05_20_MovieCountries1。其关键代码:

protected PdfFont bold;
protected PdfFont italic;
protected PdfFont normal;

protected PdfFormXObject template;

public void manipulatePdf(String dest) throws IOException, SQLException {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc, new PageSize(PageSize.A4), true);
    doc.setMargins(54, 36, 36, 36);

    bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
    italic = PdfFontFactory.createFont(FontConstants.HELVETICA_OBLIQUE);
    normal = PdfFontFactory.createFont(FontConstants.HELVETICA);

    template = new PdfFormXObject(new Rectangle(550, 803, 30, 30));
    PdfCanvas canvas = new PdfCanvas(template, pdfDoc);

    HeaderHandler headerHandler = new HeaderHandler();
    pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);

    ... ADD CONTENT ...

    canvas.beginText();
    try {
        canvas.setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12);
    } catch (IOException e) {
        e.printStackTrace();
    }
    canvas.moveText(550, 803);
    canvas.showText(Integer.toString(pdfDoc.getNumberOfPages()));
    canvas.endText();
    canvas.release();

    doc.close();
}

public class HeaderHandler implements IEventHandler {
    protected String country;

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfPage page = docEvent.getPage();
        int pageNum = docEvent.getDocument().getPageNumber(page);
        PdfCanvas canvas = new PdfCanvas(page);
        canvas.beginText();
        try {
            canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 12);
        } catch (IOException e) {
            e.printStackTrace();
        }
        canvas.moveText(34, 803);
        canvas.showText(country);
        canvas.moveText(450, 0);
        canvas.showText(String.format("Page %d of", pageNum));
        canvas.endText();
        canvas.stroke();
        canvas.addXObject(template, 0, 0);
        canvas.release();
    }

    public void setHeader(String country) {
        this.country = country;
    }
}

您还可以在那里找到许多其他示例的重写。


正如@Bruno 在评论中所说,甚至还有一个稍微不同的示例,它是真正为 iText 7 创建的(与上面的示例相反,它是 iText 5 示例的端口)。

这是iText 7: building blocks tutorialchapter 7 附带的示例。它使用showTextAligned() 来确保“Page X of”与“Y”完美匹配,无论 X 和 Y 有多少位数字,参见。其页尾事件监听方法:

public void handleEvent(Event event) {
    PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
    PdfDocument pdf = docEvent.getDocument();
    PdfPage page = docEvent.getPage();
    int pageNumber = pdf.getPageNumber(page);
    Rectangle pageSize = page.getPageSize();
    PdfCanvas pdfCanvas = new PdfCanvas(
        page.newContentStreamBefore(), page.getResources(), pdf);
    Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
    Paragraph p = new Paragraph()
        .add("Page ").add(String.valueOf(pageNumber)).add(" of");
    canvas.showTextAligned(p, x, y, TextAlignment.RIGHT);
    pdfCanvas.addXObject(placeholder, x + space, y - descent);
    pdfCanvas.release();
}

(C07E03_PageXofY.java, 事件处理类PageXofY)

【讨论】:

  • 这真的很有用 - 谢谢@mkl!不过,您错过了关键部分之一 - 它设置了总页数:canvas.showText(Integer.toString(pdfDoc.getNumberOfPages()));
  • 我一直在玩这个例子的改编版本,我认为其中有几个错误。 canvas.moveText(450,0) 将“Page X of”文本放在页面的最底部,没有边距,这看起来有点奇怪,但更重要的是,canvas.moveText(550,803) 再往上,将页数放在页面的右上角文档,而不是在“第 X 页”文本之后。
  • canvas.moveText(450,0) 将 "Page X of" 文本放在页面的最底部,没有边距 - 不,您忘记在前两行取 canvas.moveText(34, 803)考虑到这一点。因此,“Page %d of”有效地绘制在(484, 803),这显然是标题区域。 canvas.moveText(550,803) 再往上,将页数放在文档的右上角,而不是在“第 X 页”文本之后 - 右上角 在“第 X 页”文本之后。
  • 啊-好的-我的错。我去掉了“国家”部分,因为我不想这样做,并且没有指出 moveText() 是相对的。
  • 将模板视为画布上的窗口是否更有用? - 这听起来是个好主意。表单 xobject 的画布是无尽的平原(实际上它是有限的,但非常大),表单 xobject 在画布上定义了一个矩形,其内容最终将可见。
猜你喜欢
  • 2020-04-26
  • 2023-03-12
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多