查看: 121|回复: 3

Python实战:os.walk与pandas合并多文件夹Excel至总表(附完整代码)

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
在日常办公中,经常需要将分散在不同子文件夹下的Excel文件汇总到一个总表中。手动打开每个文件复制粘贴不仅耗时,而且容易出错。本文提供一个纯Python脚本解决方案,利用os.walk递归遍历目录、pandas读取Excel并纵向拼接,实现一键合并。整个过程不到30行代码,3秒即可完成。

技术原理
核心逻辑分三步:
1. 使用os.walk()递归扫描所有子文件夹,找出所有.xlsx和.xls文件。
2. 用pandas.read_excel()将每个Excel文件读取为一个DataFrame。
3. 用pandas.concat()将所有DataFrame按行合并,最后导出为新的Excel文件。

环境准备
需要安装pandas和openpyxl模块(openpyxl是pandas读取.xlsx文件的引擎):
  1. pip install pandas openpyxl
复制代码

完整代码
以下脚本定义了函数merge_excel_files,接收源文件夹路径和输出文件名,自动合并所有Excel。
  1. import os
  2. import pandas as pd
  3. from pathlib import Path
  4. def merge_excel_files(source_dir, output_file="总表汇总.xlsx"):
  5.     all_dataframes = []
  6.     file_count = 0
  7.     root_path = Path(source_dir)
  8.     if not root_path.exists():
  9.         print(f"错误:目录 {source_dir} 不存在!")
  10.         return
  11.     for dirpath, dirnames, filenames in os.walk(source_dir):
  12.         for filename in filenames:
  13.             if filename.endswith(('.xlsx', '.xls')) and not filename.startswith('~$'):
  14.                 file_path = os.path.join(dirpath, filename)
  15.                 file_count += 1
  16.                 try:
  17.                     engine = 'openpyxl' if filename.endswith('.xlsx') else 'xlrd'
  18.                     df = pd.read_excel(file_path, engine=engine)
  19.                     df['数据来源文件'] = filename
  20.                     df['数据来源路径'] = dirpath
  21.                     all_dataframes.append(df)
  22.                     print(f"[{file_count}] 已读取: {filename}")
  23.                 except Exception as e:
  24.                     print(f"[{file_count}] 读取失败 {filename}: {e}")
  25.     if not all_dataframes:
  26.         print("没有找到任何 Excel 文件!")
  27.         return
  28.     print("\n正在合并所有数据...")
  29.     merged_df = pd.concat(all_dataframes, ignore_index=True)
  30.     merged_df.to_excel(output_file, index=False, engine='openpyxl')
  31.     print(f"\n合并完成!共处理 {file_count} 个文件,总数据行数: {len(merged_df)}")
  32.     print(f"汇总文件已保存: {output_file}")
  33. if __name__ == "__main__":
  34.     SOURCE_DIR = r"D:\数据源"
  35.     merge_excel_files(SOURCE_DIR, output_file="总表汇总.xlsx")
复制代码

代码功能分解
1. 遍历文件夹
os.walk(source_dir)递归返回当前目录路径、子文件夹列表、文件列表。对于每个文件,只用endswith检查扩展名,并跳过~$开头的临时文件。
2. 读取Excel并标记来源
pd.read_excel()默认读取第一个工作表,engine自动选择openpyxl或xlrd。添加“数据来源文件”和“数据来源路径”两列方便追溯原始出处。
3. 合并与导出
pd.concat()将所有DataFrame纵向拼接,ignore_index=True重置行索引避免冲突。to_excel()保存时不导出默认行号。

进阶技巧
技巧1:指定读取的Sheet名称
如果Excel文件有多个Sheet,可以传入sheet_name参数:
  1. df = pd.read_excel(file_path, sheet_name="Sheet1", engine='openpyxl')
复制代码
或者读取所有Sheet:
  1. all_sheets = pd.read_excel(file_path, sheet_name=None, engine='openpyxl')
  2. for sheet_name, sheet_df in all_sheets.items():
  3.     sheet_df['来源Sheet'] = sheet_name
  4.     all_dataframes.append(sheet_df)
复制代码

技巧2:统一列名后再合并
当不同文件的列名不完全一致时,可以先定义映射字典并重命名列:
  1. COLUMN_MAP = {
  2.     '姓名': '姓名',
  3.     '员工姓名': '姓名',
  4.     'Name': '姓名',
  5.     '部门': '部门',
  6.     '所属部门': '部门',
  7.     '金额': '金额',
  8.     '金额(元)': '金额',
  9. }
  10. df = pd.read_excel(file_path)
  11. df.rename(columns=COLUMN_MAP, inplace=True)
复制代码

技巧3:大文件进度条
如果文件数量很多,可以安装tqdm并包装遍历循环:
  1. from tqdm import tqdm
  2. for dirpath, dirnames, filenames in tqdm(os.walk(source_dir), desc="扫描文件夹"):
  3.     for filename in filenames:
  4.         # 处理逻辑不变
复制代码

常见问题
Q1:ModuleNotFoundError: No module named 'openpyxl'
原因:缺少openpyxl库。pip install openpyxl即可解决。

Q2:合并后列的顺序乱了怎么办?
pd.concat会自动按字母顺序排列列名(pandas 1.3+),可以手动指定顺序:
  1. desired_columns = ['姓名', '部门', '金额', '日期', '数据来源文件', '数据来源路径']
  2. merged_df = merged_df[desired_columns]
复制代码

Q3:某些Excel读取为空?
可能是文件只有表头无数据,或被加密,或实际是.csv改后缀。建议读取后判断:
  1. if df.empty:
  2.     print(f"警告: {filename} 为空,跳过")
  3.     continue
复制代码

Q4:如何合并.csv文件?
将读取改为pd.read_csv(),并注意编码:
  1. if filename.endswith('.csv'):
  2.     df = pd.read_csv(file_path, encoding='utf-8-sig')
复制代码

总结
通过os.walk()遍历、pd.read_excel()读取、pd.concat()合并、to_excel()导出,一整套Excel自动化合并脚本即可完成。此方法适用于财务报表、销售数据、调查问卷等格式一致的批量汇总,显著提升工作效率。注意依赖库的安装和文件格式的兼容性,可依实际需求扩展Sheet读取、列名映射等功能。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python实战:os.walk与pandas合并多文件夹Excel至总表(附完整代码)

楼主这个脚本很实用啊,正好解决我平时汇总报表的痛点。代码结构清晰,注释也很到位,尤其是加了来源路径和文件名这两列,方便追查数据来源。另外那个统一列名的技巧也很有用,实际工作中不同部门的表格列名确实经常不统一。想请教一下,如果文件数量特别多(比如几百个)或者单个文件很大,有没有什么性能方面的优化建议?比如用分块读取或者多线程?感谢分享!
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python实战:os.walk与pandas合并多文件夹Excel至总表(附完整代码)

感谢分享!代码写得非常清晰,尤其是自动跳过临时文件和添加来源路径的设计很实用。我平时也经常用 `os.walk` 配合 pandas 做数据合并,但没考虑过列名映射的统一问题,你提到的技巧2正好能解决我常碰到的字段名不一致的痛点。另外,如果文件数量特别多,有没有考虑过用 `glob` 替代 `os.walk` 做更简单的筛选?或者用 `tqdm` 加个进度条会更直观。总之收藏了,以后直接拿来用!
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python实战:os.walk与pandas合并多文件夹Excel至总表(附完整代码)

感谢分享,写得非常详细实用!处理多个文件夹下的Excel合并确实是日常办公的高频需求,这份脚本直接拿来就能用。 想补充一个小建议:如果数据量特别大(比如几百个Excel文件或每个文件有几十万行),`pandas.concat`一次性合并可能会占用较多内存。可以考虑分批写入Excel——先创建一个空的Excel Writer,逐步追加写入每个DataFrame,这样能降低内存峰值。另外,如果有些Excel文件的实际内容为空(只有表头),读进来会报错或产生空DataFrame,可以在`try`里加一条`if df.empty: continue`跳过,避免后续拼接时出现问题。 代码里已经包含了跳过临时文件和添加来源信息的细节,很贴心。再次感谢分享!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-23 12:04 , Processed in 0.039585 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部