1. 概述编辑
1.1 应用场景
一些特殊的业务逻辑用公式校验实现起来比较复杂,希望可以交付给用户自定义的程序来判断,然后将结果返回给 FineReport 。
1.2 功能入口
设计器菜单栏点击模板>报表填报属性,设置界面选择数据校验,点击,选择自定义校验即可,如下图所示:
2. 示例编辑
2.1 准备数据
新建数据查询数据集 ds1,SQL 语句为:SELECT * FROM 销售总额
2.2 设计表格
设计填报表格, 将数据集字段拖到对应单元格中,给 A2~B2 单元格添加文本控件,如下图所示:
2.3 设置提交
设计器菜单栏点击模板>报表填报属性,提交设置项下新增一个内置SQL提交,如下图所示:
2.4 自定义校验类
可以通过如下 2 个接口实现自定义校验类:
com.fr.data.VerifyJob.class:对每条记录进行校验,校验失败时定位所有出错的单元格。
com.fr.data.TotalVerifyJob.class:对每条记录进行校验,但无法定位出错的单元格。
注:不论继承哪个接口类,都需要定义一个私有变量 type (名称可变),用来返回校验结果。type=0 表示校验成功,type=1 表示校验失败,默认 type=0。
2.4.1 方法一:com.fr.data.VerifyJob.class
示例要实现的效果是:销售总额的值小于 2000 时,弹出校验出错提示“销量值不能小于最小基数”。
1)报表填报属性界面新增一个自定义校验,点击编辑按钮,如下图所示:
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
注:也可以将外部编译得到的 class 文件放到%FR_HOME%\webapps\webroot\WEB-INF\classes文件夹下,然后点击选择按钮引用 class 文件。
Java 代码如下:
package com.fr.demo;
import com.fr.base.Utils;
import com.fr.data.DefinedVerifyJob;
import com.fr.data.JobValue;
import com.fr.data.Verifier;
import com.fr.script.Calculator;
public class VerifyJobDemo extends DefinedVerifyJob{
/*
* 必须要定义此私有变量,变量名可改,表示校验状态
* 0 表示校验成功,默认校验状态位为0
* 1 表示校验失败
*/
private int type = 0;
/**
* 当模板自定义事件增加的属性 名称与下面变量有对应时,则会自动赋值于此对应变量
*/
private JobValue salenum; // JobValue 对应单元格
private int minnum; // 非单元格,则对应具体类型值
public void doJob(Calculator calculator) throws Exception {
/*
* 如这边提供一个简单的判断来模拟执行过程
* 校验规则为销量需要大于等于最小基数:salenum >= minnum
* 校验不通过,提示“销量值不能小于最小基数”
*/
if(salenum != null){
int sale = 0;
if(salenum.getValue() instanceof Integer){ //将单元格值转为整型以便用于比较
sale = (Integer)salenum.getValue();
}else {
sale = Integer.parseInt(Utils.objectToString(salenum.getValue()));
}
if(sale < minnum){ //校验判断
type = 1;
}
}else {
type = 1;
}
}
public String getMessage() {
// 根据校验状态是成功还是失败,设置对应的返回信息
if(type == 0){
return "恭喜你,校验成功";//这个值并没有用,成功的时候不会显示这里的内容,还是显示我们默认的
}else{
return "销量值不能小于最小基数";
}
}
public Verifier.Status getType() {
// 返回校验状态
return Verifier.Status.parse(type);
}
public void doFinish(Calculator arg0) throws Exception {
// TODO Auto-generated method stub
}
}
3)点击增加属性按钮,添加 2 个属性,分别与 Java 类中的 2 个变量对应,如下图所示:
注1:minnum 即校验值,此处设置为 2000,可自行更改。
注2:如果继承自 com.fr.data.VerifyJob.class接口类,那么自定义校验中的属性名称必须与 Java 类中的变量名称保持一致。
2.4.2 方法二:com.fr.data.TotalVerifyJob.class
1)报表填报属性界面新增一个自定义校验,点击编辑按钮,如下图所示:
2)将 Java 代码拷贝到自定义函数编辑界面,点击编译按钮,只有显示编译成功后,才能保存,如下图所示:
注:也可以将外部编译得到的 class 文件放到%FR_HOME%\webapps\webroot\WEB-INF\classes文件夹下,然后点击选择按钮引用 class 文件。
Java 代码如下:
package com.fr.demo;
import com.fr.base.Utils;
import com.fr.data.JobValue;
import com.fr.data.TotalVerifyJob;
import com.fr.data.Verifier;
import com.fr.script.Calculator;
public class TotalVerifyJobDemo extends TotalVerifyJob{
/*
* type : 必须要定义此私有变量,变量名可改,表示校验状态
* 0 表示校验成功,默认校验状态位为 0
* 1 表示校验失败
*/
private int type = 0;
@Override
protected void doTotalJob(Data data, Calculator calculator)
throws Exception { // @param data 以二维表排列的所有提交数据
int sale, min;
JobValue salenum, minnum;
int row = data.getRowCount(); // 获取一共多少行数据
for (int i = 0; i < row; i++) { // 遍历每行,进行校验
salenum = (JobValue) data.getValueAt(i, 0);
sale = Integer.parseInt(Utils.objectToString(salenum.getValue()));
minnum = (JobValue) data.getValueAt(i, 1);
min = Integer.parseInt(Utils.objectToString(minnum.getValue()));
if(sale < min){ //校验判断
type = 1;
}
}
}
public String getMessage() {
// 根据校验状态是成功还是失败,设置对应的返回信息
if(type == 0){
return "恭喜你,校验成功";//这个值并没有用,成功的时候不会显示这里的内容,还是显示我们默认的
}else{
return "销量值不能小于最小基数";
}
}
public Verifier.Status getType() {
// 返回校验状态
return Verifier.Status.parse(type);
}
public String getJobType() {
return "totalVerifyJob";
}
}
3)点击增加属性按钮,添加 2 个属性,分别与 Java 类中的 2 个变量对应,如下图所示:
注:不同于 VerifyJob 方法,这里的属性名称不一定要与 Java 类中 JobValue 对象的名称一致,其是按照位置对应的,即自定义校验时,FineReport 会将这两个属性值以二维列表形式存放在 Data 参数中,按照顺序取数,Data 的第一列为第一个属性对应的值,如果属性值为单元格,则获取单元格扩展后的所有值,如果为固定值,则该列的所有行均为该值,行数由单元格扩展的行数确定。
2.5 效果预览
2.5.1 方法一:com.fr.data.VerifyJob.class
1)PC 端
保存报表,点击填报预览,前端点击数据校验后,弹出多条校验出错信息且小于 2000 的数据会被定位出来,如下图所示:
2)移动端
同时支持 App 端和 H5 端预览,但是不支持定位哪些单元格出错,如下图所示:
2.5.2 方法二:com.fr.data.TotalVerifyJob.class
1)PC 端
保存报表,点击填报预览,前端点击数据校验后,弹出一条校验出错信息,但无法定位出错单元格,如下图所示:
2)移动端
同时支持 App 端和 H5 端预览,不支持定位哪些单元格出错,如下图所示:
3. 模板下载编辑
3.1 方法一
已完成模板参见:%FR_HOME%\webapps\webroot\WEB-INF\reportlets\doc\Form\VerifyForm\自定义校验方法一.cpt
点击下载模板:自定义校验方法一.cpt
3.2 方法二
已完成模板参见:%FR_HOME%\webapps\webroot\WEB-INF\reportlets\doc\Form\VerifyForm\自定义校验方法二.cpt
点击下载模板:自定义校验方法二.cpt
5. 拓展示例编辑
下面我们再提供一个方法,校验文件控件是否上传了附件
5.1 模板制作
使用 上传文件至数据库并下载 里的上传模板,并增加一列如下图:
5.2 自定义校验类
代码如下:
package com.fr.demo;
import com.fr.base.FRContext;
import com.fr.base.Utils;
import com.fr.cache.Attachment;
import com.fr.data.DefinedVerifyJob;
import com.fr.data.JobValue;
import com.fr.data.Verifier;
import com.fr.general.FArray;
import com.fr.script.Calculator;
import com.fr.log.FineLoggerFactory;
public class VerifyJobDemo2 extends DefinedVerifyJob{
/*
* 必须要定义此私有变量,变量名可改,表示校验状态
* 0 表示校验成功,默认校验状态位为0
* 1 表示校验失败
*/
private int type = 0;
/**
* 当模板自定义事件增加的属性 名称与下面变量有对应时,则会自动赋值于此对应变量
*/
private JobValue file; // JobValue对应单元格
private JobValue yesOrno;
// private int minnum; // 如果是非单元格,则对应具体类型值
public void doJob(Calculator calculator) throws Exception {
/*
* 如这边提供一个简单的判断来模拟执行过程
* 校验规则为yesOrno等于1 并且 file 上传了附件:yesOrno == 1 && file 上传附件
* 校验不通过,提示“请上传附件”
*/
//这个是fr打印日志的接口,如果是设计器下的话 会在日志里看到对应的日志信息打印出来
FRContext.getLogger().error("##### start verigy####");
int yn = 0;
if(yesOrno.getValue() instanceof Integer){ //将单元格值转为整型以便用于比较
yn = Integer.parseInt(yesOrno.getValue().toString());
}else {
yn = Integer.parseInt(Utils.objectToString(yesOrno.getValue()));
}
FineLoggerFactory.getLogger().error("##### yn = "+yn +"####");
if (yn == 1) {
//判断file是否有上传文件
if (file.getValue() instanceof FArray && ((FArray) file.getValue()).length() > 0
&& ((FArray) file.getValue()).elementAt(0) instanceof Attachment) {
type = 0;
} else {
type = 1;
}
} else {
type = 1;
}
}
public String getMessage() {
// 根据校验状态是成功还是失败,设置校验失败的返回信息
if(type == 1){
return "请上传附件";
}
return "";
}
public Verifier.Status getType() {
// 返回校验状态
return Verifier.Status.parse(type);
}
public void doFinish(Calculator arg0) throws Exception {
// TODO Auto-g
编译 VerifyJobDemo2.java,生成 VerifyJobDemo2.class 文件放在%FR_HOME%\webapps\webroot\WEB_INF\classes\com\fr\scheduel文件夹下。
在数据校验中添加一个自定义校验,选择模板>报表填报属性>数据校验,增加一个自定义校验,点击 按钮选中 VerifyJobDemo2 类,并添加 2 个属性:
5.3 效果查看
1)上传附件并选择是,校验成功,效果如下:
2)上传附件并选择否,校验失败,提示“请上传附件”,效果如下:
若未上传附件,无论选择是或否,均会提示“请上传附件”。