拆解一个 AI Agent 技能:Excel 公式批量分析器是怎么工作的

举报
yd_261887888 发表于 2026/11/02 01:52:45 2026/11/02
【摘要】 在华为云「AI Agent 开发实践中心」里,有一个很有意思的技能仓库agent-best-practices/excel-formula-explainer:给它一个 .xlsx 文件,它会自动读出所有公式,并输出一份纠错与优化报告。这篇文章带你把它的实现方式拆开看一遍,顺便聊聊"给 Agent 写技能"这件事的工程要点。 一、为什么需要"读公式"这件事财务、运营同学每天都要和 Excel...

在华为云「AI Agent 开发实践中心」里,有一个很有意思的技能仓库
agent-best-practices/excel-formula-explainer:给它一个 .xlsx 文件,
它会自动读出所有公式,并输出一份纠错与优化报告。这篇文章带你把它的
实现方式拆开看一遍,顺便聊聊"给 Agent 写技能"这件事的工程要点。

一、为什么需要"读公式"这件事

财务、运营同学每天都要和 Excel 打交道。表格一旦复杂起来,问题就来了:

  • 公式里引用了已经被删掉的单元格(死引用);
  • 两个单元格互相引用,形成循环(循环引用),打开就报错;
  • 跨表引用到处都是,改一张表就"牵连一片";
  • 数值直接写死在公式里,换个参数就要挨个改(硬编码)。

人工核对动辄几百上千个公式,效率极低。把这件事交给一个 Agent 技能,
正好合适——它不需要"聪明",只需要确定性、可复现地跑一遍静态检查。

二、整体架构:一个小而完整的流水线

这个技能只依赖 openpyxl,代码分成五个清晰的角色:

analyze_excel.py   命令行入口:参数解析、打印/写文件
      │
excel_reader.py    读取 xlsx,提取「公式原文 + 缓存值」
      │
graph.py           构建依赖图:循环 / 死引用 / 跨表 / 硬编码 检测
      │
analyzer.py        编排上述检测,并补上每个公式的上下文
      │
report.py          把结果格式化成人类可读的报告

这是一个非常典型的 Agent 技能形态:入口薄、逻辑纯、输出可读。
没有 Web 服务、没有数据库,一个 CLI 就能被 Agent 直接调用。

三、关键实现细节

1. 公式和缓存值要读两遍

openpyxl 有个重要特性:data_only=False 读到的是公式文本,
data_only=True 读到的是最后一次保存时的计算结果。二者互不覆盖:

wb_f = openpyxl.load_workbook(filepath, data_only=False)  # 公式
wb_d = openpyxl.load_workbook(filepath, data_only=True)   # 缓存值

因此 excel_reader.py 会把文件打开两次,再把同一单元格的"公式"和"值"
拼成一条记录。这个思路值得记住:读 Excel 想同时拿到公式和结果,就得开两遍。

2. 用正则从公式里抽出引用

graph.py 用两条正则分别匹配单元格引用和区域引用:

_CELL_REF  = r"(?:'[^']*'|[A-Za-z_][\w]*(?=\!)!)?\$?[A-Z]{1,3}\$?\d+"
_RANGE_REF = r"(?:'[^']*'|[A-Za-z_][\w]*!)?\$?[A-Z]{1,3}\$?\d+:\$?[A-Z]{1,3}\$?\d+"

匹配到区域(如 A1:Z100)后,再展开成一个个单元格,从而把依赖关系
统一成"单元格 → 单元格"的图结构。有了图,很多检查就顺理成章了。

3. 四类检查各有门道

  • 循环引用:对依赖图做三色 DFS(白/灰/黑),遇到灰色节点即发现环。
  • 死引用:解析引用目标,区分"不存在"“空单元格”"常量值"三种情况,
    给出 high / medium / low 的梯度严重度。
  • 跨表引用:正则提取公式里出现的 Sheet! 前缀,与本表不同即记录。
  • 硬编码值:用正则找出紧跟在运算符/括号后面的数字,排除 0、1 这类
    正常边界值。

最后 report.py 把它们汇总成"共检测 N 个公式、M 个有问题、K 个高风险"的报告,
并逐个公式列出明细。

四、一个真实的坑:整列 / 整行引用会被漏掉

在 graph.py 里,提取公式引用的两条正则都要求引用带数字行号(如 A1):

_CELL_REF  = r"...\$?[A-Z]{1,3}\$?\d+"                      # 必须有行号
_RANGE_REF = r"...\$?[A-Z]{1,3}\$?\d+:\$?[A-Z]{1,3}\$?\d+"  # 两端都必须有行号

但 Excel 里非常常见的整列 / 整行引用并不包含行号,例如 SUM(A:A)、SUM(1:1)、
COUNTIF(Sheet2!B:B, ...)。这些写法匹配不到任何引用,于是:

extract_references("=SUM(A:A)")        # []          期望应识别 A 列
extract_references("=SUM(A:A)+B1*2")   # ['B1']       A:A 被丢失

依赖图因此缺失该依赖,循环引用、死引用检测都会跟着漏报。

教训:解析公式语法时,别默认"列 + 行"一定成对出现;整列、整行是合法且高频的写法。
另外,对整列/整行也不该逐格展开(A:A 展开会是上百万个单元格),而应建模成区间来处理。

(我顺手给这个仓库提了一个 Issue,附上了最小复现和修复方向。)

五、给 Agent 写技能的几点体会

  1. 确定性优先:能用静态规则搞定的,就别上大模型。快、准、可复现。
  2. 输出面向人:Agent 技能最终是给人看的,报告要"能直接贴进工单"。
  3. 主键要完整:跨表、跨目录、跨命名空间时,别在中间层把前缀削掉。
  4. 双读兜底:外部文件格式的协议细节(如 data_only)要照顾到边界情况。

华为云「AI Agent 开发实践中心」里还有很多类似的技能仓库,覆盖文档处理、
信息检索、桌面自动化等场景,感兴趣的可以直接去 gitcode.com 上翻一翻,
照着改一改,就是一个很好的练手项目。


本文配套示例仓库:agent-best-practices/excel-formula-explainer(GitCode)

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。