报表开发之自定义函数

简介:

对于报表开发,很多情况下,自带的函数就能满足大部分用户的报表制作需求,FineReport也不例外。但是在一些特殊领域,可能需要一些特殊的函数,在这种情况下,FineReport提供了自定义函数机制,可以由用户根据业务需要自己来定义一些函数,但这些函数必须满足函数定义规则。

先来了解一下FineReport的函数定义规则:Functionname(Para,Para,...),其中Functionname为函数名,Para为参数。

每一个函数都被定义成一个类,这个类必须要实现Function这个接口,在运算的时候首先通过函数名反射取得这个类,然后调用它的run(Object[] agrs)方法。下面以SUM这个函数为例。

SUM函数原理

由程序可以看到,SUM类用来运算SUM函数,他继承了AbstractFunction类,而AbstractFunction实现了Function这个接口。

当函数运算的时候,先根据函数名取得运算该函数的类,如SUM(2,4,true)这个函数先根据函数名取得SUM这个类,然后调用SUM类的run(Object[] args)方法,args中存放的是SUM函数的参数,运算的时候可以从args中取得参数进行运算。如执行结果为SUM(2,4,true)=2+4+1=7。

SUM函数所使用代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
packagecom.fr.report.script;
importjava.lang.reflect.Array;
importcom.fr.report.script.core.FArray;
importcom.fr.report.script.core.FunctionHelper;
public  class  SUM extendsAbstractFunction {
          public  Object run(Object[] args) {
                    double  result =  0 ;
                    for  ( int  i =  0 ; i < args.length; i++) {
                             if  (args[i] ==  null ) {
                                      continue ;
                             }
                             result += parseObject(args[i]);
                    }
                    returnFunctionHelper.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 ; i < array.length();i++) {
                                      sum +=parseObject(array.elementAt(i));
                             }
                             return  sum;
                    else  if  (obj !=  null ) {
                             try  {
                                      returnDouble.parseDouble(obj.toString());
                             catch  (NumberFormatException exp) {
                                      return  0 ;
                             }
                    }
                    return  0 ;
          }
}

实现步骤

编写自定义函数

下面以一个简单的自定义函数例子来说明使用自定义函数。我们定义一个函数StringCat,他的作用是把所有的参数以字符串的形式连接起来。

StringCat函数使用规则为StringCat(Para,Para,Para…….);

其中Para为该函数的参数,个数不限。

由概述可知AbstractFunction实现了Function这个接口,因此StringCat可以直接继承AbstractFunction类,完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package  com.fr.function;
  
importcom.fr.script.AbstractFunction;
  
public  class  StringCatextends AbstractFunction {
          public  Object run(Object[] args) {
                    String result =  "" ;
                    Object para;
                    for  ( int  i =  0 ; i < args.length; i++) {
                             para = args[i];
                             result += para.toString();
                    }
                    return  result;
          }
}

这里要注意,使用函数StringCat(Para,Para,Para…..)时,根据函数名取得运算该函数的类StringCat,并将参数传入类中的args对象数组中,执行该类的run函数。

而在run函数中即实现了将传入的参数以字符串的形式连接起来。并返回最终形成的字符串。

编译自定义函数

将编译后的StringCat.class放到FineReport的安装目录WEB-INF下面的classes目录下,因为StringCat.java属于包com.fr.function,所以StringCat.class需要放到classes\com\fr\function目录下。

注册自定义函数

生成该函数的类后需要在设计器中进行注册,才可以使用该函数。打开服务器|函数管理器,选择刚刚定义好了StringCat类,如下图


函数名称可以自定义,如这边定义为StringCat;

同时可以添加该函数的使用说明,如上图所示的描述

使用自定义函数

注册好自定义函数后,制作报表时便可直接使用了,使用方法与内置的函数是相同的。

新建报表,定义两个报表参数para1、para2,类型分别为字符串型与整形,默认值分别为空字符串与0

在空白报表的任意单元格里写入公式:=StringCat($para1,$para2)(注意:写入公式的时候在参数名前加$,表明这是使用的参数)

点击分页预览在参数控件中,写入参数值如para1为:FineReport,para2为:123。

点击查询可以看到结果

说明StringCat公式可以正常使用啦。



本文转自 雄霸天下啦 51CTO博客,原文链接:http://blog.51cto.com/10549520/1828359,如需转载请自行联系原作者
相关文章
|
数据采集 数据可视化 数据挖掘
NumPy在数据分析中的核心应用
【4月更文挑战第17天】NumPy是Python数据分析基础库,核心应用包括数据结构化、预处理、统计分析和可视化。它提供`ndarray`多维数组对象及灵活索引,用于数据存储和处理。数据预处理支持缺失值处理,统计分析涵盖描述性统计和相关性分析。虽不直接支持数据可视化,但能与Matplotlib等库集成绘制图表。掌握NumPy能提升数据分析效率,助于挖掘数据价值。
|
运维 Kubernetes jenkins
【云效最完整测评】从自建DevOps部署微服务再到云效
本人还是个在校生,不是什么业界大佬,每次社区出征文计划我都会珍惜测评的机会。因为本人专业学习的是网络方向,对开发其实还是有不少欠缺。在学习云计算时对devops进行了研究,包括容器云k8s的一些列运维搭建。很多概念上的东西要是理解错误,希望各位能够多多指教QAQ
22823 7
【云效最完整测评】从自建DevOps部署微服务再到云效
|
监控 Go 区块链
用Go实现任务栏里的兔子
之前看到 RunCat 一只可以在电脑上奔跑猫,其主要的功能是监控电脑的CPU、内存的使用情况,使用越多跑的越快。所以准备做一只在任务栏里的兔子,主要使用 Go 语言实现一个简单的到点拜年的兔子。 基本需求: - 打开应用时可以在任务栏里显示 - 实现动态兔子生成
331 0
|
存储 数据采集 边缘计算
深度揭秘:一汽红旗新能源工厂为何能“1分钟造1辆车”
年产能20万辆车——平均一分钟就能造一辆车,这就是去年投产的一汽红旗新能源工厂的效率。这个超乎想象的造车节奏,是如何产生的呢?全自动生产线的天花板又是如何被突破的呢?
1562 1
深度揭秘:一汽红旗新能源工厂为何能“1分钟造1辆车”
|
计算机视觉
初探单目相机测距——相机标定
初探单目相机测距——相机标定
1314 0
初探单目相机测距——相机标定
|
JavaScript 前端开发 API
把企业微信侧边栏的 JS-SDK 封装了,还加上了所有 TS 类型
我最近又想到了一些 idea,把侧边栏 JS-SDK 里的 API 的 TS 类型(入参、返回)都写了一遍,然后使用简单几个 API 来封装和调用原来的 wx.fn 以及 wx.invoke('xxx')。 整个封装的最终效果就是今天要说的 wecom-sidebar-jssdk,此 SDK 是专门针对企业微信侧边栏的 JS-SDK 进行封装的。
把企业微信侧边栏的 JS-SDK 封装了,还加上了所有 TS 类型
|
机器学习/深度学习 存储 算法
一文搞懂「拓扑排序」
Topological sort 又称 Topological order,这个名字有点迷惑性,因为拓扑排序并不是一个纯粹的排序算法,它只是针对某一类图,找到一个可以执行的线性顺序。 这个算法听起来高大上,如今的面试也很爱考,比如当时我在面我司时有整整一轮是基于拓扑排序的设计。 但它其实是一个很好理解的算法,跟着我的思路,让你再也不会忘记她。
1238 0
一文搞懂「拓扑排序」
sublimeText3下载安装教程
本文介绍sublimeText3下载安装的教程。
2269 0
sublimeText3下载安装教程
|
机器学习/深度学习 人工智能 算法
概率论01:你真的分得清频率、概率、几率和似然吗?
概率论01:你真的分得清频率、概率、几率和似然吗?
808 0
概率论01:你真的分得清频率、概率、几率和似然吗?