自定义计算公式思路解析:
- Jexl,表达式引擎,可以将字符串公式解析成可执行表达式
- 从数据库中查询出数据,通过计算公式计算出结果,然后将结果再存储到数据表中
- 前端报表展示:直接查询存入数据库表中的结果
计算公式解析代码工具类:
- 首先新建一个类,我这里将类名定义为:CharacterReplacementUtil
- Maven导入依赖jar包:在项目的pom文件导入,大家都知道,不做过多叙述
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl</artifactId>
<version>2.1.1</version>
</dependency>
- 公式来源:先定义需要添加公式的字段,点击新增,弹窗增加公式的窗口,输入计算公式,这里我用两个百分号作为区分,%这里是输入的中文%,中文是让客户看的,在添加公式的service层,调用工具类解析,将%%里面的中文替换成数据库中对应的表字段
- 公式解析工具类:使用正则表达式,替换%%里面的中文
图片中代码如下:
/**
-
@author: zy
-
Description: 字符串中文替换工具类 (这里将类中的方法移动到service层中了,暂时没用这个)
-
Date:2022-07-13
-
@return String
*/
@SuppressWarnings(“all”)
public class CharacterReplacementUtil {
public static String solveCharacter(String exhibitionFormula) throws Exception { // 处理函数
int i = 0;
String[] strings = {“completeNum”,“conversionRate”,“processYield”,“additionAmount”}; // 用来替换的对象
String pattern = “\KaTeX parse error: Expected group after '^' at position 2: [^̲]\
"
;
/
/
匹配
"; // 匹配
";//匹配 $ 的表达式
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(exhibitionFormula);
while(m.find()){ // 当字符串中有匹配到 {} 时
String param = m.group(0); // {} 和里面的内容
System.out.println(param.substring(1,param.length()-1)); // 输出{} 里面的内容
String subParam = param.substring(1,param.length()-1);
//判断读取的汉字是什么
switch (subParam){
case “浇筑数量”:
exhibitionFormula = exhibitionFormula.replaceFirst("\KaTeX parse error: Expected group after '^' at position 2: [^̲]\$”,strings[0]); // 替换 {} 和里面的内容
break;
case “计划数量”:
exhibitionFormula = exhibitionFormula.replaceFirst(“\KaTeX parse error: Expected group after '^' at position 2: [^̲]\$“,strings[0]); // 替换 {} 和里面的内容
break;
case “单重”:
exhibitionFormula = exhibitionFormula.replaceFirst(”\KaTeX parse error: Expected group after '^' at position 2: [^̲]\$”,strings[1]); // 替换 {} 和里面的内容
break;
case “出品率”:
exhibitionFormula = exhibitionFormula.replaceFirst(“\KaTeX parse error: Expected group after '^' at position 2: [^̲]\$“,strings[2]); // 替换 {} 和里面的内容
break;
default:
exhibitionFormula = exhibitionFormula.replaceFirst(”\KaTeX parse error: Expected group after '^' at position 2: [^̲]\$”,strings[3]); // 替换 {} 和里面的内容
break;
}
}
return exhibitionFormula; //这个返回值,就是解析后的公式字符串
}
}
数据库存入结果格式如图:
公式调用:查询公式,并计算结果
- 计算公式工具类:
第一步: 新建一个类:FormulaConversionUtil
第二步:复制代码进去,结果是保存两位小数的值
代码如图:
图片中代码如下:
public class FormulaConversionUtil {
/**
- java将字符串转换成可执行代码 工具类
- @param jexlExp
- @param map
- @return 张雨
*/
public static Object convertToCode(String jexlExp, Map<String, Object> map) {
JexlEngine jexl = new JexlEngine();
Expression expression = jexl.createExpression(jexlExp);
JexlContext jc = new MapContext();
//需要set源代码Math,否则报错
jc.set(“Math”, Math.class);
//需要set源代码 BigDecimal,否则报错
jc.set(“BigDecimal”, BigDecimal.class);
for (String key : map.keySet()) {
Object p = map.get(key);
Double val = 0.0;
if (null != p) {
if (p instanceof BigDecimal) {
BigDecimal temp = (BigDecimal) p;
val = temp.doubleValue ();
}else {
if (NumberUtils.isNumber((String) p)){
val = Double.valueOf(p.toString());
}else {
return p;
}
}
}
jc.set(key,val);
// jc.set(key, map.get(key));
}
if (null == expression.evaluate(jc)) {
return “”;
}
Object obj = expression.evaluate(jc);
BigDecimal result = new BigDecimal ( null == obj ? “0” : obj.toString () );
// return expression.evaluate(jc);
return result.setScale ( 2, BigDecimal.ROUND_HALF_UP );
}
}
计算出结果值之后,将结果值保存到数据库中
如图:
结语:
自定义解析公式,也可以自己写一个解析工具类,通过中缀转后缀表达式解析,这里就直接用java中原生的工具类进行解析,一般中下等复杂的公式解析没什么问题,超复杂的公式还没试过,不过足够满足业务需求了!
写的可能不太详细,有不懂的可以私信我,不过主要的就是那两个工具类,一个是解析前端传来带有中文的公式,一个是调用工具类结算出结果,具体如何用,还是根据业务需求来进行改动!
通过CV大法,实现这个也挺简单的,自定义公式一般业务中见得也不太多,主要用在报表,有不足的还请各位多多指教,加油!