夜雨聆风学习资料网

ARTICLE · 1144408

AI 读 Excel,求和翻车算出 0

AI 读 Excel,求和翻车算出 0

太长不看版

  • 做什么:让 AI 从 0 写个脚本,读一份带公式的 Excel,把「提成」列求和。
  • 用什么:Python 3.13 + openpyxl 3.1.5 + pandas 3.0.6,本机 Windows 11。
  • 结果:第一版直接报错(TypeError);AI 改的 data_only 版不报错却算出 0;真正修好要从「基础」列重算,正确值是 550。
  • 坑在哪:openpyxl/pandas 都不替你算公式,公式单元格默认拿到的是公式字符串或 None,拿去求和只会翻车。

为什么我要写这个

运营公众号每天要和投稿表、结算表打交道,经常要快速算个汇总。 这种活最适合丢给 AI 写个小脚本,本地跑完。 但这次翻车不在逻辑,在一个所有人都会忽略的细节:Excel 里的「公式单元格」读出来到底是什么。 我让 AI 出了一版,它看起来完全正确,跑起来却要么报错、要么给出 0。 这个坑太典型,值得记一笔:代码逻辑对,但你对「Excel 存了什么」的理解错了。

第一步:先造一份带公式的真实表

任何读表脚本,我先用 openpyxl 造一份夹具:基础是手填数字,提成写公式 =基础*0.1。 这样后面无论 AI 怎么改,我比的都是同一份输入,报错该怪谁一目了然。 造表脚本只有几行:

import openpyxlwb = openpyxl.Workbook()ws = wb.activews.title = "销售"ws.append(["月份", "基础", "提成"])for i inrange(1, 11):    r = i + 1    ws.append([f"M{i}", i * 100, f"=B{r}*0.1"])wb.save("sales.xlsx")

跑一下,确认文件生成:

图:造夹具,sales.xlsx 写入成功,预期基础合计 5500、提成合计 550(来源:真实终端运行输出)

第二步:让 AI 出第一版,直接读公式

我给 AI 的需求:遍历行,把「提成」列累加。 它给的核心逻辑很朴素——直接把单元格值加起来。

import openpyxlwb = openpyxl.load_workbook("sales.xlsx")ws = wb.activetotal = 0for row in ws.iter_rows(min_row=2, min_col=3, max_col=3):    total += row[0].value   # C 列是公式print("提成合计:", total)

先别急着跑,看一眼单元格里到底装了什么:

图:默认读 C2,拿到的不是数字,是公式字符串 '=B20.1'(来源:真实终端运行输出)*

果然,公式单元格 .value 返回的是公式本身。 那把字符串往 total 上加,直接崩:

图:v1 真实报错,TypeError: unsupported operand type(s) for +=: 'int' and 'str'(来源:真实终端运行输出)

第三步:AI 的「修复」——更隐蔽的 0

我让 AI 修,它加了 data_only=True,顺手把 None 兜底成 0。 这次不报错了,但结果让人后背发凉:

图:data_only 版跑通了,提成合计却是 0(来源:真实终端运行输出)

为什么是 0?因为 openpyxl 自己不计算公式。 data_only=True 读的是「Excel 上次保存时缓存的计算值」,而我这份表是 openpyxl 刚写的,压根没有缓存值,公式单元格一律返回 None,被兜底成 0。 更坑的是,很多人以为换个库就行,改用 pandas 读:

图:pandas 同样,基础算对 5500,提成却得 0.0(来源:真实终端运行输出)

pandas 底层也是 openpyxl,一样拿不到缓存值,静默给你 0。 这种「不报错但算错」比直接崩更危险,你根本不知道数据已经丢了。

第四步:真正修好——别读公式,读输入

公式值的坑,根因是你在「读一个还没算出来的结果」。 最稳的做法是别依赖缓存,从可靠的输入列重算:

import openpyxlwb = openpyxl.load_workbook("sales.xlsx")ws = wb.activetotal = 0for row in ws.iter_rows(min_row=2, min_col=2, max_col=3):    base = row[0].value      # B 列是手填数字,可靠    total += base * 0.1# 提成 = 基础 * 0.1print("提成合计(从基础重算):", total)

跑一下,550,对上了:

图:从基础列重算,提成合计 550.0,与预期一致(来源:真实终端运行输出)

如果你确实必须读「别人算好的结果」,记住一个前提:文件得先用 Excel 或 LibreOffice 打开保存过,让缓存值落盘,再 data_only=True 才有效。 或者用 formulas / pycel 这类公式引擎在 Python 里现算。但对本地小脚本,从输入列重算最省心。

结果

最终能用的脚本不到 15 行,依赖只有 openpyxl。 它正确算出提成合计 550,和手填基础的 5500 对得上。 局限也很清楚:它假定「提成」永远等于「基础*0.1」,公式一改就得跟着改;遇到合并单元格、空白行还要额外处理。 但作为日常快速汇总,这版已经够用,而且不会再 silently 给 0。

我的态度

这种「读 Excel 算个汇总」的脚本,AI 出框架很快,五分钟就能跑起来。 但「公式单元格读出来是什么」这种细节,AI 十次有八次不会主动提醒你,得自己踩一次。 我现在的规定:凡是涉及 Excel 公式的读取,一律先 print(repr(cell.value)) 看一眼,确认拿到的是数字再累加。 这一行调试,能省掉后面半天找「为什么总和是 0」的弯路。

第二个感受:比起直接崩,data_only 静默给 0 才是真陷阱。 报错至少拦得住你,静默错误会一路带到报表里。所以我对「不报错的结果」反而更警惕,重要数字一定交叉验证。

顺带一个意外收获:我一开始把脚本命名为 inspect.py,结果直接 import 不进 numpy——因为我的文件名把 Python 标准库 inspect 覆盖了。 给脚本起名,千万别碰标准库和常用第三方库的名字(inspect、random、test、json 都危险)。这坑和 Excel 无关,但同样真实。

结尾

如果你也常让 AI 帮你读 Excel 算数,先确认它有没有碰公式单元格。 觉得有用,点个在看,转发给那个正被「总和是 0」折磨的同事。

相关学习资料