扩展Pentaho Report Designer报表工具
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 屬性按如下設置:
方式一:
方式二:
把函數拖入報表即可:
展示樣式:
三、本地構建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=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.SleepFunctionDescription4.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\u30024.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.RegexFunctionDescription4.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
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的扩展Pentaho Report Designer报表工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios打包报错:User interac
- 下一篇: Serv-u 10.3 的图文安装教程及