用pd.excelwriter是批量导出多个dataframe到同一excel不同sheet的唯一可靠方式,需用with上下文管理器复用文件句柄,显式指定engine='openpyxl',注意sheet名合法性、写入位置偏移及空dataframe跳过。

用 pd.ExcelWriter 写入多个 Sheet 是唯一可靠方式
直接调用 df.to_excel() 只能写单个 Sheet;想批量导出多个 DataFrame 到同一个 Excel 文件的不同 Sheet,必须用 pd.ExcelWriter 上下文管理器。它底层封装了 openpyxl 或 xlsxwriter 引擎,能复用一个文件句柄,避免反复打开/关闭导致的覆盖或报错。
常见错误是循环里对同一文件多次调用 to_excel(),结果只有最后一个 DataFrame 被保留——因为每次都会重写整个文件。
实操建议:
- 显式指定
engine='openpyxl'(推荐),尤其当要后续读写已存在的 Excel 或操作样式时;xlsxwriter不支持读取,且不能修改已有文件 - 确保每个
sheet_name是合法字符串:长度 ≤31 字符、不包含:\/?*[],否则抛ValueError: Invalid sheet name - 用
with pd.ExcelWriter(...)确保异常时自动释放资源,不留下损坏的 .xlsx 文件
如何控制每个 Sheet 的写入位置和格式
ExcelWriter 默认从 A1 开始写,但你可以用 startrow 和 startcol 参数偏移写入起点,适合拼接表头、留空行或合并多个小表。注意:这些参数只影响当前 to_excel() 调用,不影响其他 Sheet。
格式控制本身 Pandas 不直接支持(比如设置列宽、字体),但可通过底层引擎对象操作:
- 用
openpyxl引擎时,通过writer.book和writer.sheets['Sheet1']访问 worksheet 对象,再调用.column_dimensions['A'].width = 20等 - 不要在写入中途调用
writer.save()—— 这会提前关闭句柄,后续to_excel()报ValueError: Workbook is closed - 若某 Sheet 数据为空 DataFrame,
to_excel()仍会创建该 Sheet(仅含表头),如需跳过,先加if not df.empty:判断
导出大量 Sheet 时的内存与性能陷阱
每增加一个 Sheet,Excel 文件体积和写入时间非线性增长,尤其当单个 DataFrame 行数超 10 万或含大量字符串列时。openpyxl 在写入阶段会把整张 Sheet 加载进内存构建 DOM 树,容易触发 MemoryError。
缓解方法:
- 对超大 DataFrame 分块写入:用
df.iloc[i:i+50000].to_excel(..., header=(i==0)),但注意header=False仅首块保留列名 - 导出前删掉无用列:
df = df[useful_cols],字符串列尽量用category类型节省内存 - 避免在循环内重复创建
ExcelWriter实例——这是最常被忽略的性能杀手,务必把所有to_excel()放进同一个with块
导出后无法打开?检查这三类典型问题
生成的 .xlsx 打不开,或提示“文件已损坏”,大概率不是代码逻辑错,而是引擎行为差异或路径/权限问题:
-
FileNotFoundError:路径中含中文或空格,且没用 raw string 或双反斜杠;正确写法:r"输出\报表.xlsx"或"输出/报表.xlsx" - 用
xlsxwriter引擎时写了datetime类型列却没设datetime_format,Excel 会显示为数字(实际是序列值);加engine_kwargs={'options': {'datetime_format': 'yyyy-mm-dd'}} - Windows 下杀毒软件(尤其是 McAfee、360)可能锁定刚生成的文件,导致双击打不开;临时退出杀软或换路径测试
多 Sheet 导出真正的难点不在语法,而在于写入顺序、内存水位和引擎边界条件——别等跑完 20 分钟才发现第 15 个 Sheet 没写进去。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











