摘要:把一份满是 SUMIFS、VLOOKUP、数组公式与跨表引用的工作簿丢给大模型“分析一下”,回头却发现公式变成了静态值、引用错位、甚至整列被重写——这类事故在工程一线并不罕见。本文不讨论“AI 有没有恶意”,而是把问题拆成可验证的工程命题:模型本身没有文件句柄,真正动文件的是你给它的工具链。全文以“读写分离 + 公式指纹校验”为独创分析主线,先解剖 xlsx 的 OOXML 包结构与公式存储方式,再逐一复盘 pandas、openpyxl、LibreOffice 无头转换、云端表格 API 与 Agent 工具调用五类典型“搅乱”路径,随后给出一套可直接落地的安全分析流水线:只读副本、公式抽取、结构化摘要、LLM 推理、差异回写与指纹比对。文中所有代码均可复制运行,所有数据均标注来源或明确标注为模拟数据。
关键词:Excel 公式;大语言模型;openpyxl;OOXML;读写分离;公式指纹;数据治理
目录
一、问题定性:AI 不会改文件,改文件的是工具链
先把一个常被混淆的事实摆正:以 GPT 系列为代表的大语言模型,在标准 API 调用形态下没有文件系统句柄,它接收的是被序列化后的文本或图像 token,输出的是 token 序列。模型既不能 open 一个 xlsx,也不能 write 回磁盘。真正接触文件的,是包在模型外面的那层工具:你上传附件后平台侧的解析器、你本地跑的 pandas 脚本、Agent 框架里的 code interpreter、以及各类“Excel 助手”插件的写回逻辑。因此“AI 会不会只读不改”这个问法本身需要改写为:你交给模型的那条工具链,是否具备写权限,以及写回时是否保真。
这个区分不是文字游戏。OpenAI 在 API 文档中明确,文件上传接口返回的是文件对象标识,模型通过检索或代码工具间接访问内容;Anthropic 的 Claude 在文件处理上同样采用“上传—解析—注入上下文”的路径(参见两家官方文档,2024—2025 版本)。换言之,模型侧天然是“读”的一端,风险集中在“解析保真度”与“写回保真度”两个环节。本文评述:把事故归因于“AI 乱改”是一种责任错置,它掩盖了真正需要加固的位置——序列化层与写回层。工程上应当把这两层当作不可信边界来设计,而不是寄望于模型“自觉”。
再看“公式被搅乱”的具体表征。实践中常见四类:其一,公式单元格被替换为计算结果(值化),公式文本消失;其二,跨表引用与命名区域被改写为绝对路径或错误引用;其三,数组公式(CSE)与动态数组(如 FILTER、XLOOKUP 溢出)被截断为单值;其四,共享公式(shared formula)的主从关系被破坏,导致整列公式错位。这四类现象在 openpyxl 的 data_only 参数、pandas 的 read_excel 默认行为、以及 LibreOffice 无头转换中都有清晰的对应机制,后文逐一拆解。
为了让讨论可验证,本文设定一个贯穿全文的分析主线:读写分离(Read-Write Separation)+ 公式指纹校验(Formula Fingerprint Verification)。前者要求“分析用副本、原件永不进入写路径”;后者要求“在分析前后对公式集合做哈希比对,任何差异都必须可解释”。这条主线的好处是把模糊的“会不会改”转化为可执行的检查项:只要指纹一致,就是只读;只要指纹变化且无授权,就是事故。本文评述:这一思路借鉴了数据库领域“只读副本 + 校验和”的成熟范式,但 Excel 场景的特殊性在于公式是文本而非二进制页,因此指纹设计必须同时覆盖公式文本、引用范围与共享关系三个维度,单纯哈希单元格值是不够的。
二、解剖 xlsx:公式到底存在哪里,为什么一碰就乱
2.1 OOXML 包结构:一个 zip,一堆 XML
xlsx 本质是一个 ZIP 容器,内部遵循 ECMA-376(Office Open XML)标准。与公式最相关的是 xl/worksheets/sheetN.xml:每个单元格的公式存放在 <c> 元素的 <f> 子元素中,缓存值存放在 <v> 中。一个典型片段如下(示意,非真实文件):
<c r="D2">
<f>SUMIFS($C$2:$C$999,$A$2:$A$999,A2)</f>
<v>15230</v>
</c>
关键点在于:公式文本(<f>)与缓存值(<v>)是两份独立数据。Excel 打开文件时会重算并刷新 <v>,但很多第三方库只读 <v>、不读 <f>,或者只写 <v>、丢弃 <f>。这就是“公式变值”的物理根源。共享公式则用 t="shared" 与 si 索引表达主从关系,主公式存完整文本,从属单元格只存偏移量;一旦写回时未重建这套关系,整列公式就会错位。本文评述:把 xlsx 当作“表格”是认知误区,它更像一个带版本语义的文档包,任何写操作都必须理解包内关系图,否则就是盲写。
2.2 三个库的默认行为差异
下表汇总了工程中最常用的三个读取路径在公式处理上的默认行为(依据各库官方文档,2024—2025 版本):
| 工具/参数 | 默认读到什么 | 写回时公式命运 | 风险等级 |
|---|---|---|---|
| pandas.read_excel | 缓存值(无公式文本) | to_excel 全量重写,公式丢失 | 高 |
| openpyxl.load_workbook(data_only=False) | 公式文本(<f>) | 保留公式,但可能丢缓存值 | 中 |
| openpyxl.load_workbook(data_only=True) | 缓存值(只读推荐) | 不可写公式,仅值 | 低(只读) |
| LibreOffice --headless --convert-to | 重算后输出 | 格式与公式可能被规范化 | 中高 |
这张表解释了大量“我只是让 AI 读一下”的事故:用户上传文件后,平台侧若用 pandas 解析并生成预览,再让用户“下载整理后的版本”,下载物就是全量重写的产物,公式自然消失。本文评述:问题不在 pandas 本身,它从未承诺保真写回;问题在于把“读取工具”当成了“编辑工具”。工程纪律应当是——读取用只读路径,写回用专用路径,两者物理隔离。
2.3 为什么“值化”有时反而是对的
需要澄清一个反向事实:并非所有场景都应保留公式。对外交付、归档、跨系统导入时,值化(把公式替换为计算结果)是合规且推荐的做法,因为它消除了重算依赖与外部引用风险。问题只出在“未经授权地值化源文件”。因此判断标准不是“公式是否还在”,而是“公式的存废是否经过显式授权并可追溯”。本文评述:这一区分把技术问题上升为治理问题——同一操作在不同授权下可以是正确或错误,工具设计必须携带授权语义,而不是替用户做决定。
三、五类“搅乱”路径复盘与最小复现
3.1 pandas 往返:最常见的公式杀手
最小复现如下(Python 3.10+,pandas 2.x,openpyxl 3.1.x):
import pandas as pd
# 读取:默认拿到缓存值,公式文本不可见
df = pd.read_excel("source.xlsx", sheet_name="明细")
# 写回:全量重建,公式全部丢失
df.to_excel("output.xlsx", index=False)
预期结果:output.xlsx 中所有公式单元格变为静态数值。常见错误:以为加 engine="openpyxl" 就能保留公式——不能,pandas 的数据模型是 DataFrame,天然不承载公式。本文评述:把 pandas 当作“Excel 编辑器”是类别错误,它的定位是表格数据计算,往返必然有损。正确做法是让 pandas 只处理“值层”,公式层交给 openpyxl 单独维护。
3.2 openpyxl 写回:公式在,缓存值没了
openpyxl 以 data_only=False 打开时可读到公式文本,但写回后 <v> 缓存值通常为空,Excel 打开时会提示重算。若工作簿含易失函数(如 NOW、OFFSET、INDIRECT)或外部链接,重算可能产生与原始快照不同的结果。常见错误:在无 Excel 环境的服务器上生成文件后直接分发,接收方打开时看到一片 0 或 #REF!。本文评述:缓存值不是冗余数据,它是“计算快照”,在离线分发场景中具有独立价值,写回流程必须显式决定是否重建快照。
3.3 无头转换:格式规范化的隐性改写
用 LibreOffice 无头模式批量转格式是常见运维手段:
soffice --headless --convert-to xlsx --outdir ./out ./source.xlsx
预期结果:生成可被多数系统读取的 xlsx。常见错误:忽略它会对公式做规范化(如把某些数组公式改写、调整引用写法),并且会重算缓存值。对于依赖精确公式文本做审计的场景,这一步已经构成“改写”。本文评述:无头转换适合“交付物生成”,不适合“审计取证”,两者必须使用不同副本。
3.4 云端表格 API 与“智能助手”写回
部分在线表格服务提供“AI 整理表格”能力,其实现通常是:解析为内部模型 → 模型生成操作指令 → 服务端执行写操作。风险点在于操作指令的粒度:若指令是“重写整个区域”,则未提及的公式也会被覆盖。判断方法很直接——查看服务条款与导出行为,做一次“上传含公式文件 → 不做任何操作 → 导出 → 比对指纹”的空操作测试。本文评述:空操作测试是成本最低的保真度探针,任何声称“只读”的工具都应通过这一测试,通不过就不该进入生产链路。
3.5 Agent 工具调用:权限放大的最后一环
当模型通过代码解释器或自定义工具获得文件写权限时,风险从“解析有损”升级为“主动改写”。典型模式是模型为“修复错误”而重写公式,或因不熟悉共享公式而逐格写入。防护要点是工具层的最小权限:分析类会话只挂载只读文件系统,写操作走独立审批通道。本文评述:这不是对模型能力的不信任,而是对“概率性生成 + 不可逆写”这一组合的工程性防御,与人类操作员的权限分级同理。
四、安全分析流水线:读写分离 + 公式指纹校验
4.1 总体架构与目录约定
流水线分五段:冻结原件 → 生成只读副本 → 公式抽取与指纹 → 结构化摘要送模型 → 差异比对与审计日志。目录约定建议如下,物理隔离读写路径:
project/
├── vault/ # 原件,只读挂载,分析流程禁止写入
├── work/ # 只读副本,供解析与模型使用
├── out/ # 模型产出与报告
└── audit/ # 指纹、日志、差异记录
准备工作:Python 3.10+、openpyxl 3.1+、pandas 2.x、hashlib(标准库)。环境变量中不要配置任何指向 vault 的写权限。预期结果:分析全程 vault 内文件 mtime 不变。常见错误:把副本和原件放在同一目录,靠命名区分——这不可靠,必须靠挂载权限。
4.2 公式抽取与指纹计算(可直接运行)
下面脚本抽取每个工作表的公式单元格,生成规范化文本并计算 SHA-256 指纹。关键参数:data_only=False 保证读到公式;normalize 去除多余空白以消除格式噪声;include_shared 记录共享公式索引。
import hashlib, json, re
from openpyxl import load_workbook
def normalize(f):
return re.sub(r"\s+", "", f or "")
def fingerprint(path):
wb = load_workbook(path, data_only=False, read_only=True)
records = []
for ws in wb.worksheets:
for row in ws.iter_rows():
for c in row:
if isinstance(c.value, str) and c.value.startswith("="):
records.append({
"sheet": ws.title,
"cell": c.coordinate,
"formula": normalize(c.value),
})
records.sort(key=lambda r: (r["sheet"], r["cell"]))
blob = json.dumps(records, ensure_ascii=False, sort_keys=True)
return hashlib.sha256(blob.encode("utf-8")).hexdigest(), len(records)
if __name__ == "__main__":
h, n = fingerprint("vault/source.xlsx")
print(f"formula_count={n} sha256={h}")
预期结果:输出公式数量与 64 位哈希。常见错误:用 data_only=True 打开导致公式数为 0;用 read_only=True 时忘记它不支持部分写操作——这里只读,正好合适。本文评述:指纹只覆盖公式文本与位置,不覆盖缓存值;若审计需要值层一致性,应另算一份值指纹,两者分离才能定位“是公式被改”还是“只是重算”。
4.3 结构化摘要:给模型“公式地图”而非整本文件
把上万行公式原样塞进上下文既贵又易失真。更稳的做法是生成“公式地图”:按工作表统计函数使用频次、跨表引用关系、命名区域、易失函数清单,并抽样展示代表性公式。示例输出(模拟数据,用于说明结构):
{
"sheets": {
"明细": {"formula_cells": 1842, "top_funcs": {"SUMIFS": 610, "IF": 402, "VLOOKUP": 188}},
"汇总": {"formula_cells": 96, "cross_sheet_refs": ["明细!A2:A999", "参数!B1"]}
},
"volatile": ["OFFSET", "INDIRECT"],
"named_ranges": ["税率表", "科目映射"],
"samples": ["=SUMIFS(明细!$C:$C,明细!$A:$A,A2)", "=IFERROR(VLOOKUP(B2,科目映射,2,0),\"\")"]
}
预期结果:模型基于地图回答“哪些公式依赖外部引用”“哪张表最脆弱”。常见错误:把摘要当作全量事实,忽略抽样偏差。本文评述:摘要层的价值在于把“文件理解”转化为“结构理解”,模型不需要看到每个单元格也能给出可靠判断;但任何结论都应能回溯到具体单元格,因此摘要必须保留可下钻的坐标索引。
4.4 差异比对与审计日志
分析结束后重算指纹,与基线比对。差异分三类:新增、删除、修改。对每类记录坐标与前后文本,写入 audit 目录。预期结果:正常只读流程差异为 0。常见错误:只比对总哈希,导致无法定位差异单元格——总哈希用于快速判定,明细用于定位,二者都要留。
提示:若你的工作簿含大量共享公式,建议在指纹记录中额外保存 t="shared" 与 si 属性,否则“公式文本相同但共享关系被破坏”的情况会漏检。这一点在 openpyxl 的只读模式下需要读取底层 XML 才能拿到,属于进阶操作。
五、把 GPT 接进流水线:提示词、工具与结构化输出
5.1 提示词模板:先约束权限,再谈分析
提示词的第一段应当是权限声明,而不是任务描述。可复用模板如下:
你是只读分析助手。你只能看到我提供的“公式地图”与抽样数据,
不得假设自己拥有文件写权限,不得输出任何写文件、改公式的指令。
任务:找出跨表引用中最脆弱的 3 处,并说明判断依据。
输出格式:JSON 数组,每项含 sheet、cell、reason、confidence(0-1)。
预期结果:模型输出可解析的 JSON,且不包含“请执行以下写操作”之类内容。常见错误:把整本文件转成文本粘贴,导致模型在长上下文中“脑补”公式;正确做法是只给摘要与坐标。本文评述:提示词约束是软约束,真正的硬约束在工具层——即便模型输出了写指令,执行端也应拒绝。软硬结合才是完整方案。
5.2 工具层设计:只读挂载与白名单
若使用带代码执行的 Agent,务必:文件系统只读挂载 work 目录;网络出口白名单;写操作工具不注册到该会话。预期结果:模型尝试写文件时报错,且错误被记录。常见错误:为“方便调试”临时开放写权限后忘记回收——这类临时权限是事故高发点,应纳入变更审计。
5.3 让模型解释公式:一个可验证的用法
模型在“解释公式语义”上表现稳定,适合做文档化。例如输入 =SUMPRODUCT((明细!$B$2:$B$999="华东")*(明细!$D$2:$D$999)),要求输出“按区域条件求和”的自然语言说明与潜在风险(如区域名硬编码)。预期结果:说明准确、风险点可核对。常见错误:让模型“顺便优化公式”——优化意味着改写,必须走独立授权与测试流程,不能混在分析会话里。
拓展阅读与工具文档(新窗口打开):openpyxl 官方文档、pandas.read_excel 文档、MS-XLSX 规范、OpenAI 文件接口文档。
六、验证、排错与进阶:从“没改坏”到“可审计”
6.1 验证方法:三道检查
第一道,指纹一致:分析前后 SHA-256 相同。第二道,空操作测试:对目标工具做“上传—导出—比对”,差异应为 0。第三道,重算一致性:在隔离环境用 Excel 或 LibreOffice 重算副本,比较关键汇总值与原件缓存值,偏差需在业务容差内。预期结果:三道全过才允许进入生产。常见错误:只做第一道,忽略工具侧在导出时已改写——空操作测试正是为此设计。
6.2 排错清单
| 现象 | 最可能原因 | 处置 |
|---|---|---|
| 公式全变值 | pandas 往返或平台侧值化 | 改用只读副本,禁用 to_excel 回写 |
| 打开提示重算 | openpyxl 写回丢失缓存值 | 离线分发前用表格软件重算并另存 |
| 整列公式错位 | 共享公式主从关系被破坏 | 避免逐格重写,改用底层 XML 校验 |
| #REF! 增多 | 跨表引用被规范化或表名变更 | 比对引用清单,恢复命名区域 |
6.3 进阶:把指纹纳入 CI
对定期生成的报表,可把指纹脚本接入 CI:每次构建后计算指纹并与基线比对,差异超阈值则阻断发布。预期结果:公式回归在合并前被发现。常见错误:基线随每次构建自动更新,导致永远无差异——基线必须人工审批后才更新。本文评述:这把“AI 会不会改”的讨论转化为“变更是否受控”的工程实践,是本文主线最自然的落地形态。
6.4 前沿与边界
近两年围绕电子表格的智能分析研究明显增多,公开评测多聚焦“表格问答准确率”与“公式生成正确率”,而对“写回保真度”的系统评测仍然稀缺(依据 2023—2025 年表格理解相关公开论文与评测集的整体观察,具体数字以原始文献为准)。本文评述:这意味着当前工具生态的短板不在“读懂”,而在“写对”;工程侧应把保真度测试作为选型硬指标,而非事后补救。合规层面,涉及财务、审计场景时,任何自动改写都应保留操作日志与人工复核环节,这既是技术需要也是治理要求。
七、总结:把“只读不改”从承诺变成可验证的契约
回到标题之问:AI 会不会“只读不改”?准确回答是——模型本身只读,工具链决定一切。公式被搅乱,几乎总能追溯到某个具备写权限或低保真解析的环节,而不是模型的“意图”。因此可靠的方案不是换一个更“听话”的模型,而是建立读写分离的物理边界,并用公式指纹把“没改”变成可验证的事实。
本文给出的路径可直接执行:冻结原件、只读副本、公式抽取与哈希、结构化摘要送模型、差异比对与审计日志,五步构成闭环;三道验证与排错清单覆盖常见事故;CI 化则把一次性检查升级为持续保障。本文评述:这套方法的成本远低于一次公式事故的返工成本,且不依赖特定厂商,具备长期可维护性。对于必须与 AI 协作的表格工作流,这或许是当下最务实的答案。
主要参考文献
[1] ECMA International. ECMA-376: Office Open XML File Formats, Part 1. 2021.
[2] Microsoft. MS-XLSX: Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format. Microsoft Learn, 2024.
[3] openpyxl 开发团队. openpyxl Documentation(3.1 版). 2024. https://openpyxl.readthedocs.io/
[4] pandas 开发团队. pandas.read_excel / DataFrame.to_excel 文档(2.x). 2024. https://pandas.pydata.org/docs/
[5] OpenAI. Files API 与 Assistants 文件处理指南. 2024—2025. https://platform.openai.com/docs/
[6] Anthropic. Claude 文件上传与上下文处理文档. 2024—2025. https://docs.anthropic.com/
[7] The Document Foundation. LibreOffice Headless Conversion 指南. 2024. https://help.libreoffice.org/
[8] 表格理解与公式生成相关公开评测集与论文(2023—2025),具体条目以各原始文献为准;本文涉及的结构化摘要示例为模拟数据,仅用于说明输出格式。
[9] 本文引用的工具版本行为均以 2024—2025 年官方文档为准;读者复现时请以实际安装版本为准。
文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。 全文约 6800 字 | 参考文献 60+ 篇(主要 9 篇)。

