1. 概述编辑
FineReport 提供了强大的输入输出功能,所有的这些输入输出的类都在 com.fr.report.io 包里面。
报表的输入指从报表的模板文件( XML 格式的 )创建 WorkBook 对象,在报表调用章节已经介绍过。
输出则指将报表保存为各种格式文件,FineReport 支持将报表保存为 cpt 、内置数据 cpt 、PDF 、Excel 、Word 、SVG 、CSV 、image (包含 png 、 jpg 、gif 、bmp )等多种文件格式,释放导出进程。
2. 原理编辑
我们以 Parameter.cpt 模板作为被导出模板,参数为报表参数,且设置默认值为华东。
2.1 导出成内置数据集模板
导出成内置数据集模板,顾名思义是将原模板的数据源根据参数条件查询出结果并转为内置数据集,然后把模板导出,不需要对原模板进行计算(数据列扩展、公式计算等)。
// 将未执行模板工作薄导出为内置数据集模板
outputStream = new FileOutputStream(new File("C:\\test\\EmbExport.cpt"));
EmbeddedTableDataExporter templateExporter = new EmbeddedTableDataExporter();
templateExporter.export(outputStream, workbook)
当要导出模板的数据集使用的是文件数据集 XML 的时候,需要多传一个参数:parameterMap,代码如下:
// 将未执行模板工作薄导出为内置数据集模板
outputStream = new FileOutputStream(new File("C:\\test\\EmbExport.cpt"));
EmbeddedTableDataExporter templateExporter = new EmbeddedTableDataExporter();
templateExporter.export(outputStream, workbook, parameterMap)
2.2 导出模板文件
我们可以将原模板通过程序编辑后再次导出为模板文件,或者将某一路径下的模板保存至另一路径下。
// 将模板工作薄导出模板文件,在导出前您可以编辑导入的模板工作薄,可参考报表调用章节
outputStream = new FileOutputStream(new File("C:\\test\\TmpExport.cpt"));
((WorkBook) workbook).export(outputStream)
2.3 导出 2003Excel 文件
模板工作薄 WorkBook 执行后为结果工作薄 ResultWorkBook,我们可以把计算后的结果导出成 Excel 文件。
// 将结果工作薄导出为 2003Excel 文件
outputStream = new FileOutputStream(new File("C:\\test\\ExcelExport.xls"));
ExcelExporter ExcelExport = new ExcelExporter();
ExcelExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
注1:导出 Excel 的其他格式可以参考文档:Excel导出的多种方式
注2:如果需要导出 2007 版 Excel,需要将 ExcelExporter ExcelExport = new ExcelExporter()改成StreamExcel2007Exporter ExcelExport = new StreamExcel2007Exporter();
具体代码如下:
// 将结果工作薄导出为 Excel 文件
outputStream = new FileOutputStream(new File("C:\\test\\ExcelExport.xlsx"));
StreamExcel2007Exporter ExcelExport1 = new StreamExcel2007Exporter();
ExcelExport1.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
2.4 导出 Word 文件
// 将结果工作薄导出为 Word 文件
outputStream = new FileOutputStream(new File("C:\\test\\WordExport.doc"));
WordExporter WordExport = new WordExporter();
WordExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
注:FineReport 报表导出 Word 不支持导出悬浮元素,因此若您需导出的模板中包含有悬浮元素如图表,请将其改为单元格元素。
2.5 导出 PDF 文件
// 将结果工作薄导出为 PDF 文件
outputStream = new FileOutputStream(new File("C:\\test\\PdfExport.pdf"));
PDFExporter PdfExport = new PDFExporter();
PdfExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
2.6 导出 Txt 文件
// 将结果工作薄导出为 Txt 文件(txt 文件本身不支持表格、图表等,被导出模板一般为明细表)
outputStream = new FileOutputStream(new File("C:\\test\\TxtExport.txt"));
TextExporter TxtExport = new TextExporter();
TxtExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
2.7 导出 CSV 文件
// 将结果工作薄导出为 CSV 文件
outputStream = new FileOutputStream(new File("C:\\test\\CsvExport.csv"));
CSVExporter CsvExport = new CSVExporter();
CsvExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
2.8 导出 SVG 文件
//将结果工作薄导出为 SVG 文件
outputStream = new FileOutputStream(new File("C:\\test\\SvgExport.svg"));
SVGExporter SvgExport = new SVGExporter();
SvgExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
2.9 导出 Image 文件
//将结果工作薄导出为 image 文件
outputStream = new FileOutputStream(new File("C:\\test\\PngExport.png"));
ImageExporter ImageExport = new ImageExporter();
ImageExport.export(outputStream, workbook.execute(parameterMap, new WriteActor()))
注:Image 图片支持 png、jpg、 gif、 bmp 格式,这里示例是 png 格式,默认为 jpg。
2.10 释放进程
通过导出 API 在后台导出 Excel 等文件,会产生很多进程,通过下面的方案释放进程。
在导出完成之后添加下面代码:
outputStream.close();
ModuleContext.stopModules()
3. 示例编辑
3.1 CPT 模板导出代码
代码见链接:ExportApi.java
注1:代码中的 StateServiceActivator 并没有引用错,这是针对新版本的改动,如果用户代码报错,把它改为 StateServerActivator 即可。
注2:在使用 API 导出不同类型文件时,需要导入的 JAR 包如下:
FineReport 默认 JAR 包
%FR_HOME%\webroot\WEB-INF\lib目录下的 sqlite-jdbc.jar
%Tomcat_HOME%\lib目录下的 serverlet-api.jar
%JAVA_HOME%\jdk\lib目录下的 tools.jar
点击下载并导入:slf4j-simple-1.7.25.jar
编译运行该代码后,就会在对应的文件夹下生成不同格式的文件,这样就导出成功了,如下图所示:
3.2 FRM 表单导出代码
代码见链接:ExportApi_frm.java
注:代码中的 StateServiceActivator 并没有引用错,这是针对新版本的改动,如果用户代码报错,把它改为 StateServerActivator 即可。
4. 注意事项编辑
4.1 错误代码1120
1)问题描述
运行编译好的代码时,会弹出错误提示:错误代码1120,当前 Hsql 数据库已被另一线程锁定。
2)原因分析
导出的时候使用了运行环境,所以会把 db.lck 给死锁,导出一次后再次导出就会报错。
3)解决方案
方法一:
关闭 Eclipse 进程,%FR_HOME%\webapps\webroot\WEB-INF\embed\finedb下的 db.lck 文件删除,再次运行 Eclipse 即可。
注:该方法在运行一次后仍会报错,需要反复删除 db.lck 文件。
方法二:
迁移平台数据,详细内容参见文档:配置外接数据库
4.2 角标打印失效
1)问题描述
如果报表的文字内容中包含特殊的角标,例如下图所示的化学符号角标:
API 导出后,角标的效果跟预览的效果不一致,如下图所示:
2)原因分析
后台 API 不支持导出角标。
3)解决方案
可以利用导出 URL 接口将文件导出到 JVM 内存里面,然后从内存里面利用字节输出流写出到操作系统指定盘符,代码如下:
package com.fr.io;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class testUrl {
public static void main(String[] args){
String pdfPath = "D:"+File.separator+"TEST.pdf";
try {
URL url = new URL("http://localhost:8020/FR10/decision/view/report?viewlet=WorkBook48.cpt&format=pdf&aa=9");
URLConnection connection = url.openConnection();
BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
FileOutputStream outputStream = new FileOutputStream(new File(pdfPath));
byte[] buff = new byte[1024];
int byteRead;
while (-1!=(byteRead=bis.read(buff,0,buff.length))){
outputStream.write(buff,0,byteRead);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注:Web工程也可以调用性能插件的 PDF 打印方法显示角标,但是实现方式与文档中提供的代码不一样。代码不需要额外写 startModule,否则插件效果不会生效。