正确做法是用一个pd.excelwriter实例统一管理多sheet写入,通过with语句确保资源自动释放;重复创建实例会导致覆盖或permissionerror;sheet名需合法且唯一,推荐使用openpyxl引擎配合if_sheet_exists参数处理已有文件。

用 pd.ExcelWriter 创建多工作表文件
直接调用 to_excel() 只能写入单个 sheet;要写多个,必须用 pd.ExcelWriter 作为容器。它本质是一个上下文管理器,负责打开、缓存、最终保存整个 Excel 文件。
常见错误是重复创建多个 ExcelWriter 实例写同一个文件——这会导致后写入的覆盖前一个,或抛出 PermissionError(Windows 下尤其明显)。
正确做法是:一个文件对应一个 ExcelWriter,所有 to_excel() 都指定 sheet_name 并共用这个 writer:
with pd.ExcelWriter("output.xlsx") as writer:
df1.to_excel(writer, sheet_name="汇总", index=False)
df2.to_excel(writer, sheet_name="明细", index=True)
df3.to_excel(writer, sheet_name="统计", index=False)
工作表名不能重复或含非法字符
Excel 对 sheet 名有硬性限制:最长 31 字符、不能含 / ? * [ ]、不能全为空格、不能与已有 sheet 同名。Pandas 不会自动截断或转义,出错时抛 XlsxWriterException 或静默失败(取决于引擎)。
建议在写入前做校验和清洗:
- 用
re.sub(r'[\/?*[]]', '_', name)替换非法字符 - 用
name[:31].strip()截断并去首尾空格 - 维护一个已用 names 列表,避免重复
不同引擎对格式和大文件的支持差异
ExcelWriter 默认用 xlsxwriter 引擎(适合写新文件),但不支持读/改已有 Excel;若需追加或修改已有文件,得换 openpyxl 引擎,并且要加 if_sheet_exists="replace" 或 "overlay" 参数(pandas ≥ 1.4.0)。
性能方面:xlsxwriter 写纯数据快、内存友好;openpyxl 支持样式/公式但更吃内存。导出超 10 万行时,建议关掉索引(index=False)、避免写入 NaN 字符串(先 df.fillna(""))。
导出时保留日期/数字格式的注意事项
Pandas 导出时默认把 datetime64 当字符串处理,Excel 里显示为普通文本而非可排序日期。解决方法有两个:
- 用
xlsxwriter引擎时,在to_excel()后手动调用worksheet.write_datetime()(需拿到底层 worksheet 对象) - 更简单的是提前转为字符串并指定格式:
df["date"] = df["date"].dt.strftime("%Y-%m-%d")
数字列如果含逗号分隔符(如 "1,234"),Excel 会当文本处理——务必确保导出前是 float 或 int 类型,不要用 astype(str) 破坏数值属性。
sheet 名冲突、引擎选错、日期变文本——这三个点实际项目里被踩最多,尤其是交接给业务方后,他们双击打开看到“#VALUE!”才反馈问题。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











