{"id":11632,"date":"2018-08-11T08:00:26","date_gmt":"2018-08-11T08:00:26","guid":{"rendered":"http:\/\/www.icterra.com\/java-reporting-made-easy-with-dynamicjasper\/"},"modified":"2021-01-29T08:35:09","modified_gmt":"2021-01-29T08:35:09","slug":"java-reporting-made-easy-with-dynamicjasper","status":"publish","type":"post","link":"https:\/\/www.icterra.com\/de\/java-reporting-made-easy-with-dynamicjasper\/","title":{"rendered":"Java: Reporting Made Easy with DynamicJasper"},"content":{"rendered":"
Author:\u00a0<\/strong>Emre MORG\u00dcL, Senior SW Engineer \u2013 Defence Application SW Group<\/p>\n <\/p>\n Reporting is one of the most crucial and fundamental part of almost every application. Unfortunately, this process can easily become a programmer\u2019s nightmare depending on demands of users. Programmers need powerful and flexible reporting tools to meet these requirements. Fortunately, there are many reporting tools available for Java. Most powerful and popular one of them is\u00a0JasperReports<\/em>\u00a0[1]<\/a>. It is quite configurative and provides various features that allow user to generate exceptionally detailed reports. However,\u00a0JasperReports<\/em>\u00a0requires a template to build a report, which complicates things and limits its flexibility. So, what happens if we want to generate dynamic reports?<\/p>\n DynamicJasper<\/em>\u00a0[2]<\/a>\u00a0is just the right tool for this purpose. It is built upon\u00a0JasperReports<\/em>\u00a0library. Therefore, it takes advantage of all the features\u00a0JasperReports<\/em>\u00a0provides. Besides, it is open source and extraordinarily easy to use. To create a dynamic report, all you need to do is have required libraries and write a few lines of code.<\/p>\n DynamicJasper<\/em>\u00a0offers different ways of creating a report. Essentially, it needs a\u00a0DynamicJasper<\/em>\u00a0object to represent a reporting table. To build this object, they provide\u00a0DynamicReportBuilder<\/em>\u00a0class which implements builder design pattern, therefore, it allows an easy and readable way of configuring the table. In addition,\u00a0DynamicJasper<\/em>\u00a0offers other types of\u00a0ReportBuilder<\/em>\u00a0classes that extend\u00a0DynamicReportBuilder<\/em>.<\/p>\n In my examples, I will use\u00a0FastReportBuilder<\/em>\u00a0class for simplicity because it automatically handles some of the non-crucial configurations.<\/p>\n Building Simple Report with a Single Table<\/strong><\/p>\n The first thing you need to do is create a\u00a0FastReportBuilder<\/em>\u00a0object and configure its general properties.<\/p>\n FastReportBuilder\u00a0reportBuilder\u00a0=\u00a0new<\/strong>\u00a0FastReportBuilder(); FastReportBuilder provides many configuration options and every setter method in this class returns itself. Therefore, these method calls can be chained and written in a single line of code. To setup page configurations, they even provide a\u00a0Page<\/em>\u00a0class that can be passed to the report builder as a parameter.<\/p>\n In this example, I covered some of the basic configurations such as setting the title as \u201cTable Name\u201d, page size as A4 and orientation as landscape. There are many other configurations options available in\u00a0FastReportBuilder,<\/em>\u00a0such as adding footer, header, page numbers etc.<\/p>\n FastReportBuilder\u00a0<\/em>has\u00a0addColumn()<\/em>\u00a0methods that accepts either various parameters or an\u00a0AbstractColumn<\/em>\u00a0object. Former ones offer less flexibility but can be used for simple tables.<\/p>\n for<\/strong>\u00a0(int<\/strong>\u00a0column\u00a0=\u00a01;\u00a0column\u00a0<=\u00a0numberOfColumns;\u00a0column++) { <\/p>\n Parameters for the\u00a0addColumn<\/em>() method used in this example, respectively, are given below:<\/p>\n There are other\u00a0addColumn()<\/em>\u00a0methods that accept different number of parameters but this one covers most of the essential configurations.<\/p>\n AbstractColumn\u00a0<\/em>gives user more control over columns. For this purpose, they provide the\u00a0ColumnBuilder<\/em>\u00a0class which implements builder design pattern.<\/p>\n for<\/strong>\u00a0(int<\/strong>\u00a0column\u00a0= 1;\u00a0column\u00a0<=\u00a0numberOfColumns;\u00a0column++) { Essentially, both of these methods do the same thing. However,\u00a0AbstractColumn<\/em>\u00a0offers many more configuration options and is easier to use.<\/p>\n Additionally, it is possible to set cell styles for both headers and details of the table. For this purpose, they provide the\u00a0Style<\/em>\u00a0class. It has configuration options for setting border, transparency, alignment, font, orientation, text color, background color etc.<\/p>\n Preparing the data structure for the generated table is the tricky part. To feed actual data into a table, we need to generate a separate\u00a0HashMap<\/em>\u00a0object for each row. Key value used while adding a column is critical in this step. For example, if we used key (property) \u2018idColumn<\/em>\u2019 for our column creation, we map data to that column as\u00a0HashMap.put(\u201cidColumn\u201d, DATA)<\/em>. Finally, we need to collect all these\u00a0HashMaps\u00a0<\/em>in a\u00a0List<\/em>\u00a0object (preferably an\u00a0ArrayList<\/em>). Each of these\u00a0HashMaps<\/em>\u00a0represents a single row of our table.<\/p>\n for<\/strong>\u00a0(int<\/strong>\u00a0row\u00a0= 1;\u00a0row\u00a0<=\u00a0numberOfRows;\u00a0row++) { JasperPrint<\/em>\u00a0object is our final report object, which contains the table along with inserted rows. We need to use a\u00a0DynamicReport<\/em>\u00a0object to create a\u00a0JasperPrint<\/em>\u00a0object. Calling our\u00a0FastReportBuilder<\/em>\u00a0object\u2019s\u00a0build()<\/em>\u00a0method converts it into a\u00a0DynamicReport<\/em>\u00a0object. Then we need to match our data structure with this\u00a0DynamicReport<\/em>\u00a0object.<\/p>\n DynamicReport\u00a0dynamicReport\u00a0=\u00a0reportBuilder.build(); Finally, we can export this generated report object into desired data format.\u00a0JasperReports<\/em>\u00a0provide many file exporter classes for different types of data format. Supported data formats in\u00a0JasperReports<\/em>\u00a0are PDF, HTML, XLS, RTF, ODT, CSV, TXT and XML. It is possible to set additional configurations while exporting into a file.<\/p>\n Excel Exporter Example: <\/p>\n PDF Exporter Example: <\/p>\n Additionally, you can use\u00a0JasperReports\u2019<\/em>\u00a0built-in\u00a0JasperViewer<\/em>\u00a0class to preview your final report. This viewer also allows user to print or save the report in any of the provided formats.<\/p>\n JasperViewer.viewReport<\/em>(finalReport);<\/p>\n Final PDF file generated in this example is shown below:<\/p>\n <\/p>\n Even though, this is the simplest report you can generate with\u00a0DynamicJasper<\/em>, it covers all the necessary steps needed for creating reports with variable number of columns and rows. Yet, it does not demonstrate any of the more advanced capabilities of\u00a0DynamicJasper<\/em>.<\/p>\n DynamicJasper<\/em>\u00a0is not limited to reports that only have a single table. On the contrary, it is possible to generate reports that have any number of concatenated tables and subreports. Besides, it provides many visual configurations that can be applied to these tables. Furthermore,\u00a0DynamicJasper<\/em>\u00a0offers various charts that can be easily generated and configured. Programmers can use these charts to produce complex reports. However, purpose of this post is simply to introduce\u00a0DynamicJasper<\/em>\u00a0and show its basics. Other topics will be covered thoroughly in the future.<\/p>\n REFERENCES<\/strong><\/p>\n\n
\n
\nPage\u00a0page\u00a0= Page.Page_A4_Landscape<\/em>();
\nreportBuilder.setTitle(\u201cTable Name\u201d)
\n.setPageSizeAndOrientation(page)
\n.setUseFullPageWidth(true<\/strong>)
\n.setReportName(\u201cReport Name\u201d);<\/p>\n
\n\n
\n
\nreportBuilder.addColumn(\u201cColumn \u201c\u00a0+\u00a0column,
\n\u201ckey\u201d\u00a0+\u00a0column,
\nString.class<\/strong>.getName(),
\n30);
\n}<\/p>\n
\n\n
\n
\nAbstractColumn\u00a0newColumn\u00a0=
\nColumnBuilder.getNew<\/em>()
\n.setColumnProperty(\u201ckey\u201d\u00a0+\u00a0column,
\nString.class<\/strong>.getName())
\n.setTitle(\u201cColumn \u201c\u00a0+\u00a0column)
\n.setWidth(30)
\n.build();
\nreportBuilder.addColumn(newColumn);
\n}<\/p>\n
\n\n
\n
\nList\u00a0rowsDataList\u00a0=\u00a0new<\/strong>\u00a0ArrayList();<\/span><\/p>\n
\nHashMap<String, String>\u00a0rowHashMap\u00a0=\u00a0new<\/strong>\u00a0HashMap<>();
\n\u00a0 \u00a0 \u00a0 \u00a0 for<\/strong>\u00a0(int<\/strong>\u00a0column\u00a0= 1;\u00a0column\u00a0<=\u00a0numberOfColumns;\u00a0column++) {
\nrowHashMap.put(\u201ckey\u201d\u00a0+\u00a0column,
\n\u201cRow\u201d\u00a0+\u00a0row\u00a0+\u00a0\u201d Column \u201c\u00a0+\u00a0column);
\n}
\nrowsDataList.add(rowHashMap);
\n}
\n<\/span><\/p>\n
\n\n
\n
\nJasperPrint\u00a0finalReport\u00a0=\u00a0DynamicJasperHelper.generateJasperPrint<\/em>(dynamicReport,
\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0new<\/strong>\u00a0ClassicLayoutManager(),
\nrowsDataList);<\/p>\n
\n\n
\n<\/strong><\/p>\n
\n
\nJRXlsExporter\u00a0xlsExporter\u00a0=\u00a0new<\/strong>\u00a0JRXlsExporter();
\nExporterInput\u00a0exporterInput\u00a0=\u00a0new<\/strong>\u00a0SimpleExporterInput(finalReport);
\nOutputStreamExporterOutput\u00a0exporterOutput\u00a0=\u00a0new<\/strong>\u00a0SimpleOutputStreamExporterOutput(filePath);
\nxlsExporter.setExporterOutput(exporterOutput);
\nxlsExporter.setExporterInput(exporterInput);
\n<\/span><\/p>\n
\nSimpleXlsReportConfiguration\u00a0configuration\u00a0=\u00a0new<\/strong>\u00a0SimpleXlsReportConfiguration();
\nconfiguration.setOnePagePerSheet(false<\/strong>);
\nconfiguration.setWhitePageBackground(true<\/strong>);
\nconfiguration.setRemoveEmptySpaceBetweenColumns(false<\/strong>);
\nxlsExporter.setConfiguration(configuration);
\n<\/span><\/p>\n
\nxlsExporter.exportReport();<\/span><\/p>\n
\n
\n<\/strong><\/p>\n
\n
\nJRPdfExporter\u00a0pdfExporter\u00a0=\u00a0new<\/strong>\u00a0JRPdfExporter();
\nExporterInput\u00a0exporterInput\u00a0=\u00a0new<\/strong>\u00a0SimpleExporterInput(finalReport);
\nOutputStreamExporterOutput\u00a0exporterOutput\u00a0=\u00a0new<\/strong>\u00a0SimpleOutputStreamExporterOutput(filePath);
\npdfExporter.setExporterOutput(exporterOutput);
\npdfExporter.setExporterInput(exporterInput);
\n<\/span><\/p>\n
\nSimplePdfReportConfiguration\u00a0configuration\u00a0=\u00a0new<\/strong>\u00a0SimplePdfReportConfiguration();configuration.setIgnoreHyperlink(true<\/strong>);
\npdfExporter.setConfiguration(configuration);
\n<\/span><\/p>\n
\npdfExporter.exportReport();<\/span><\/p>\n
\n
\n
\n