Java. Печатаем PDF отчеты на основе HTML шаблонов.
Однажды я столкнулся с ситуацией, когда мне нужно было быстро сделать функционал для печати одного отчета из Java, который был несложен по структуре данных, но должен был быть красиво оформлен (с определенными шрифтами, изображением и т.п.). Если формировать PDF программно из Java, этого добиться сложно. Как правило, для печати PDF отчетов по шаблону, в Java используются библиотеки вроде JasperReports, Apache PDFBox и пр. Следовательно, если использовать типичные библиотеки для формирования отчетов, то нужно в первую очередь разработать соответствующий шаблон отчета. И здесь я подумал: "один отчет, нужен дизайн шаблона. Быстро сделать дизайн? HTML/CSS!". Лень - двигатель прогресса. В итоге, я сделал печать PDF отчета на основе HTML шаблона. Приведу пример, который показывает, как можно получить PDF документ на основе HTML5 шаблона с произвольным дизайном. Разумеется, такой способ печати PDF не претендует на замену традиционных решений, но в некоторых случаях может быть полезен.
Итак, в качестве шаблона используется HTML5 документ, который определяет структуру и дизайн шаблона. Данные, которые необходимо отображть в PDF отчете будут заполняться в документе с помощью библиотеки JSoup. Затем, заполненный документ будет преобразовываться в PDF с помощью библиотеки Openhtmltopdf. В демонстрационном проекте будет использоваться следующая структура:
В папке fonts положим шрифт, который будем использовать в отчете (он необходим для формирования PDF документа). items_report.html - шаблон отчета. В папку print будет сохраняться итоговый PDF документ.
Шаблон для отчета выглядит таким образом:
<!DOCTYPE HTML> <html> <head> <title></title> <meta charset="utf-8"> <!-- CSS пропущен --> </head> <body> <h2>Перечень товаров</h2> <table id="goods-rows"> <tr class="header-row"> <td>Название</td> <td>Количество</td> <td>Цена, руб</td> <td>Наличие</td> </tr> <tr class="row-template"> <td class="name"></td> <td class="count"></td> <td class="price"></td> <td class="available"></td> </tr> </table> <h3>Дата отчета: <span id="date"></span></h3> </body> </html>
При заполнении отчета данными, в качестве селекторов будут использоваться id элемента. В это примере возможно заполнение отдельных полей, которые идентифицируются по id элемента, и заполнение таблиц, которые также ищутся в HTML документе по id. В таблице должна присутствовать строка с классом row-template. Селекторами для столбцов являются CSS классы.
В классе HTMLPrintUtil имеется статический метод, который заполняет HTML шаблон данными и возвращает байты сформированного PDF документа (полный код см. HTMLPrintUtil.java):
public static byte[] printPdfReport(String reportTemplate, Map<String, Object> data) throws Exception { Document report = fillReportTemplate(reportTemplate, data); org.w3c.dom.Document w3cDoc = DOMBuilder.jsoup2DOM(report); return buildPdfReportFromDocument(w3cDoc); }
Вызов печати (полный код см. Main.java) будет выглядеть таким образом:
public static void main(String [] args) { try { byte[] pdf = HTMLPrintUtil.printPdfReport("items_report.html", getTestData()); FileUtils.writeByteArrayToFile(new File("src/main/resources/print/goods.pdf"), pdf); } catch (Exception e) { e.printStackTrace(); } }
В результате вызова метода печати будет сформирован PDF документ такого вида:
Теги: java programming
comments powered by Disqus