Handsontable动态列行求和:存在子列的列组取最大值累计总合计
实现思路
- 对动态获取的列配置做预处理,按
parent字段规则完成列分组,生成固定的求和映射规则 - 替换原有Total列的全量累加逻辑,按分组规则计算合计:
- 存在子列的列组:取组内所有列当前行数值的最大值计入总计
- 无匹配子列的单列:直接取列值计入总计
- 兼容空值、非数值的异常输入,避免计算异常
代码修改步骤
1. 列配置预处理
拿到数据库返回的动态列数组后,在初始化Handsontable前,先生成计算规则:
// 定义计算规则容器 const calcRule = { // 存储需要取最大值的列组,每个元素是组内所有列的实际序号数组 groups: [], // 存储直接累加的单列序号 singleCols: [] }; // 遍历所有带parent属性的数值列(排除Name列、Total列) const groupMap = {}; columnsConfig.forEach((col, realIdx) => { // 跳过无parent属性的Name列、Total列 if (!col.parent || col.data === 'total') return; // 生成组ID:去掉parent末尾的|h后缀 const groupKey = col.parent.replace(/\|h$/, ''); if (!groupMap[groupKey]) groupMap[groupKey] = []; groupMap[groupKey].push(realIdx); }); // 归类计算规则 Object.values(groupMap).forEach(colIdxArr => { if (colIdxArr.length >= 2) { // 多列组:取最大值 calcRule.groups.push(colIdxArr); } else { // 单列:直接累加 calcRule.singleCols.push(colIdxArr[0]); } });
2. 替换Total列的渲染逻辑
把原有Total列renderer中的循环累加逻辑,替换为基于calcRule的计算:
{ data: 'total', title: 'Total', readOnly: true, width: 100, renderer: function(instance, td, row, col, prop, value, cellProperties) { let total = 0; // 累加所有单列值 calcRule.singleCols.forEach(colIdx => { const cellVal = Number(instance.getDataAtCell(row, colIdx)) || 0; total += cellVal; }); // 累加所有组的最大值 calcRule.groups.forEach(colIdxArr => { const groupVals = colIdxArr.map(colIdx => Number(instance.getDataAtCell(row, colIdx)) || 0); total += Math.max(...groupVals); }); // 触发原生文本渲染,保持样式一致 Handsontable.TextCell.renderer.apply(this, arguments); td.innerHTML = total; } }
适配注意点
- 预处理时的列序号必须和Handsontable实际渲染的列顺序完全一致,不能用过滤后数组的下标,否则会取错列值
- 如果列配置后续动态更新,需要重新执行列预处理逻辑,刷新
calcRule的内容,保证计算规则和当前列结构匹配 - 空值、非数值的单元格内容会被自动转换为0,不会触发NaN计算错误
- 原有代码中定义但未使用的
hexRenderer函数,无特殊需求可直接删除,不影响核心逻辑运行
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

