资源描述
FineReport报表二次开发
在大多数情况下FineReport都可以完全满足用户制作各种报表的需求,但是为了能够满足个别用户的个性化需求,FineReport提供了丰富二次开发接口,方便用户将FineReport和自己的项目实现无缝结合,用户在进行二次开发的工程中可以更加深入的体会到FineReport工具的强大功能。
例如:在一些特殊领域,可能需要一些特殊的函数。或者要将某个模板文件通过指定的打印机打印等等。
目录
Report的输入输出………………………………………………………… 3
单元格格式设置……………………………………………………………… 7
将模板通过指定打印机打印………………………………………………… 10
自定义函数…………………………………………………………………… 12
URL 传递参数……………………………………………………………… 22
向报表中添加单元格…………………………………………………………25
读取单元格内容………………………………………………………………29
创建程序网络模版……………………………………………………………32
读取模板报表…………………………………………………………………36
Report的输入输出
FineReport提供了强大的输入输出功能,所有的这些输入输出的类都在com.fr.report.io包里面。Report的输入指从报表的模板文件(XML格式的)创建Report对象,输出指将Report保存为模板文件,FineReport还支持将Report保存为PDF,Excel,Word,SVG,HTML,CSV等文件格式。
· 读取模板文件
· 保存成模板文件
· 输出成PDF文件
· 输出成Word文件
· 输出成Excel文件
· 输出成文本文件
· 可执行代码
读取模板文件
// 读取模板
File cptFile = new File("D:\\stuff.cpt");
TemplateImporter templateImporter = new TemplateImporter(); WorkBook workBook = (WorkBook)templateImporter.generate(cptFile);
Stuff.cpt是用报表设计器生成的模板文件。只需要用建立一个TemplateImporter对象, 然后调用它的generateReport()方法来产生一个Report对象,同时可以将产生的Report对象强制转换成WorkSheet或者GroupReport。
保存成模板文件
// CPT
// 清空公式计算结果
E:\\newtemplate\\stuff.cpt这个是导出后新文档生成的地址
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.cpt"));
TemplateExporter templateExporter = new TemplateExporter();
templateExporter.export(outputStream,workBook.execute(parameterMap)) ;
通过调用TemplateExporter的exportReport(...)方法, 可以把Report对象以CPT格式保存到外部磁盘文件当中。
可执行代码
读取报表模板stuff.cpt,再分别保存为stuff.cpt,stuff.pdf和stuff.xls。
package com.fr.demo;
import java.io.File;
import java.io.FileOutputStream;
import com.fr.base.FRContext;
import com.fr.base.dav.LocalEnv;
import com.fr.report.WorkBook;
import com.fr.report.core.ReportHelper;
import com.fr.report.io.ExcelExporter;
import com.fr.report.io.PDFExporter;
import com.fr.report.io.TemplateExporter;
import com.fr.report.io.TemplateImporter;
import com.fr.report.io.TextExporter;
import com.fr.report.io.WordExporter;
/**
* 演示如何导入导出模板
* @author edgar duan
* @version 6.5
*/
public class ReportIO {
/**
* @param args
*/
public static void main(String[] args) {
// 报表运行环境路径, WEB-INF目录所放的位置
String envPath = "C:/FineReport6.5/WebReport/WEB-INF";
// 设置当前报表运行环境, 报表预览时需要一个运行环境
// 没有WEB-INF目录时, 路径设置为null. FRContext.setCurrentEnv(new LocalEnv(null));
FRContext.setCurrentEnv(new LocalEnv(envPath));
try {
// 读取模板
File cptFile = new File("D:\\stuff.cpt");
TemplateImporter templateImporter = new TemplateImporter();
WorkBook workBook = (WorkBook)templateImporter.generate(cptFile);
java.util.Map parameterMap = new java.util.HashMap();
FileOutputStream outputStream;
//生成 CPT
// 清空公式计算结果
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.cpt"));
TemplateExporter templateExporter = new TemplateExporter();
templateExporter.export(outputStream, workBook.execute(parameterMap)) ;
//生成 PDF
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.pdf"));
PDFExporter pdfExporter = new PDFExporter();
pdfExporter.export(outputStream, workBook.execute(parameterMap)) ;
// 生成DOC
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.doc"));
WordExporter wordExporter = new WordExporter();
wordExporter.export(outputStream,workBook.execute(parameterMap));
// 生成XLS
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.xls"));
ExcelExporter excelExporter = new ExcelExporter();
excelExporter.export(outputStream,workBook.execute(parameterMap));
//生成 TXT
ReportHelper.clearFormulaResult(workBook);
outputStream = new FileOutputStream(new File("E:\\newtemplate\\stuff.txt"));
TextExporter textExporter = new TextExporter(); textExporter.export(outputStream,workBook.execute(parameterMap));
} catch(Exception e) {
e.printStackTrace();
}
}
}
单元格格式设置
// 新建一个单元格, 位置为(2, 2), 列宽为2
// 行高为 2, 值为文本 "FineReport"
CellElement cellElement = new CellElement(2, 2, 2, 2, "FineReport");
// 得到CellElement的样式,如果没有新建默认样式
Style style = cellElement.getStyle();
if(style == null) {
style = Style.getInstance();
}
// 设置字体和前景的颜色
FRFont frFont = FRFont.getInstance("Dialog", Font.BOLD, 14);
frFont = frFont.applyForeground(new Color(21, 76, 160));
style = style.deriveFRFont(frFont);
// 设置背景
ColorBackground background = ColorBackground.getInstance(new Color(255, 255, 177));
style = style.deriveBackground(background);
// 设置水平居中
style = style.deriveHorizontalAlignment(Constants.CENTER);
// 设置边框
style = style.deriveBorder(Constants.LINE_DASH_DOT, Color.red, Constants.LINE_DASH_DOT, Color.yellow, Constants.LINE_DASH_DOT, Color.BLUE, Constants.LINE_DASH_DOT, Color.CYAN);
// 改变单元格的样式
cellElement.setStyle(style);
改变单元格的格式,应先取出该单元格(CellElement)的格式(Style)。在默认的情况下Style是null,故当取出Style后应先判断其值是否为null,如果这个值为空,则需先新建一个Style,然后再将该值赋给CellElement。最后根据Style和FRFont中的方法进一步地设置该单元格的各种属性。可执行代码如下:
package com.fr.demo;
import java.awt.Color;
import java.awt.Font;
import com.fr.base.Constants;
import com.fr.base.FRFont;
import com.fr.base.Style;
import com.fr.base.background.ColorBackground;
import com.fr.report.CellElement;
import com.fr.report.DefaultCellElement;
import com.fr.report.WorkBook;
import com.fr.report.WorkBookTemplate;
import com.fr.report.WorkSheet;
import com.fr.web.Reportlet;
import com.fr.web.ReportletRequest;
/**
* ReportletFromTemplateDemo.
* @author marks
* 设置单元格格式
*/
public class CellElementStyleDemo implements Reportlet {
public CellElementStyleDemo() {
}
//建立新报表需要传参(ReportletRequest reportletRequest)
public WorkBookTemplate createReport(ReportletRequest reportletRequest) {
//new a WorkSheet
WorkBook wb = new WorkBook();
WorkSheet workSheet = new WorkSheet();
//new a cellElement with String "FineReport"
CellElement cellElement1 = new DefaultCellElement(1, 1, "FineReport");
//add the cellElement to the workSheet
workSheet.addCellElement(cellElement1);
//set the columnWidth of 1 to 200px,rowHeight of 1 to 30px
workSheet.setColumnWidth(1, 200);
workSheet.setRowHeight(1, 30);
//set the font of cellElement1
Style style = Style.getInstance();
FRFont frFont = FRFont.getInstance("Tahoma", Font.BOLD | Font.ITALIC, 20);
frFont = frFont.applyForeground(Color.red);
style = style.deriveFRFont(frFont);
// 设置背景
ColorBackground background = ColorBackground.getInstance(new Color(255, 255, 177));
style = style.deriveBackground(background);
// 设置水平居中
style = style.deriveHorizontalAlignment(Constants.CENTER);
// 设置边框
style = style.deriveBorder(Constants.LINE_DASH_DOT, Color.red, Constants.LINE_DASH_DOT, Color.yellow, Constants.LINE_DASH_DOT, Color.BLUE, Constants.LINE_DASH_DOT, Color.CYAN);
cellElement1.setStyle(style);
//set the columnWidth of 4 to 200px,rowHeight of 5 to 50px
workSheet.setColumnWidth(4, 200);
wb.addReport(workSheet);
return wb;
}
}
结果如下图所示:
将模板通过指定打印机打印
用户在使用FineReport进行二次开发的过程中有时候需要对不同文件通过不同的打印机打印出来,比如A打印机只能打印A.TXT; B打印机只能打印b.txt.。
得到当前报表运行环境
String envPath = "C:/FineReport6.5/WebReport/WEB-INF";
// 设置当前报表运行环境, 报表预览时需要一个运行环境
// 没有WEB-INF目录时, 路径设置为null. FRContext.setCurrentEnv(new LocalEnv(null));
FRContext.setCurrentEnv(new LocalEnv(envPath));
读取模板文件
// 读取模板
WorkBookTemplate wbTpl = FRContext.getCurrentEnv().readTemplate("stuff.cpt");
指定打印机打印
PrintUtils.print(wbTpl.execute(null).generateReportPageSet().getTraversingCase(), false, "Smart Print");
可执行代码
package com.fr.demo;
import com.fr.base.FRContext;
import com.fr.base.dav.LocalEnv;
import com.fr.base.print.PrintUtils;
import com.fr.report.WorkBookTemplate;
/**
* 演示如何将模板通过指定打印机打印
*
* @author edgar duan
* @version 6.5
*/
public class PrintDemo {
public static void main(String[] args) {
// 报表运行环境路径, WEB-INF目录所放的位置
String envPath = "C:/FineReport6.5/WebReport/WEB-INF";
// 设置当前报表运行环境, 报表预览时需要一个运行环境
// 没有WEB-INF目录时, 路径设置为null. FRContext.setCurrentEnv(new LocalEnv(null));
FRContext.setCurrentEnv(new LocalEnv(envPath));
try {
WorkBookTemplate wbTpl = FRContext.getCurrentEnv().readTemplate("stuff.cpt");
//null 为模板需要传的参数,false为是否弹出提示窗口,Smart Print 为打印机名称 PrintUtils.print(wbTpl.execute(null).generateReportPageSet().getTraversingCase(), false, "Smart Print");
} catch(Exception e) {
e.printStackTrace();
}
}
}
自定义函数
FineReport已经提供了大量的自带函数,在正常情况下足够满足用户的报表制作需求,但是在一些特殊领域,可能需要一些特殊的函数,在这种情况下,FineReport提供了自定义函数机制,可以由用户根据业务需要自己来定义一些函数,但这些函数必须满足FineReport函数定义规则。
FineReport函数定义规则:Functionname(Para,Para,...),其中Functionname为函数名,Para为参数。
函数原理
在FineReport中,每一个函数都被定义成一个类,这个类必须要实现Function这个接口,在运算的时候首先通过函数名反射取得这个类,然后调用它的run(Object[] agrs)方法。下面以SUM这个函数为例。
/*
* Copyright(c) 2001-2008, FineReport Inc, All Rights Reserved.
*/
package com.fr.report.script.function;
import com.fr.report.script.NormalFunction;
import com.fr.report.script.core.FArray;
import com.fr.report.script.core.FunctionHelper;
/**
* Function.
*/
public class SUM extends NormalFunction {
/**
* Run the function on the stack. Pops the arguments from the stack,
* then return the result.
*/
public Object run(Object[] args) {
double result = 0;
for(int i = 0; i < args.length; i++) {
//p:需要先判断是否为null.
if(args[i] == null) {
continue;
}
result += parseObject(args[i]);
}
return FunctionHelper.parsePrimitiveDouble(result);
}
/*
* 把Object转成double类型的值
*/
private double parseObject(Object obj) {
if (obj instanceof Number) {
return ((Number)obj).doubleValue();
} else if (obj instanceof Boolean) {
return ((Boolean)obj).booleanValue() ? 1 : 0;
} else if (obj instanceof FArray) {
FArray array = (FArray)obj;
double sum = 0;
for(int i = 0, len = array.length(); i < len; i++) {
sum += parseObject(array.elementAt(i));
}
return sum;
} else if(obj != null) {
try {
return Double.parseDouble(obj.toString());
} catch(NumberFormatException exp) {
return 0;
}
}
return 0;
}
public String getCN(){
return "SUM(number1,number2,…): 求一个指定单元格区域中所有数字之和。\n"
+"Number1,number2,…:1到30个参数或指定单元格区域中所有数字。\n"
+"备注:\n"
+" 函数将直接键入参数中的数值、逻辑值及文本表达式计算在内。\n"
+" 若参数是数组或引用,则只有数组或单元格引用中的数值进行计算。\n"
+"示例:\n"
+"SUM(70,80)等于150。\n"
+"SUM(\"70\",80,TRUE)等于151,逻辑值“TRUE”作为1来计算;“FALSE”作为0计算;文本“70”作为70来计算。";
}
public String getEN(){
return "SUM(number1,number2,…): Adds all the numbers in a range of cells.\n"
+"Number1, number2, ... are 1 to 30 arguments for which you want the total value or sum.\n"
+"\n"
+"Remarks:\n"
+"1. Numbers, logical values, and text representations of numbers that you type directly into the list of arguments are counted. See the first and second examples following. \n"
+"2. If an argument is an array or reference, only numbers in that array or reference are counted. Empty cells, logical values, text, or error values in the array or reference are ignored. See the third example following. \n"
+"\n"
+"Example:\n"
+" SUM(70,80)=150.\n"
+" SUM(\"70\",80,TRUE)=151, TRUE is calculated as 1, FALSE for 0, String \"70\" fo 70.";
}
}SUM类用来运算SUM函数,它继承了AbstractFunction这个类,而AbstractFunction实现了Function这个接口,在函数元算的时候首先根据函数名取得运算这个函数的类,比如SUM(2,4,true)这个函数首先根据函数名SUM取得SUM这个类,然后调用SUM类的run(Object[] agrs)方法,agrs中存放的是SUM函数的参数,在运算的时候可以从args中取得参数进行运算。
自定义函数步骤
下面以一个自定义函数的例子来说明如何使用自定义函数,我们定义一个函数FunctionDemo,它的功能是填报数据校验的时候,某个单元格的值希望与数据库中的某个值进行比较。
实现FunctionDemo.java
编译FunctionDemo.java
注册函数FunctionDemo
使用函数FunctionDemo
实现FunctionDemo.java
代码如下:
package com.fr.demo;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.logging.Level;
import com.fr.base.FRContext;
import com.fr.base.dav.LocalEnv;
import com.fr.base.file.DatasourceManager;
import com.fr.data.impl.DatabaseConnection;
import com.fr.report.script.NormalFunction;
public class FunctionDemo extends NormalFunction {
/**
* 此方法用于定义数据库连接 C:/FineReport6.5/WebReport/WEB-INF 是当前报表运行环境
* FRDemo 是当前的数据库连接名
*
*/
public static Connection getConn() {
LocalEnv env = new LocalEnv("C:/FineReport6.5/WebReport/WEB-INF");
FRContext.setCurrentEnv(env);
try {
DatasourceManager datasourceManager = FRContext
.getDatasourceManager();
FRContext.getLogger().log(Level.WARNING, datasourceManager + "");
com.fr.data.impl.Connection dcon = datasourceManager
.getConnection("FRDemo");
if (dcon instanceof DatabaseConnection) {
return ((DatabaseConnection) dcon).createConnection();
}
} catch (Exception e) {
FRContext.getLogger().log(Level.WARNING, e.getMessage(), e);
}
return null;
}
public String getManageName() {
String resText = "";
String selSQL = "SELECT province FROM demo1 where number = 1";
Connection con = getConn();
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(selSQL);
while (rs.next()) {
resText = rs.getString(1);
break;
}
rs.close();
con.close();
} catch (Exception exp) {
tr
展开阅读全文