填报自定义校验

编辑
  • 文档创建者:文档助手1
  • 浏览次数:14949次
  • 编辑次数:25次
  • 最近更新:Kevin-s 于 2019-06-04
  • 1. 描述

    在 Web 页面录入数据后,提交前,可能存在一些特殊的业务逻辑,用 FineReport 现有的校验公式实现起来比较复杂,或者是用户已经有了一套校验标准,希望FineReport 能够将这种校验交付给用户自己的程序来判断,然后将结果返回给 FineReport,这个时候就可以用自定义校验

    2. 模板设计

    用自定义校验来验证每个销售员的销售总额数据是否正确,所有的销售总额数据均不能小于 2000。

    1)新建数据查询 ds1:SELECT * FROM 销售总额

    2)将数据列拖曳至模板中,并为数据列所在单元格添加文本控件,如下图:

    3)点击模板>报表填报属性,添加一个内置 SQL,如下图:


    3. 自定义校验类

    自定义校验功能,该功能是指用户可以通过 Java 类来校验填报页面上数据是否符合规则,并获得返回值。

    自定义校验类既可通过接口类 com.fr.data.VerifyJob.class 对每条记录进行校验,校验失败时定位至出错单元格,也可以通过 com.fr.data.TotalVerifyJob 接口类对页面数据进行校验,下面分别介绍:

    注:不论继承哪个接口类,都需要定义一个私有变量 type(名称可改变),用来返回校验结果,type=0,表示校验成功,type=1 表示校验失败,默认 type=0。

    3.1 方法一:com.fr.data.VerifyJob.class

    通过该接口编写自定义校验类,可以对每条记录进行校验,校验失败时可以定位至出错单元格。

    该接口类有一下方法:

    doJob(Calculator calculator):calculator 可以获得当前报表、当前单元格;

    getType() :获取用户设置的标志位 type 的值;

    getMessage() :根据type类型设置返回信息。

    VerifyJob接口是每一条记录执行一次 doJob 方法,执行完后将该记录的结果 get 出来,放到 list 里面,返回信息,以便在 BS 下定位错误单元格。继承 VerifyJob 接口时,用户在其自定义校验类中定义的field名必须与添加的属性名称匹配。

    下面编写 VerifyJobDemo 类,继承自 VerifyJob,对填报页面数据进行校验,如果销售总额的值小于 2000,则提示“销量值不能小于最小基数”。

    (1)代码如下:


    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  
      
        }  
      
    }

    注: 校验成功的时候不会返回 "恭喜你,校验成功",还是显示我们默认的。

    编译上述 Java 类,将 class 文件复制到%FR_HOME%\webapps\webroot\WEB_INF\classes\com\fr\demo文件夹下。

    如上代码,定义了 3 个变量 type、salenum、minnum,其中 type 是结果变量,其他两个变量则是通过报表填报属性>数据校验>自定义校验中传过来的属性名称,如下图,在数据校验中添加一个自定义校验,点击选择按钮选中 VerifyJobDemo 类:

     

    点击增加属性,添加 2 个属性,分别与 Java 类中的 2 个变量对应,由于salenum变量为JobValue对象,故其对应的值应该为单元格(必须是单元格),minnum 变量则是一般类型的变量:


    注:如果继承自 com.fr.data.VerifyJob.class接口类,那么模板填报属性-数据校验中的属性名称必须与 Java 类中的变量名称保持一致。

    (2)效果查看

    填报预览模板,点击提交按钮,如下图:


    3.2 方法二:com.fr.data.TotalVerifyJob.class

    通过该接口类编写的自定义校验类,通过 Data 参数(以二维表排列的所有提交数据)获取所有属性值,在类中逐条逐条对数据进行校验,并返回一个最终的校验结果。

    该接口类有以下方法:

    doTotalJob(Data data> Calculator calculator) Data 以二维表中的形式存储了自定义校验界面添加的属性对应的值,calculator 可以获得当前报表、当前单元格;

    getType() 获取用户设置的标志位type的值;

    getMessage() 根据type类型设置返回信息。

    编写 TotalVerifyJobDemo 类,集成自 TotalVerifyJob 类,对填报页面数据进行校验,如果销售总额小于 2000,则提示“销量值不能小于最小基数”。

    (1)代码如下:

    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";  
        }  
    }

    注:校验成功的时候不会返回 "恭喜你,校验成功",显示默认的校验提示。

    编辑 Java 文件,将 class 文件保存到%FR_HOME%\webapps\webroot\WEB_INF\classes\com\fr\demo文件夹下。

    不同于 VerifyJob 接口类中的方法,TotalVerifyJob 接口是先将自定义校验中添加的所有属性值全部取出来,组成一个二维列表,存放在 Data 参数中,然后在类中一个一个校验,并且不论属性值的单元格对象还是一般类型数值,都必须先转换为JobValue对象,然后再将JobValue对象转换为实际的数据类型,故自定义校验中需要添加几个属性,那么 Java 类中就需要定义几个 JobValue 对象。

    如上代码,定义了 5 个变量 type、salenum、minnum、sale、min,其中t ype 是结果变量,salenum 和 minnum是 JobValue 对象,用来接收 Data 参数中存储的 2个属性值,sale 和 min 变量则是相应的具体数据类型,用来在校验时,存储转换之后的实际值,并进行校验。
    如下图,在数据校验中添加一个自定义校验,点击选择按钮选中 TotalVerifyJobDemo  类:


    点击增加属性,添加 2 个属性,属性名称不一定要与 Java 类中 JobValue 对象保持一致:


    注:不同于 VerifyJob 方法,这里的属性名称不一定要与 Jav a类中 JobValue 对象的名称一致,其是按照位置对应的,即自定义校验时,FR会将这两个属性值以二维列表形式存放在 Data 参数中,按照顺序取数,Data 的第一列为第一个属性对应的值,如果属性值为单元格,则获取单元格扩展后的所有值,如果为固定值,则该列的所有行均为该值,行数由单元格扩展的行数确定。

    (2)效果查看

    如下图:


    4. 总结

    自定义校验类有 2 个接口可以继承,VerifyJob 接口类可定位到具体出错单元格,其是根据属性名称一条一条校验,故可定位到具体出错单元格,而 TotalVerifyJob 接口类不能定位到具体出错单元格,其是先将所有属性值全部取出来存放到 Data 参数中,然后再通过 Data 参数进行比较,故无法定位到具体出错单元格位置。

    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)上传附件并选择否,校验失败,提示“请上传附件”,效果如下:


    若未上传附件,无论选择是或否,均会提示“请上传附件”。


    附件列表


    主题: 填报应用
    标签: 暂无标签 编辑/添加标签
    如果您认为本文档还有待完善,请编辑

    文档内容仅供参考,如果你需要获取更多帮助,付费/准付费客户请咨询帆软技术支持
    关于技术问题,您还可以前往帆软社区,点击顶部搜索框旁边的提问按钮
    若您还有其他非技术类问题,可以联系帆软传说哥(qq:1745114201

    此页面有帮助吗?只是浏览 [ 去社区提问 ]