使用QLExpress动态制定计算公式 您所在的位置:网站首页 excel如何自定义公式求平均数的方法 使用QLExpress动态制定计算公式

使用QLExpress动态制定计算公式

2023-12-18 13:22| 来源: 网络整理| 查看: 265

QLExpress的使用

最近公司要统计一些数据,需要定义一些统计数据的计算公式,然后通过计算公式统计数据。于是我去找了找有没有什么好用的工具。说实话,现在做开发,网上能找到许多实用的工具,而且还是开源的,非常感谢大佬们的分享。今天要说的是QLExpress。

QLExpress的简单介绍

​ QLExpress由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。它具有以下特性:

线程安全。高效执行。弱类型脚本语言。安全控制。代码精简,依赖最小。 简单的例子 添加依赖 com.alibaba QLExpress 3.2.0 添加代码 public static void main(String[] args) throws Exception{ String express = "2 * 3 / 2 + 4 - 5"; ExpressRunner runner = new ExpressRunner(); Object result = runner.execute(express,null, null, false,false); // 输出结果,结果为2,使用的时候还是挺方便的 System.out.println("计算公式的结果:" + result); } /** * 以下复制于官网的说明 * * 执行一段文本 * @param expressString 程序文本 * @param context 执行上下文,可以扩展为包含ApplicationContext * @param errorList 输出的错误信息List * @param isCache 是否使用Cache中的指令集,建议为true * @param isTrace 是否输出详细的执行指令信息,建议为false * @param aLog 输出的log * @return * @throws Exception */ Object execute(String expressString, IExpressContext context,List errorList, boolean isCache, boolean isTrace, Log aLog);

​ 当然,这只是一个简单的例子,QLExpress可不止这样。

实战场景

​ 背景之前也说过了,公式需要先设置一个计算公式,而计算公式可不是像"2 * 3 / 2 + 4 - 5"这样直接将需要计算的值直接写死在公式里的,而是像这样:“avg(item_code_f,item_code_b) +item_code_a ÷ item_code_k - 100”,item_code_f这类数据其实就是数据表里的唯一编码。

​ 计算的时候需要先把通过编码去查找对应的数据值,然后带入公式。其中要注意的是avg是我们自定义的计算符号,意为计算平均值。而且为了用户方便理解,乘法计算的符号是用×而不是*,除法则是÷而不是/,所以这些东西都需要自己去处理。

​ 于是我整理了一下思路,想出了解决的办法,下面是我写的一个demo,可能有些地方略显粗糙,但是我总不能把公司代码直接贴出来,将就着看吧 T_T。

表结构 CREATE TABLE `calculation_rules` ( `id` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '主键', `module_id` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '数据板块id', `rule` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '计算公式', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='计算公式表'; CREATE TABLE `data_item_table` ( `id` varchar(32) NOT NULL COMMENT '主键', `item_code` varchar(10) NOT NULL COMMENT '数据项编码', `item_name` varchar(255) NOT NULL COMMENT '数据项名称', PRIMARY KEY (`id`), UNIQUE KEY `uk_item_code` (`item_code`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='数据项表'; CREATE TABLE `commodity_price` ( `id` varchar(32) NOT NULL COMMENT '主键', `item_code` varchar(32) NOT NULL COMMENT '数据项编码', `insert_time` datetime NOT NULL COMMENT '日期', `amount` decimal(13,2) NOT NULL COMMENT '数量/金额,这里反正根据需求,就是一个计算要用到的值', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品价格表'; 如何通过表id去查找对应的数据值,然后带入公式。 public static void main(String[] args) { // 统计时,会传递日期和数据板块id,数据板块id的用处就是获取计算公式 // 假如这就是我们获取到的某一个数据板块的公式 String str = "avg(item_code_f,item_code_b) +item_code_a ÷ item_code_k - 100"; // 处理一下÷和×,毕竟是以*和/作为乘法除法符号的 str = str.replace("÷","/"); str = str.replace("×","*"); // 定义一个正则表达式,过滤掉计算符号 String regex = "[()*+/-]"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); List list = new ArrayList(); // 这里注意要先转成Set然后再转成List,因为有可能计算的时候要使用一个数据项的值多次,但是其实都是同一个值 list.addAll(Arrays.asList(m.replaceAll(" ").split(" ")).stream().filter(s->{ // 通过流来单独过滤avg和数字 return !s.equals("avg")&&!s.equals("")&&!isNumeric(s); }).collect(Collectors.toSet())); // 输出一下结果:[item_code_f,item_code_b,item_code_a,item_code_k],这样就成功的将数据项编码给分离出来 System.out.println(list.toString()); // 然后通过数据项编码可以把对应的统计日期下,对应的数据项编码的数量或者金额获取到,然后通过replace()方法替换调即可 // 具体从数据库里取值和替换的代码省略。。。嘿嘿,偷个懒 >_ Double total=0.0; Double average=0.0; for(Double obj: objArray){ Double num=Double.valueOf(obj.toString()); total = total + num; } average = total/objArray.length; return average; } }); // 计算结果,这里是一个重载方法,没有log Object result = runner.execute(express,null, null, false,false); // 顺利拿到结果:1415 Double resultNum = Double.valueOf(result.toString()); } /** * 判断是否是数字 */ public static boolean isNumeric(String str){ Pattern pattern = Pattern.compile("[0-9]*"); Matcher isNum = pattern.matcher(str); if( !isNum.matches() ){ return false; } return true; }

​ QLExpress使用还是挺方便的,而且也很简单,而我上面展示的也只是它的一小部分。实战是最好的老师,有兴趣的同学可以自己去敲上一段代码,另附上官网地址:QLExpress官网。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有