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 判断。
重新保存时明确选择文件格式
普通“另存为”已经无效,重新保存时请检查保存对话框中的具体格式,并使用新文件名:
- 若原文件使用 Strict Open XML,尝试保存为普通的“Excel 工作簿(*.xlsx)”。
- 用新文件的明确路径再次运行诊断代码,确认没有继续读取旧文件。
- 若仍失败,可以新建工作簿,将
Data的数据复制进去,再保存并读取。
复制数据时按需要选择保留公式或仅保留值,并核对日期、行列数和关键数据。新建工作簿后能读取,只能说明这种重建方式绕过了原文件的问题,不能单独确定原文件的故障原因。
如果仍需定位根因,最有用的补充信息是实际 openpyxl 版本、完整加载警告,以及脱敏后的工作表声明和对应关系记录。当前材料不足以断言文件损坏,或认定某一种格式就是原因。
备注:内容仅供参考。
