[Bug]: a spreadsheet whose first 100 rows are blank loses every row when the used range is over 10000

该报错发生在用 RAGFlow 的 Excel 解析器( deepdoc/parser/excel_parser.py )解析工作表时,如果工作表 used range 超过 10000 行,而前 100 行恰好全是空白,解析器会把整张表当成空表丢弃, RAGFlowExcelParser.html

快速结论:该报错发生在用 RAGFlow 的 Excel 解析器(deepdoc/parser/excel_parser.py)解析工作表时,如果工作表 used range 超过 10000 行,而前 100 行恰好全是空白,解析器会把整张表当成空表丢弃,RAGFlowExcelParser.html 返回 0 个 chunk。优先检查数据起始行是否在 100 行之后,以及工作表是否因样式单元格(如加粗、无值单元格)把 used range 撑到 10000 行以上。

适用环境:Issue 中已确认的环境为:从源码运行 parser,commit 70601910e,Python 3.13.14,openpyxl 3.1.5,macOS 26.6.2 arm64,无 Docker 镜像。问题是 deepdoc/parser/excel_parser.py 中的逻辑,容器构建不会改变它。

最快修复方案:升级到包含 PR #19237 的版本。Issue 关闭说明中确认该 PR 已修复此问题,验证 commit 为 58035bdfe

注意事项:该修复替换了原来的 100 行 guard,改为扫描已物化的单元格,因此空白前导行不再被误判为空表。选择其他 PR 时要注意:#19219 只改搜索后的行数上限,不修搜索前的 guard,对本文场景仍返回 0;#19234 替换整个函数,也能返回正确行数。这是与 #19185(数据中间有空白间隙、以及二进制搜索后的 500 行上限)不同的触发路径,两者都需要 used range 超过 10000 行。

问题场景

用户从源码运行 RAGFlow,调用 deepdoc/parser/excel_parser.py 中的 RAGFlowExcelParser.html 解析 Excel/工作表。工作表的 used range 超过 10000 行,但前 100 行没有任何值,真实数据从第 101 行之后开始。此时解析器返回 0 个 chunk,整张表被静默丢弃,没有任何警告。

典型真实文件形态:表头行上方存在标题块、logo、空白打印区域,或者某个远处单元格被设置了样式但没有值,从而把 used range 撑到 10000 行以上。

报错原文

[Bug]: a spreadsheet whose first 100 rows are blank loses every row when the used range is over 10000

复现脚本的关键输出:

print(len(p.html(build(1, 200))))     # 1  chunk, correct
print(len(p.html(build(150, 350))))   # 0  chunks, every row lost

原因分析

问题出现在 deepdoc/parser/excel_parser.py:172 的 guard:

if not any(row_has_data(i) for i in range(1, min(101, max_row + 1))):
    return 0

该判断只看前 100 行:如果前 100 行没有任何数据,就直接返回 0,把工作表当成空表。随后 _get_rows_limited 将 0 映射为空列表,html 再通过 if not rows: continue 跳过该工作表,所以所有行都丢失。

而当 used range 不超过 10000 行时,_get_actual_row_count 会直接返回 max_row,不会走到这段 guard,因此该问题只在 used range 超过 10000 行、且前 100 行为空时触发。guard 下方的二进制搜索本来可以找到真实数据,但被提前返回拦截了。

环境排查

  • 确认 RAGFlow 源码 commit 是否为 70601910e 或包含相同 guard 逻辑的版本。
  • 确认 Python 版本,Issue 中为 3.13.14。
  • 确认 openpyxl 版本,Issue 中为 3.1.5。
  • 确认操作系统与架构,Issue 中为 macOS 26.6.2 arm64。
  • 确认问题是否来自 deepdoc/parser/excel_parser.py,而不是容器镜像或 Docker 构建;该问题与容器构建无关。
  • 检查目标工作表的 used range 是否超过 10000 行,以及前 100 行是否为空。
  • 检查是否存在无值但有样式的单元格(例如加粗字体),它会把 used range 撑大。

解决步骤

  1. 先用复现脚本确认现象:分别构造数据从第 1 行开始、从第 150 行开始且远处第 12000 行有样式单元格的工作簿,调用 RAGFlowExcelParser.html,观察前者返回 1 个 chunk、后者返回 0 个 chunk。
  2. 在 helper 层确认 _get_actual_row_count 对空白前导表返回 0,而期望值应为实际数据结束行。
  3. 升级或切换到包含 PR #19237 的版本。Issue 关闭说明确认该修复将 100 行 guard 替换为对已物化单元格的扫描。
  4. 如果暂时无法升级,可优先尝试人工规避:在数据上方插入有效内容或移除把 used range 撑到 10000 行以上的远处样式单元格,使 _get_actual_row_count 不走 100 行 guard 分支。该规避方式未在 Issue 中明确验证,属于可优先尝试的临时手段。
  5. 如果必须在 #19219 和 #19234 之间选择,注意 #19219 对本文场景仍返回 0,#19234 返回正确行数。

验证方法

在修复后的版本上重新运行报告中的复现脚本,并对照 Issue 关闭说明中的验证表:数据从 1 到 200 行、max_row 为 12000 时,_get_actual_row_count70601910e58035bdfe 下都返回 200;数据从 101 到 300、150 到 350、500 到 700 行时,70601910e 返回 0,58035bdfe 分别返回 300、350、700。第 1 行作为对照不应发生变化。

参考来源

infiniflow/ragflow #19236

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 23500

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注