最稳方案是glob找文件+pd.read_excel逐个读+pd.concat合并;excelwriter不适用于读取合并,仅用于写新文件或覆盖;需注意glob路径、排序、读取参数、concat选项及数据格式校验。

直接说结论:用 glob 找文件 + pd.read_excel 逐个读 + pd.concat 合并,是最稳、最可控的方案;别图省事用 openpyxl 或 xlsxwriter 手动拼接,那不是快,是给自己埋雷。
为什么不用 pd.ExcelWriter 一次性写入?
很多人看到“合并 Excel”,第一反应是打开一个 ExcelWriter 对象往里追加 sheet——这在逻辑上就错了。ExcelWriter 是用于**写新文件或覆盖写**的,它不提供“读多个文件再拼数据”的能力。强行用它处理上百个文件,要么反复打开关闭(极慢),要么内存爆掉(每个 Workbook 实例都吃内存)。
- 真正要的是“把所有表格的数据行堆在一起”,不是“把所有 sheet 塞进一个文件”
-
pd.concat处理的是DataFrame,不是文件,这才是高效的核心 - 如果最终真要输出多 sheet 的汇总文件,那是合并完成后的**另一次独立操作**
用 glob.glob 匹配文件时的三个关键点
glob 看似简单,但在真实目录里很容易漏文件或读错顺序:
- 路径通配符必须用
**/*.xlsx(加recursive=True)才能扫子目录,否则只查当前层 - 文件名含空格或中文?没问题,但一定要用原始字符串:
r"../data/**/*.xlsx",避免反斜杠转义出错 - 顺序很重要!
glob返回无序列表,sorted()必须跟上,否则每次运行合并结果的行序可能不同(尤其涉及时间戳列时)
示例:
import glob<br>files = sorted(glob.glob(r"reports/**/*.xlsx", recursive=True))
pd.read_excel 读取时最容易踩的坑
成百上千个文件里,格式从来不会完全一致。不加控制地读,concat 会直接报 ValueError: All objects passed were None 或列对不齐:
- 统一指定
sheet_name=0,别让它自动猜——有些文件有隐藏 sheet,有些默认是最后一个,行为不一致 - 加
usecols(比如"A:C"或[0,2,4])强制读固定列,跳过格式混乱的附加列 - 加
dtype=str或按列指定类型(如{"ID": str, "Amount": float}),避免某张表里“123”被读成 int、“123.0”被读成 float,后续concat会生成object列,无法计算 - 加
skiprows或header显式声明表头位置,别依赖“第一行是标题”这种假设
pd.concat 合并不止是把 DataFrame 列表传进去
直接 pd.concat(dfs) 在小数据上能跑,一到千级文件就卡死或内存溢出:
- 务必加
ignore_index=True,否则索引重复(每个read_excel默认从 0 开始),后续.drop_duplicates()会失效 - 加
sort=False,避免内部自动按列名排序(列顺序不一致时会重排,耗时且易出错) - 如果内存紧张,改用分批
concat:每 50 个文件合一次,再把中间结果合并,比一次性全读进内存安全得多 - 最后记得
.reset_index(drop=True),清理掉 concat 带来的冗余索引层级
示例(带错误跳过):
dfs = []<br>for f in files:<br> try:<br> df = pd.read_excel(f, sheet_name=0, usecols="A:D", dtype={"ID": str})<br> df["source_file"] = f # 记录来源,方便后续排查<br> dfs.append(df)<br> except Exception as e:<br> print(f"跳过 {f},错误:{e}")<br>result = pd.concat(dfs, ignore_index=True, sort=False).reset_index(drop=True)
真正麻烦的不是代码几行,而是每个 Excel 文件都可能悄悄换一种格式:空行、合并单元格、额外备注行、列名大小写不一致、甚至用“-”代替空值……这些不会报错,但会让合并后的数据在第 837 个文件处开始错位两列。动手前先抽样看 5 个文件的 df.head().to_dict() 输出,比写完再 debug 快十倍。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











