周五下午四点,领导丢过来一个文件夹:「这里面是各个分公司的销售报表,你帮我合并到一个表里,下班前给我。」打开一看——300 多个 Excel 文件,每个里面四五个 sheet。如果一个个打开复制粘贴,周末肯定没了。最后我用几行 Python 代码十分钟搞定。今天把这段代码分享出来,下次你遇到类似的活直接拿去用。
那天下午四点十分,我点开那个文件夹数了一下。317 个文件。其中大概十几个文件后缀还不一样——有的是.xls,有的是.xlsx,有的是.csv。文件名也没有统一规范:「深圳分公司-销售报表(修订版).xlsx」「北京-销售数据-最终版.csv」「上海-别删-这是最新的.xls」。
我不知道你看到这种文件命名方式什么感受。我看到「修订版」「最终版」「别删这是最新的」同时出现在一个文件夹里的时候,血压已经上来了。
领导在钉钉上又弹了一条消息:「尽量下班前给我。」
我回:「好。」
然后关掉钉钉,打开终端。
第零步:先把环境搭好
如果你电脑上还没有 Python,去 python.org 下载安装。安装的时候注意勾选「Add Python to PATH」——这步漏了后面命令会报错。
装好之后打开终端(Windows 按 Win+R 输入 cmd,Mac 打开「终端」),装两个库:
pip install pandas openpyxl看到 Successfully installed 就说明装好了。
然后把领导给你的那一堆 Excel 文件全部扔到一个文件夹里。比如在桌面新建一个叫 excel_work 的文件夹,把所有文件拖进去。等会在代码里把路径指到这个文件夹就行。
第一步:先把所有文件的路径拿到手
Python 有个内置模块叫glob,专门干这个。一行代码就能把一个文件夹里所有 Excel 文件的路径列出来。
import globfiles = glob.glob(「销售报表/*.xls*」)print(f「找到 {len(files)} 个文件」)它会输出:找到 317 个文件。比你手动数快 317 倍。
第二步:全部读进来,拼成一个大表
pandas库里有个函数叫read_excel,读一个文件。你把 317 个文件路径全丢给它,它一个个读完拼到一起。
import pandas as pdall_data = []for f in files: df = pd.read_excel(f) all_data.append(df)result = pd.concat(all_data, ignore_index=True)print(f「合并完成,共 {len(result)} 行」)第一次跑这三行代码的时候,我盯着屏幕看了大概五秒。317 个文件,合并完大概 3 万多行,花了不到十秒。如果手动干,打开第一个文件的时间都不止十秒。
但事情没这么简单。跑完第一遍发现报错了。
有些文件里面的表头不一样——深圳分公司用的是「销售额」,北京用的是「销售金额」,上海那家直接写了英文「Revenue」。表头不统一,拼出来的表一列变三列。
第三步:统一表头再合并
这就需要在读每个文件的时候先检查一下列名,不一样的就统一。
import pandas as pdimport globfiles = glob.glob(「销售报表/*.xls*」)all_data = []for f in files: df = pd.read_excel(f) # 统一列名:不管原文件叫什么,全改成标准名称 df.columns = df.columns.str.replace(「销售额|销售金额|Revenue」, 「销售额」, regex=True) all_data.append(df)result = pd.concat(all_data, ignore_index=True)result.to_excel(「合并完成.xlsx」, index=False)print(f「合并完成,共 {len(result)} 行,已保存」)第四步:有些文件不是 Excel 格式
还有几个.csv文件藏在里面。read_excel读不了 csv,得用read_csv。
改一下,先判断文件后缀:
for f in files: if f.endswith('.csv'): df = pd.read_csv(f) else: df = pd.read_excel(f) df.columns = df.columns.str.replace(「销售额|销售金额|Revenue」, 「销售额」, regex=True) all_data.append(df)完整代码
上面几步拼起来,就是最终的版本。我把它整理好放在这里,下次你遇到直接复制,改三个地方就行——文件夹路径、想要统一的列名、输出的文件名。
import pandas as pdimport glob# 1. 找到所有表格文件files = glob.glob(「你的文件夹路径/*.xls*」) + glob.glob(「你的文件夹路径/*.csv」)# 2. 逐个读取,统一列名,拼在一起all_data = []for f in files: # 根据后缀选择读取方式 if f.endswith('.csv'): df = pd.read_csv(f) else: df = pd.read_excel(f) # 统一列名——把你要统一的列名映射写在这里 df.columns = df.columns.str.replace(「销售额|销售金额|Revenue」, 「销售额」, regex=True) all_data.append(df)# 3. 合并 + 保存result = pd.concat(all_data, ignore_index=True)result.to_excel(「合并完成.xlsx」, index=False)print(f「搞定!共合并 {len(files)} 个文件,{len(result)} 行数据」)不只合并——学会了这个模式,能干的活多了去了
怎么运行这段代码? 把上面的完整代码复制,打开记事本粘贴进去,保存为 merge_excel.py(注意后缀是 .py 不是 .txt)。然后把文件放到你的 excel_work 文件夹旁边,在终端里 cd 到那个目录,执行:
python merge_excel.py看到「搞定!共合并 317 个文件,38241 行数据」就说明跑完了。
你掌握了「批量读取 → 处理 → 合并」这个模式之后,能干的活多了去了。举几个我自己用过的例子:
批量提取关键信息: 文件夹里一百多个合同 Excel,只要提取每个文件的「合同金额」和「签约日期」这两列。
for f in files: df = pd.read_excel(f) # 只取需要的两列 info = df[[「合同金额」, 「签约日期」]].iloc[0] all_data.append(info)批量筛选: 把每个分公司报表里「销售额超过 10 万」的行挑出来,单独存一个文件。
result = result[result[「销售额」] > 100000]批量改格式: 把所有文件的日期列统一成同一个格式,把金额列全部保留两位小数。
df[「日期」] = pd.to_datetime(df[「日期」]).dt.strftime(「%Y-%m-%d」)df[「销售额」] = df[「销售额」].round(2)那天下午四点四十,我把合并好的 Excel 发给了领导。
他回:「这么快?」
我说:「嗯,写了个脚本。」
他说:「好。」
他没问我写的什么脚本。我也没解释。但那天我五点半准时下班了。经过了楼下的柠檬茶店,要了一杯冰的。坐在店门口的椅子上,看了会儿天。周五下午五点半,天还没黑,风是凉的。在那一刻我觉得,会一点自动化真挺好的。
你被 Excel 折磨过吗?有没有什么自己摸索出来的骚操作?评论区教教大家。
夜雨聆风