2019独角兽企业重金招聘Python工程师标准>>>

前言:这里以一个例子来说明PRD报表工具强大的扩展功能。 我们用4种不同的方式来实现一个REGE()函数,其目的用来来提取想要的内容。需要传入两个参数,一个是原始字符串,一个是包含一个分组的正则表达式,表达式运算结果是正则表达式匹配的第一个分组。

相关说明:

a)、示例数据库:Pentaho自带的SampleData

b)、示例的SQL脚本:

SELECT"ORDERFACT"."PRODUCTCODE","PRODUCTS"."PRODUCTNAME","PRODUCTS"."PRODUCTLINE",SUM("ORDERFACT"."QUANTITYORDERED") AS QUANTITYORDERED,SUM("ORDERFACT"."TOTALPRICE") AS TOTALPRICE
FROM "ORDERFACT" INNER JOIN "PRODUCTS" ON "ORDERFACT"."PRODUCTCODE" ="PRODUCTS"."PRODUCTCODE"
GROUP BY "PRODUCTS"."PRODUCTLINE","ORDERFACT"."PRODUCTCODE","PRODUCTS"."PRODUCTNAME"
ORDER BY "PRODUCTS"."PRODUCTLINE","ORDERFACT"."PRODUCTCODE","PRODUCTS"."PRODUCTNAME"

c)、关于如何创建一个PRD报表文件请参考链接文档

http://www.jianshu.com/p/e9b1762061fa

一、内置JAVA脚本

这里用 BeanShell(BSH)来实现一个表达式。打开函数对话框,展开 Script 分组,选
择BeanShell(BSH)。

按下面设置 Expression 属性:

import java.util.regex.*;Object getValue() {try{// 创建一个基于正则表达式的输入模式final Pattern pattern = Pattern.compile("S(\\d+)_.*");//final Matcher matcher = pattern.matcher(dataRow.get("PRODUCTCODE"));// 查找的字段,如果不为空,创建一个匹配final  Object object = dataRow.get("PRODUCTCODE");if( object == null ){return null;}final Matcher matcher = pattern.matcher(object.toString());// 在字符串中找到第一个匹配项matcher.find();// 返回第一组内找到匹配return matcher.group(1);}catch(Exception e){return e.getMessage();}
}

将上述代码添加到下图箭头所指处:

把函数拖入报表即可:

展示样式:

二、内置JavaScript脚本

用 Javascript 来 实 现 。 选 择 Script 下 面 的 JavaScript 函 数 , 或 者 选 择 Bean-Scripting
Framework(BSF)并把表达式编程语言属性设置为 javascript。
Expression 属性按如下设置:

dataRow.get("PRODUCTCODE").match(/S(\d+)_.*/)[1]

方式一:

方式二:

把函数拖入报表即可:

展示样式:

三、本地构建PRD源码的目录结构

        以上的2种方式为PRD报表工具内置的扩展功能的脚本化方式,不过通过这种方式实现的表达式仅限于当前报表有效,如果用户想要定义一套全局都有效的表达式该如何操作喃?辛运的是,Pentaho Reporting 有一套扩展系统的方式,能够无侵入性地增加功能。这主要是通过定义模块、加载模块的方式来实现的。

        接下来我们将PRD的源码从GitHub上Maven到本地,利用JAVA语言编写相应的功能模块,并将其update到报表工具中,进而扩展PRD的功能!

1、Maven项目到本地

官方github地址:https://github.com/pentaho/pentaho-reporting

小编github地址:https://github.com/TaoPengFei/pentaho-reporting

  • 设置settings.xml文件

(1)、 如果你使用IDEA自导的Maven的项目管理,请将settings.xml放置在你本地C盘/.m2目录下

(2)、 如果你本地创建了Maven构件库,请将settings.xml放置在你Maven安装目录下

我的安装目录是:D:\Maven\apache-maven-3.3.9\conf

  • 用IDEA打开Maven项目 File Open -> pom.xml

  • 等待Maven依赖包下载完毕,之前没有用过Maven的同学可能得自己学习一下Maven的简单实用,可以参考这篇文章http://blog.csdn.net/myarrow/article/details/50824793 ;
  • PRD源码目录结构

2、报表引擎

Pentaho Reporting 包含几大部分:
 基础库(libraries)
 报表引擎核心(engine core)
        其依赖于基础库。代码是 org.pentaho.reporting.engine.classic.core.**
 报表扩展(extentions),包括各种数据源适配器,脚本支持等
 报表设计器(designer)

3、Libraries基础库

主要基础库的解释

3.1、libformula

libformula是一个提供公式支持的基础库,包括:公式解析、公式运算以及一批预定义的表
达式和函数。公式的语法基于 OpenFormula 标准。

  • Function接口

接口 Function 是 libformula 中所有预定义的函数实现的接口。 一个函数是一个任意的运算,
返回的值类型只有在函数运算完成后才可用。函数必须是无状态的,这意味着,使用完全相
同的参数调用相同的函数必须总是返回相同的计算结果。当需要自定义函数时,如果函数跟报表状态无关,并且内部不需要访问报表的当前数据行,那么可以选择实现 libformula 的 Function 接口。

Function 接口只有两个方法:


package org.pentaho.reporting.libraries.formula.function;import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.lvalues.TypeValuePair;import java.io.Serializable;public interface Function extends Serializable {public String getCanonicalName();public TypeValuePair evaluate( FormulaContext context,ParameterCallback parameters )throws EvaluationException;
}
  • Expression 接口

在报表引擎核心模块的 function 包有一个 Expression 接口,表示一个表达式。表达式不维护
状态,因此是轻量级的函数。表达式用于在报表的一行内计算值,可以用一个 dataRow 变
量来访问这个报表内当前行的其他字段、表达式或函数。

Expression 接口主要的方法有:

package org.pentaho.reporting.engine.classic.core.function;import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory;
import org.pentaho.reporting.libraries.base.config.Configuration;
import java.io.Serializable;public interface Expression extends Cloneable, Serializable {public String getName();public void setName( String name );public Object getValue();public boolean isActive();public DataRow getDataRow();public Object clone() throws CloneNotSupportedException;public int getDependencyLevel();public void setDependencyLevel( int level );public Expression getInstance();public ResourceBundleFactory getResourceBundleFactory();public Configuration getReportConfiguration();public void setRuntime( ExpressionRuntime runtime );public ExpressionRuntime getRuntime();public boolean isDeepTraversing();public boolean isPreserve();
}

4、实现SLEEP()函数

现在自定义一个SLEEP()的函数。可以通过实现 LibFormula 库 Function 接口的方式来自定义函数。

4.1、定义函数分类类

用于创建新的Others分类。

package org.pentaho.reporting.libraries.formula.function.others;import org.pentaho.reporting.libraries.formula.function.AbstractFunctionCategory;
import org.pentaho.reporting.libraries.formula.function.FunctionCategory;/*** Created by 陶鹏飞 on 2017/3/6.*/
public final class OthersFunctionCategory extends AbstractFunctionCategory {public static final FunctionCategory CATEGORY = new OthersFunctionCategory();private OthersFunctionCategory(){super("org.pentaho.reporting.libraries.formula.function.others.category");}
}

4.2、定义函数类

重点是实现 evaluate 方法。

package org.pentaho.reporting.libraries.formula.function.others;import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.LibFormulaErrorValue;
import org.pentaho.reporting.libraries.formula.function.Function;
import org.pentaho.reporting.libraries.formula.function.ParameterCallback;
import org.pentaho.reporting.libraries.formula.lvalues.TypeValuePair;
import org.pentaho.reporting.libraries.formula.typing.Type;
import org.pentaho.reporting.libraries.formula.typing.coretypes.LogicalType;/*** Created by 陶鹏飞 on 2017/3/3.*/
public class SleepFunction implements Function {private  static  final long serialVersionUID = 4984027687466610131L;private  static  final TypeValuePair RETURN_INTERRUPTED = new TypeValuePair( LogicalType.TYPE, Boolean.FALSE );private  static  final TypeValuePair RETURN_UNINTERRUPTED = new TypeValuePair(LogicalType.TYPE,Boolean.TRUE);public SleepFunction(){// Constructor}@Override/* (non-Javadoc)* @see org.pentaho.reporting.libraries.formula.function.Function#getCanonicalName()*/public String getCanonicalName() {return "SLEEP";}@Override/* (non-Javadoc)* @see org.pentaho.reporting.libraries.formula.function.Function#evaluate(org.pentaho.reporting.libraries.formula.FormulaContext, org.pentaho.reporting.libraries.formula.function.ParameterCallback)*/public TypeValuePair evaluate(FormulaContext context, ParameterCallback parameters) throws EvaluationException {final  int parameterCount = parameters.getParameterCount();if ( parameterCount < 1 ){throw new EvaluationException(LibFormulaErrorValue.ERROR_ARGUMENTS_VALUE);}final Type type1 = parameters.getType(0);final Object value1 = parameters.getValue(0);final Number result = context.getTypeRegistry().convertToNumber(type1,value1);if ( result == null || (result.intValue() < 0) ){throw new EvaluationException(LibFormulaErrorValue.ERROR_INVALID_ARGUMENT_VALUE);}Boolean  sleepInterrupted = false;// The number should be the number of milliseconds to sleeptry {Thread.sleep(result.intValue());} catch (InterruptedException e) {//e.printStackTrace();sleepInterrupted = true;}// Whether the function was interrupted or completed.return sleepInterrupted ? RETURN_INTERRUPTED : RETURN_UNINTERRUPTED;}}

4.3、定义函数描述类

需要为函数定义一个函数描述类。需要调用父构造函数的方法,以加载资源。

package org.pentaho.reporting.libraries.formula.function.others;import org.pentaho.reporting.libraries.formula.function.AbstractFunctionDescription;
import org.pentaho.reporting.libraries.formula.function.FunctionCategory;
import org.pentaho.reporting.libraries.formula.function.information.InformationFunctionCategory;
import org.pentaho.reporting.libraries.formula.typing.Type;
import org.pentaho.reporting.libraries.formula.typing.coretypes.LogicalType;
import org.pentaho.reporting.libraries.formula.typing.coretypes.NumberType;/*** Created by 陶鹏飞 on 2017/3/3.*/
public class SleepFunctionDescription extends AbstractFunctionDescription {private static  final long serialVersionUID = 2368106667495213328L;public SleepFunctionDescription() {super("SLEEP", "org.pentaho.reporting.libraries.formula.function.others.Sleep-Function");}@Overridepublic Type getValueType() {return LogicalType.TYPE;}@Overridepublic FunctionCategory getCategory() {return OthersFunctionCategory.CATEGORY;}@Overridepublic int getParameterCount() {return 1;       // 1 Parameter - number of milliseconds}/*** Returns the parameter type at the given position using the function metadata. The first parameter is at the* position 0;** @param position The parameter index.* @return The parameter type.*/@Overridepublic Type getParameterType(int position) {return NumberType.GENERIC_NUMBER;}/*** Defines, whether the parameter at the given position is mandatory. A mandatory parameter must be filled in, while* optional parameters need not to be filled in.** @param position* @return*/@Overridepublic boolean isParameterMandatory(int position) {return true;}
}

4.4、定义资源文件

需要定义一个资源文件用于界面显示。

  • Others分类资源文件
#
# Created by 陶鹏飞 on 2017/3/6.
#
display-name=Others
description=Contains some user-defined statistical functions.
  • 说明函数资源文件(国际化)
#
# Created by 陶鹏飞 on 2017/3/6.
#
display-name=SLEEP
description=Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.
parameter.0.display-name=Number
parameter.0.description=The number of milliseconds to sleep (positive number only).
#
# Created by 陶鹏飞 on 2017/3/6.
#
display-name=SLEEP
description=\u4f7f\u5f53\u524d\u6267\u884c\u7684\u7ebf\u7a0b\u4e3a\u6307\u5b9a\u7684\u6beb\u79d2\u6570\u4f11\u7720\uff08\u6682\u65f6\u505c\u6b62\u6267\u884c\uff09.
parameter.0.display-name=Number
parameter.0.description=\u7761\u7720\u7684\u6beb\u79d2\u6570\uff08\u4ec5\u6b63\u6570).

4.5、注册函数

为了把函数注册到 libformula 模块,需要增加一个名为 libformula.properties 的属性文件,内容如下:

##
# Others functions
org.pentaho.reporting.libraries.formula.functions.others.Sleep.class=org.pentaho.reporting.libraries.formula.function.others.SleepFunction
org.pentaho.reporting.libraries.formula.functions.others.Sleep.description=org.pentaho.reporting.libraries.formula.function.others.SleepFunctionDescription

4.6、使用及效果

利用IDEA将libformula文件夹编译成libformula-6.1.0.1-196.jar包,并替换PRD报表开发工具目录D:\prd-ce-6.1.0.1-196\report-designer\lib下的libformula-6.1.0.1-196.jar包,重启 PRD。

效果展示:

四、在步骤三的基础上实现REGE()函数

现在根据步骤三自定义一个REGE()函数。因为不需要访问报表状态和数据行,所以可以通过
实现 LibFormula 库 Function 接口的方式来自定义函数。我们将REGE()放置在Others分类下,所以不需要在创建定义函数分类的JAVA类了。

4.1、定义函数类

首先要实现一个函数类,这里是 RegexFunction。重点是实现 evaluate 方法。

package org.pentaho.reporting.libraries.formula.function.others;import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.LibFormulaErrorValue;
import org.pentaho.reporting.libraries.formula.function.Function;
import org.pentaho.reporting.libraries.formula.function.ParameterCallback;
import org.pentaho.reporting.libraries.formula.lvalues.TypeValuePair;
import org.pentaho.reporting.libraries.formula.typing.TypeRegistry;
import org.pentaho.reporting.libraries.formula.typing.coretypes.TextType;import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** Created by 陶鹏飞 on 2017/3/3.*/
public class RegexFunction implements Function{@Overridepublic String getCanonicalName() {return "REGEX";}@Overridepublic TypeValuePair evaluate(FormulaContext context, ParameterCallback parameters) throws EvaluationException {if ( parameters.getParameterCount() != 2 ){throw new EvaluationException(LibFormulaErrorValue.ERROR_ARGUMENTS_VALUE);}final TypeRegistry  typeRegistry = context.getTypeRegistry();final String param1 = typeRegistry.convertToText( parameters.getType(0), parameters.getValue(0) );final String param2 = typeRegistry.convertToText( parameters.getType(1), parameters.getValue(1) );try {final Pattern pattern = Pattern.compile(param1);final Matcher matcher = pattern.matcher(param2);matcher.find();return new TypeValuePair(TextType.TYPE, matcher.group(1));}catch (Exception e){return new TypeValuePair(TextType.TYPE,e.getMessage());}}
}

4.2、定义函数描述类

需要为函数定义一个函数描述类。需要调用父构造函数的方法,以加载资源。

package org.pentaho.reporting.libraries.formula.function.others;import org.pentaho.reporting.libraries.formula.function.AbstractFunctionDescription;
import org.pentaho.reporting.libraries.formula.function.FunctionCategory;
import org.pentaho.reporting.libraries.formula.typing.Type;
import org.pentaho.reporting.libraries.formula.typing.coretypes.LogicalType;
import org.pentaho.reporting.libraries.formula.typing.coretypes.TextType;/*** Created by 陶鹏飞 on 2017/3/3.*/
public class RegexFunctionDescription extends AbstractFunctionDescription{public RegexFunctionDescription(){//确保调用父构造函数,带上函数名和函数的资源包名super("REGEX","org.pentaho.reporting.libraries.formula.function.others.Regex-Function");}//把函数放到Others分类中@Overridepublic FunctionCategory getCategory() {return OthersFunctionCategory.CATEGORY;}//函数返回2个参数@Overridepublic int getParameterCount() {return 2;}/*** Returns the parameter type at the given position using the function metadata. The first parameter is at the* position 0;** @param position The parameter index.* @return The parameter type.*/@Overridepublic Type getParameterType(int position) {return TextType.TYPE;}@Overridepublic Type getValueType() {return LogicalType.TYPE;}/*** Defines, whether the parameter at the given position is mandatory. A mandatory parameter must be filled in, while* optional parameters need not to be filled in.** @param position* @return*/@Overridepublic boolean isParameterMandatory(int position) {return true;}
}

4.3、资源文件(国际化)

需要定义一个资源文件用于界面显示。这里叫 Regex-Function.properties。

#
# Created by 陶鹏飞 on 2017/3/6.
#
display-name=REGEX
description=Executes a regular expression on a string, returning the first found group
parameter.0.display-name=Regular Expression
parameter.0.description=A Java Regular Expression string, with a grouping defined within the string.
parameter.1.display-name=String Input
parameter.1.description=A string to parse.
#
# Created by 陶鹏飞 on 2017/3/6.
#
display-name=REGEX
description=\u5728\u5b57\u7b26\u4e32\u4e0a\u6267\u884c\u6b63\u5219\u8868\u8fbe\u5f0f\uff0c\u8fd4\u56de\u7b2c\u4e00\u4e2a\u5df2\u627e\u5230\u7684\u7ec4\u3002
parameter.0.display-name=Regular Expression
parameter.0.description=\u4e00\u4e2ajava\u6b63\u5219\u8868\u8fbe\u5f0f\u7684\u5b57\u7b26\u4e32\uff0c\u7528\u5b57\u7b26\u4e32\u4e2d\u5b9a\u4e49\u7684\u5206\u7ec4\u3002
parameter.1.display-name=String Input
parameter.1.description=\u89e3\u6790\u5b57\u7b26\u4e32\u3002

4.4、注册函数

为了把函数注册到 libformula 模块,需要增加一个名为 libformula.properties 的属性文件,内容如下:

##
# Others functions
org.pentaho.reporting.libraries.formula.functions.others.Sleep.class=org.pentaho.reporting.libraries.formula.function.others.SleepFunction
org.pentaho.reporting.libraries.formula.functions.others.Sleep.description=org.pentaho.reporting.libraries.formula.function.others.SleepFunctionDescriptionorg.pentaho.reporting.libraries.formula.functions.others.Regex.class=org.pentaho.reporting.libraries.formula.function.others.RegexFunction
org.pentaho.reporting.libraries.formula.functions.others.Regex.description=org.pentaho.reporting.libraries.formula.function.others.RegexFunctionDescription

4.5、使用及效果

五、在步骤三的基础上实现REGE()表达式

、、、

六、相关资源下载

  • libformula-6.1.0.1-196.jar包下载:http://download.csdn.net/detail/github_37559821/9774131
  • 示例报表文件下载:http://download.csdn.net/detail/github_37559821/9774156

转载于:https://my.oschina.net/TaoPengFeiBlog/blog/854017

扩展Pentaho Report Designer报表工具相关推荐

  1. Pentaho Report Designer 教程(一)初识

    软件版本 Pentaho Report Designer 5.0.1-stable 一.Pentaho Report Designer 的安装 Pentaho Report Designer(PRD) ...

  2. seal report mysql_Seal Report开放数据库报表工具(.Net)

    概述:开放数据库报表工具(.Net) 简介:Seal-Report提供了一个完整的框架,用于从任何数据库生成日常报告和仪表板.Seal-Report是Microsoft .NET Framework完 ...

  3. 15个Java的报表工具简介

    1. BIRT Project BIRT报表是一款非常流行的开源报表开发工具.拥有和Dreamweaver一般的操作界面,可以像画table一样画报表,生成图片,导出Excel,html分页样样齐全, ...

  4. 12个最好的开源报表工具

    23顶 10踩 12个最好的开源报表工具 2009-11-18 17:05 by 资深编辑 wutao0603 评论(13) 有20017人浏览 收藏 .声明:JavaEye新闻文章的版权属于Java ...

  5. 定制自己的报表!7款实用开源报表工具

    https://www.evget.com/article/2014/4/8/20794.html 1. Pentaho Pentaho Report Designer是一款所见即所得的开源报表设计工 ...

  6. 【转载】java报表工具报表软件选型经验总结分享

    本人研二学生一枚,计算机专业,主要学的语言是java,这学期跟着导师开始做项目了,导师比较牛,给各个行业都做过很多项目,在学校和业内口碑都非常不错. 进入项目第一天,导师就给安排了任务--调研报表工具 ...

  7. 轻量级报表工具Telerik Report 2020新版亮点

    Telerik Reporting最新版下载    Telerik Report Server最新版下载 Telerik Reporting和Telerik Report Server的最新版本包含重 ...

  8. 杜邦分析模型 java_如何用java报表工具Style Report 制作财务分析杜邦分析

    Java报表软件设计--数据墨水让报表表格数据更快更准确的显示 Java报表软件设计--数据墨水让报表表格数据更快,更准确的显示 业界专家Edward Tufte提出了数据墨水(Data Ink)的概 ...

  9. Java报表工具技巧--Style Report报表套打模板设计

    在报表软件和报表工具领域,报表套打是最为常见的一个用户需求,例如发票.支票.信封.对账单.保单以及各类证件表格的打印都需要根据既定的表格样式快速批量打印出结果.报表套打功能也是各种报表工具必备的功能之 ...

最新文章

  1. ubuntu 进入 recovery mode
  2. 主从式网络的优点_贸泽电子原创开发板大赛【创意奖作品】物联网开发板做成主从机形式,是创意还是多此一举?...
  3. SAP MM模块-实施顾问岗位-面试手册-目录
  4. 多数据源报表解析之简单多源报表
  5. 现在在做的项目的一些感想.
  6. 理解CSS3属性transition
  7. NHibernate剖析:Mapping篇之Mapping-By-Code(2):运用ModelMapper
  8. 【IRA/GSM/UCS2】the difference of IRA/GSM/UCS2 character set
  9. VS2012 注册密钥
  10. 10种web前端开发可视化在线工具大全
  11. 抖音巨量百应怎么入驻?
  12. jNs 在 ASP.NET MVC 项目中的应用
  13. js 编写一个程序实现统计一串字符串中的英文小写字母个数!
  14. sql查取时间并进行相减后存入excel
  15. 机器学习测试模型 的混淆矩阵
  16. 阿里云官方出品:全面总结阿里云云原生架构方法论与实践经验
  17. 项目管理 | 项目资源管理(一)
  18. 【开发】后端框架——SpringBoot
  19. 实战篇ConstraintLayout的崛起之路
  20. python学习 之 pyqt5前后端分离试验(进度条)

热门文章

  1. Java调用net的Webservice时提示:undefined element declaration 's:schema'
  2. VMware中为linux设置网络
  3. Flutter创建圆圈图标按钮
  4. 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载
  5. git log 获取构建时间_Docker 运行 Jenkins 自动化构建 .NET Core 项目
  6. 神策数据正式成为国家级信创工委会成员单位!
  7. Dockerfile 布局的良好实践
  8. bzoj1833: [ZJOI2010]count 数字计数 codevs1359 数字计数
  9. websocket与socket.io
  10. Lamp的搭建--centos6.5下安装mysql