\n\n\n\n\nI was on pager duty and a user hit Export to Excel right before a big meeting. The spinner felt like a staring contest. Tomcat was fine, CPU was bored, yet the report took ages. I cracked open the logs, watched JasperReports fill pages like a careful scribe, and realized the export was not slow by accident. It was slow by design choices we made months earlier. That night turned into my checklist for
speedy PDF and XLS exports without touching business logic. Here is the short list I keep on my desk. \n\n\n\nWhat actually slows your report\n\n\n\nThe heavy cost lives in three places.
Data fetch,
layout decisions, and
exporter settings. Compiling JRXML on every request is a tax you can avoid: compile once, cache the JasperReport, and reuse it. For big lists, set the JDBC fetch size and keep the result stream moving. Subreports are great for reuse, but too many of them can stall the fill step, so cache subreport JasperReports as well and pass data sources instead of making each one hit the database again. When rows are many, use a
JRVirtualizer so large pages are swapped to disk and your heap stays calm. \n\n\n\nIf the report is going only to Excel,
ignore pagination during fill. JasperPrint can be created as a long flow with no page breaks, which makes the XLS exporter breathe. Layout matters more than we like to admit. Overlapping elements and lots of stretch rules force Jasper to compute bounds for every row. Keep elements aligned to a grid and avoid repeated resizes. Images and big vector shapes make exporters work harder than necessary, so remove what does not help the reader. \n\n\n\nMake PDF faster without losing quality\n\n\n\nPDF speed usually sinks because of fonts and images. If you do not need to embed fonts, do not. Jasper lets you pick the
pdfFontName and whether it is embedded. Base 14 fonts like Helvetica render everywhere and keep files small. Turn on compression in the PDF exporter. Resize images before the report sees them and prefer JPEG for photos. Avoid transparent PNG layers since blending is pricey. Lines and rectangles are cheap, but gradients and complex shapes add work. Keep text as text, not as images, so the reader can search and copy. \n\n\n\n
// PDF exporter with compression and cached report\nJasperReport report = getCached("invoice.jasper"); // your cache\nMap<String,Object> params = new HashMap<>();\n\n// Virtualizer for large prints\nJRFileVirtualizer v = new JRFileVirtualizer(50, "/tmp/jasper");\nparams.put(JRParameter.REPORT_VIRTUALIZER, v);\n\nJasperPrint print = JasperFillManager.fillReport(report, params, dataSource);\n\nJRPdfExporter pdf = new JRPdfExporter();\npdf.setParameter(JRExporterParameter.JASPER_PRINT, print);\npdf.setParameter(JRExporterParameter.OUTPUT_STREAM, out);\npdf.setParameter(JRPdfExporterParameter.IS_COMPRESSED, Boolean.TRUE);\npdf.exportReport();\n\nv.cleanup();
\n\n\n\n
\n<textElement>\n <font pdfFontName="Helvetica" isPdfEmbedded="false"/>\n</textElement>
\n\n\n\nXLS that opens fast and looks right\n\n\n\nExcel readers want data over perfect print layout. The
JRXlsExporter is quick when fed a clean grid. Avoid overlapping elements and remove empty vertical gaps. Detect cell types so numbers stay numbers. Turn off white page backgrounds and do not split by page unless you really want separate sheets. Ignore graphics for pure data exports. If the report exists only for Excel, set ignore pagination during fill and let the sheet grow as needed. \n\n\n\n
// Fill without pagination for Excel\nMap<String,Object> xlsParams = new HashMap<>();\nxlsParams.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);\n\nJasperPrint xlsPrint = JasperFillManager.fillReport(report, xlsParams, dataSource);\n\n// Fast XLS export settings\nJRXlsExporter xls = new JRXlsExporter();\nxls.setParameter(JRExporterParameter.JASPER_PRINT, xlsPrint);\nxls.setParameter(JRExporterParameter.OUTPUT_STREAM, out);\nxls.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);\nxls.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);\nxls.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);\nxls.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);\nxls.setParameter(JRXlsExporterParameter.IS_IGNORE_GRAPHICS, Boolean.TRUE);\nxls.setParameter(JRXlsExporterParameter.IS_COLLAPSE_ROW_SPAN, Boolean.TRUE);\nxls.exportReport();
\n\n\n\nData and memory tips that pay off right away\n\n\n\nFor large exports, no trick beats moving fewer bytes. Select only the columns you print. Use a
forward only result set and set a fetch size that the driver respects. On some databases you get streaming with a special fetch size, so test with your driver. Keep the fill cycle short by using a prepared statement and simple expressions inside the report. Cache compiled reports in a static map at startup and watch cold starts vanish from the logs. \n\n\n\n
// Streaming fetch for large result sets\nStatement st = conn.createStatement(\n ResultSet.TYPE_FORWARD_ONLY,\n ResultSet.CONCUR_READ_ONLY\n);\nst.setFetchSize(500); // adjust per driver\nResultSet rs = st.executeQuery(sql);\n\nJRResultSetDataSource ds = new JRResultSetDataSource(rs);\nJasperPrint p = JasperFillManager.fillReport(report, params, ds);
\n\n\n\nJRVirtualizer saves memory by swapping big chunks to disk. Keep the swap path on a fast disk and right size the page count. Release the virtualizer after export. For subreports, pass the parent virtualizer down so every piece shares the same pool. If you run inside a servlet, reuse exporters per request and close streams with a try finally. These small bits do not look fancy, yet they turn red bars on the dashboard into short green blips. \n\n\n\nSummary\n\n\n\nTo speed
exporting to PDF and XLS with JasperReports, think in layers. Feed less data. Keep the layout simple. Fill once with smart defaults like
ignore pagination for Excel and a
virtualizer for big runs. For PDF, avoid font embedding and enable compression. For XLS, detect cell types and skip graphics. Cache compiled reports so the CPU spends time on your users instead of on your templates. The easiest wins come from exporter settings and layout discipline. The rest is patience and a coffee while the first timed run proves you got it right. \n