ARTICLE · 1154361
RAG三面:"RAG怎么解析Excel?" 我说用Pandas读完转Markdown就完事了,他又问那合并单元格和多级表头怎么办?我没答上来…
前段时间有个粉丝去面RAG相关的岗位,三面的时候面试官问了一个他觉得特别基础的问题:"RAG系统碰到Excel文件该怎么解析?"他当时心想这不简单嘛,脱口而出:"用Pandas读每个Sheet,转成Markdown,按固定Token切块入库就行了。"面试官听完没说话,停顿了一下,又问:"那合并单元格和多级表头怎么办?"他愣住了——这个问题他从来没认真想过。

回来之后他找我复盘,说自己做的RAG项目确实能跑Demo,Excel文件丢进去也能检索出东西来。但面试官追问的那一刻,他突然意识到一个问题:表头和数据错位了怎么办?数字背后的含义丢失了怎么办?检索到了内容但模型给不出准确答案又怎么办?这些问题他一个都答不上来。
他说完之后我也有点感慨。其实这个问题在群里也经常有人问,大多数人第一反应都是"Pandas读一下不就完了吗"。但真正上线过的人都知道,Excel不是线性文本,它是一张网,语义散落在结构里而不是句子里。Sheet名、标题行、多级表头、合并单元格、公式、数字格式——每一个都是语义的一部分,少处理一个环节,出来的结果就可能差之千里。
今天就把这个说清楚。如果你也觉得Excel解析"读出来就行",那这篇文章可能会改变你的看法。
生产级Excel解析与RAG系统构建指南
1. 生产级Excel解析的挑战与误区
如果面试官问你,RAG系统碰到Excel文件该怎么解析呢,你脱口而出"用Pandas读每个Sheet、转Markdown、按固定Token切块入库",这个思路嘛,不算错,只是不太够用罢了。它确实能让Demo跑起来,但是呢,撑不住生产环境的。一旦上线的话,几乎必然会撞见三类问题:一个是表头和数据错位,一个是数字背后的真实含义丢失,还有一个是检索到了内容却给不出准确答案。
就像京东三面那位面试官追问的,合并单元格和多级表头怎么处理?这两个问题只是冰山一角。根源说起来其实挺简单的。Word和PDF是线性文本嘛,读起来就像一条河。但是Excel呢,它更像一张网,语义散落在结构里而不是句子里头。Sheet名呢,它圈定了业务范围;标题行呢,点明了主题;多级表头呢,定义了字段边界;合并单元格呢,暗示了层级关系;颜色边框呢,划出了区域;公式呢,描述了计算逻辑;数字格式呢,则决定了一个数字到底是日期、百分比、金额还是编号。所以啊,生产级Excel解析真正要做的事情,从来就不是"把字挖出来"这么简单,而是要把整本工作簿翻译成一份可检索、可计算、也可追溯的事实清单才行。

这件事的紧迫性呢,也能从数据上感受到的。据MarketsandMarkets的行业报告估算,全球RAG相关市场规模在2025年大概是19.4亿美元,到2030年有望增长到98.6亿美元左右,年复合增长率超过38%。金融、医疗这些对数据准确性要求特别高的行业,恰恰是Excel密度最高的场景。这也就是为什么"表格解析"正在逐渐从RAG流程里一个不起眼的预处理步骤,变成决定系统能不能真正投产的一个关卡。

2. 第一步:文件识别、安全与资源管控
拿到文件先别急着去读数据,第一件事情是要搞清楚"这是个什么文件"。XLS和XLSX底层格式差别是很大的,指望一个解析器包打天下并不现实的。开源方案通常需要组合Pandas、OpenPyXL,再加一个专门处理XLS、XLSB的引擎才行。企业级场景里呢,Apache POI更常见一些,尤其是要处理加密文件的时候。但要注意的是,Pandas天生擅长处理规则表格里的数据本身,让它独自去承担"还原工作簿结构"这件事,多半会力不从心的。
如果把视野放宽一点的话,市面上其实已经出现了专门做复杂文档解析的托管服务,可以作为自建方案之外的一个参照系。比如说LlamaIndex旗下的LlamaParse吧,走的是LLM驱动的解析路线,在处理嵌套表格、复杂版式上表现挺突出的,也直接支持xlsx这些Office格式,按页计费但精度比较高。另一条路线呢,是开源的Unstructured.io,胜在文件类型覆盖广、可以自托管、社区也活跃,但是面对高度嵌套的表格结构时,准确率通常不如前者。对于一个只处理Excel的生产系统来说,这两类工具更适合作为"能力上限"的参照,而不是直接去照搬。毕竟它们是通用文档解析器嘛,对Excel特有的合并单元格、公式缓冲值、多级表头这些细节,未必有专门的优化。

安全和资源管控这一步是不能省的。上传入口要校验扩展名和文件真实内容是不是一致,还要限制文件大小、Sheet数量、行列数和单元格总数。加密、损坏或格式异常的文件应该进隔离队列单独处理,外部链接和嵌入对象默认只记录不执行。毕竟XLSX本质上是一个压缩包嘛,解压环节本身就是攻击面。解析任务要设超时、内存上限和解压上限,避免一个畸形文件把整条服务链路给拖垮了。生产文件还要生成哈希指纹和解析任务ID,后续不管是文档更新还是问题排查,都要靠这两个ID来串联。
3. 第二步:建立工作簿结构清单与逻辑表识别

打开工作簿之后呢,千万别把一个Sheet直接当成一张表来处理。正确的顺序是先建清单:有哪些Sheet,哪些是可见的、哪些是隐藏的、哪些是超隐藏的;每个Sheet的有效区域、合并区域、命名区域、Excel Table分别是什么;筛选状态、隐藏行列、批注和超链接又是什么情况。隐藏内容不能默认删掉的,它很可能是别的Sheet引用的计算底表,一删就断链了。但是送入检索系统的时候呢,必须带上"隐藏"这个可见性标签和来源说明,否则模型可能把一份废弃的中间计算表当成正式数据来引用。
真正的难点在于识别逻辑表。设想一下,一个Sheet里头,上面是标题说明,中间是销售明细,右边挂着一张汇总表,下面又插了一张同比对照表。如果整个Sheet一股脑导出的话,几张表的表头和数据就会互相串味,后续任何基于字段名的检索都会失真。生产环境的做法呢,是优先信任显式边界,也就是Excel Table、命名区域这些结构本身声明的范围是最可靠的。没有显式边界的时候呢,再退而结合连续非空区域、空行空列的分隔、合并标题、边框样式变化、字体和数字格式跳变、以及重复出现的表头行来做切分。识别完成之后呢,给每个逻辑表分配一个稳定的Table ID,同时记录它在原文件里对应的Sheet名和单元格范围。这个ID会贯穿后面所有的重建和检索环节。
4. 第三步:重建表头与单元格语义
面试官问的合并单元格和多级表头,确实是Excel解析里最容易翻车的地方了。举个例子吧:第一行写着"2025年",第二行拆成"销售额"和"利润",第三行再细分成"一季度""二季度"。如果只取最后一行当字段名的话,"一季度"这三个字就完全丢失了上下文。正确做法是把整条表头路径拼接展开,变成"2025年_销售额_一季度"这样自解释的完整字段名。合并单元格通常只有左上角那格真正存了值,可以在合并区域内部把标题语义补齐,但是绝不能对整张表做无脑向下填充。否则本来该是空的数据,会被误标成了上一行的延续值,这个错误比不填还危险。重复表头、备注行、小计行、合计行也得单独打标签,不能和普通数据行混为一谈,否则汇总的时候会重复计算或者漏算。

单元格本身至少要留三层信息:一个是原始值,一个是用户在Excel界面上实际看到的显示值,还有一个是数据类型、格式和单位。同一个底层数字0.15,显示出来可能是"15%";一个整数经过格式渲染可能变成一个日期;"00125"如果被转成整数125的话,员工编号就废了。日期换算尤其要小心,得读取工作簿自己的日期系统,不能默认套用同一个起始点。不同版本、不同平台生成的Excel,起点并不总是一致的。

公式的处理逻辑也值得多说一句:要同时保留公式表达式和它的结果值。有些解析库读到的只是单元格上次保存时留下的缓冲结果,并不会触发重新计算,这个值可能是空的,也可能早就过期了。生产系统应当明确标记这是"缓冲值"还是"重新计算值"。需要精确重算的时候呢,可以接入受控的LibreOffice或专门的公式计算服务。遇到解析不了的外部引用、自定义函数、宏公式,要老老实实标成"未解析",绝不能悄悄当成零处理。把未知当成零,是财务类数据里最容易埋雷的做法。
5. 第四步:按表格类型生成检索内容
结构还原完之后呢,不同类型的Excel不该套用同一种转换方式,否则就等于白还原了。规则明细表适合转成自包含记录:每一行或一小组行独立成句,比如"文件:华东销售表,Sheet:销售明细,统计月份:2025年3月,城市:杭州,产品A,销售额120万元,同比增长8%"。关键在于每条记录都要重复必要的表名、字段名、单位和时间,这样切块之后,哪怕单独拎出一条记录,也不会变成一串没头没尾的孤立数字。键值对形式的配置表呢,比如"姓名:张三,部门:研发部",就该转成键值事实而不是硬套明细记录的格式。叙述性的经营看板呢,按标题层级和局部区域生成描述性文本会更自然。一张表如果同时存在多个时间维度的话,可以按业务列组来拆分,但拆分之后,维度标签、时间标签和核心业务维度必须在每一块里重复出现,不然模型很容易把不同时间段的数据张冠李戴。
图表部分容易被低估,不该只做截图OCR,应该优先提取图表标题、系列名称以及它引用的底层数据。图片里的文字只有确实承载业务信息时才值得做OCR,否则纯属浪费算力。最终建议留两份产出:一份面向检索的文本或JSON,一份是规范化的结构化数据,两者互为校验。每个片段都带上File ID、Sheet名、Table ID、Row Range、Cell Range、Version这些元数据,这样模型给出某个数字时,才能精确回溯到原文件、原Sheet、原单元格范围。这一点呢,恰恰是纯向量检索工具容易忽略的细节,不管是自建的还是LlamaParse这类通用解析服务,它们更擅长"读懂内容",未必天然具备"逐格溯源"的设计。
6. 第五步:切块策略与非结构化+结构化双通道
切块不该按固定Token数走,而要按逻辑表的边界来走。核心原则就三条:表头不能和数据分离,一行数据不能失去字段含义,同一条业务记录尽量不要被硬生生拆开。常见做法是父块保留表名、用途说明、单位、时间范围和数据规模,子块保存若干行具体记录,并在每个子块里重复完整表头。子块到底放20行还是100行呢,不建议写死成一个固定数字,应该根据列数、Token预算和实际检索评测结果来动态调整。
不过这里有个容易被忽视的边界:向量检索天生擅长"找相关",不擅长"算精确"。用户问"华东区退款原因是什么"的时候,走向量检索加关键信息提取没问题。但是用户问"全国销售额是多少,哪个城市增长最快"的时候,就不该指望召回几段文字让大模型心算了。大模型的心算能力呢,恰恰是它在处理结构化数据时最弱的一环,这也是行业内公认的共识。比较靠谱的方案是把规范化数据同步进OLAP、DuckDB或数据仓库,RAG只负责理解问题、定位表和字段,再生成受控查询完成聚合计算。换句话说呢,生产级Excel RAG本质上不是一个纯检索系统,而是非结构化检索和结构化查询拼在一起的混合系统。这也是它和纯文本RAG最大的架构差异,值得在设计阶段就想清楚,而不是等上线后被"算错数"的投诉倒逼重构。

举个具体的例子吧:假设上传一份全国销售经营表,里面有首页汇总、订单明细、退货明细和字段说明四个Sheet。解析系统先识别出三张业务表和一张数据字典,再把"华南""四月""退货金额"这些字段统一到标准口径。用户问"华南区四月退货率为什么上升"的时候,系统先从数据字典和备注里检索退货率的定义,再到结构化数据里计算三月与四月的退货金额、销售额和变化幅度,最后检索对应的退货原因记录。回答里既给结论,也附上用到的计算口径、Sheet名、表格范围和文件版本。定义靠检索,数字靠查询,原因靠证据,三条路径分工明确,不会串戏。
7. 第六步:检索策略、增量更新与质量评测
检索层建议关键词、向量、元数据过滤三者组合使用,各管一段。订单号、产品编码、精确字段名这类查询呢,更依赖关键词检索。业务描述类的模糊问题呢,走向量检索效果更好。时间、区域、Sheet名、表类型、版本这些维度呢,交给元数据过滤来筛选。召回后返回的不能只是一段文字,还要带上来源坐标,方便用户点一下就能定位到原始单元格,也方便人工核验。
文件更新的时候呢,不要图省事把全部内容重新入库,可以按Sheet、逻辑表或组件计算指纹,只重建真正发生变化的部分,同时删掉旧版本对应的向量,避免新旧数据同时存在造成混乱。质量监控这一环容易被压缩预算,但恰恰是不能省的,要覆盖Sheet覆盖率、逻辑表识别率、行数对账、空值异常率、公式未解析率和类型转换异常这几项指标。检索层最好准备一套黄金问题集,至少覆盖精确查词、条件筛选、跨Sheet关联、汇总计算和来源追溯这五类场景。只有解析结果能对账、答案能验证、来源坐标能还原,这套系统才算真正具备上线资格,而不是停留在Demo阶段的半成品。
8. 总结

串起来看呢,生产级Excel解析的完整链路是这样的:先识别逻辑表,再重建表头、类型、单元格和公式,同时生成可检索文本与可计算数据,最后用来源坐标和版本信息,把每一个答案追溯回原始单元格。如果面试时能讲清楚文件治理、逻辑表识别、语义还原、结构化与非结构化双通道、增量更新和质量评测这六件事,基本就说明你不是在背概念,而是真的踩过生产环境的坑。
下次面试再被问到"RAG怎么解析Excel",希望你不会再脱口而出"Pandas读一下就完事了"。这套流程看起来确实挺繁琐的,但省不掉的原因在于什么呢?就是Excel的"结构性语义"和"数值精度"这两个要求,本身就和向量检索的模糊匹配天然存在张力。与其指望一个更强的Embedding模型把这个矛盾抹平,不如老老实实把"检索"和"计算"拆成两条路径。这大概率会比堆更贵的模型更划算,也更容易在生产环境里稳定跑下去。
你遇到过Excel解析的坑吗?评论区聊聊,看看大家都是怎么处理的。