1.概述编辑
1.1 问题描述
用户在做填报报表时,希望点击提交按钮并不是往数据库中填报数据,而是要获取到填报页面的数据进行进一步处理,这个该如何解决呢?
1.2 实现思路
在 报表填报属性 中介绍了报表填报属性有 2 种设置方式,一个是内置 SQL 直接绑定字段,往数据库中填报数据,另外一种是添加自定义事件,如果需要获取数据对数据进行进一步处理,则可选择添加自定义事件,下面详细介绍。
2.示例编辑
2.1 准备数据
新建数据查询数据集 ds1,SQL 语句为:SELECT studentno,name,grade FROM STSCORE where name <> ''
2.2 设计填报表格
1)设计填报表格,将数据集相应字段拖到单元格中,A2 和 C2 单元格添加「数字控件」,B2 单元格添加「文本控件」,表格样式如下图所示:
2)C2 单元格设置为汇总求和,如下图所示:
3)点击「模板>报表填报属性」,新增一个自定义提交,点击编辑按钮,如下图所示:
注:也可以将外部编译得到的 class 文件放到 %FR_HOME%\webapps\webroot\WEB-INF\classes 文件夹下,然后点击「选择按钮」引用 class 文件。若修改了 class 文件,需要重启设计器,或重新选择文件,修改的代码才会生效。
2.3 自定义提交类
2.3.1 方法一
1)在类里面定义几个 JobValue,每一个 JobValue 对应一个单元格,在报表填报属性中通过属性列表中将其与对应的单元格绑定起来,具体使用如 DemoSubmitJob1:
package com.fr.data;
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()方法获取此对应单元格的状态
//单元格有六种状态:
// 删除(JobValue.VALUE_STATE_DELETED)
// 默认(JobValue.VALUE_STATE_DEFAULT)
// 修改(JobValue.VALUE_STATE_CHANGED)
// 插入(JobValue.VALUE_STATE_INSERT)
// 修改删除(单元格修改值之后被删除JobValue.VALUE_STATE_CHANGED_AND_DELETED)
// 插入修改(插入状态的单元格再被修改JobValue.VALUE_STATE_CHANGED_AND_INSERT)
if (studentno.getState().checkChanged()) {
// 此单元格的值在报表初始化后被修改过(包含修改和修改删除和修改插入三种状态)
} else if (studentno.getState().checkInsert()) {
// 此单元格是在报表初始化后新增的(包括插入和修改插入两种状态)
} else if (studentno.getState().checkDeleted()) {
// 此单元格所在的记录被执行了删除操作(包含删除和修改删除两种状态)
} else if (studentno.getState().checkDefault()) {
// 此单元格在报表初始化后没有变化
}
// 值获取
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 代码拷贝到自定义函数编辑界面,点击「编译」按钮,显示编译成功后,点击「保存」按钮,如下图所示:
3)点击增加属性按钮,给提交事件添加 4 个属性,注意值的选择为「单元格」和「公式」,如下图所示:
注1:属性名称跟类文件中定义的 JobValue 是一致的,必须保证「报表填报属性」处添加的属性名称与类文件中定义的名称保持一致。如果在类文件中对应参数类型不是 JobValue 的话,则必须与属性的数据类型保持一致。
注2:一般来说,为了便于维护,可以将 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()方法获取此对应单元格的状态
//单元格有六种状态:
// 删除(JobValue.VALUE_STATE_DELETED)
// 默认(JobValue.VALUE_STATE_DEFAULT)
// 修改(JobValue.VALUE_STATE_CHANGED)
// 插入(JobValue.VALUE_STATE_INSERT)
// 修改删除(单元格修改值之后被删除JobValue.VALUE_STATE_CHANGED_AND_DELETED)
// 插入修改(插入状态的单元格再被修改JobValue.VALUE_STATE_CHANGED_AND_INSERT)
if (ce.getState().checkChanged()) {
// 此单元格的值在报表初始化后被修改过(包含修改和修改删除和修改插入三种状态)
} else if (ce.getState().checkInsert()) {
// 此单元格是在报表初始化后新增的(包括插入和修改插入两种状态)
} else if (ce.getState().checkDeleted()) {
// 此单元格所在的记录被执行了删除操作(包含删除和修改删除两种状态)
} else if (ce.getState().checkDefault()) {
// 此单元格在报表初始化后没有变化
}
System.out.print(ce.getValue()); // 通过 JobValue 的 getValue 方法获得单元格的值
} else {
// 非单元格,则对应具体类型值
System.out.print(entry.getValue());
}
}
System.out.println();
}
}
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
3)点击增加属性按钮,给提交事件添加 4 个属性,如下图所示:
注:方法二中是通过 Calculator 参数属性 PROPERTY_VALUE 来获取报表填报属性处的属性与属性值,再通过 JobValue 来得到单元格的值,在类文件中并不是一一对应的获取属性与属性值,而是通过 map 遍历来获取属性与属性值,所以在报表填报属性处增加属性时,属性名字可随意定义,但是后面的值如果是单元格的话,必须选择单元格类型。
2.3.3 方法三
1)自定义事件除了可继承自 DefinedSubmitJob 这个接口之外,还可以继承 TotalSubmitJob 接口,这两个接口的区别在于 DefinedSubmitJob 多次执行,即一行一行的获取模板中的数据,获取一行数据则执行一次自定义事件,而 TotalSubmitJob 接口只执行一次,即先获取到模板中所有的数据,然后在类里面循环,具体使用如 DemoTotalSubmitJob:
package com.fr.data;
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()方法获取此对应单元格的状态
//单元格有六种状态:
// 删除(JobValue.VALUE_STATE_DELETED)
// 默认(JobValue.VALUE_STATE_DEFAULT)
// 修改(JobValue.VALUE_STATE_CHANGED)
// 插入(JobValue.VALUE_STATE_INSERT)
// 修改删除(单元格修改值之后被删除JobValue.VALUE_STATE_CHANGED_AND_DELETED)
// 插入修改(插入状态的单元格再被修改JobValue.VALUE_STATE_CHANGED_AND_INSERT)
if (ce.getState().checkChanged()) {
// 此单元格的值在报表初始化后被修改过(包含修改和修改删除和修改插入三种状态)
} else if (ce.getState().checkInsert()) {
// 此单元格是在报表初始化后新增的(包括插入和修改插入两种状态)
} else if (ce.getState().checkDeleted()) {
// 此单元格所在的记录被执行了删除操作(包含删除和修改删除两种状态)
} else if (ce.getState().checkDefault()) {
// 此单元格在报表初始化后没有变化
}
value = ce.getValue(); // 通过 JobValue 的 getValue 方法获得单元格的值
}
System.out.print(data.getColumnName(j) + " : " + value);
}
System.out.print("}");
System.out.println();
}
}
}
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
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 其他应用
自定义事件不仅可用于报表填报属性处,也可用于按钮控件中的提交事件,具体应用参见文档:上传下载文件插件
3.模板下载编辑
1)方法一
已完成模板可参见:%FR_HOME%\webapps\webroot\WEB-INF\reportlets\doc\Form\LineForm\填报自定义提交.cpt
点击下载模板:填报自定义提交.cpt
2)方法二
已完成模板可参见:%FR_HOME%\webapps\webroot\WEB-INF\reportlets\doc\Form\LineForm\填报自定义提交2.cpt
点击下载模板:填报自定义提交2.cpt
3)方法三
已完成模板可参见:%FR_HOME%\webapps\webroot\WEB-INF\reportlets\doc\Form\LineForm\填报自定义提交3.cpt
点击下载模板:填报自定义提交3.cpt