1.概述编辑
1.1问题描述
用户在做填报报表时,希望点击提交按钮并不是往数据库中填报数据,而是要获取到填报页面的数据进行进一步处理,这个该如何解决呢?
1.2实现思路
在 报表填报属性 中介绍了报表填报属性有 2 种设置方式,一个是内置 SQL 直接绑定字段,往数据库中填报数据,另外一种是添加自定义事件,如果需要获取数据对数据进行进一步处理,则可选择添加自定义事件,下面详细介绍。
2.示例编辑
2.1 准备数据
新建数据查询数据集 ds1,SQL 语句为:SELECT * FROM STSCORE where name <> '' 。
2.2 设计填报表格
1)设计填报表格,并将数据集相应字段拖到单元格中,A2 和 C2 单元格添加数字控件,B2 单元格添加文本控件,如下图所示:
2)C2 单元格设置为汇总求和,如下图所示:
3)报表填报属性界面新增一个自定义提交,点击编辑按钮,如下图所示:
2.3自定义提交类
2.3.1方法一:
1)在类里面定义几个 JobValue,每一个 JobValue 对应一个单元格,在报表填报属性中通过属性列表中将其与对应的单元格绑定起来,具体使用如 DemoSubmitJob1:
package com.fr.data; import com.fr.data.DefinedSubmitJob; import com.fr.data.JobValue; import com.fr.script.Calculator; public class DemoSubmitJob1 extends DefinedSubmitJob { /** * 当模板自定义事件增加的属性 名称与下面变量有对应时,则会自动赋值于此对应变量 */ public String getJobType(){ return " "; } private JobValue studentno; // JobValue 对应单元格 private JobValue name; private JobValue grade; private boolean isPass; // 非单元格,则对应具体类型值 /** * 每一条记录执行一次此方法 * 同一提交事件在一个处理事务内,此对象是唯一的 */ public void doJob(Calculator calculator) throws Exception { // JobValue 的 getValueState()方法获取此对应单元格的状态 if (studentno.getValueState() == JobValue.VALUE_STATE_CHANGED) { // 此单元格的值在报表初始化后被修改过 } else if (studentno.getValueState() == JobValue.VALUE_STATE_INSERT) { // 此单元格是在报表初始化后新增的(例如执行了插入行操作) } else if (studentno.getValueState() == JobValue.VALUE_STATE_DELETED) { // 此单元格所在的记录被执行了删除操作 } else if (studentno.getValueState() == JobValue.VALUE_STATE_DEFAULT) { // 此单元格在报表初始化后没有变化 } // 值获取 System.out.print(" 学号: " + studentno.getValue()); // 通过 JobValue 的 getValue 方法获得单元格的值 System.out.print(" 姓名: " + name.getValue()); System.out.print(" 总分: " + grade.getValue()); System.out.print(" 是否达标: " + isPass); System.out.println(); } }
注:可以将所有变量全部定义成 JobValue 对象,通过 getValue() 获取对象的值。
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
注:也可以将外部编译得到的class文件放到%FR_HOME%\webapps\webroot\WEB-INF\classes文件夹下,然后点击选择按钮引用class文件。
3)点击增加属性按钮,给提交事件添加 4 个属性,如下图所示:
注:属性名称跟类文件中定义的 JobValue 是一致的,必须保证报表填报属性处添加的属性名称与类文件中定义的名称保持一致。如果在类文件中对应参数类型不是 JobValue 的话,则必须与属性的数据类型保持一致。一般来说,为了便于维护,可以将 Java 类中的所有变量全部设为 JobValue 对象,不论报表填报属性中的属性类型是什么,均可以通过 GetValue 获取其值。
2.3.2方法二:
1)通过 doJob 的方法参数 Calculator 中的 Property_Value 属性, Property_Value 属性对应一个 map 对象,Map 中包含报表填报属性中所有属性名称以及它们对应的值,使用 map 中的 getValue() 方法获取属性值,即单元格,接着使用 JobValue的getValue() 方法获取单元格的值,详细如 DemoSubmitJob2:
package com.fr.data; import com.fr.script.Calculator; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class DemoSubmitJob2 extends DefinedSubmitJob { /** * 每一条记录执行一次此方法 * 同一提交事件在一个处理事务内,此对象是唯一的 */ public String getJobType(){ return " "; } public void doJob(Calculator calculator) throws Exception { // 同样可以直接在传入的 calculator 中获取定义的属性及其对应的值 Map map = (Map)calculator.getAttribute(PROPERTY_VALUE); if (map == null) return; Set set = map.entrySet(); Iterator it = set.iterator(); Entry entry; // 遍历Map获取所有属性及其值 while (it.hasNext()) { entry = (Entry)it.next(); System.out.print(" " + entry.getKey() + ": "); // JobValue对应单元格 if (entry.getValue() instanceof JobValue) { JobValue ce = (JobValue)entry.getValue(); // JobValue的getValueState()方法获取此对应单元格的状态 if (ce.getValueState() == JobValue.VALUE_STATE_CHANGED) { // 此单元格的值在报表初始化后被修改过 } else if (ce.getValueState() == JobValue.VALUE_STATE_INSERT) { // 此单元格是在报表初始化后新增的(例如执行了插入行操作) } else if (ce.getValueState() == JobValue.VALUE_STATE_DELETED) { // 此单元格所在的记录被执行了删除操作 } else if (ce.getValueState() == JobValue.VALUE_STATE_DEFAULT) { // 此单元格在报表初始化后没有变化 } System.out.print(ce.getValue()); // 通过 JobValue 的 getValue 方法获得单元格的值 } else { // 非单元格,则对应具体类型值 System.out.print(entry.getValue()); } } System.out.println(); } }
注:方法二中是通过 Calculator 参数属性 PROPERTY_VALUE 来获取报表填报属性处的属性与属性值,再通过 JobValue 来得到单元格的值,在类文件中并不是一一对应的获取属性与属性值,而是通过 map 遍历来获取属性与属性值,所以在报表填报属性处增加属性时,属性名字可随意定义,但是后面的值如果是单元格的话,必须选择单元格类型。
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
注:也可以将外部编译得到的class文件放到%FR_HOME%\webapps\webroot\WEB-INF\classes文件夹下,然后点击选择按钮引用class文件。
3)点击增加属性按钮,给提交事件添加 4 个属性,如下图所示:
2.3.3方法三:
1)自定义事件除了可继承自 DefinedSubmitJob 这个接口之外,还可以继承 TotalSubmitJob 接口,这两个接口的区别在于 DefinedSubmitJob 多次执行,即一行一行的获取模板中的数据,获取一行数据则执行一次自定义事件,而 TotalSubmitJob 接口只执行一次,即先获取到模板中所有的数据,然后在类里面循环,具体使用如DemoTotalSubmitJob:
package com.fr.data; import com.fr.data.JobValue; import com.fr.data.TotalSubmitJob; import com.fr.script.Calculator; public class DemoTotalSubmitJob extends TotalSubmitJob { /** * 同一提交事件,在一个提交事务内只执行一次 * @param data 以二维表排列的所有提交数据 * */ public String getJobType(){ return " "; } protected void doTotalJob(Data data, Calculator calculator) throws Exception { data.getColumnCount(); // 获取列的数量,每一列对应一个添加的属性 for (int i = 0; i < data.getColumnCount(); i++) { System.out.println(data.getColumnName(i)); // 获取对应的属性名称 } for (int i = 0; i < data.getRowCount(); i++) { // getRowCount 获取一共多少行数据 System.out.print("ROW " + i + " {"); for (int j = 0; j < data.getColumnCount(); j++) { if (j > 0) System.out.print(", "); Object value = data.getValueAt(i, j); // 获取对应位置的值 if (value instanceof JobValue) { JobValue ce = (JobValue)value; // JobValue的getValueState()方法获取此对应单元格的状态 if (ce.getValueState() == JobValue.VALUE_STATE_CHANGED) { // 此单元格的值在报表初始化后被修改过 } else if (ce.getValueState() == JobValue.VALUE_STATE_INSERT) { // 此单元格是在报表初始化后新增的(例如执行了插入行操作) } else if (ce.getValueState() == JobValue.VALUE_STATE_DELETED) { // 此单元格所在的记录被执行了删除操作 } else if (ce.getValueState() == JobValue.VALUE_STATE_DEFAULT) { // 此单元格在报表初始化后没有变化 } value = ce.getValue(); // 通过 JobValue 的 getValue 方法获得单元格的值 } System.out.print(data.getColumnName(j) + " : " + value); } System.out.print("}"); System.out.println(); } } }
注:方法三与方法二中的使用方式类似。
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
注:也可以将外部编译得到的class文件放到%FR_HOME%\webapps\webroot\WEB-INF\classes文件夹下,然后点击选择按钮引用class文件。
3)点击增加属性按钮,给提交事件添加 4 个属性,如下图所示:
2.4效果预览
2.4.1方法一:
1)保存报表,选择填报预览,前端点击提交按钮,如下图所示:
2)成功提交后,文件夹%FR_HOME%\bin下会生成文件out.log,如下图所示:
3)记事本打开out.log,可以看到导出的填报信息,如下图所示:
2.4.2方法二:
1)保存报表,选择填报预览,前端点击提交按钮,如下图所示:
2)成功提交后,文件夹%FR_HOME%\bin下会生成文件out.log,如下图所示:
3)记事本打开out.log,可以看到导出的填报信息,如下图所示:
2.4.3方法三:
1)保存报表,选择填报预览,前端点击提交按钮,如下图所示:
2)成功提交后,文件夹%FR_HOME%\bin下会生成文件out.log,如下图所示:
3)记事本打开out.log,可以看到导出的填报信息,如下图所示:
2.5 其他应用
自定义事件不仅可用于报表填报属性处,也可用于按钮控件中的提交事件,具体应用参见文档:上传下载文件插件