How to add HTML headers and footers to a page?
Why is there an error when there are 2+ pages?
We want to add HTML headers and footers to a document. Currently, we have extended PdfPageEventHelper
and overriden the onStartPage()
and onEndPage()
methods. This works fine for the first page, but it throws a RuntimeWorkerException
when we get to 2+ pages.
@Override void onStartPage(PdfWriter writer, Document document) { InputStream is = new ByteArrayInputStream(header?.getBytes()); XMLWorkerHelper.getInstance().parseXHtml(writer, document, is); } @Override void onEndPage(PdfWriter writer, Document document) { InputStream is = new ByteArrayInputStream(footer?.getBytes()); XMLWorkerHelper.getInstance().parseXHtml(writer, document, is); }
Posted on StackOverflow on Oct 28, 2015 by froi
It is forbidden to add content in the onStartPage()
event in general. It is forbidden to add content to the document
object in the onEndPage()
. You should add your header and your footer in the onEndPage()
method using PdfWriter
, NOT document. Also: you are wasting plenty of CPU by parsing the HTML over and over again.
Please take a look at the HtmlHeaderFooter example.
It has two snippets of HTML, one for the header, one for the footer.
public static final String HEADER =
"<table width=\"100%\" border=\"0\"><tr><td>Header</td><td align=\"right\">Some title</td></tr></table>";
public static final String FOOTER =
"<table width=\"100%\" border=\"0\"><tr><td>Footer</td><td align=\"right\">Some title</td></tr></table>";
Note that there are better ways to describe the header and footer than by using HTML, but maybe it's one of your requirements.
We will read these HTML snippets only once in our page event and then we'll render the elements over and over again on every page:
public class HeaderFooter extends PdfPageEventHelper {
protected ElementList header;
protected ElementList footer;
public HeaderFooter() throws IOException {
header = XMLWorkerHelper.parseToElementList(HEADER, null);
footer = XMLWorkerHelper.parseToElementList(FOOTER, null);
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
ColumnText ct = new ColumnText(writer.getDirectContent());
ct.setSimpleColumn(new Rectangle(36, 832, 559, 810));
for (Element e : header) {
ct.addElement(e);
}
ct.go();
ct.setSimpleColumn(new Rectangle(36, 10, 559, 32));
for (Element e : footer) {
ct.addElement(e);
}
ct.go();
} catch (DocumentException de) {
throw new ExceptionConverter(de);
}
}
}
Do you see the mechanism we use to add the Element
objects obtained from XML Worker? We create a ColumnText
object that will write to the direct content of the writer
(using the document
is forbidden). We define a Rectangle
and we are using go()
to render the elements.
The results is shown in html_header_footer.pdf.