乐于分享
好东西不私藏

01:一键合并——多文件夹下百份 Excel 自动汇总至总表

01:一键合并——多文件夹下百份 Excel 自动汇总至总表

01:一键合并——多文件夹下百份 Excel 自动汇总至总表

第一阶段:Excel / 数据表高效处理(1-8)

场景引入

每月底,财务部门的同事小张总会遇到这样的噩梦:公司下属 12 个分公司各自把报表放在不同的文件夹里,每个文件夹又有 5-10 份 Excel 文件,格式基本一致但文件名五花八门。小张需要手动打开每一份文件,复制粘贴到汇总表里——每次都要花掉整整半天时间。

学完本节,你可以用 不到 30 行 Python 代码,一键遍历所有文件夹、读取所有 Excel 文件,自动合并成一张总表,全程只需 3 秒钟。

欢迎大家关注此公众号,后台点击按钮【免费资料】可免费获取【Python入门30节课】电子书

  1. 此外小庄推荐一本适合于新手\小白入手一本 Python基础书籍,欢迎大家订阅,也感谢大家支持,我才有更新的动力


技术原理

核心思路分三步:

  1. 遍历目录树:使用 Python 内置的 os.walk() 或 pathlib 递归扫描所有子文件夹
  2. 读取 Excel 文件:使用 pandas.read_excel() 将每个 Excel 文件读取为 DataFrame
  3. 纵向拼接:使用 pandas.concat() 将多个 DataFrame 按行合并,最后导出为新的 Excel 文件
文件夹结构示意:数据源/├── 北京分公司/│   ├── 1月报表.xlsx│   └── 2月报表.xlsx├── 上海分公司/│   ├── Q1汇总.xlsx│   └── Q2汇总.xlsx└── 广州分公司/    └── 年度报表.xlsx         ↓ Python 自动遍历 + 合并    ↓总表.xlsx(包含所有数据)

环境准备

安装依赖库

pip install pandas openpyxl
库名
作用
pandas
数据处理核心,提供 DataFrame 结构和 concat 合并功能
openpyxl
pandas 读取 .xlsx 文件的引擎(必须安装)

完整代码

import osimport pandas as pdfrom pathlib import Pathdef merge_excel_files(source_dir, output_file="总表汇总.xlsx"):"""    遍历指定目录下所有子文件夹中的 Excel 文件,合并为一张总表    参数:        source_dir: 包含 Excel 文件的根目录路径        output_file: 输出汇总文件的文件名    """    all_dataframes = []  # 存储所有读取到的 DataFrame    file_count = 0# 统计处理的文件数# 将路径转为 Path 对象,方便操作    root_path = Path(source_dir)if not root_path.exists():print(f"错误:目录 {source_dir} 不存在!")return# os.walk 递归遍历所有子文件夹for dirpath, dirnames, filenames in os.walk(source_dir):for filename in filenames:# 只处理 .xlsx 和 .xls 文件if filename.endswith(('.xlsx''.xls')) and not filename.startswith('~$'):                file_path = os.path.join(dirpath, filename)                file_count += 1try:# 读取 Excel 文件(默认读取第一个 sheet)                    df = pd.read_excel(file_path, engine='openpyxl' if filename.endswith('.xlsx'else 'xlrd')# 可选:添加一列来源信息,记录数据来自哪个文件                    df['数据来源文件'] = filename                    df['数据来源路径'] = dirpath                    all_dataframes.append(df)print(f"[{file_count}] 已读取: {filename}")except Exception as e:print(f"[{file_count}] 读取失败 {filename}{e}")if not all_dataframes:print("没有找到任何 Excel 文件!")return# 将所有 DataFrame 纵向拼接(按行合并)print("\n正在合并所有数据...")    merged_df = pd.concat(all_dataframes, ignore_index=True)# 导出为新的 Excel 文件    merged_df.to_excel(output_file, index=False, engine='openpyxl')print(f"\n合并完成!")print(f"共处理 {file_count} 个文件")print(f"总数据行数: {len(merged_df)}")print(f"总数据列数: {len(merged_df.columns)}")print(f"汇总文件已保存: {output_file}")# ==================== 使用示例 ====================if __name__ == "__main__":# 修改这里为你的数据文件夹路径    SOURCE_DIR = r"D:\数据源"# 执行合并    merge_excel_files(SOURCE_DIR, output_file="总表汇总.xlsx")

代码逐行解析

1. 导入模块

import osimport pandas as pdfrom pathlib import Path
  • os:操作系统接口,用于遍历文件夹
  • pandas as pd:数据处理库,核心工具
  • Path:面向对象的路径操作,比字符串拼接更安全

2. 递归遍历文件夹

for dirpath, dirnames, filenames in os.walk(source_dir):

os.walk() 是 Python 内置的目录遍历函数,它会递归地进入每个子文件夹。每次迭代返回三个值:

变量
含义
示例
dirpath
当前文件夹的完整路径
"D:\\数据源\\北京分公司"
dirnames
当前文件夹下的子文件夹列表
["1月", "2月"]
filenames
当前文件夹下的文件列表
["1月报表.xlsx", "2月报表.xlsx"]

3. 文件过滤

if filename.endswith(('.xlsx''.xls')) and not filename.startswith('~$'):
  • endswith(('.xlsx', '.xls')):只处理 Excel 文件
  • not filename.startswith('~$'):排除 Excel 的临时锁文件(编辑时自动生成)

4. 读取 Excel 并标记来源

df = pd.read_excel(file_path, engine='openpyxl')df['数据来源文件'] = filenamedf['数据来源路径'] = dirpath
  • pd.read_excel() 将 Excel 文件读取为 DataFrame(类似表格的数据结构)
  • 添加两列来源信息,方便后续追溯数据出处

5. 合并所有数据

merged_df = pd.concat(all_dataframes, ignore_index=True)

pd.concat() 是关键函数:

  • 将列表中的所有 DataFrame 纵向拼接(上下连接)
  • ignore_index=True 重置行索引,避免索引重复

6. 导出结果

merged_df.to_excel(output_file, index=False, engine='openpyxl')
  • index=False 不导出 pandas 自动生成的行号
  • 最终得到一个包含所有数据的汇总 Excel 文件

进阶技巧

技巧 1:指定读取的 Sheet 名称

如果 Excel 文件有多个 Sheet,可以指定读取特定 Sheet:

df = pd.read_excel(file_path, sheet_name="Sheet1", engine='openpyxl')

或读取所有 Sheet 并合并:

all_sheets = pd.read_excel(file_path, sheet_name=None, engine='openpyxl')for sheet_name, sheet_df in all_sheets.items():    sheet_df['来源Sheet'] = sheet_name    all_dataframes.append(sheet_df)

技巧 2:统一列名后再合并

如果不同文件的列名不完全一致,可以先做列名映射:

# 定义统一列名映射COLUMN_MAP = {'姓名''姓名','员工姓名''姓名','Name''姓名','部门''部门','所属部门''部门','金额''金额','金额(元)''金额',}# 读取后统一列名df = pd.read_excel(file_path)df.rename(columns=COLUMN_MAP, inplace=True)

技巧 3:添加进度条(大文件友好)

from tqdm import tqdmfor dirpath, dirnames, filenames in tqdm(os.walk(source_dir), desc="扫描文件夹"):for filename in filenames:# ... 处理逻辑

常见问题

Q1:报错 ModuleNotFoundError: No module named 'openpyxl'

原因:没有安装 openpyxl 库,pandas 读取 .xlsx 需要此依赖。

解决:运行 pip install openpyxl

Q2:合并后列的顺序乱了怎么办?

pd.concat() 会自动对齐列名,但列顺序可能不一致。可以手动指定列顺序:

desired_columns = ['姓名''部门''金额''日期''数据来源文件''数据来源路径']merged_df = merged_df[desired_columns]

Q3:某些 Excel 文件读取出来是空的?

可能原因:

  • 文件本身没有数据(只有表头)
  • 文件被加密
  • 文件格式不是真正的 Excel(如 .csv 改了后缀)

建议在读取后加判断:

if df.empty:print(f"警告: {filename} 为空,跳过")continue

Q4:如何合并 .csv 文件?

只需将读取方式改为 pd.read_csv()

if filename.endswith('.csv'):    df = pd.read_csv(file_path, encoding='utf-8-sig')

总结

步骤
核心函数
作用
遍历文件夹
os.walk()
递归扫描所有子目录
读取文件
pd.read_excel()
将 Excel 转为 DataFrame
合并数据
pd.concat()
纵向拼接多个 DataFrame
导出结果
to_excel()
保存为新的 Excel 文件

本节掌握了 Python 办公自动化中最常用的技能之一——多文件自动合并。无论是财务报表、销售数据还是调查问卷,只要格式一致,都可以用这套代码一键汇总。

下一节预告:02:精准拆分——按城市/部门将总表数据秒拆成独立文件,学完本节后你会知道如何反向操作,把一张大表按条件拆分成多个文件!