万象EXCEL开发(八)excel公式解析与依赖映射 ——东方仙盟金丹期

公式解析与依赖映射实现方案

一、公式解析函数:提取依赖项并构建 dependentsMap

针对你带左右等式、支持分号分隔多公式的格式,先实现解析函数,从公式中提取 "被依赖的 param" 和 "当前公式所属的 param",并更新到 dependentsMap。

1. 核心解析函数 parseFormulaToDependents

javascript

复制代码
/**
 * 解析带左右等式的公式,更新依赖映射表
 * @param {string} formula - 完整公式(如 "$param7=$param4*$param5+$param3-$param1;$param8=$param7/2")
 * @param {object} dependentsMap - 依赖反向映射表(需提前初始化,如 {})
 * @returns {object} 更新后的 dependentsMap
 */
function parseFormulaToDependents(formula, dependentsMap) {
  // 1. 按分号分割多公式(处理一个单元格的多重计算)
  const formulaList = formula.split(';').filter(item => item.trim() !== '');
  
  formulaList.forEach(singleFormula => {
    // 2. 分割左右等式(左侧是当前公式所属的param,右侧是计算逻辑)
    const [leftPart, rightPart] = singleFormula.split('=').map(item => item.trim());
    if (!leftPart || !rightPart) return; // 跳过格式错误的公式
    
    // 3. 提取左侧的当前param(如 "$param7" → "param7")
    const currentParam = leftPart.match(/\$(\w+)/)[1]; // 匹配 $ 后的param名称
    if (!currentParam) return;
    
    // 4. 提取右侧所有被依赖的param(如 "$param4*$param5" → ["param4", "param5"])
    const dependentParams = rightPart.match(/\$(\w+)/g) || [];
    const cleanDependents = dependentParams.map(param => param.slice(1)); // 去掉 $ 符号
    
    // 5. 更新 dependentsMap:给每个被依赖param,添加当前param到依赖列表
    cleanDependents.forEach(depParam => {
      if (!dependentsMap[depParam]) {
        dependentsMap[depParam] = []; // 初始化依赖列表
      }
      // 避免重复添加同一依赖
      if (!dependentsMap[depParam].includes(currentParam)) {
        dependentsMap[depParam].push(currentParam);
      }
    });
  });
  
  return dependentsMap;
}

2. 调用示例(用你给的公式测试)

javascript

复制代码
// 初始化依赖映射表
let dependentsMap = {};

// 你的测试公式
const testFormula = "$param7=$param4*$param5+$param3-$param1";

// 执行解析
parseFormulaToDependents(testFormula, dependentsMap);

// 解析结果:dependentsMap 变成
// {
//   param4: ["param7"],
//   param5: ["param7"],
//   param3: ["param7"],
//   param1: ["param7"]
// }
console.log(dependentsMap);

二、依赖触发函数:通过 data-key 找到依赖项并执行计算

当焦点离开 data-key="param4" 的文本框时,调用此函数,通过 data-key 从 dependentsMap 找到所有依赖它的 param,再执行你的计算逻辑(计算部分你已实现,这里只负责 "找到要计算的目标 param")。

1. 依赖触发函数 triggerDependentCalculation

javascript

复制代码
/**
 * 通过 data-key 找到依赖项,触发计算
 * @param {string} dataKey - 文本框的 data-key 值(如 "param4")
 * @param {object} dependentsMap - 已构建的依赖反向映射表
 * @param {function} calculateFunc - 你的计算函数(参数为目标param,需你实现)
 * @returns {void}
 */
function triggerDependentCalculation(dataKey, dependentsMap, calculateFunc) {
  // 1. 从 dependentsMap 中找到所有依赖当前dataKey的目标param
  const targetParams = dependentsMap[dataKey] || [];
  
  if (targetParams.length === 0) {
    console.log(`没有参数依赖 ${dataKey}`);
    return;
  }
  
  // 2. 遍历目标param,调用你的计算函数(计算逻辑由你实现)
  targetParams.forEach(targetParam => {
    console.log(`触发计算:${targetParam}`);
    calculateFunc(targetParam); // 你已实现的计算函数,传入要计算的param
  });
}

2. 调用示例(模拟焦点离开事件)

javascript

复制代码
// 1. 假设你的计算函数(示例,实际由你提供)
function myCalculateFunc(targetParam) {
  // 你的逻辑:读取 targetParam 的公式(dataset.formula)、执行计算、更新input值
  console.log(`执行计算逻辑:${targetParam}`);
}

// 2. 模拟焦点离开 data-key="param4" 的文本框
const changedDataKey = "param4"; // 从文本框的 data-key 属性获取
triggerDependentCalculation(changedDataKey, dependentsMap, myCalculateFunc);

// 执行结果:
// 触发计算:param7
// 执行计算逻辑:param7

三、整体流程梳理(和你的系统适配)

  1. 公式存储 :用户在某个单元格设置公式后,将公式存入该单元格的 dataset.formula(如 param7 的 dataset.formula 存 "\(param7=\)param4*\(param5+\)param3-$param1")。
  2. 解析公式 :调用 parseFormulaToDependents,传入公式和 dependentsMap,完成依赖关系构建。
  3. 值修改触发 :当 data-key="param4" 的文本框焦点离开时,获取 data-key 值,调用 triggerDependentCalculation,找到依赖 param4 的 param7,执行你的计算函数。

四、扩展:处理多公式场景

如果公式是多组(分号分隔),比如 $param7=$param4*$param5;$param8=$param7/2,解析后 dependentsMap 会变成:

javascript

复制代码
{
  param4: ["param7"],
  param5: ["param7"],
  param7: ["param8"]
}

此时修改 param4,会先触发 param7 计算,若你需要连动计算 param8,可在 myCalculateFunc 中递归调用 triggerDependentCalculation(计算完 param7 后,再触发它的依赖项 param8)。

需要调整解析规则或函数参数吗?比如 param 的命名规则(是否都是 $param + 数字)、多公式的分隔符等,都可以根据你的实际系统修改。

阿雪技术观

让我们积极投身于技术共享的浪潮中,不仅仅是作为受益者,更要成为贡献者。无论是分享自己的代码、撰写技术博客,还是参与开源项目的维护和改进,每一个小小的举动都可能成为推动技术进步的巨大力量

Embrace open source and sharing, witness the miracle of technological progress, and enjoy the happy times of humanity! Let's actively join the wave of technology sharing. Not only as beneficiaries, but also as contributors. Whether sharing our own code, writing technical blogs, or participating in the maintenance and improvement of open source projects, every small action may become a huge force driving technological progrss.

相关推荐
David凉宸4 分钟前
vue2与vue3的差异在哪里?
前端·javascript·vue.js
笔画人生9 分钟前
Cursor + 蓝耘API:用自然语言完成全栈项目开发
前端·后端
avi911113 分钟前
Unity Data Excel读取方法+踩坑记;和WPS Excel的一些命令
unity·游戏引擎·excel·wps·data
AC赳赳老秦24 分钟前
外文文献精读:DeepSeek翻译并解析顶会论文核心技术要点
前端·flutter·zookeeper·自动化·rabbitmq·prometheus·deepseek
小宇的天下31 分钟前
Calibre 3Dstack --每日一个命令day18【floating_trace】(3-18)
服务器·前端·数据库
毕设源码-钟学长37 分钟前
【开题答辩全过程】以 基于web技术的酒店信息管理系统设计与实现-为例,包含答辩的问题和答案
前端
css趣多多1 小时前
this.$watch
前端·javascript·vue.js
干前端1 小时前
Vue3虚拟滚动列表组件进阶:不定高度及原理分析!!!
前端·前端组件
雨季6661 小时前
Flutter 三端应用实战:OpenHarmony “极简文本行数统计器”
开发语言·前端·flutter·ui·交互
梦幻通灵1 小时前
Excel多个sheet合并透视表实现方案【持续更新】
excel