PAYATHON 2026

Excel 中有工作表,为什么 openpyxl 的 sheetnames 返回空列表?

数据阿明

结论

wb.sheetnames 返回 [],表示 openpyxl 加载后没有创建任何工作表对象,但这不能证明文件中没有数据。仅凭现有代码,无法确定文件的具体问题。

data_only=True 控制公式单元格返回公式还是已保存的计算结果,不负责筛选工作表,因此修改它通常不能解决工作表列表为空的问题。参数含义可参见 load_workbook 文档。

建议先确认 Python 读取的文件,再检查加载警告和文件内部的工作表引用。

先核对路径并显示加载警告

相对路径取决于 Python 进程的当前工作目录。先确认脚本读取的文件与 Excel 中打开的是同一份,同时记录 openpyxl 版本和加载警告:

from pathlib import Path
import warnings
import openpyxl

path = Path("IS-2-1000.xlsx").resolve(strict=True)
print("File:", path)
print("openpyxl:", openpyxl.__version__)

with warnings.catch_warnings(record=True) as captured:
    warnings.simplefilter("always")
    wb = openpyxl.load_workbook(path, data_only=True)

print("Sheets:", wb.sheetnames)
for warning in captured:
    print("Warning:", warning.message)

如果警告提到无效的工作表定义,应优先检查工作表关联信息。openpyxl 文档展示的读取实现会跳过未解析出关联 ID 的工作表,也会跳过关联目标文件不存在的工作表。这两种情况都可能导致加载后没有工作表。参见 工作表引用解析和工作表加载逻辑。具体行为还需结合实际安装的版本判断。

检查 XLSX 内部的工作表引用

XLSX 是一个 ZIP 包。对于常见的文件布局,可以检查:

  • xl/workbook.xml:是否声明了 Data 工作表及其关联 ID。
  • xl/_rels/workbook.xml.rels:该 ID 对应哪个工作表文件。
  • 关联的工作表 XML:是否实际存在于 ZIP 包中。

下面的代码只读取结构,不修改文件:

from zipfile import ZipFile
from xml.etree import ElementTree as ET

with ZipFile(path) as archive:
    names = set(archive.namelist())
    parts = (
        "xl/workbook.xml",
        "xl/_rels/workbook.xml.rels",
    )

    for part in parts:
        print("\nPart:", part)
        if part not in names:
            print("Missing at this path")
            continue

        root = ET.fromstring(archive.read(part))
        print("Root:", root.tag)
        for element in root.iter():
            local_name = element.tag.rsplit("}", 1)[-1]
            if local_name in {"sheet", "Relationship"}:
                print(element.attrib)

    print("\nWorksheet XML files:")
    for name in sorted(names):
        if name.startswith("xl/worksheets/") and name.endswith(".xml"):
            print(name)

检查时,把 Data 的关联 ID 与 .rels 中的 Id 对照,再核对 Target 指向的文件。相对 Target 应以工作簿所在目录解析。例如,工作簿位于 xl/workbook.xml 时,worksheets/sheet1.xml 对应 xl/worksheets/sheet1.xml。

这些是常见路径。某个路径缺失本身不能证明文件损坏,特殊布局还需根据包内关系定位工作簿。能够解析 XML、找到工作表文件,也不能证明整个工作簿完全有效。

还要留意关联 ID 属性的 XML namespace。前缀是否叫 r 并不关键,影响属性识别的是实际的 namespace。如果文件采用 Strict Open XML 或其他不同于读取器预期的结构,可以把它作为兼容性线索继续核查,不能仅凭扩展名 .xlsx 判断。

重新保存时明确选择文件格式

普通“另存为”已经无效,重新保存时请检查保存对话框中的具体格式,并使用新文件名:

  1. 若原文件使用 Strict Open XML,尝试保存为普通的“Excel 工作簿(*.xlsx)”。
  2. 用新文件的明确路径再次运行诊断代码,确认没有继续读取旧文件。
  3. 若仍失败,可以新建工作簿,将 Data 的数据复制进去,再保存并读取。

复制数据时按需要选择保留公式或仅保留值,并核对日期、行列数和关键数据。新建工作簿后能读取,只能说明这种重建方式绕过了原文件的问题,不能单独确定原文件的故障原因。

如果仍需定位根因,最有用的补充信息是实际 openpyxl 版本、完整加载警告,以及脱敏后的工作表声明和对应关系记录。当前材料不足以断言文件损坏,或认定某一种格式就是原因。

备注:内容仅供参考。