应显式指定sheet_name列表并统一dtype、表头、列结构,用reindex对齐列顺序,合并后校验dtypes一致性,写入时设index=false并按需添加source_sheet列。

直接用 pandas.concat() 拼接多个 pd.DataFrame 即可,但必须先统一列名、数据类型和索引逻辑,否则合并后会出现空值或类型错乱。
读取所有 Sheet 时别用 pd.read_excel(sheet_name=None) 后再手动遍历
虽然 sheet_name=None 能一次性读成 dict,但容易忽略 Sheet 名称隐含的业务含义(比如 “2023_Q1” 和 “2023_Q2” 可能需要加时间列),也难控制读取参数一致性。
- 更稳妥的做法是显式指定
sheet_name列表,例如['Sales', 'Marketing', 'Support'],避免误读隐藏 Sheet 或跳过空 Sheet - 每个 Sheet 都应加
dtype参数强制列类型,尤其对含前导零的编号列(如订单号),不加会变成float64导致后续匹配失败 - 用
skiprows或header显式声明表头行,不同 Sheet 表头位置不一致时,header=0可能错位
合并前必须对齐列结构,不能依赖 concat(..., ignore_index=True) 掩盖问题
ignore_index=True 只是重置行号,不解决字段缺失或顺序错乱。真实场景中,各 Sheet 往往列数/列名不完全一致。
- 先用
df.columns.tolist()检查所有 Sheet 的列名,找出最小公共列集,或补全缺失列为pd.NA - 对非公共列,按业务决定是否保留(例如某 Sheet 多一列
reviewer,其他没有,则统一加该列并填pd.NA) - 用
reindex(columns=common_cols, fill_value=pd.NA)统一列顺序和填充,比靠concat自动对齐更可控
写入新 Excel 时,to_excel() 默认只写一个 Sheet,别漏掉 index=False
如果直接 merged_df.to_excel("output.xlsx"),生成文件里只有 “Sheet1”,且第一列会多出 pandas 自动生成的整数索引列。
- 务必加
index=False,否则业务方打开 Excel 会看到多余的序号列 - 若需保留原始 Sheet 名作为来源标识,合并前就加一列:
df["source_sheet"] = "Sales" - 大文件(>10 万行)慎用
openpyxl引擎写入,改用xlsxwriter更快;但后者不支持追加写入已有文件
最常被跳过的一步是:合并后没校验 dtypes 是否一致——比如 “amount” 列在 Sheet A 是 int64,Sheet B 是 float64,拼一起后全变 float64,后续做 groupby().sum() 看似没问题,但导出到数据库可能因类型不匹配被截断。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











