查看: 80|回复: 1

AutoCalculate:告别硬编码,实现前端表格自动计算公式引擎

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
在税务系统等企业级应用中,表格(Grid)的单元格间计算、跨表格联动计算是常见的开发痛点。传统做法是手写大量前台JS和后台代码,每次需求变更都要修改代码,维护成本极高。笔者曾参与这类系统开发,发现团队80%的时间都在处理表格计算逻辑。受Excel公式启发,我们设计了一个轻量级自动计算引擎 AutoCalculate,让开发者只需定义公式字符串,引擎自动解析并计算结果,大幅减少硬编码。

一、核心思路:公式即代码

AutoCalculate 的核心由两部分组成:公式字符串和计算引擎(AutoCalculate.js)。公式采用类似 Excel 的语法,例如 [Month1,1] = [Month1,2] + [Month1,3] 表示第1行第1列等于第1行第2列加第3列的值。其中 [y,x] 表示单元格,y 是列名(纵坐标),x 是行号(横坐标,对应参考字段的值)。

二、基础用法:实例化与计算

首先引入引擎:
  1. import AutoCalculate from '../components/AutoCalculate';
复制代码

定义公式数组,创建实例:
  1. let formulas = ['[Month1,1] = [Month1,2] + [Month1,3]'];
复制代码
  1. let autoCal = new AutoCalculate(formulas);
复制代码

调用 cal 方法传入表格数据和参考字段名:
  1. autoCal.cal(gridDatas, 'RowNo');
复制代码

其中 gridDatas 是表格数据数组,refField 是用于定位横坐标的字段(如 RowNo 或唯一键)。

三、高级公式:区域公式与占位符

对于多列重复公式(如1到10月),可用大括号 { } 定义列名集合,结合占位符 @ 简化书写:
  1. {Month1,Month2,...,Month10}[@,1] = [@,2] + [@,3]
复制代码

占位符 @ 可代替纵坐标或横坐标。例如计算年度合计,需要将多个月份数据累加到指定行,可用区域公式:
  1. {2,3,4,5,6,7,9,12,13}[YearTotal,@] = [Month1,@] + [Month2,@] + ... + [Month10,@]
复制代码

这样一条公式替代了9条硬编码。

四、动态行数:无需显式横坐标的 [y] 公式

当表格行数不确定(如数据库结果行数可变),可用 [y] 形式表示整列所有行:
  1. [column3] = [column2] - [column1]
复制代码

引擎自动将公式应用于 column3 列下的每一行。

五、合计列 & 小数位数

如需引用某列合计值,用 <列名> 表示。例如计算占比:
  1. [GroupApprovedTotalPercent] = <GroupApprovedTotal> === 0 ? 0 : [GroupApprovedTotal] / <GroupApprovedTotal>
复制代码

默认保留2位小数;如需4位小数,在等号左侧单元格后加 #4:
  1. [GroupApprovedTotalPercent]#4 = ...
复制代码

注意 # 和小数位数之间不能有空格。

六、支持JS语法与注意事项

公式右侧支持任意JS表达式(包括三元运算符、Math函数等),但禁止使用数组元素(因方括号与单元格表示法冲突)。

空格规则:单元格内不能有空格,如 [Month12,1] 正确,[Month12,1 ] 错误;# 与数字之间无空格。

七、跨数据源计算(三元单元格)

从其他数据表取值时,用 [数据源名, y, x] 格式,例如:
  1. [Month1,4] = [OutputTax,Month1,7]
复制代码

实例化时通过 options.externalDatas 传入外部数据源:
  1. let options = {
  2.   externalDatas: [
  3.     { name: 'OutputTax', refField: 'RowNo', datas: outputTaxDatas },
  4.     { name: 'TaxRate', refField: 'RowNo', datas: taxRateDatas }
  5.   ]
  6. };
复制代码
  1. let autoCal = new AutoCalculate(formulas, options);
复制代码

调用 calculate 方法得到最新数据:
  1. let newDatas = autoCal.calculate(payableTaxDatas, 'RowNo');
复制代码

这个过程同样适用于后台(需借助V8引擎执行JS公式)。

八、后台调用封装

实际项目中将公式提取为独立JS文件,后台封装方法示例:
  1. // 伪代码
  2. var engine = new V8Engine();
  3. var formulas = engine.evaluate(jsFileContent);
  4. var autoCal = new AutoCalculate(formulas, options);
  5. var newDatas = autoCal.calculate(currentDatas, refField);
复制代码

这样前后台共享同一套公式定义,避免逻辑不一致。

九、适用性与总结

AutoCalculate 不依赖具体UI框架,适用于ElementUI、EasyUI、ParamQuery Grid等所有支持数据提取的表格控件。核心优势:将计算逻辑从代码中剥离,写入可维护的公式文本,响应业务变更只需调整公式,无需重新编译。经项目实践,可减少80%表格计算代码量,大幅提升开发效率。

注意:公式调试时建议先在前台验证,确认结果正确后再后台部署。对于复杂嵌套或循环依赖,需提前设计好计算方法避免死循环。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: AutoCalculate:告别硬编码,实现前端表格自动计算公式引擎

楼主这个思路太实用了!税务系统里表格计算确实是个大坑,硬编码改一次就要动前后台,维护成本高还容易漏。AutoCalculate 把公式提炼成可配置的字符串,前后台复用同一套规则,能省掉大量重复劳动。尤其区域公式加占位符 @ 那条,十个多月一条公式搞定,比逐列硬编码清爽太多。 想请教一下楼主,如果出现公式间循环依赖(比如 A 依赖 B,B 又依赖 A),引擎里有没有做检测或排序处理?还是需要开发者自己保证无环?另外跨数据源的三元单元格,如果外部数据还没加载完,调用 calculate 时会不会抛错?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-11 15:01 , Processed in 0.030408 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部