FineReport报表软件API源代码之程序数据集、自定义函数和导出API.doc_第1页
FineReport报表软件API源代码之程序数据集、自定义函数和导出API.doc_第2页
FineReport报表软件API源代码之程序数据集、自定义函数和导出API.doc_第3页
FineReport报表软件API源代码之程序数据集、自定义函数和导出API.doc_第4页
FineReport报表软件API源代码之程序数据集、自定义函数和导出API.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

概述随着FineReport的发展,它提供的设计器和服务器应该能够满足您绝大部分的需求,完全实现零编码的软件开发,革命性地加快软件开发速度,提高软件稳定性。但是需求是千变万化的,而FineReport所包含的功能是报表行业中比较普遍的、典型的,也许某些个性化的功能通过FineReport软件无法实现。因此FineReport开放了能够进行二次开发的接口,来更好的满足您软件产品或项目中的个性化的需求。您可以根据该引擎API文档学习各类接口的使用方法,另外若您是一名程序员,且对FineReport报表深感兴趣,希望更深入地了解FineReport软件的内部原理,您也可以阅读该章节。FineReport引擎API文档对如何定义类、编译类文件及JAVA开发平台使用等JAVA基础知识未作介绍,因此在您查看引擎API文档前请确保您有一定的JAVA基础。目录1. 程序数据源2.1 简单程序数据集2.2 带参程序数据集2. 自定义函数1233.1 自定义函数3.2 SubSection函数-Oracle查询参数个数限制3.3 自定义函数生产UPC条形码3. 导出api注:另有报表调用的相关代码,如有需要可以另行下载。程序数据集简单程序数据集FineReport报表的数据来源可以是数据库数据或是文本数据,并且还可以是其它任何类型的数据,因为FineReport是通过TableData接口来读取数据源的,而上述所有的数据来源都实现了该接口,因此用户只要实现了TableData接口,也就可以用自定义类型的数据源了(程序数据集),FineReport报表引擎就能够读取定义的数据源作为报表数据源使用。TableData接口主要有5个方法,如下:/获取TableData的总列数publicintgetColumnCount();/获取TableData中第columnIndex列的列名publicStringgetColumnName(intcolumnIndex); /判断是否存在第rowIndex行,这主要是用于处理超大数据时,完全遍历所有数据获取总行数相当困难,用这个方法来判断第rowIndex行是否存在,存在则可读取publicbooleanhasRow(introwIndex);/获取TableData的总行数publicintgetRowCount();/获取TableData中第columnIndex列,第rowIndex行的数据publicObjectgetValueAt(introwIndex,intcolumnIndex);使用程序数据集分为如下三个步骤: 在某些应用场景中,需要在程序中对数据进行处理后再作为报表的数据源使用,以下例子即为一个简单的不带参程序数据集ArrayTableData的使用过程,并以此简要说明程序数据集的使用方法。1.定义程序数据源由之前的概述可知,程序数据集需要实现TableData接口,可以直接继承该接口,实现其5个方法,也可以从AbstractTableData扩展,因为AbstractTableData已经实现了默认的hasRow(int rowIndex)方法。 该例中的程序数据集ArrayTableData就是直接从AbstractTableData扩展的,完整代码如下:package com.fr.data;import com.fr.data.AbstractTableData;public class ArrayTableDataDemo extends AbstractTableData /定义程序数据集的列名与数据保存位置 private String columnNames; private Object rowData; /实现构建函数,在构建函数中准备数据 public ArrayTableDataDemo() String columnNames =Name,Score; Object datas = Alex,new Integer(15),Helly,new Integer(22),Bobby,new Integer(99); this.columnNames = columnNames; this.rowData = datas; /实现TableData的其他四个方法,因为AbstractTableData已经实现了hasRow方法 public int getColumnCount() return columnNames.length; public String getColumnName(int columnIndex) return columnNamescolumnIndex; public int getRowCount() return rowData.length; public Object getValueAt(int rowIndex, int columnIndex) return rowDatarowIndexcolumnIndex; 1.1 把上面代码复制到txt文档重命名为ArrayTableDataDemo.java放到报表环境/WebReport/WEB-INF/classes/com/fr/data这个目录下1.2 编译ArrayTableData.java生成ArrayTableData.class类将生成的类文件拷贝到报表工程/WEB-INF/classes目录下。由于该类是在com. fr.data包中的,因此最终应该将该ArrayTableData.class放在/WEB-INF/classes/com/fr/data下面。此时该程序数据源便定义好了。2. 配置程序数据源2.1 新建报表在报表数据集中新建程序数据源,选择我们定义好的程序数据集,如下图名字可以自定义,如student3.使用程序数据集配置好程序数据源后便可以使用定义的student程序数据集了,与其他类型的数据集使用方法是相同的,可以通过拖拽方法实现单元格数据列绑定。如下图带参程序数据集 在实际应用中,可能需要根据表名动态地改变数据源,比如在程序数据集中,通过传进的表名参数,到数据库取出对应的表作为数据源。因为FineReport是通过TableData接口来读取数据源的,而上述所有的数据来源都实现了该接口,因此用户只要实现了TableData接口,也就可以用自定义类型的数据源了(程序数据集),FineReport报表引擎就能够读取定义的数据源作为报表数据源使用。以下就对这种情况举例说明。TableData接口主要有5个方法,如下:/获取TableData的总列数publicintgetColumnCount();/获取TableData中第columnIndex列的列名publicStringgetColumnName(intcolumnIndex); /判断是否存在第rowIndex行,这主要是用于处理超大数据时,完全遍历所有数据获取总行数相当困难,用这个方法来判断第rowIndex行是否存在,存在则可读取publicbooleanhasRow(introwIndex);/获取TableData的总行数publicintgetRowCount();/获取TableData中第columnIndex列,第rowIndex行的数据publicObjectgetValueAt(introwIndex,intcolumnIndex);使用程序数据集分为如下三个步骤: 定义程序数据源 配置程序数据源 使用程序数据集1. 定义程序数据源 首先在构建函数中定义好所用的程序数据集表结构,通过参数获得表名;其次在初始化函数中准备数据并放入定义的表中;完整代码如下:package com.fr.data;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;import java.util.ArrayList;import java.util.logging.Level;import com.fr.base.FRContext;import com.fr.data.AbstractTableData;import com.fr.report.parameter.Parameter;public class ParamTableDataDemo extends AbstractTableData / 列名数组,保存程序数据集所有列名 private String columnNames = null; / 定义程序数据集的列数量 private int columnNum = 10; / 保存查询表的实际列数量 private int colNum = 0; / 保存查询得到列值 private ArrayList valueList = null; / 构造函数,定义表结构,该表有10个数据列,列名为column#0,column#1,。column#9 public ParamTableDataDemo() / 定义tableName参数 this.parameters = new Parameter new Parameter(tableName) ; / 定义程序数据集列名 columnNames = new StringcolumnNum; for (int i = 0; i = colNum) return null; return (Object) valueList.get(rowIndex)columnIndex; / 准备数据 public void init() / 确保只被执行一次 if (valueList != null) return; / 保存得到的数据库表名 String tableName = parameters0.getValue().toString(); / 构造SQL语句,并打印出来 String sql = select * from + tableName + ; FRContext.getLogger().log(Level.INFO, Query SQL of ParamTableDataDemo: n + sql); / 保存得到的结果集 valueList = new ArrayList(); / 下面开始建立数据库连接,按照刚才的SQL语句进行查询 Connection conn = this.getConnection(); try Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); / 获得记录的详细信息,然后获得总列数 ResultSetMetaData rsmd = rs.getMetaData(); colNum = rsmd.getColumnCount(); / 用对象保存数据 Object objArray = null; while (rs.next() objArray = new ObjectcolNum; for (int i = 0; i colNum; i+) objArrayi = rs.getObject(i + 1); / 在valueList中加入这一行数据 valueList.add(objArray); / 释放数据库资源 rs.close(); stmt.close(); conn.close(); / 打印一共取到的数据行数量 FRContext.getLogger().log( Level.INFO, Query SQL of ParamTableDataDemo: n + valueList.size() + rows selected); catch (Exception e) e.printStackTrace(); / 获取数据库连接 driverName 和 url 可以换成您需要的 public Connection getConnection() String driverName = sun.jdbc.odbc.JdbcOdbcDriver; String url = jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=C:FineReport6.5WebReportFRDemo.mdb; String username = ; String password = ; Connection con = null; try Class.forName(driverName); con = DriverManager.getConnection(url, username, password); catch (Exception e) e.printStackTrace(); return null; return con; / 释放一些资源,因为可能会有重复调用,所以需释放valueList,将上次查询的结果释放掉 public void release() throws Exception super.release(); this.valueList = null; 1.1 把上面代码复制到txt文档重命名为ParamTableDataDemo.java放到报表工程WebReportWEB-INFclassescomdemo这个目录下1.2 编译ParamTableDataDemo.java 将生成的ParamTableDataDemo.class类文件拷贝到报表工程/WEB-INF/classes目录下。由于该类是在com.fr.data包中的,因此最终应该将该类放在/WEB-INF/classes/com/fr/data下面。此时该程序数据源便定义好了。2. 配置程序数据源新建报表在报表数据集中新建程序数据源,选择我们定义好的程序数据集,如下图名字可以自定义,如divtable3. 使用程序数据集 配置好程序数据源后便可以使用定义的divtable程序数据集了,选中该数据集点击预览按钮,即可以输入表名动态地获取相应的数据表,并制作模板,如下图可以看到,我们已经将stscore表中的数据提取至程序数据集表中,像其他类型的数据集一样,可以通过拖拽方法实现单元格数据列绑定。自定义函数函数定义规则 FineReport已经提供了大量的自带函数,在正常情况下足够满足用户的报表制作需求,但是在一些特殊领域,可能需要一些特殊的函数,在这种情况下,FineReport提供了自定义函数机制,可以由用户根据业务需要自己来定义一些函数,但这些函数必须满足FineReport函数定义规则。FineReport函数定义规则:Functionname(Para,Para,.),其中Functionname为函数名,Para为参数。函数原理在FineReport中,每一个函数都被定义成一个类,这个类必须要实现Function这个接口,在运算的时候首先通过函数名反射取得这个类,然后调用它的run(Object agrs)方法。下面以SUM这个函数为例。package com.fr.report.script;import com.fr.report.script.core.FArray;import com.fr.report.script.core.FunctionHelper;public class SUM extends NormalFunction public Object run(Object args) double result = 0; for(int i=0;iargs.length;i+) if(argsi = null) continue; result += parseObject(argsi); return FunctionHelper.parsePrimitiveDouble(result); 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;iarray.length();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; 由程序可以看到,SUM类用来运算SUM函数,他继承了NormalFunction类,而NormalFunction实现了Function这个接口。当函数运算的时候,先根据函数名取得运算该函数的类,如SUM(2,4,true)这个函数先根据函数名取得SUM这个类,然后调用SUM类的run(Object args)方法,args中存放的是SUM函数的参数,运算的时候可以从args中取得参数进行运算。如执行结果为SUM(2,4,true)=2+4+1=7。自定义函数使用步骤 自定义函数使用分为四个步骤,如下:自定义函数编译自定义函数注册自定义函数使用自定义函数简单的自定义函数 下面以一个简单的自定义函数例子来说明使用自定义函数的四个步骤。我们定义一个函数STRINGCAT,他的作用是把所有的参数以字符串的形式连接起来。 STRINGCAT函数使用规则为STRINGCAT(Para,Para,Para.); 其中Para为该函数的参数,个数不限。1.定义自定义函数由概述可知NormalFunction实现了Function这个接口,因此STRINGCAT可以直接继承NormalFunction类,完整代码如下:package com.fr.demo;import com.fr.report.script.NormalFunction;public class stringcat extends NormalFunction public Object run(Object args) String result = ; Object para; for(int i = 0;iargs.length;i+) para = argsi; result +=para.toString(); return result; 说明:使用函数STRINGCAT(Para,Para,Para.)时,根据函数名取得运算该函数的类STRINGCAT,并将参数传入类中的args对象数组中,执行该类的run函数。而在run函数中即实现了将传入的参数以字符串的形式连接起来。并返回最终形成的字符串。2.编译自定义函数将编译后的STRINGCAT.CLASS放到FineReport的安装目录WEB-INF下面的classes目录下,因为STRINGCAT.JAVA属于包com.fr.demo,所以STRINGCAT.CLASS需要放到classescomfrdemo目录下。3.注册自定义函数生成该函数的类后需要在设计器中进行注册,才可以使用该函数。打开服务器|函数管理器,选择刚刚定义好了STRINGCAT类,如下图函数名称可以自定义,如这边定义为Stringcat;同时可以添加该函数的使用说明,如上图所示的描述4. 使用自定义函数注册好自定义函数后,制作报表时便可直接使用了,使用方法与内置的函数是相同的。4.1 新建报表4.2 定义两个报表参数para1、para2,类型分别为字符串型与整形,默认值分别为空字符串与0在空白报表的任意单元格里写入公式:=Stringcat($para1,$para2)(注意:写入公式的时候在参数名前加$,表明这是使用的参数)点击预览会弹出填写参数的对话框,写入参数值如下确定后可以看到结果说明STRINGCAT公式可以正常使用啦。SubSection函数之Oracle查询参数个数限制如有一个参数查询语句:SELECT * FROM Stscore WHERE Stdno IN ($studentno)实际情况中studenno可能是根据其他条件查询出来的结果列表,也许超过1000个学号,如最终为SELECT * FROM Stscore WHERE Stdno IN (10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 10009, 10010, 10011, 10012, 10013, ,10989, 10990, 10991, 10992, 10993, 10994, 10995, 10996, 10997, 10998, 10999, 11000,11001)直接执行上述语句,由于studentno参数的个数超过了1000个,数据库端将报ORA-01795的错误,如下图如何解决该问题呢?此时,如果将studentno参数分割成多段,如以500为单位进行分割,将上述11001个参数值分为3部分,形成3条查询条件,便可避免该问题。 即变为SELECT * FROM Stscore WHERE Stdno IN (10001,10002,10500) or Stdno IN (10501,10502,11000) or Stdno IN (11001) FineReport并没有实现该功能的内置函数,对于这种情况,我们可以自定义一个SubSection分组函数该函数的使用规则为:SubSection(para)参数para为字符串形式,该函数的作用即将字符串参数以500为单位进行分割,并返回分割后形成的数组。完整代码如下:package com.fr.demo;import com.fr.report.script.NormalFunction;import com.fr.report.script.core.FArray;public class SubSection extends NormalFunction public Object run(Object args) /获取第一个对象,即取得传入的参数 Object para = args0; String parastr = para.toString(); /由于是复选参数,因此要去掉前后的(和) if(parastr.startsWith() & parastr.endsWith() parastr = parastr.substring(1, parastr.length()-1); /将字符串转为,分割的数组 String test = parastr.split(,); int len = test.length; int loopnum = len/500; if(len%500!=0) loopnum +=1; ; /返回的值是数组,需要定义成我们内部的类型FArray FArray result = new FArray(); String str = ; int k = 1; for(int i=0;iloopnum;i+) for(int j=500*i;j500*(i+1) & jlen;j+) if(k != 500 & j != (len-1) str += testj + ,; else str += testj; k+; /每500个形成一组并在每组外部加上(和) str = ( + str + ); result.add(str); str = ; k=1; return result; 注:当返回有多个值,并且保存在数组中时,定义返回值的类型必须是FineReport内部的数组类型FArray,才能正确返回结果。编译自定义函数将编译后的SubSection.class放到FineReport的安装目录WEB-INF下面的classes目录下,因为SubSection.java属于包com.fr.demo,所以SubSection.class需要放到classescomfrdemo目录下。注册并使用自定义函数 注册好定义的函数后便可进行使用了,注册与使用方法在上一节简单的自定义函数中已经介绍过,在此就不详细描述了。由于实际获得的参数格式不定,可以根据具体情况调整java程序。如何使用UPCBarCode条形码自问世以来,为适应多种需要,产生了众多的编码系统。但目前得到国际公认用于商品包装的主要有两种,即UPC和EAN。这两种编码系统属同一类型,每个字符均由数条黑白相间的条纹组成,中间有两条窄条纹向下伸出少许,将条形码分成左右两部分。这两种条形码虽然只能表示0到9,十个数字,但具有高度的查核能力,扫描操作简单可靠。其中UPC条形码是由美国和加拿大共同组织的“统一编码委员会”(Universal Code Council,UCC)选定以IBM公司提出的 Dalta-Distance为基础而通过的。UPC码(Uniform Product Code)作为美、加产品统一的标识符号。因此,我国产品若要销往美国,加拿大,则应使用UPC码,而出口到其他国家和地区则需使用EAN码。UPC的构成:由11位数字的通用产品代码和1位校验码组成。产品代码的第1位数字为编码系统字符;中间5位数字表示制造商号,后5位数字为产品代码。FineReport中自带有EAN型编码,但却没有UPC条形码,此时若您希望在报表中使用UPC编码的条形码应该怎么办呢?FineReport可以通过自定义函数引用第三方包来生成UPC编码的条形码并显示出来,如输入数值12345678912,将会得到以下UPC条形码:实现步骤如下:1. 在eclipse中导入第三方包barcode4j-light.jar,并新建一个类UPCCODE,具体代码如下:package com.fr.report.script.function;import java.awt.image.BufferedImage;import org.krysalis.barcode4j.impl.upcean.UPCABean;import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;import org.krysalis.barcode4j.tools.UnitConv;import com.fr.report.script.NormalFunction;public class UPCCode extends NormalFunction public Object run(Object args) if(args = null | args.length 1) return 参数不对,必须有一个参数; try UPCABean bean = new UPCABean(); final int dpi = Integer.parseInt(args1.toString(); bean.setModuleWidth(UnitConv.in2mm(1.0f / dpi); / makes the narrow bean.doQuietZone(false); BitmapCanvasProvider canvas = new BitmapCanvasProvider(dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0); / Generate the barcode bean.generateBarcode(canvas, + args0); / Signal end of generation canvas.finish(); / return image return canvas.getBufferedImage(); catch (Exception e) e.printStackTrace(); return args0; 2. 将编译后的UPCCODE.class文件放在报表环境目录WebReportWEB-INFlib fr-server-6.5.jarcomfrreportscriptfunction下3. 将第三方包barcode4j-light.jar放在报表环境目录WebReportWEB-INFlib文件夹下4. UPCCODE()函数的使用重启服务器,在报表中使用公式UPCCODE(num1, num2),num1为需要生成条形码的数值,num2为生成的图片的高度。如输入公式:=UPCCODE(12345678912,100),预览便可以看到条形码了。导出apiFineReport提供了强大的输入输出功能,所有的这些输入输出的类都在com.fr.report.io包里面。Report的输入指从报表的模板文件(XML格式的)创建Report对象,输出指将Report保存为模板文件,FineReport还支持将Report保存为PDF,Excel,Word,SVG,HTML,CSV等文件格式。读取模板文件 / 读取模板 File cptFile = new File(D:stuff.cpt); TemplateImp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论