当前位置: 首页 > 知识库问答 >
问题:

iText 7动态页眉问题

哈扬
2023-03-14

我正在尝试使用EventHandlers使用itext7创建动态页面标题。我正在为此使用以下代码:

    public static void main(String[] args) throws Exception {
    File file = new File("C:\\Test\\variable_header.pdf");
    file.getParentFile().mkdirs();
    new VariableHeader().manipulatePdf(DEST);
}

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
    Document doc = new Document(pdfDoc);
    VariableHeaderEventHandler handler = new VariableHeaderEventHandler();
    pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, handler);
    handler.setHeader("First Header");
    for (int i = 1; i <= 50; i++) {
        doc.add(new Paragraph("Added First content"));
     }
    doc.add(new AreaBreak());
    handler.setHeader("Second Header");
    for (int i = 1; i <= 15; i++) {
        doc.add(new Paragraph("Added Second content"));
    }
    doc.close();
}

protected class VariableHeaderEventHandler implements IEventHandler {
    protected String header;

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

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
        try {
            new PdfCanvas(documentEvent.getPage())
                    .beginText()
                    .setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12)
                    .moveText(450, 806)
                    .showText(header)
                    .endText()
                    .stroke();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

在这里,我创建了“VariableHeaderEventHandler”,它为文档的每一页呈现动态页眉。

最初,我将页面标题设置为“第一个标题”,并将文本“添加第一个内容”添加到文档中50次。然后我添加了区域分隔符,在渲染之前的内容后,该分隔符将使页面的另一部分是空的,任何进一步的内容都将在新页面中渲染。然后我将页面标题更改为“第二个标题”,并在文档中添加了15次“添加了第二个内容”的文本。

因此,根据上述代码,页面标题“第二个标题”应仅从显示文本“添加的第二个内容”的页面呈现。但“第二个标题”在上一页中呈现,其中显示文本“添加的第一个内容”,如下所示:

iText7动态头问题:

iText 7.0.1中的事件处理机制似乎存在一些问题。

有没有办法解决这个问题?任何帮助都将不胜感激。

共有1个答案

晋骏喆
2023-03-14

您正在使用PdfDocument的低级事件以及通过Document的高级布局<代码>结束页面事件在页面刷新到输出流时触发。虽然低级PdfDocument和高级文档是相关的,但是没有一个契约会在页面转到新页面后立即刷新页面。事实上,Document确实会在默认情况下以一定的延迟刷新页面,这是更细粒度的布局功能所需要的。页面被延迟刷新的事实导致新设置的标题出现在第一类内容的“旧”页面上。所以这是预期的行为,至少目前是这样。

有很多方法可以绕过这种行为,实现你想要的。我将讲述其中一个。

AreaBreak添加到文档后,您可以向DocumentRenderer询问可用于呈现其余内容的当前区域,该区域将包含当前页码:

doc.add(new AreaBreak());
int secondContentStartPageNumber = doc.getRenderer().getCurrentArea().getPageNumber();

然后,您可以将该信息传递给事件处理程序:

handler.setSecondAreaStartPage(secondContentStartPageNumber);

并在决定为页面输出哪个标题时使用该信息:

int pageNumber = documentEvent.getDocument().getPageNumber(documentEvent.getPage());
String textToShow = pageNumber < secondAreaStartPage ? firstHeader : secondHeader;

完整的VariableHeaderEventHandler类如下所示:

protected class VariableHeaderEventHandler implements IEventHandler {
    private String firstHeader = "First Header";
    private String secondHeader = "Second Header";
    private int secondAreaStartPage = Integer.MAX_VALUE;

    public void setSecondAreaStartPage(int newValue) {
        secondAreaStartPage = newValue;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
        int pageNumber = documentEvent.getDocument().getPageNumber(documentEvent.getPage());
        try {
            new PdfCanvas(documentEvent.getPage())
                    .beginText()
                    .setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12)
                    .moveText(450, 806)
                    .showText(pageNumber < secondAreaStartPage ? firstHeader : secondHeader)
                    .endText()
                    .stroke();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

当然,对于两个以上的区域,代码会变得更加复杂,但这更多的是一个编程练习,而不是一个关于iText的问题。

 类似资料:
  • 我最近在Spring开始使用thymeleaf模板引擎。我想实现的是-如果我的控制器是这样的 我更喜欢把头部部分作为页眉片段,内容来自控制器,页脚来自页脚片段。 所以总的来说--我是如何做到这一点的: /fragment/header.html http://www.thymeleaf.org/doc/articles/layouts.html https://looksok.wordpress.

  • 我正在尝试从预定义的HTML内容生成PDF。我设法生成了内容,但没有所需的HTML页眉、HTML页脚和阿拉伯语也不受支持。 我的要求: > 阿拉伯语支持。 生成超过10页的能力。 页脚可能因页而异。 有一个Web应用程序向WCF服务发送请求,该服务返回一个包含PDF的字节数组。 所以,我一直在寻找一个好的工具,我发现SelectPdf,它是完美的,除了它不是免费的,所以唯一的解决方案是IText7

  • 我试图创建一个带有页眉和页脚的PDF。页眉和页脚都是图像。由于我的pdf创建了随机数量的页面,我需要自动将其添加到每一页。我知道我需要使用某种eventhandler。不幸的是,我找不到vb.net语言中的任何示例,我只能找到java/C#示例,我真的不擅长阅读/转换这些语言vb.net.我还不是编程专家。 谁能给我指一下正确的方向吗。 Edit4:删除的随机内容不再需要回答我的问题。 下面这段代

  • 我当前正试图添加一个链接到pdf文档的页脚页眉,但是库给出了以下错误System.IndexoutOfrangeException:“请求的页码0已超出范围。”当使用IText7库将链接添加到标头时。 我在IText7中找不到任何关于这个问题的在线代码示例,ITextSharp中的解决方案不再适用。 我的问题是我如何添加一个链接到一个外部网站到PDF的标题?当前的行为是库中的bug还是有意的? 包

  • 我想将我的导航从透明背景更改为白色背景。导航应该缩小,徽标应该消失。 它应该与此页面上的完全相同:https://www.praxis-loeber.de 我已经为它编写了jQuery代码,但不幸的是,它仍然不起作用。 如果有人能告诉我错误在我的代码中,我会非常高兴。 这是我的代码:

  • 问题内容: 静态HTML /XHTML是否有一种不错的方法来创建要显示在网站的每个页面上的通用页眉/页脚文件?我知道您显然可以使用PHP或服务器端指令来执行此操作,但是有没有办法完全不依赖服务器将所有内容拼接在一起呢? 编辑:所有非常好的答案,这是我所期望的。HTML是静态的。没有运行服务器端或客户端的东西,没有真正的方法来改变它。我发现Server Side Includes似乎是我最好的选择,