Python · 3 分钟阅读
Pandas 写入 Excel
2026 年现状:
openpyxl仍是.xlsx主力;读.xls用xlrd(2.0 之后只读 .xls 格式)。大文件多 sheet 落盘有三种思路:一次性写完、用ExcelWriter增量写、用pyarrow+ Excel 二进制替代(暂不成熟)。本篇用 2.2+ 风格。
准备
pip install "pandas[pyarrow]" openpyxl
openpyxl是 Pandas 写.xlsx的默认引擎。xlsxwriter适合复杂格式(图表、条件格式)。
最简单的写法
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Carol"],
"age": [30, 25, 40],
"city": ["BJ", "SH", "GZ"],
})
df.to_excel("out.xlsx", index=False)
index=False必加——否则 Pandas 会把 0、1、2 这种索引用作第一列写进去。
多个 sheet
with pd.ExcelWriter("report.xlsx", engine="openpyxl") as w:
df1.to_excel(w, sheet_name="users", index=False)
df2.to_excel(w, sheet_name="orders", index=False)
summary.to_excel(w, sheet_name="summary", index=False)
with 块退出时文件自动关闭,失败也能正确清理。
指定起始单元格
df.to_excel("out.xlsx", sheet_name="data", startrow=2, startcol=1)
把表头从 C3 开始——常用于"先放标题,再放表"的报表模板。
处理大文件
写大 Excel(>100 万行)会遇到两个瓶颈:
- 内存:一次性
to_excel全装进内存再写 - 格式:
.xlsx本身对 1,048,576 行有硬限制
# 1) 分块写多个文件
for i, chunk in enumerate(pd.read_csv("big.csv", chunksize=200_000)):
chunk.to_excel(f"big_part_{i:03d}.xlsx", index=False)
# 2) 落地为 Parquet / CSV,再用 Excel 打开看
df.to_parquet("big.parquet", engine="pyarrow")
真大数据:别用 Excel。Parquet / DuckDB / SQLite 是 2026 年的默认答案。
改样式
Pandas 的样式 API 写起来很啰嗦,复杂格式通常用 openpyxl 直接画:
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill
with pd.ExcelWriter("styled.xlsx", engine="openpyxl") as w:
df.to_excel(w, sheet_name="data", index=False)
ws = w.sheets["data"]
# 表头加粗 + 背景色
header_font = Font(bold=True, color="FFFFFF")
header_fill = PatternFill("solid", fgColor="305496")
for cell in ws[1]:
cell.font = header_font
cell.fill = header_fill
# 列宽
ws.column_dimensions["A"].width = 20
ws.column_dimensions["B"].width = 10
多个 DataFrame 写到同一 sheet
with pd.ExcelWriter("multi.xlsx", engine="openpyxl") as w:
df1.to_excel(w, sheet_name="all", index=False, startrow=0)
df2.to_excel(w, sheet_name="all", index=False, startrow=len(df1) + 2)
注意留一行空行(+2 而不是 +1)做分隔。
日期与时区
df = pd.DataFrame({
"ts": pd.to_datetime(["2026-08-04 10:00", "2026-08-04 11:00"]),
"val": [1, 2],
})
with pd.ExcelWriter("time.xlsx", engine="openpyxl", datetime_format="YYYY-MM-DD HH:MM:SS") as w:
df.to_excel(w, index=False)
datetime_format 控制时间列在 Excel 里怎么显示。
只写部分列
df.to_excel("out.xlsx", columns=["name", "age"], index=False)
columns 决定写哪些列 + 顺序。
常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
ModuleNotFoundError: openpyxl |
没装 | pip install openpyxl |
| 第一列多了索引 | 默认行为 | index=False |
| 写中文乱码 | 多半没事,但 Excel 可能要求 .xlsx 编码 | 用 .xlsx,避免 .xls |
| 100 万行写失败 | xlsx 硬限制 | 分文件 / 改 Parquet |
| 读回来类型变了 | Excel 不保留类型信息 | dtype 显式指定 |
实战:导出一份带样式的月报
import pandas as pd
from openpyxl.styles import Font, PatternFill, Alignment
df = pd.read_parquet("sales.parquet") # 列式读取,类型完整
# 简单聚合
pivot = (
df.pivot_table(index="city", columns="month", values="amount", aggfunc="sum")
.fillna(0)
.round(0)
)
with pd.ExcelWriter("sales_report.xlsx", engine="openpyxl") as w:
pivot.to_excel(w, sheet_name="summary")
ws = w.sheets["summary"]
header = Font(bold=True, color="FFFFFF")
fill = PatternFill("solid", fgColor="305496")
for cell in ws[1]:
cell.font = header
cell.fill = fill
cell.alignment = Alignment(horizontal="center")
# 数字格式
for row in ws.iter_rows(min_row=2, max_row=ws.max_row, min_col=2):
for c in row:
c.number_format = "#,##0"
一些经验
- 报表场景:先
Parquet落盘做计算,最后一步才导 Excel 给非技术同事 - 复杂样式(条件格式、图表、合并单元格)直接用
openpyxl/xlsxwriter,别死磕 Pandas 风格 API - 多个 sheet + 跨 sheet 引用:用
xlsxwriter写公式最稳 - Excel 当数据库用:会有"日期被转成 45678 数字"等坑,加载时
parse_dates=