Reputation: 778
I have an HTML code that I'm using in my report footer. However the height of this footer may vary according to the content of my HTML code. Is it possible to do some work to resize the height of my footer automatically according to the size of my code?
Footer.java
public class Footer extends PdfPageEventHelper {
protected ElementList footer;
public Footer(String html) throws IOException {
footer = XMLWorkerHelper.parseToElementList(html, null);
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
ColumnText ct = new ColumnText(writer.getDirectContent());
// In my case this rectagle is resizeable height
ct.setSimpleColumn(new Rectangle(36, 200, 559, 32));
for (Element e : footer) {
ct.addElement(e);
}
ct.go();
} catch (DocumentException de) {
throw new ExceptionConverter(de);
}
}
}
Upvotes: 2
Views: 1960
Reputation: 95918
Your footer does not appear to have any dynamic parts, differing from page to page. In that case you can simply start by rendering that html to some throw-away PDF and measuring its dimensions, and then use these dimensions to set margins of the actual document you create.
You can implement this approach e.g. using a page event listener class like this:
public static class Footer extends PdfPageEventHelper {
private final Rectangle boundingBox;
private final List<Element> elements;
private PdfTemplate template = null;
private float blankAfter = 0;
public Footer(String html, float width) throws DocumentException, IOException {
this(XMLWorkerHelper.parseToElementList(html, null), width);
}
public Footer(List<Element> elements, float width) throws DocumentException, IOException {
this.elements = elements;
try ( OutputStream os = new NullOutputStream() ) {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, os);
document.open();
Rectangle bbox = new Rectangle(0, 0, width, 1000);
float bottomLine = createTemplate(writer, bbox);
boundingBox = new Rectangle(width, bbox.getTop() - bottomLine);
template = null;
writer.setPageEmpty(false);
document.close();
}
}
float createTemplate(PdfWriter writer, Rectangle boundingBox) throws DocumentException {
template = writer.getDirectContent().createTemplate(10000, 10000);
template.setBoundingBox(boundingBox);
ColumnText columnText = new ColumnText(template);
Rectangle bbox = template.getBoundingBox();
columnText.setSimpleColumn(bbox.getLeft(), bbox.getBottom(), bbox.getRight(), bbox.getTop());
for (Element element : elements) {
columnText.addElement(element);
}
columnText.go();
return columnText.getYLine() + columnText.getDescender();
}
void ensureTemplate(PdfWriter writer) throws DocumentException {
if (template == null) {
createTemplate(writer, boundingBox);
}
}
public void setBottomMargin(Document document, float blankBefore, float blankAfter) {
float marginBottom = boundingBox.getHeight() + blankBefore + blankAfter;
document.setMargins(document.leftMargin(), document.rightMargin(), document.topMargin(), marginBottom);
this.blankAfter = blankAfter;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
ensureTemplate(writer);
Rectangle bbox = template.getBoundingBox();
Rectangle pageSize = document.getPageSize();
float x = pageSize.getLeft((pageSize.getWidth() - bbox.getWidth()) / 2f - bbox.getLeft());
float y = pageSize.getBottom(blankAfter - bbox.getBottom());
writer.getDirectContentUnder().addTemplate(template, x, y);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onEndPage(writer, document);
}
}
(StaticFooter helper class)
You apply it like this:
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(new File(RESULT_FOLDER, "StaticFooterShort.pdf")));
String html = "<p>Short Test Footer.</p>";
Footer footer = new Footer(html, document.right() - document.left());
writer.setPageEvent(footer);
footer.setBottomMargin(document, 10, 10);
document.open();
for (int i = 0; i < 200; i++) {
document.add(new Paragraph("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ..."));
}
document.close();
(StaticFooter test testShortFooter
)
PS: The NullOutputStream
class I used is an Apache Commons IO helper but you can easily implement something similar if you don't want that extra dependency, simply implement an OutputStream
that ignores all input.
Upvotes: 1