4

A common use of Freemarker is the generation of a PDF.

Unfortunally I have to generate a pdf with a lot of pages and "they" asking me to put an header with some information and a footer with somethings like "page 2/60" etc...

Searching on web I found how to create a Macro template but it only share some common tags (like css) but it doesn't tell freemarker how to manage multipage PDF.

In addition to this, sometimes I have, inside ftl, a "page-break css class" so I cant determine when and where a new page is created.

Im using Freemakrer 2.3 on Java

Thanks for any help.

MrMime
  • 665
  • 4
  • 10
  • 24
  • I have used Freemarker for template engine only, as Smarty for PHP. I would rcomand POI to use it for PDF –  May 21 '13 at 13:06
  • It's not a choice of mine. They use freemarker and so I have to. – MrMime May 21 '13 at 13:11
  • What do you generate with Freemarker ? An HTML document which is then transformed into PDF with another tool, or directly the PDF document ? – obourgain May 21 '13 at 13:44
  • We start with HTML filled by a Map to match freemarker place-holders with: final String xhtml = createXHTML("foo.ftl.html", mapFullOfThings); Than we create a byte[] "pdf" and finally handler = new ResourceStreamRequestHandler(new ByteArrayResourceStream(pdf, "application/pdf")); – MrMime May 21 '13 at 13:58
  • One step is missing in your description. Freemarker generates an HTML document (String xhtml variable). This HTML is then converted to a PDF (byte[] pdf variable). What tool do you use for this transformation ? – obourgain May 21 '13 at 16:06
  • As written below, I use freemarker template function to make substitution from template to placeholder on HTML file. String result (xhtml) is passed to these: InputStream is = new ByteArrayInputStream(xhtml.getBytes()); Tidy td = new Tidy(); td.setXHTML(true); td.parse(is, reportStreamTidy); final ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(reportStreamTidy.toString()); renderer.layout(); renderer.createPDF(reportStream); return reportStream.toByteArray(); – MrMime May 22 '13 at 07:26
  • After you generated the PDF with HTML, you can reuse IText to generate the PDF again with the page numbers. No need to do it in the HTML. How to do this has been answered [here](http://stackoverflow.com/questions/759909/how-to-add-total-page-number-on-every-page-with-itext). – Tom Verelst May 24 '13 at 10:46

1 Answers1

1

You can specify a header and a footer (including page numbers) with CSS. This will work if the tool used to transform your XHTML into the PDF byte array supports the paged media instructions.

In the CSS:

@page { 
    @top-center {content: element(header)}      /* Header */
    @bottom-center {content: element(footer)}   /* Enpied */
}
#header {position: running(header);}
#footer {position: running(footer);}
#pagenumber:before {content: counter(page);}
#pagecount:before {content: counter(pages);}

In the HTML:

<div id="header">YOUR HEADER HERE</div>
<div id="footer">Page <span id="pagenumber" /> / <span id="pagecount" /></div>
obourgain
  • 8,856
  • 6
  • 42
  • 57
  • With this solution I have the header in the first page and the footer in the last page with the text: "Page 54/54". – MrMime May 21 '13 at 15:34
  • XHTML function is only: Template template = freemarkerConfig.getTemplate(templateName + ".ftl.html", Constants.DEFAULT_ENCODING); StringWriter writer = new StringWriter(); template.process(mapFullOfThings, writer); return writer.toString(); Template is a freemarker class: package freemarker.template; – MrMime May 21 '13 at 15:48