1. 概述
1.1 应用场景
FineReport 支持预览报表时将报表导出成各种通用的文件格式,如 PDF 、Excel 、Word 等;FineReport 设计器中也支持将模板导出成通用的文件格式或者内置数据模板。如下图所示:
如果用户不想通过预览报表或操作设计器导出文件,想直接后台导出,该如何实现呢?
1.2 实现思路
FineReport 提供了强大的输入输出功能,所有的这些输入输出的类都在 com.fr.report.io 包里面。
报表的输入指从报表的模板文件( XML 格式的 )创建 WorkBook 对象,在报表调用章节已经介绍过;输出则指将报表保存为各种格式文件,即通过编译 Java 程序调用工程资源后台将模板导出成 cpt 、内置数据 cpt 、PDF 、Excel 、Word 、SVG 、CSV 、image (包含 png 、 jpg 、gif 、bmp )等多种文件格式,导出后释放进程。
注:示例代码方案不支持 使用新计算引擎模板 的导出。
1.3 接口介绍
注:导出时,不同的预览方式将对应不同的计算结果报表代码。填报预览导出:Writeactor、分析预览导出:Viewactor,分页预览导出:PageActor
1)导出成内置数据集模板
导出成内置数据集模板就是将原模板的数据源根据参数条件查询出结果并转为内置数据集,然后把模板导出,不需要对原模板进行计算。代码如下:
/**将模板工作薄导出为内置数据集模板文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"EmbExport.cpt"));
EmbeddedTableDataExporter templateExporter = new EmbeddedTableDataExporter();
templateExporter.export(outputStream, workbook);
2)导出成模板文件
可以将原模板通过程序编辑后再次导出为模板文件,或者将某一路径下的模板保存至另一路径下。代码如下:
/**将模板工作薄导出为模板文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"TmpExport.cpt"));
((WorkBook) workbook).export(outputStream);
3)导出成 2003Excel 文件
模板工作薄 WorkBook 执行后为结果工作薄 ResultWorkBook,可以把计算后的结果导出成 2003Excel 文件。代码如下:
/**将结果工作薄导出为2003Excel文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"ExcelExport2003.xls"));
ExcelExporter ExcelExport = new ExcelExporter();
ExcelExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
4)导出 2007Excel 文件
模板工作薄 WorkBook 执行后为结果工作薄 ResultWorkBook,可以把计算后的结果导出成 20037Excel 文件。代码如下:
/**将结果工作薄导出为2007Excel文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"ExcelExport2007.xlsx"));
StreamExcel2007Exporter ExcelExport1 = new StreamExcel2007Exporter();
ExcelExport1.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
5)导出 Word 文件
注:FineReport 报表导出 Word 不支持导出悬浮元素,若您需导出的模板中包含悬浮元素如图表,请将其改为单元格元素如单元格中插入图表。
/**将结果工作薄导出为Word文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"WordExport.doc"));
WordExporter WordExport = new WordExporter();
WordExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
6)导出 PDF 文件
/**将结果工作薄导出为Pdf文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"PdfExport.pdf"));
PDFExporter PdfExport = new PDFExporter();
PdfExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
7)导出 Txt 文件
/**将结果工作薄导出为Txt文件(txt文件本身不支持表格、图表等,被导出模板一般为明细表)*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"TxtExport.txt"));
TextExporter TxtExport = new TextExporter();
TxtExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
8)导出 CSV 文件
/**将结果工作薄导出为Csv文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"CsvExport.csv"));
CSVExporter CsvExport = new CSVExporter();
CsvExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
9)导出 SVG 文件
/**将结果工作薄导出为SVG文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"SvgExport.svg"));
SVGExporter SvgExport = new SVGExporter();
SvgExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
10)导出 Image 文件
注:Image 图片支持 png、jpg、 gif、 bmp 格式,这里示例是 png 格式,默认为 jpg。
/**将结果工作薄导出为image文件*/
outputStream = new FileOutputStream(new java.io.File(outputUrl+"PngExport.png"));
ImageExporter ImageExport = new ImageExporter();
ImageExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()));
11)释放进程
通过导出 API 在后台导出 Excel 等文件,会产生很多进程,在导出完成之后添加如下代码可释放进程:
outputStream.close();
module.stop();
2. 示例
下面实现后台导出 GettingStarted.cpt 模板,参数为报表参数,且设置默认值为华东。
2.1 准备编译环境
编译程序前,需先创建一个 Java 工程环境,并且需要一个 Java 编辑器,如 Eclipse 或 idea 。
在编辑器工程中引入 FineReport 工程 JAR 包。包括安装的报表工程
%FR_HOME%\webapps\webroot\WEB-INF\lib目录下 fine 开头的 13 个 JAR 包。
%FR_HOME%\webapps\webroot\WEB-INF\lib目录下的 sqlite-jdbc.jar
%Tomcat_HOME%\libTomcat目录下的 servlet-api.jar
%JAVA_HOME%\jdk\lib JDK 目录下的 tools.jar
slf4j-simple-1.7.25.jar ,点击可下载:slf4j-simple-1.7.25.jar
如果报表中需要查询数据库,还需要导入对应的 jdbc 驱动或者插件的 JAR 包(如使用 JSON 数据集,就要引入 JSON 数据集插件下的 JAR 包)。
详细引入过程可参考:编译Java程序
2.2 编写 Java 程序
在编辑器中编写 Java 程序 ExportApi.java,即引入必要类后,获取模板,将模板导出成指定格式的文件。完整代码可参见:
注1:代码中 StateServiceActivator 是针对 2020.4.26 JAR 包之后的改动,若之前版本报错将其改为 StateServerActivator 即可。
注2:用户使用时,注意将示例代码中的工程路径、模板名称和导出路径替换为用户自己工程下的。
普通报表 cpt 代码:
https://code.fanruan.com/demo/example/src/branch/persist/10.0/src/main/java/com/fr/io/ExportApi.java
决策报表 frm 代码:
2.3 编译 Java 文件
Java 程序编写完成后,在编译器中编译 ExportApi.java ,编译通过后,运行java代码,就会在代码中导出路径的文件夹下生成不同格式的文件,这样就导出成功了。如下图所示:
如果想自动触发程序导出,可以通过 Java 写定时任务触发执行;也可以通过「定时调度>自定义附件处理」功能实现定时触发。如下图所示:
了解自定义附件处理功能可查看:自定义上传文件至磁盘
3. 注意事项
3.1 FineDB 锁死
问题描述:
运行编译好的代码时,会弹出错误提示:SQLException : Database lock acquisition failure: lockFile:.....。如下图所示:
原因分析:
导出的时候启用了运行环境,如打开了设计器,因为报表内置的数据库为 HSQL 数据库,HSQL 数据库不能多线程访问,所以在导出时启用运行环境就会把 FineDB 锁死,导出时报错。
解决方案:
方法一:
关闭 java 编辑器,如 idea、 Eclipse 进程,将代码中导出模板工程 %FR_HOME%\webapps\webroot\WEB-INF\embed\finedb 下的 db.lck 文件删除,再次打开java 编辑器运行代码运即可。
注:该方法在运行一次后仍会报错,需要反复删除 db.lck 文件。
方法二:
报表工程内置的 HSQL 数据库不能多线程访问,可以将其迁移为其他数据库。迁移方法可参考文档:配置外接数据库