41.仿简道云公式函数实战-数学函数-SUMIF

1. SUMIF函数

SUMIF 函数可用于计算子表单中满足某一条件的数字相加并返回和。

2. 函数用法

SUMIF(range, criteria, [sum_range])

其中各参数的含义及使用方法如下:

  • range:必需;根据 criteria 的条件规则进行检测的判断字段。支持的字段包括:子表单中的数字、单行文本、下拉框、单选按钮组;

  • criteria:必需;用于判断的条件规则。支持的形式和使用规则如下表:

支持形式是否需要加引号示例注意事项
数字不需要20、32
表达式需要“>32”、"!=苹果"支持的运算符号包括:>、<、==、!=、>=、<=
文本需要“苹果”、"水果"
字段不需要字段1)在主表字段中使用 SUMIF 函数时,只能选择主表字段2)在子表字段中使用 SUMIF 函数时,只能选择择主表字段和当前子表字段

3. 函数示例

如,计算入库明细中产品类型为「水果」的全部入库数量,则可以在「水果类数量总计」字段设置公式为:

4. 代码实战

首先我们在function包下创建math包,在math包下创建SumIfFunction类,代码如下:

package com.ql.util.express.self.combat.function.math;import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ql.util.express.Operator;
import com.ql.util.express.self.combat.exception.FormulaException;import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;/*** 类描述: SUMIF函数** @author admin* @version 1.0.0* @date 2023/11/24 10:33*/
public class SumIfFunction extends Operator {public SumIfFunction(String name) {this.name = name;}@Overridepublic Object executeInner(Object[] lists) throws Exception {//边界判断if (lists.length == 0 || lists.length<3 || lists.length >4) {throw new FormulaException("操作数异常");}BigDecimal res = BigDecimal.ZERO;Object range = null;Object criteria = null;List<Map<String,Object>> subFormVal =null;String rangeS ="";String key = "";if (lists.length == 3) { // 两个参数// 获取参数key = lists[0].toString();range = lists[1];criteria = lists[2];rangeS = range.toString();subFormVal = JSON.parseObject(key,List.class);res = cal(subFormVal,rangeS,criteria.toString(),rangeS);} else {// 三个参数处理Object sumRange = lists[3];key = lists[0].toString();range = lists[1];criteria = lists[2];rangeS = range.toString();subFormVal = JSON.parseObject(key,List.class);// 循环subFormVal集合res = cal(subFormVal,rangeS,criteria.toString(),sumRange.toString());}return res;}// 计算结果private BigDecimal cal(List<Map<String, Object>> list, String range, String criteria, String sumRange) {// criteria判断类型boolean isNum = CriteriaUtil.isNum(criteria);boolean isExpress = CriteriaUtil.isExpress(criteria);// 根据criteria类型 生成PredicateList<Map<String, Object>> collect =null;if (isExpress) {// 如果是表达式// 提取符号String symbol = CriteriaUtil.extractSymbol(criteria);String symbol_value = criteria.replaceAll(symbol,"");boolean sybolValueIsNum = CriteriaUtil.isNum(symbol_value);if (sybolValueIsNum) {// 如果是数字collect = list.stream().filter(paramMap -> {boolean res = false;if ("==".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) == Double.parseDouble(symbol_value)?true:false;} else if (">".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) > Double.parseDouble(symbol_value)?true:false;} else if (">=".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) >= Double.parseDouble(symbol_value)?true:false;} else if ("<".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) < Double.parseDouble(symbol_value)?true:false;} else if ("<=".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) <= Double.parseDouble(symbol_value)?true:false;} else if ("!=".equals(symbol)) {res = Double.parseDouble(paramMap.get(range).toString()) != Double.parseDouble(symbol_value)?true:false;}return res;}).collect(Collectors.toList());} else {collect = list.stream().filter(paramMap -> {boolean res = false;if ("==".equals(symbol)) {res = String.valueOf(paramMap.get(range)).equals(symbol_value);} else if ("!=".equals(symbol)) {res = !(String.valueOf(paramMap.get(range)).equals(symbol_value));} else {throw new RuntimeException("字符暂不支持的操作符号为:"+symbol);}return res;}).collect(Collectors.toList());}} else {// 没有表达式 直接默认为==if (isNum) {// 如果是数字collect = list.stream().filter(paramMap -> Double.parseDouble(paramMap.get(range).toString()) == Double.parseDouble(criteria)?true:false).collect(Collectors.toList());} else {collect = list.stream().filter(paramMap -> String.valueOf(paramMap.get(range)).equals(criteria)).collect(Collectors.toList());}}// 满足条件的集合统计出来后,按照sumRange字段统计求和BigDecimal sum = BigDecimal.ZERO;for (Map<String,Object> map:collect) {BigDecimal tmp = new BigDecimal(map.get(sumRange).toString());sum = sum.add(tmp);}return sum;}static class CriteriaUtil {public static boolean isNum (String criteria) {return StrUtil.isNumeric(criteria);}public static boolean isExpress(String criteria) {List<String> symbols = Arrays.asList(">",">=","<","<=","==","!=");boolean res = symbols.stream().anyMatch(s -> criteria.contains(s));return res;}/**** 提取表达式中的符号* @param criteria* @return*/public static String extractSymbol(String criteria) {List<String> symbols = Arrays.asList(">",">=","<","<=","==","!=");final Optional<String> first = symbols.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return criteria.contains(s);}}).findFirst();return first.get();}}}

把SumIfFunction类注册到公式函数入口类中,代码如下:

package com.ql.util.express.self.combat.ext;import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressResourceLoader;
import com.ql.util.express.parse.NodeTypeManager;
import com.ql.util.express.self.combat.function.logic.*;
import com.ql.util.express.self.combat.function.math.*;/*** 类描述: 仿简道云公式函数实战入口类** @author admin* @version 1.0.0* @date 2023/11/21 15:29*/
public class FormulaRunner extends ExpressRunner {public FormulaRunner() {super();}public FormulaRunner(boolean isPrecise, boolean isTrace) {super(isPrecise,isTrace);}public FormulaRunner(boolean isPrecise, boolean isStrace, NodeTypeManager nodeTypeManager) {super(isPrecise,isStrace,nodeTypeManager);}public FormulaRunner(boolean isPrecise, boolean isTrace, IExpressResourceLoader iExpressResourceLoader, NodeTypeManager nodeTypeManager) {super(isPrecise,isTrace,iExpressResourceLoader,nodeTypeManager);}@Overridepublic void addSystemFunctions() {// ExpressRunner 的内部系统函数super.addSystemFunctions();// 扩展公式函数this.customFunction();}/**** 自定义公式函数*/public void customFunction() {// 逻辑公式函数this.addLogicFunction();// 数学公式函数this.addMathFunction();}public void addLogicFunction() {// AND函数this.addFunction("AND",new AndFunction("AND"));// IF函数this.addFunction("IF",new IfFunction("IF"));// IFS函数this.addFunction("IFS",new IfsFunction("IFS"));// XOR函数this.addFunction("XOR",new XorFunction("XOR"));// TRUE函数this.addFunction("TRUE",new TrueFunction("TRUE"));// FALSE函数this.addFunction("FALSE",new FalseFunction("FALSE"));// NOT函数this.addFunction("NOT",new NotFunction("NOT"));// OR函数this.addFunction("OR",new OrFunction("OR"));}public void addMathFunction() {// ABS函数this.addFunction("ABS",new AbsFunction("ABS"));// AVERAGE函数this.addFunction("AVERAGE",new AvgFunction("AVERAGE"));// CEILING函数this.addFunction("CEILING",new CeilingFunction("CEILING"));// RADIANS函数this.addFunction("RADIANS",new RadiansFunction("RADIANS"));// COS函数this.addFunction("COS",new CosFunction("COS"));// COT函数this.addFunction("COT",new CotFunction("COT"));// COUNT函数this.addFunction("COUNT",new CountFunction("COUNT"));// COUNTIF函数this.addFunction("COUNTIF",new CountIfFunction("COUNTIF"));// FIXED函数this.addFunction("FIXED",new FixedFunction("FIXED"));// FLOOR函数this.addFunction("FLOOR",new FloorFunction("FLOOR"));// INT函数this.addFunction("INT",new IntFunction("INT"));// LARGE函数this.addFunction("LARGE",new LargeFunction("LARGE"));// LOG函数this.addFunction("LOG",new LogFunction("LOG"));// MAX函数this.addFunction("MAX",new MaxFunction("MAX"));// MIN函数this.addFunction("MIN",new MinFunction("MIN"));// MOD函数this.addFunction("MOD",new ModFunction("MOD"));// POWER函数this.addFunction("POWER",new PowerFunction("POWER"));// PRODUCT函数this.addFunction("PRODUCT",new ProductFunction("PRODUCT"));// RAND函数this.addFunction("RAND",new RandFunction("RAND"));// ROUND函数this.addFunction("ROUND",new RoundFunction("ROUND"));// SIN函数this.addFunction("SIN",new SinFunction("SIN"));// SMALL函数this.addFunction("SMALL",new SmallFunction("SMALL"));// SQRT函数this.addFunction("SQRT",new SqrtFunction("SQRT"));// SUM函数this.addFunction("SUM",new SumFunction("SUM"));// SUMIF函数this.addFunction("SUMIF",new SumIfFunction("SUMIF"));}
}

创建测试用例

package com.ql.util.express.self.combat;import com.alibaba.fastjson.JSON;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.self.combat.ext.FormulaRunner;
import org.junit.Test;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 类描述: 实战测试类** @author admin* @version 1.0.0* @date 2023/11/21 15:45*/
public class CombatTest {@Testpublic void SUMIF() throws Exception{FormulaRunner formulaRunner = new FormulaRunner(true,true);// 创建上下文DefaultContext<String, Object> context = new DefaultContext<>();List<Map<String,Object>> list = new ArrayList<>();Map<String,Object> map = new HashMap<>();map.put("record.type","红富士");map.put("record.name","苹果");map.put("record.num",20.0);Map<String,Object> map2 = new HashMap<>();map2.put("record.type","红富士");map2.put("record.name","苹果");map2.put("record.num",42.0);Map<String,Object> map3 = new HashMap<>();map3.put("record.type","红星");map3.put("record.name","苹果");map3.put("record.num",30.0);Map<String,Object> map4 = new HashMap<>();map4.put("record.type","美国");map4.put("record.name","苹果");map4.put("record.num",13000.0);Map<String,Object> map5 = new HashMap<>();map5.put("record.type","夏黑");map5.put("record.name","葡萄");map5.put("record.num",15);Map<String,Object> map6 = new HashMap<>();map6.put("record.type","阳光玫瑰");map6.put("record.name","葡萄");map6.put("record.num",30);Map<String,Object> map7 = new HashMap<>();map7.put("record.type","芝麻蕉");map7.put("record.name","香蕉");map7.put("record.num","20");list.add(map);list.add(map2);list.add(map3);list.add(map4);list.add(map5);list.add(map6);list.add(map7);String s = JSON.toJSONString(list);String express = "SUMIF(aa,bb,cc,dd)";context.put("aa",s);context.put("bb","record.type");context.put("cc","!=美国");context.put("dd","record.num");Object object = formulaRunner.execute(express, context, null, true, true);System.out.println(object);}}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2811859.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

RC4算法

RC4 RC4是Ron Rivest为RSA设计的序列密码,RC4算法简单、速度快、容易用软硬件实现,因此应用广泛。比如WEP、WPA、SSL/TLS应用了RC4;Windows、Lotus notes、Apple APCE等软件系统也应用了RC4。 1. RC4算法 RC4具体算法如下: 第一步:密钥调度算法(The Key-Scheduling Alg…

3. Java中的锁

文章目录 乐观锁与悲观锁乐观锁(无锁编程,版本号机制)悲观锁两种锁的伪代码比较 通过 8 种锁运行案例,了解锁锁相关的 8 种案例演示场景一场景二场景三场景四场景五场景六场景七场景八 synchronized 有三种应用方式8 种锁的案例实际体现在 3 个地方 从字节码角度分析 synchroni…

排序(9.17)

1.排序的概念及其运用 1.1排序的概念 排序 &#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性 &#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记…

OSI参考模型和TCP/IP网络参考模型

1、OSI参考模型 1.1 产生背景 为了解决网络之间的兼容性问题,实现网络设备间的相互通讯,国际标准化组织ISO于1984年提出了OSIRM(Open System Interconnection Reference Model,开放系统互连参考模型)。OSI参考模型很快成为计算机网络通信的基础模型。由于种种原因,并没有…

Redis高可用三主三从集群部署

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容使用宝塔面板搭建集群规划配置验证 使用docker搭建使用脚本搭建&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博…

聊一聊bpmn-js中的elementFactory模块

上一篇文章里我们了解了bpmn-js使用palette模块进行左侧小工具区域(也可以理解为调色板区域)的功能扩展,今天这个话题则是延续上期的palette进行开展的。 从上篇文章《聊一聊bpmn-js中的Palette》我们知道,PaletteProvider通过getPaletteEntries方法提供小工具Map对象,而单…

Python 实现 CR 指标计算 (带状能量线):股票技术分析的利器系列(13)

Python 实现 CR 指标计算 (带状能量线&#xff09;&#xff1a;股票技术分析的利器系列&#xff08;13&#xff09; 介绍算法公式 代码rolling函数介绍核心代码计算MID计算CR计算移动平均 完整代码 介绍 CR指标&#xff0c;又称带状能量线&#xff0c;通过计算股价的动能和变化…

MySQL的21个SQL经验

1. 写完SQL先explain查看执行计划(SQL性能优化) 日常开发写SQL的时候,尽量养成这个好习惯呀:写完SQL后,用explain分析一下,尤其注意走不走索引。 explain select userid,name,age from user where userid =10086 or age =18;2、操作delete或者update语句,加个limit(S…

BTC网络 vs ETH网络

设计理念 BTC 网络 比特币是一种数字货币&#xff0c;旨在作为一种去中心化的、不受政府或金融机构控制的电子货币。其主要目标是实现安全的价值传输和储存&#xff0c;比特币的设计强调去中心化和抗审查。 ETH 网络 以太坊是一个智能合约平台&#xff0c;旨在支持分散的应…

计网Lesson15 - TCP可靠传输

文章目录 1. 停止等待ARQ协议2. 连续ARQ协议与滑动窗口协议 1. 停止等待ARQ协议 ARQ&#xff08;Automatic Repeat–reQuest&#xff09;自动重传请求 几种重传情况 发送端丢失 发送方过久没有接收到接收方的确认报&#xff0c;这种情况会触发超时重传机制&#xff0c;发送方…

瑞_Redis_Redis客户端

文章目录 1 Redis客户端1.1 Redis命令行客户端1.2 图形化桌面客户端1.2.1 资源准备1.2.2 安装1.2.3 建立连接 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《Redis》的基础篇的Redis客户端章节。由于博主是从B站黑马程序员的《Redis》学习其相关知识&#xff0c;所以本…

适配器模式(Adapter Pattern) C++

上一节&#xff1a;原型模式&#xff08;Prototype Pattern&#xff09; C 文章目录 0.理论1.组件2.类型3.什么时候使用 1.实践1.基础接口和类2.类适配器实现3.对象适配器实现 0.理论 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允…

通过Power automate上传文件到SharePoint

上传文件到SharePoint 背景过程Apps开发准备Flow开发SharePoint数据库测试 背景 我们通常都可以通过一些form表单直接上传文件&#xff0c;但是有些时候我们需要对文件名字等信息做一些处理。这个时候我们就需要将文件的内容json流化&#xff0c;然后在流中还原回来。 过程 …

OpenHarmony分布式购物车案例展示~

简介 分布式购物车demo 模拟的是我们购物时参加满减活动&#xff0c;进行拼单的场景&#xff1b;实现两人拼单时&#xff0c;其他一人添加商品到购物车&#xff0c;另外一人购物车列表能同步更新&#xff0c;且在购物车列表页面结算时&#xff0c;某一人结算对方也能实时知道结…

STM32存储左右互搏 QSPI总线FATS文件读写FLASH W25QXX

STM32存储左右互搏 QSPI总线FATS文件读写FLASH W25QXX FLASH是常用的一种非易失存储单元&#xff0c;W25QXX系列Flash有不同容量的型号&#xff0c;如W25Q64的容量为64Mbit&#xff0c;也就是8MByte。这里介绍STM32CUBEIDE开发平台HAL库Quad SPI总线实现FATS文件操作W25Q各型号…

第12章-生成树协议

1. STP产生背景 1.1 桥接网络&#xff1a;网桥 1.2 交换机网络 1.3 解决方案 2. STP生成树协议 2.1 概念 2.2 BPDU(Bridge Protocol Data Unit) 2.3 选举机制&#xff08;网桥&#xff1a;一进一出&#xff09; 2.4 例题 2.5 端口状态 2.6 STP计时器 2.7 STP的问题 …

家装服务管理:Java技术的创新应用

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

C++ //练习 9.16 重写上一题的程序,比较一个list<int>中的元素和一个vector<int>中的元素。

C Primer&#xff08;第5版&#xff09; 练习 9.16 练习 9.16 重写上一题的程序&#xff0c;比较一个list中的元素和一个vector中的元素。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /**********************************…

C++ //练习 9.14 编写程序,将一个list中的char*指针(指向C风格字符串)元素赋值给一个vector中的string。

C Primer&#xff08;第5版&#xff09; 练习 9.14 练习 9.14 编写程序&#xff0c;将一个list中的char*指针&#xff08;指向C风格字符串&#xff09;元素赋值给一个vector中的string。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim…

基于 ResNet50和 SVM + 决策树的人脸口罩检测

欢迎收看&#xff0c;这篇文章是关于我如何使用 ResNet50作为特征提取器来构建掩码检测&#xff0c;然后使用支持向量机(SVM) 决策树和叠加集成方法作为分类器的一个快速解释。 为了向研究人员致敬&#xff0c;这个应用程序是基于研究论文&#xff0c;题目是“在2019冠状病毒…