概述
随着FineReport的发展,它提供的设计器和服务器应该能够满足您绝大部分的需求,完全实现零编码的软件开发,革命性地加快软件开发速度,提高软件稳定性。但是需求是千变万化的,而FineReport所包含的功能是报表行业中比较普遍的、典型的,也许某些个性化的功能通过FineReport软件无法实现。因此FineReport开放了能够进行二次开发的接口,来更好的满足您软件产品或项目中的个性化的需求。您可以根据该引擎API文档学习各类接口的使用方法,另外若您是一名程序员,且对FineReport报表深感兴趣,希望更深入地了解FineReport软件的内部原理,您也可以阅读该章节。
FineReport引擎API文档对如何定义类、编译类文件及JAVA开发平台使用等JAVA基础知识未作介绍,因此在您查看引擎API文档前请确保您有一定的JAVA基础。
目录
1.报表调用
1.1读取编辑报表
1.2创建程序报表
1.3单元格格式设置
1.4程序报表添加单元格
1.5遍历读取单元格内容
1.6读取报表参数并赋值
注:另有报表程序数据集、自定义函数和导出API的相关代码,如有需要可以另行下载。
报表调用
读取编辑报表
通过内核结构的介绍,可知我们能在程序中修改报表的属性,下面我们就以一个完整的例子说明如何在程序中读取一张报表,修改后重新导出。
1.读取报表
读取某一路径下的模板cpt文件,并将其转为WorkBook对象,有两种读取报表的方法:
一、直接以文件绝对路径读取;二、先定义报表运行环境,然后从运行环境中直接读取
相对路径下的模板。
1.1 绝对路径读取模板
// 读取模板
File cptfile = new
File("C:\\FineReport6.5\\WebReport\WEB-INF\\reportlets\\gettingstarted.cpt"); TemplateImporter tplimp = new TemplateImporter();
WorkBook workbook = tplimp.generateTemplate(cptfile);
1.2 读取报表运行环境下的模板
//定义报表运行环境,读取环境下的报表
String envPath = " C:\\FineReport6.5\\WebReport \\WEB-INF";
FRContext.setCurrentEnv(new LocalEnv(envPath));
TemplateWorkBook workbook =
FRContext.getCurrentEnv().readTemplate("gettingstarted.cpt");
2. 编辑报表属性
//获得WorkBook中的WorkSheet,进而修改A2单元格的前景色为红色
Report report = workbook.getReport(0);
//getCellElement(int column, int row),column和row都从0开始,因此A2单元格便是第0列第1行
CellElement cellA2 = report.getCellElement(0,1);
FRFont frFont = FRFont.getInstance();
frFont = frFont.applyForeground(Color.red);
Style style = Style.getInstance();
style = style.deriveFRFont(frFont);
cellA2.setStyle(style);
3. 导出报表
// 保存模板
FileOutputStream outputStream = new FileOutputStream(new
File("D:\\newGettingStarted.cpt"));
TemplateExporter templateExporter = new TemplateExporter();
templateExporter.export(outputStream, workbook);
具体的执行代码如下:
package com.fr.demo;
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import com.fr.base.FRFont;
import com.fr.base.Style;
import com.fr.report.CellElement;
import com.fr.report.Report;
import com.fr.report.WorkBook;
import com.fr.report.io.TemplateExporter;
import com.fr.report.io.TemplateImporter;
public class SimpleDemo {
public static void main(String[] args) {
try {
// 读取模板
File cptfile = new
File("C:\\FineReport6.5\\WebReport\\WEB-INF\\reportlets\\gettingstarted.cpt"); TemplateImporter tplimp = new TemplateImporter();
WorkBook workbook = tplimp.generateTemplate(cptfile);
//获得WorkBook中的WorkSheet,进而修改A2单元格的前景色为红色
Report report = workbook.getReport(0);
//getCellElement(int column, int row),column和row都从0开始,因此A2单元格便是第0列第1行
CellElement cellA2 = report.getCellElement(0,1);
FRFont frFont = FRFont.getInstance();
frFont = frFont.applyForeground(Color.red);
Style style = Style.getInstance();
style = style.deriveFRFont(frFont);
cellA2.setStyle(style);
// 保存模板
FileOutputStream outputStream = new FileOutputStream(new File("D:\\newGettingStarted.cpt"));
TemplateExporter templateExporter = new TemplateExporter(); templateExporter.export(outputStream, workbook);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 查看导出结果
编译运行上述代码,将会在D盘根目录下输出报表newGettingStarted.cpt,我们用设计器打开导出模板,可以看到,A2单元格的前景色变成了红色。
创建程序报表
由服务器原理章节,我们可以了解到所谓的网络报表就是指实现了Reportlet接口的文件,程序网络报表的存在可以用来解决某些特殊应用,而由于程序网络报表需要自己来实现Reportlet接口,接下来我们给以详细说明。
建议在开始本章节钱稍微了解一下FineReport提供的API学习,当然需要一定的程序语言基础。
FineReport报表设计器可以设计出绝大多数的报表而不用写一行代码,只有少部分的报表由于有特殊需求需要用写程序的方式来设计,FineReport提供了丰富的API接口可以让用户很轻松的做出需要的报表,下面这个例子就是要新建一个报表,在(1,1)单元格内插入FineReport 这个字符串,对字符串进行格式设置,在其中(4,5)单元格内插入一个FineReport的log标志,用J2EE服务器来发布,通过浏览器来浏览,下面以这个简单的例子来详细的介绍如何创建程序网络报表。
1.新建JAVA类文件
创建程序网络报表需要新建一个JAVA类,我们把这个类命名成SimpleReportletDemo,这个类需要实现com.fr.web.Reportlet这个接口,并且需要实现public Report
createReport(ReportletRequest reportletRequest)这个方法。
?实现com.fr.web.Reportlet接口,格式如下:
public class SimpleReportletDemo implements Reportlet {
public SimpleReportletDemo() {
}
public WorkBookTemplate createReport(ReportletRequest reportletRequest) { }
?实现public Report createReport(ReportletRequest reportletRequest)方法,这个方法需要返回一个Report类型的对象,代码格式如下:
public Report createReport(ReportletRequest reportletRequest){
WorkBook wb=new WorkBook();
WorkBook wb=new WorkBook();
WorkSheet workSheet=new WorkSheet();
return wb;
}
下面我们可以给workSheet加上一些需要的单元格内容。
?我们现在可以给这个workSheet的(1,1)格子内加上一个字符串,如下所示://new a cellElement with String "FineReport"
CellElement cellElement1 = new DefaultCellElement(1, 1, "FineReport");
//add the cellElement to the workSheet
workSheet.addCellElement(cellElement1);
?然后可以给这个workSheet调整列宽和行高,如下所示:
//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);
cellElement1.setStyle(style);
完整代码如下所示:
package com.fr.demo;
import java.awt.Color;
import java.awt.Font;
import com.fr.base.FRFont;
import com.fr.base.Style;
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 SimpleReportletDemo implements Reportlet {
public SimpleReportletDemo() {
}
//建立新报表需要传参(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);
cellElement1.setStyle(style);
//set the columnWidth of 4 to 200px,rowHeight of 5 to 50px
workSheet.setColumnWidth(4, 200);
wb.addReport(workSheet);
return wb;
}
}
2.编译JAVA文件
下面命令用于编译JAVA文件:
注意在编译时将fr-server-6.5.jar放置在当前目录
C:\>javac -classpath fr-server-6.5.jar SimpleReportletDemo.java
将编译后的SimpleReportletDemo.class放到网络报表根目录下,存放地址如下:
WEB-INF\classes\com\fr\demo
3.发布并浏览
首先启动报表服务器,既FineReport安装目录下面的Jetty服务器,Jetty服务器启动完毕后打开浏览器,在浏览器中输入下列地址:
http://localhost:8079/WebReport/ReportServer?reportlet=com.fr.demo.SimpleReportletD emo
结果如下所示:
单元格格式设置
// 新建一个单元格, 位置为(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, 17
7));
style = style.deriveBackground(background);
// 设置水平居中
style = style.deriveHorizontalAlignment(Constants.CENTER);
// 设置边框
style = style.deriveBorder(Constants.LINE_DASH_DOT, Color.red, Constants.LINE_D ASH_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;
}
}
结果如下图所示:
程序报表添加单元格
报表是由单元格元素组成,单元格元素CellElement构成了FineReport内核最基本的单元,CellElement的最基本的属性有五个:col,row,colSpan,rowSpan,value,这些属性构成了CellElement的基本性质。(col,row)表示了CellElement在Report中的位置,而colSpan 和rowSpan分别表示了CellElement在列方向和行方向上占据了几个格子,默认的是1,默认一个格子的长和宽分别是72px和19px,当单元格元素所占的行宽(colSpan)和列高(rowSpan)大于一个格子的长宽,那么这个单元格元素是merged的。
FineReport能够设计极度复杂的报表都是由这些单元格根据不同的形式组织起来的,下面的代码演示了如何创建CellElement并且将他们添加到Report中:
1.// 新建一个CellElement, 列为 1, 行为 1, 列宽为 1,
2.// 行高为 1, 值为文本:"FineReport"
3.CellElement cellElement1 = new CellElement(1,1,"FineReport");
4.workSheet.addCellElement(cellElement1);
5.// 新建一个CellElement, 列为 2, 行为 2, 列宽为 2,
6.// 行高为 1, 值为当前日期
7.CellElement cellElement2 = new CellElement(2, 10, 2, 1, new Date());
8.workSheet.addCellElement(cellElement2);
9.// 新建一个CellElement, 列为 4, 行为 5, 列宽为 3,
10.// 行高为 4, 值为公式 = 23 * 34
11.CellElement cellElement3 = new CellElement(4, 5, 3, 4, new Formula("23 * 34
"));
12.workSheet.addCellElement(cellElement3);
根据所给的列、行、列宽、行高及元素值创建出不同的CellElement对象,再利用report接口中的addCellElement方法将新建的CellElement添加到报表中。可执行代码如下:
package com.fr.demo;
import java.awt.Color;
import java.awt.Font;
import java.util.Date;
import com.fr.base.FRFont;
import com.fr.base.Style;
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.report.cellElement.Formula;
import com.fr.web.Reportlet;
import com.fr.web.ReportletRequest;
/**
* ReportletFromTemplateDemo.
* @author marks
* 增加单元格
*/
public class AddCellElementsToReport implements Reportlet {
public AddCellElementsToReport() {
}
//建立新报表需要传参(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");
// 新建一个CellElement, 列为 2, 行为 1, 列宽为 2,
// 行高为 1, 值为当前日期
CellElement cellElement2 = new DefaultCellElement(2, 1, 2, 1, new Date()); workSheet.addCellElement(cellElement2);
// 新建一个CellElement, 列为 , 行为 1, 列宽为 3,
// 行高为 4, 值为公式 = 23 * 34
CellElement cellElement3 = new DefaultCellElement(4, 1, 3, 4, new Formula("23 * 34"));
//add the cellElement to the workSheet
workSheet.addCellElement(cellElement1);
workSheet.addCellElement(cellElement2);
workSheet.addCellElement(cellElement3);
//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);
cellElement1.setStyle(style);
cellElement2.setStyle(style);
cellElement3.setStyle(style);
//set the columnWidth of 4 to 200px,rowHeight of 5 to 50px
workSheet.setColumnWidth(4, 200);
wb.addReport(workSheet);
return wb;
}
}.
1.编译JAVA文件
下面命令用于编译JAVA文件:
注意在编译时将fr-server-6.5.jar放置在当前目录
C:\>javac -classpath fr-server-6.5.jar AddCellElementsToReport.java
将编译后的AddCellElementsToReport.class放到网络报表根目录下,存放地址如下:
WEB-INF\classes\com\fr\demo
2.发布并浏览
首先启动报表服务器,既FineReport安装目录下面的Jetty服务器,Jetty服务器启动完毕后打开浏览器,在浏览器中输入下列地址:
http://localhost:8079/WebReport/ReportServer?reportlet=com.fr.demo. AddCellElementsToReport结果如下所示:
遍历读取单元格内容
TemplateImporter templateImporter = new TemplateImporter(cptFile);
Report workSheet = templateImporter.generateReport();
// 根据参数确定这个区域的,为(0, 0, 4, 3);第一个数字为最左边的列,第二个数字为最上面的行,第三个为列宽,第四个为行高
// 遍历这个区域:数据存在list中
List vauleList = new ArrayList();
Iterator cells = workSheet.intersect(0, 0, 4, 3);
while(cells.hasNext()) {
CellElement cellElement = (CellElement)cells.next();
vauleList.add(cellElement.getValue());
System.out.println(cellElement.getRow() + " " + cellElement.getColumn() + " "
+ cellElement.getValue().toString());
}
这里通过Report的intersect(int column, int row, int width, int height)方法获取Report中部分的单元格,这些单元格放在Iterator中,可以像遍历普通的Iterator对象一样遍历其中的单元格,本例为了演示做了很简单的操作,只是把单元格的行列,值打印出来,可执行代码如下:
package com.fr.demo;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.fr.report.CellElement;
import com.fr.report.Report;
import com.fr.report.WorkBook;
import com.fr.report.io.TemplateImporter;
/**
*演示如何从报表中得到部分单元格
*
*/
public class IntersectCellIteratorDemo {
public static void main(String[] args) {
File cptFile = new File("D:\\stuff.cpt");
try {
TemplateImporter templateImporter = new TemplateImporter();
WorkBook workbook = templateImporter.generate(cptFile);
// 所取得的单元格区域开始位置为(0,0), 宽为4, 高为3
// 参数两个,例如a1,b2
// 根据参数确定这个区域的,为(0, 0, 2, 2);第一个数字为最左边的列,第二个数字为最上面的行,第三个为列宽,第四个为行高
// 遍历这个区域:数据存在list中
Report report = workbook.getReport(0);
List
Iterator> cells = report.intersect(1, 0, 1, 20);
while(cells.hasNext()) {
CellElement cellElement = (CellElement)cells.next(); vauleList.add(cellElement.getValue());
System.out.println(cellElement.getRow() + " " + cellElement.getColumn() + " "
+ cellElement.getValue().toString());
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
效果如下图展示:
原报表:
程序读出第一列的值:
读取报表参数并赋值
这个例子是要从URL中接收传递的参数,对报表模板进行参数值的修改。
?步骤一:在设计器中新建一个自由报表的模板,在报表|报表参数中新建两个参数,命名为province ,country,如下图所示:
?步骤二:新建实现了Reportlet的类URLParameterDemo
在createReport(ReportletRequest req)这个方法中需要从req中得到参数的值,并且用它来设置刚才建的模板中的参数值,首先要先得到模板的所有参数,然后取得这个参数,根据参数名在URL中取得参数的值,再用取得的值来设置模板中的参数,代码如下所示:
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.WorkBookTemplate;
import com.fr.report.io.TemplateExporter;
import com.fr.report.parameter.Parameter;
/**
*模板传参
*@author edgar duan
*@version 6.5
*/
public class URLParameterDemo {
/**
*@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 {
WorkBookTemplate wbTpl =
FRContext.getCurrentEnv().readTemplate("URLParameterDemo.cpt");
java.util.Map parameterMap = new java.util.HashMap();
Parameter[] ps = wbTpl.getParameters();
for (int i = 0; i < ps.length; i++) {
//向报表中传入两个参数,province是参数名称北京是参数值
parameterMap.put("province ", "北京");
parameterMap.put("country", "china");
}
FileOutputStream outputStream;
//得到参数后重新生成报表
outputStream = new FileOutputStream(new
File("E:\\newtemplate\\URLParameterDemo.cpt"));
TemplateExporter templateExporter = new TemplateExporter();
templateExporter.export(outputStream, wbTpl.execute(parameterMap)) ;
} catch(Exception e) {
e.printStackTrace();
}
}
}
效果对比如下:
未传参之前:
添加条件后输出模板为: