欢迎光临
我们一直在努力

Python办公自动化实战:用openpyxl十几行代码解放Excel批量汇总

摘要: 面对堆积如山的Excel文件,手动复制粘贴汇总数据不仅耗时费力,还极易出错。本文针对这一办公痛点,手把手教你利用Python的openpyxl库,通过十几行核心代码实现Excel数据的自动化批量汇总。你将掌握从环境搭建、文件遍历、数据精准提取到结果保存的完整流程,获得“Python办公自动化”、“Excel批量处理”的实战技能。阅读本文后,你将能立即将这套方法应用于日常的销售报表、财务数据、库存清单等汇总场景,彻底告别“复制粘贴地狱”,让工作效率提升十倍。

从“复制粘贴地狱”到“一键汇总”

想象一下这个场景:周五下午四点,老板突然走到你工位旁,甩过来一个文件夹,里面躺着一百个 Excel 文件。文件名分别是"1 月销售表.xlsx"、“2 月销售表.xlsx”……一直到"100 月销售表.xlsx"(夸张了点,但道理一样)。老板的要求很明确:“把这些表里的‘总销售额’这一列数据,全部汇总到一个新的 Excel 表里,下班前给我。”

如果是手工操作,你的流程大概是这样的:打开第一个表,找到“总销售额”列,复制;切换到汇总表,粘贴;切回第一个表,关闭;打开第二个表,重复上述动作……如此循环一百次。这不仅仅是枯燥的体力活,更是一场注意力的考验。只要手滑一次,复制错了行,或者粘贴错了位置,整个数据就全乱了。一下午的时间,就在机械的点击和切换中流逝,最后还得顶着黑眼圈担心数据有没有出错。

但对于掌握了 Python 办公自动化的人来说,这根本不算个事儿。你只需要写一段十几行的代码,保存,运行,然后就可以安心地去接杯咖啡。等你回来,屏幕上那个新的汇总表格已经整整齐齐地躺在文件夹里了。这不是魔法,这是 Python 赋予普通办公人员的“超能力”。今天我们就来拆解这个“魔法”,看看如何用极少的代码量,解决最让人头疼的批量报表问题。

手动 vs 自动化:效率对比

为了更直观地展示 Python 自动化相比传统手工操作的优势,我们通过以下表格进行多维度对比:

对比维度手动操作Python 自动化效率提升
耗时 处理 100 个文件,每个文件 50 行数据,平均每个文件操作(打开、定位、复制、粘贴、关闭)约需 30 秒,总计约 50 分钟。 编写脚本约 10 分钟,运行脚本(含数据读取、处理、写入)约 10 秒。 从小时级缩短至秒级,首次投入后复用几乎零耗时。
出错率 高。人工疲劳、注意力分散易导致复制错行、漏文件、粘贴错位,错误率随文件数量增加而显著上升。 极低。程序严格按逻辑执行,只要代码逻辑正确,结果 100% 准确,无疲劳导致的失误。 从人工不可控风险降至近乎零风险。
可重复性 差。每次任务都需从头开始重复机械劳动,过程无法复用,且难以保证每次操作完全一致。 强。脚本可保存、复用、修改,适应不同数据源,一键执行,结果稳定可靠。 从一次性劳动变为可复用的资产。
技能要求 低。仅需基本电脑操作(打开、复制、粘贴),但要求高度专注和耐心。 中。需掌握基础 Python 语法、openpyxl 库基本用法,但学习曲线平缓,本文即可入门。 从体力劳动升级为技能投资,一次学习,终身受益。
工作体验 枯燥、重复、易疲劳,成就感低,且面临 deadline 压力,容易焦虑。 创造性、有掌控感,将时间用于思考和优化,解放双手,提升职业价值和满足感。 从“操作工”转变为“流程设计师”。

工欲善其事:openpyxl 与环境准备

在开始编写代码之前,我们需要一把趁手的“兵器”。Python 本身虽然功能强大,但处理特定格式的文件(如 Excel)通常需要借助第三方库。对于 .xlsx 格式的 Excel 文件,业界公认最好用的库是 openpyxl。它不仅能读取数据,还能写入数据、调整样式,甚至处理公式,完全满足我们日常办公的需求。

安装过程非常简单,只要你电脑上已经安装了 Python,打开命令行工具(Windows 下是 CMD 或 PowerShell,Mac 下是 Terminal),输入以下命令并回车即可:

pip install openpyxl

如果你的网络环境导致下载缓慢,可以使用国内镜像源加速,例如:

pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完成后,你可以在 Python 环境中尝试导入一下,如果没有报错,就说明环境已经准备就绪:

import openpyxl
print(openpyxl.__version__)

除了 openpyxl,我们还需要用到 Python 内置的 os 模块。这个模块不需要安装,它是 Python 标准库的一部分,专门用来跟操作系统打交道,比如获取文件夹里的文件列表、拼接文件路径等。有了这两个工具,我们的自动化脚本就可以动工了。

核心实战:十几行代码搞定百表汇总

接下来是重头戏。我们将模拟一个真实的办公场景:假设有一个名为 sales_data 的文件夹,里面存放着 100 个结构完全相同的销售报表。每个报表的第一行是标题,第二行开始是数据,我们需要提取每个文件中 C 列(即第 3 列)从第 2 行开始的所有销售额数据,并将它们合并到一个名为 summary.xlsx 的新文件中。

第一步:让程序“看见”所有文件

首先,我们需要告诉 Python 去哪个文件夹找文件,并把所有符合条件的 Excel 文件名都列出来。这就用到了 os 模块。

import os

### 完整脚本一览

为了方便读者直接使用,我们将前面分步讲解的代码整合成一个完整的、可直接复制运行的 Python 脚本。脚本包含了必要的导入、路径设置、主逻辑、异常处理以及详细的注释。

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Excel 批量数据汇总脚本
功能:遍历指定文件夹下所有 .xlsx 文件,提取指定列的数据,合并到一个新的 Excel 文件中。
作者:CSDN 博客
"""

import os
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font

def main():
# ========== 1. 配置部分:请根据你的实际情况修改 ==========
# 待处理 Excel 文件所在的文件夹路径
folder_path = r'D:\\Work\\sales_data' # 请修改为你的实际路径

# 输出汇总文件的名称
output_filename = 'summary_result.xlsx'

# 数据提取规则(根据你的 Excel 表格结构调整)
# 假设:数据从第 2 行开始(第 1 行为标题行)
data_start_row = 2
# 要提取的列号(Excel 列号,A=1, B=2, C=3, D=4, …)
date_column = 2 # B 列:日期
product_column = 3 # C 列:产品名称
sales_column = 4 # D 列:销售额

# ========== 2. 主逻辑开始 ==========

# 获取文件夹下所有 .xlsx 文件
try:
file_list = os.listdir(folder_path)
excel_files = [f for f in file_list if f.endswith('.xlsx')]
print(f'✅ 共发现 {len(excel_files)} 个 Excel 文件待处理')
except FileNotFoundError:
print(f'❌ 错误:找不到文件夹 "{folder_path}",请检查路径是否正确。')
return
except PermissionError:
print(f'❌ 错误:没有权限访问文件夹 "{folder_path}"。')
return

if len(excel_files) == 0:
print('⚠️ 目标文件夹中没有找到 .xlsx 文件,请检查路径和文件后缀。')
return

# 创建汇总工作簿并设置表头
wb_summary = Workbook()
ws_summary = wb_summary.active
ws_summary.title = '汇总数据'
ws_summary.append(['来源文件', '日期', '产品名称', '销售额'])

# 设置表头为粗体(可选,让表头更醒目)
bold_font = Font(bold=True)
for cell in ws_summary[1]:
cell.font = bold_font

processed_count = 0
error_files = []

# 遍历每一个 Excel 文件
for filename in excel_files:
file_full_path = os.path.join(folder_path, filename)
print(f'正在处理: {filename}')

try:
# 加载工作簿,data_only=True 确保读取计算后的值,而不是公式本身
wb = load_workbook(file_full_path, data_only=True)
ws = wb.active

# 获取实际数据行数
max_row = ws.max_row

# 如果数据起始行大于最大行,说明可能是空表或只有标题
if data_start_row > max_row:
print(f' ⚠️ 文件 {filename} 可能为空或格式不符,跳过。')
wb.close()
continue

# 从指定起始行开始读取数据
for row in range(data_start_row, max_row + 1):
date_val = ws.cell(row=row, column=date_column).value
product_val = ws.cell(row=row, column=product_column).value
sales_val = ws.cell(row=row, column=sales_column).value

# 将读取到的数据追加到汇总表
ws_summary.append([filename, date_val, product_val, sales_val])

wb.close() # 关闭文件,释放资源
processed_count += 1

except Exception as e:
error_msg = f' ❌ 处理文件 {filename} 时出错: {e}'
print(error_msg)
error_files.append((filename, str(e)))
continue

# 保存汇总结果
output_path = os.path.join(folder_path, output_filename)
try:
wb_summary.save(output_path)
print(f'\\n🎉 汇总完成!')
print(f' 成功处理文件数: {processed_count}/{len(excel_files)}')
print(f' 汇总文件已保存至: {output_path}')

if error_files:
print(f'\\n⚠️ 以下文件处理失败:')
for fname, err in error_files:
print(f' – {fname}: {err}')
except PermissionError:
print(f'❌ 错误:无法保存文件,请检查 "{output_path}" 是否被其他程序(如 Excel)打开。')
except Exception as e:
print(f'❌ 保存文件时发生未知错误: {e}')

if __name__ == '__main__':
main()

如何使用这个脚本

运行效果展示

为了让你更直观地感受脚本的执行过程和最终成果,这里模拟了一个典型的运行场景。假设 D:\\Work\\sales_data 文件夹中有 3 个销售数据文件:1月销售表.xlsx、2月销售表.xlsx、3月销售表.xlsx,每个文件包含若干行销售记录。

控制台输出(模拟截图)

当你运行脚本时,控制台会实时显示处理进度和结果,类似下面这样:

D:\\Work> python excel_summary.py
✅ 共发现 3 个 Excel 文件待处理
正在处理: 1月销售表.xlsx
正在处理: 2月销售表.xlsx
正在处理: 3月销售表.xlsx

🎉 汇总完成!
成功处理文件数: 3/3
汇总文件已保存至: D:\\Work\\sales_data\\summary_result.xlsx

如果某个文件格式有问题或读取失败,脚本会给出明确的错误提示,例如:

✅ 共发现 3 个 Excel 文件待处理
正在处理: 1月销售表.xlsx
正在处理: 2月销售表.xlsx
⚠️ 文件 2月销售表.xlsx 可能为空或格式不符,跳过。
正在处理: 3月销售表.xlsx

🎉 汇总完成!
成功处理文件数: 2/3
汇总文件已保存至: D:\\Work\\sales_data\\summary_result.xlsx

⚠️ 以下文件处理失败:
2月销售表.xlsx: [Errno 2] No such file or directory: 'D:\\\\Work\\\\sales_data\\\\2月销售表.xlsx'

汇总结果预览(模拟表格)

脚本运行成功后,生成的 summary_result.xlsx 文件内容大致如下(前10行示例):

来源文件日期产品名称销售额
1月销售表.xlsx 2025-01-05 笔记本电脑 8999.00
1月销售表.xlsx 2025-01-12 无线鼠标 129.00
1月销售表.xlsx 2025-01-18 机械键盘 599.00
1月销售表.xlsx 2025-01-25 显示器 2499.00
2月销售表.xlsx 2025-02-03 笔记本电脑 8999.00
2月销售表.xlsx 2025-02-10 USB-C 扩展坞 299.00
2月销售表.xlsx 2025-02-17 固态硬盘 699.00
3月销售表.xlsx 2025-03-08 笔记本电脑 8999.00
3月销售表.xlsx 2025-03-15 蓝牙耳机 399.00
3月销售表.xlsx 2025-03-22 平板电脑 3299.00

说明:

  • 来源文件列:清晰记录了每条数据来自哪个原始文件,便于追溯。
  • 日期、产品名称、销售额列:从每个源文件的指定列精准提取而来。
  • 数据顺序:按照文件遍历顺序(通常是文件名排序)和源文件内的行顺序排列。
  • 格式保留:数值(如销售额)保持了原有的数字格式,日期也保持了日期类型。

打开这个汇总文件,你会看到所有月份的数据已经整齐地合并在一起,无需任何手动复制粘贴。这正是自动化脚本的魅力所在——将繁琐、易错的手工操作,转化为一键执行的可靠流程。

  • 修改路径:将脚本第 15 行的 folder_path 变量值改为你存放 Excel 文件的文件夹实际路径。
  • 调整列号:根据你的 Excel 表格结构,修改第 22-24 行的 date_column、product_column、sales_column 变量值(例如,如果日期在 A 列,则改为 1)。
  • 运行脚本:将脚本保存为 .py 文件(如 excel_summary.py),在命令行中执行 python excel_summary.py。
  • 脚本已包含基本的异常处理(如文件夹不存在、文件被占用、权限错误等),并会在控制台输出详细的处理进度和结果。你可以直接复制上面的代码,根据注释修改几个关键参数,即可应用于你自己的数据汇总任务。

    设定文件夹路径,请根据实际情况修改

    folder_path = r’D:\\Work\\sales_data’

    获取文件夹下所有文件名

    file_list = os.listdir(folder_path)

    筛选出以 .xlsx 结尾的文件

    excel_files = [f for f in file_list if f.endswith(‘.xlsx’)]

    print(f’共发现 {len(excel_files)} 个 Excel 文件待处理’)

    这里有个小细节需要注意:在 Windows 系统中,文件路径通常包含反斜杠 `\\`,而在 Python 字符串中反斜杠是转义字符。为了避免路径解析错误,建议在路径字符串前加一个 `r`,表示“原始字符串”,这样 `\\` 就会被当作普通字符处理。`os.listdir()` 函数会返回指定文件夹下所有文件和子文件夹的名字列表,我们通过列表推导式,只保留那些后缀名是 `.xlsx` 的文件,过滤掉可能存在的临时文件或无关文档。

    ### 第二步:创建汇总表并定义表头

    在开始读取数据之前,我们先要把“容器”准备好。我们需要创建一个新的 Excel 工作簿,并在第一行写入表头,方便后续查看数据来源。

    ```python
    from openpyxl import Workbook

    # 创建一个新的工作簿
    wb_summary = Workbook()
    ws_summary = wb_summary.active

    # 写入表头
    ws_summary.append(['来源文件', '日期', '产品名称', '销售额'])

    # 也可以设置一下表头的样式,让它更显眼(可选)
    from openpyxl.styles import Font
    bold_font = Font(bold=True)
    for cell in ws_summary[1]:
    cell.font = bold_font

    Workbook() 用于创建一个新的空白 Excel 文件对象,.active 属性获取当前激活的工作表(通常是 Sheet1)。append() 方法非常实用,它可以一次性将列表中的数据作为一行写入表格。这里我们定义了四个字段:来源文件(记录数据来自哪个表)、日期、产品名称和销售额。虽然原始表中可能有更多列,但我们只关心这几项核心数据,这也体现了自动化的灵活性——只取所需。

    第三步:循环遍历,精准提取数据

    这是整个脚本的核心逻辑。我们需要遍历刚才获取的文件列表,逐个打开文件,定位到特定的单元格,读取数据,然后写入汇总表。

    from openpyxl import load_workbook

    # 遍历每一个 Excel 文件
    for filename in excel_files:
    # 拼接完整的文件路径
    file_full_path = os.path.join(folder_path, filename)

    # 加载工作簿,data_only=True 确保读取的是计算后的值而不是公式
    wb = load_workbook(file_full_path, data_only=True)
    ws = wb.active

    # 假设数据从第 2 行开始,第 1 行是标题
    # 获取最大行数,避免读取空行
    max_row = ws.max_row

    # 从第 2 行遍历到最后一行
    for row in range(2, max_row + 1):
    # 读取指定列的数据
    # 假设:B 列是日期,C 列是产品名称,D 列是销售额
    date_val = ws.cell(row=row, column=2).value
    product_val = ws.cell(row=row, column=3).value
    sales_val = ws.cell(row=row, column=4).value

    # 将读取到的数据连同文件名一起追加到汇总表
    ws_summary.append([filename, date_val, product_val, sales_val])

    # 关闭当前文件,释放资源(虽然 Python 垃圾回收会处理,但显式关闭是好习惯)
    wb.close()

    print('数据提取完成!')

    这段代码逻辑非常清晰。load_workbook() 负责打开现有的 Excel 文件,参数 data_only=True 非常重要。在很多销售表中,销售额可能是通过公式计算出来的(例如 单价 * 数量)。如果不加这个参数,openpyxl 读取到的将是公式字符串(如 =B2*C2),而不是计算后的数值。加上它,就能直接拿到最终结果。

    在读取具体单元格时,我们使用了 ws.cell(row=row, column=col) 的方法。相比于 ws['A1'] 这种写法,cell() 方法在循环中更加灵活,因为行列号可以是变量。我们根据实际报表的列分布,分别读取了 B、C、D 列的数据。每读取一行,就立即调用 ws_summary.append() 将其写入汇总表。这种“读一行、写一行”的策略,内存占用极低,即使处理成千上万个文件也不会卡顿。

    第四步:保存成果,见证奇迹

    当循环结束时,所有的数据都已经汇聚到了 wb_summary 这个对象中。最后一步,就是把它保存到硬盘上。

    # 保存汇总表
    output_path = os.path.join(folder_path, 'summary_result.xlsx')
    wb_summary.save(output_path)

    print(f'汇总完成!文件已保存至:{output_path}')

    save() 方法需要指定完整的保存路径。运行完这段代码,你去文件夹里刷新一下,会发现多出了一个 summary_result.xlsx 文件。打开它,你会发现上百个文件的数据已经井然有序地排列在一起,连格式都保持得完好无损。

    把上面几段代码整合起来,去掉注释和打印语句,核心逻辑其实不到二十行。这就是 Python 的魅力:用极简的语法,解决极繁琐的问题。

    避坑指南与进阶技巧

    虽然代码很短,但在实际落地过程中,新手往往会遇到一些“小石头”。提前了解这些坑,能让你的自动化之路走得更顺畅。

    1. 文件路径的“玄学”
    很多初学者在运行代码时,会报 FileNotFoundError。这通常是因为路径写错了。在 Windows 上,路径分隔符是反斜杠 \\,但在 Python 字符串里,\\n 代表换行,\\t 代表制表符。如果你写 D:\\new_folder\\data.xlsx,Python 可能会把 \\n 解析成换行符,导致路径失效。
    解决方案:始终在路径字符串前加 r,如 r'D:\\new_folder\\data.xlsx';或者使用正斜杠 /,Windows 也兼容,如 'D:/new_folder/data.xlsx';最稳妥的方式是使用 os.path.join() 函数拼接路径,它会自动识别操作系统并使用正确的分隔符。

    2. 表格格式不统一
    我们的代码是基于“所有表格格式完全一致”这个前提写的。如果其中某个表的列顺序变了,或者标题行多了几行,代码就会读取到错误的数据,甚至报错。
    解决方案:在正式运行批量处理前,先随机抽查几个文件,确认结构一致。如果存在细微差异,可以在代码中加入判断逻辑。例如,先读取第一行,判断是否包含“销售额”这个关键词,以此动态确定列的位置,而不是硬编码 column=4。

    3. 文件被占用
    如果你试图处理的 Excel 文件正被其他人打开,或者被你自己手动打开了,load_workbook 可能会失败,或者保存时出现权限错误。
    解决方案:运行脚本前,确保所有待处理的 Excel 文件都已关闭。如果是团队协作环境,最好先将文件复制到本地临时文件夹进行处理,处理完再上传。

    4. 大数据量的性能优化
    如果文件数量达到几千个,或者单个文件有几万行数据,逐行 append 可能会稍慢。
    解决方案:可以先将所有数据读取到一个大的 Python 列表中,最后一次性通过 ws_summary.append() 分批写入,或者利用 pandas 库进行更高效的数据框操作(当然,对于几十兆以内的常规办公数据,openpyxl 的速度已经完全足够)。

    性能与边界条件考量

    前面的脚本已经能很好地处理日常办公场景(如几十个文件,每个文件几百行数据)。但当你面对更大规模的数据时,了解脚本的性能边界并掌握优化方法,能让你更从容地应对挑战。本节将详细分析当前 openpyxl 方案在不同数据量下的表现,并提供针对超大规模文件的优化建议。

    不同数据量下的性能预期

    为了让你对脚本的处理能力有直观感受,我们基于典型办公电脑配置(Intel i5 处理器,8GB 内存,SSD 硬盘)进行估算:

    数据规模预估耗时内存占用说明与建议
    小规模(10个文件 × 100行) 1-3 秒 约 50-100 MB 瞬间完成,体验流畅。这是最常见的办公场景。
    中规模(100个文件 × 1000行) 10-30 秒 约 200-500 MB 可接受范围。脚本会逐个文件打开、读取、关闭,内存会随着处理文件数增加而波动,但总体可控。
    较大规模(500个文件 × 5000行) 2-5 分钟 可能达到 1-2 GB 开始感受到等待时间。内存占用主要来自 openpyxl 加载工作簿对象和汇总表的数据累积。建议分批处理或考虑优化。
    超大规模(单个文件 10万行) 30秒 – 2分钟 约 500 MB – 1 GB openpyxl 读取大文件时,会将整个工作表加载到内存。虽然能处理,但速度和内存消耗明显增加。
    极限挑战(单个文件 50万行以上) 可能超过 5 分钟,甚至因内存不足而崩溃 可能超过 2-3 GB openpyxl 的默认读取方式可能遇到性能瓶颈或内存压力。需要采用优化策略。

    注意:以上时间为粗略估算,实际耗时受电脑性能、硬盘速度、文件复杂度(是否包含公式、样式)等因素影响。

    为什么 openpyxl 在处理超大文件时会变慢?

    openpyxl 默认使用“读取所有单元格到内存”的模式(read_only=False)。这意味着当你打开一个包含 50 万行的工作表时,它会尝试在内存中构建一个包含所有单元格对象的树形结构。这个过程会消耗大量内存和时间,尤其是当文件包含复杂样式或公式时。

    优化建议与替代方案

    如果你的数据量确实达到了“超大规模”级别,可以尝试以下策略:

    1. 启用 read_only 模式(针对纯数据读取)

    如果你的源文件只包含数据,不需要修改样式或读取公式,可以在 load_workbook 时启用 read_only=True 模式。此模式下,openpyxl 不会将整个文件加载到内存,而是以流式方式读取,能显著降低内存占用并提升大文件的读取速度。

    修改脚本中的读取部分:

    # 原代码:
    wb = load_workbook(file_full_path, data_only=True)

    # 优化为:
    wb = load_workbook(file_full_path, data_only=True, read_only=True)
    ws = wb.active

    # 注意:在 read_only 模式下,某些操作(如 ws.max_row)可能不准确,
    # 建议通过迭代行的方式读取,直到遇到空行。
    for row in ws.iter_rows(min_row=data_start_row, values_only=True):
    # row 是一个元组,例如 (日期, 产品名称, 销售额)
    date_val = row[date_column 1] # 注意列索引调整
    product_val = row[product_column 1]
    sales_val = row[sales_column 1]
    ws_summary.append([filename, date_val, product_val, sales_val])
    # 无需调用 wb.close(),read_only 模式会自动管理资源。

    适用场景:源文件数据量极大(>10万行),且你只需要读取数据,不关心单元格格式。

    2. 分批处理与写入

    即使使用 read_only 模式,如果最终汇总表行数过多(例如超过 100 万行),ws_summary.append() 逐行写入的方式也会变慢。此时可以改为先将数据累积到 Python 列表中,然后分批写入。

    # 在循环外定义一个列表
    batch_data = []
    BATCH_SIZE = 10000 # 每累积10000行写入一次

    for filename in excel_files:
    # … 读取数据的逻辑 …
    for row in range(data_start_row, max_row + 1):
    # … 获取 date_val, product_val, sales_val …
    batch_data.append([filename, date_val, product_val, sales_val])

    # 达到批次大小时,批量写入并清空列表
    if len(batch_data) >= BATCH_SIZE:
    for data_row in batch_data:
    ws_summary.append(data_row)
    batch_data = [] # 清空列表
    wb_summary.save(output_path) # 可选:阶段性保存,防止程序中断丢失全部进度

    # 循环结束后,写入剩余数据
    if batch_data:
    for data_row in batch_data:
    ws_summary.append(data_row)

    适用场景:汇总数据量极大,需要平衡内存和写入性能。

    3. 终极方案:切换到 pandas(并启用分块读取)

    对于单个文件超过 50 万行或总数据量超过百万行的场景,pandas 通常是更好的选择,尤其是其 read_excel 函数支持 chunksize 参数,可以分块读取数据,避免一次性加载到内存。

    import pandas as pd
    import os

    folder_path = r'D:\\Work\\sales_data'
    output_path = os.path.join(folder_path, 'summary_large.xlsx')

    all_chunks = []

    for filename in os.listdir(folder_path):
    if filename.endswith('.xlsx'):
    file_path = os.path.join(folder_path, filename)
    # 分块读取,每块 10000 行
    chunk_reader = pd.read_excel(file_path,
    skiprows=1,
    usecols='B:D',
    header=None,
    names=['日期', '产品名称', '销售额'],
    chunksize=10000)
    for chunk in chunk_reader:
    chunk['来源文件'] = filename
    all_chunks.append(chunk)

    if all_chunks:
    # 将所有块合并
    summary_df = pd.concat(all_chunks, ignore_index=True)
    summary_df = summary_df[['来源文件', '日期', '产品名称', '销售额']]
    # 保存时也可以分块写入,但 to_excel 不支持 chunksize,对于极大结果可考虑 to_csv 或 to_parquet
    summary_df.to_excel(output_path, index=False)
    print(f'处理完成,共 {len(summary_df)} 行数据。')

    优势:

    • 内存友好:chunksize 确保即使处理 1GB 的 Excel 文件,内存占用也基本恒定。
    • 性能卓越:pandas 的底层是 C/Cython,数据操作速度远超纯 Python 循环。
    • 功能集成:合并后可直接进行数据清洗、分析、可视化。

    代价:需要额外安装 pandas 库,且会丢失源文件的单元格样式。

    总结与选型建议

    场景推荐方案关键理由
    日常办公,文件 < 100个,单文件 < 1万行 本文的 openpyxl 基础脚本 简单直接,无需额外依赖,可保留样式。
    数据量中等,单文件 1万 – 10万行 openpyxl + read_only=True 模式 显著降低内存,提升读取速度。
    数据量巨大,单文件 > 10万行,或需要复杂数据处理 pandas(基础版或分块读取版) 处理速度最快,内存可控,且为后续分析铺路。
    需要保留原始文件格式、样式、公式 openpyxl(必要时结合 read_only 和分批写入) pandas 会丢失格式,openpyxl 是唯一选择。

    核心原则:没有最好的方案,只有最适合当前场景的方案。建议你先用基础脚本处理中小规模数据,当遇到性能瓶颈时,再根据上述建议进行针对性优化。技术的价值在于解决问题,而不是追求极致的复杂度。

    进阶方案:pandas 实现

    在前面的教程中,我们使用 openpyxl 库实现了 Excel 数据的批量汇总。openpyxl 的优势在于对 Excel 文件格式的精细控制,比如单元格样式、公式等。然而,如果你处理的数据量更大(比如数万行),或者需要进行更复杂的数据清洗、转换和分析,那么 pandas 库会是更高效、更简洁的选择。

    pandas 的优势

  • 代码更简洁:pandas 提供了高级的 DataFrame 数据结构,可以用一行代码完成数据的读取、筛选、合并等操作,大大减少了循环和底层单元格操作的代码量。
  • 性能更高:对于大数据量的读取和写入,pandas 底层使用 C 或 Cython 优化,速度通常比逐行操作的 openpyxl 更快。
  • 功能更强大:内置了丰富的数据处理函数(如分组、聚合、透视表、数据清洗等),方便你在汇总前后进行复杂的数据处理。
  • 下面是一个与文中 openpyxl 脚本功能等效的 pandas 实现示例,核心逻辑仅需约 10 行代码:

    import pandas as pd
    import os

    # 配置路径和列名
    folder_path = r'D:\\Work\\sales_data' # 修改为你的文件夹路径
    output_path = os.path.join(folder_path, 'summary_pandas.xlsx')

    # 用于存储每个文件数据的列表
    all_data_frames = []

    # 遍历文件夹下所有 .xlsx 文件
    for filename in os.listdir(folder_path):
    if filename.endswith('.xlsx'):
    file_path = os.path.join(folder_path, filename)
    # 使用 pandas 读取 Excel 文件,指定数据起始行(skiprows=1 跳过标题行)
    # usecols 参数可以指定读取哪些列,例如 'B:D' 表示读取 B、C、D 列
    df = pd.read_excel(file_path, skiprows=1, usecols='B:D', header=None, names=['日期', '产品名称', '销售额'])
    # 添加一列记录来源文件名
    df['来源文件'] = filename
    all_data_frames.append(df)

    # 使用 pd.concat 将所有 DataFrame 合并成一个
    if all_data_frames:
    summary_df = pd.concat(all_data_frames, ignore_index=True)
    # 调整列顺序,将“来源文件”放到第一列
    summary_df = summary_df[['来源文件', '日期', '产品名称', '销售额']]
    # 保存到新的 Excel 文件
    summary_df.to_excel(output_path, index=False)
    print(f'汇总完成!文件已保存至:{output_path}')
    else:
    print('未找到任何 .xlsx 文件。')

    代码解读:

    • pd.read_excel():一行代码即可读取整个 Excel 文件,并返回一个 DataFrame。参数 skiprows=1 表示跳过第一行(标题行),usecols='B:D' 表示只读取 B、C、D 三列,header=None 表示文件没有表头(因为我们跳过了标题行),names 参数为读取的列指定新的列名。
    • pd.concat():将多个 DataFrame 列表 (all_data_frames) 合并成一个大的 DataFrame,ignore_index=True 会重置索引。
    • df['来源文件'] = filename:为每个文件的 DataFrame 添加一个新列,记录文件名。
    • to_excel():将最终的汇总 DataFrame 保存为 Excel 文件,index=False 表示不保存 DataFrame 的索引列。

    两种方案如何选择?

    特性openpyxl 方案pandas 方案
    代码复杂度 较低,但需要手动循环遍历单元格。 极低,高级 API 让代码非常简洁。
    性能 适合中小型数据(单个文件几万行以内)。 更适合大数据量,批量读取和合并效率更高。
    功能侧重点 精细控制 Excel 文件(样式、公式、图表等)。 专注于数据处理和分析(清洗、转换、统计、可视化)。
    学习成本 较低,概念直观(工作簿、工作表、单元格)。 中等,需要理解 DataFrame 和 Series 的概念。
    适用场景 1. 需要保留或设置单元格格式、颜色、边框等。2. 需要读取或写入公式。3. 文件结构复杂,需要操作多个工作表或特定区域。 1. 数据量较大,追求处理速度。2. 汇总后需要进行数据清洗、分析或生成统计图表。3. 只需要关注数据本身,不关心文件样式。

    简单来说:如果你的核心需求是快速、准确地把数据从一堆表格里捞出来并合并,且后续可能要做数据分析,那么 pandas 是更优解。如果你需要对生成汇总表的样式进行精细调整(如加粗表头、设置单元格颜色),或者源文件中包含需要读取的公式,那么 openpyxl 提供了更底层的控制能力。

    作为办公自动化新手,你可以先掌握 openpyxl 的基础操作,当遇到更复杂的数据处理需求时,再学习 pandas,你的工具箱将更加全面。

    常见错误与排查

    即使有了完整的脚本,新手在第一次运行时仍可能遇到一些报错。别担心,这是学习过程中的正常现象。本节将针对文中脚本,列举三个最常见的错误,分析原因并提供详细的解决步骤,帮你快速定位问题。

    错误 1:ModuleNotFoundError: No module named ‘openpyxl’

    错误现象:
    运行脚本时,命令行或终端中报错,提示类似以下信息:

    Traceback (most recent call last):
    File "excel_summary.py", line 10, in <module>
    from openpyxl import Workbook, load_workbook
    ModuleNotFoundError: No module named 'openpyxl'

    原因分析:
    这是最典型的环境问题。Python 解释器找不到 openpyxl 这个库,因为它还没有被安装到你的 Python 环境中。可能的原因包括:

  • 你还没有安装 openpyxl。
  • 你安装了多个 Python 版本(例如系统自带一个,Anaconda 一个),而运行脚本时使用的 Python 解释器和你安装库时使用的不是同一个。
  • 安装过程因网络问题失败。
  • 解决步骤:

  • 确认安装:打开命令行(CMD、PowerShell 或 Terminal),输入以下命令并回车:pip install openpyxl

    如果看到 Successfully installed openpyxl-x.x.x 的提示,说明安装成功。

  • 使用镜像加速:如果下载速度慢或超时,可以使用国内的镜像源,例如清华源:pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 检查 Python 版本:如果你有多个 Python 环境,请确保你用来运行脚本的 Python 和用来安装库的 pip 是配对的。可以分别运行以下命令查看:python –version
    pip –version

    如果 pip 显示的 Python 版本与 python –version 不一致,可能需要使用 python -m pip install openpyxl 来确保为当前 Python 解释器安装。

  • 验证安装:安装后,可以打开 Python 交互环境测试一下:python
    >>> import openpyxl
    >>> print(openpyxl.__version__)

    如果没有报错并输出版本号,说明环境已就绪。

  • 错误 2:PermissionError: [Errno 13] Permission denied

    错误现象:
    脚本运行过程中报错,提示权限被拒绝。错误可能出现在两个地方:

  • 读取文件夹时:PermissionError: [Errno 13] Permission denied: 'D:\\\\Work\\\\sales_data'
  • 保存汇总文件时:PermissionError: [Errno 13] Permission denied: 'D:\\\\Work\\\\sales_data\\\\summary_result.xlsx'
  • 原因分析:
    这是文件或文件夹被占用或权限不足导致的。

    • 读取失败:可能因为目标文件夹被其他程序(如资源管理器、杀毒软件)锁定,或者当前用户没有该文件夹的读取权限。
    • 保存失败:最常见的原因是汇总文件(summary_result.xlsx)正被 Excel 或其他程序打开。脚本无法覆盖一个正在被使用的文件。

    解决步骤:

  • 关闭所有相关文件:这是首要步骤。请确保:
    • 所有待处理的 Excel 源文件都已关闭。
    • 之前可能生成的 summary_result.xlsx 文件也已关闭(如果存在)。
  • 检查文件路径权限:右键点击脚本中配置的 folder_path 文件夹(如 D:\\Work\\sales_data),选择“属性” -> “安全”,确保你的用户账户有“读取”和“写入”权限。
  • 以管理员身份运行(仅限 Windows,且仅在权限问题持续时尝试):右键点击你的命令行终端(CMD 或 PowerShell),选择“以管理员身份运行”,然后再次执行脚本。
  • 修改输出文件名:如果怀疑是汇总文件被占用,可以临时修改脚本中的 output_filename 变量,换一个全新的名字(如 summary_result_v2.xlsx)试试。
  • 复制文件到本地处理:如果源文件在共享网络驱动器或受限制的目录,可以先将它们复制到本地一个你有完全控制权的文件夹(如桌面),修改脚本路径后运行。
  • 错误 3:汇总表数据错乱或为空

    错误现象:
    脚本成功运行,没有报错,也生成了汇总文件。但打开汇总表后发现:

    • 数据全是 None 或空值。
    • 数据错位(例如日期跑到了产品名称列)。
    • 汇总表只有表头,没有数据。

    原因分析:
    这几乎总是因为脚本中的列号配置(date_column, product_column, sales_column)或数据起始行(data_start_row)与你的实际 Excel 表格结构不匹配。

    • 列号错误:Excel 列号从 1 开始(A=1, B=2, C=3…)。如果你的数据中“日期”在 A 列,但脚本里 date_column = 2(B列),读到的就是 B 列的内容,可能是空的或错误数据。
    • 起始行错误:如果表格的标题行不止一行(例如第1行是大标题,第2行才是列名,数据从第3行开始),而脚本设置 data_start_row = 2,就会漏掉第2行的数据或读取到标题。

    解决步骤:

  • 打开一个待处理的源文件,仔细查看数据结构。
  • 确定数据起始行:找到真正的数据是从第几行开始的(即标题行之后的第一行数据)。将这个行号赋值给脚本中的 data_start_row 变量。
  • 确定列号:
    • 数一下“日期”在第几列。A列是1,B列是2,以此类推。
    • 将正确的数字赋值给 date_column。
    • 同理,确定“产品名称”和“销售额”所在的列号,修改 product_column 和 sales_column。
  • 使用一个小样本测试:修改脚本,只处理1-2个文件,或者临时将 excel_files 列表改为只包含一个文件名(如 excel_files = ['测试文件.xlsx']),快速运行验证数据是否正确提取。
  • 打印调试:在读取数据的循环内,临时添加 print 语句,查看读取到的值,这是最直接的调试方法:for row in range(data_start_row, max_row + 1):
    date_val = ws.cell(row=row, column=date_column).value
    product_val = ws.cell(row=row, column=product_column).value
    sales_val = ws.cell(row=row, column=sales_column).value
    # 临时添加打印,运行后观察控制台输出
    print(f"行{row}: 日期={date_val}, 产品={product_val}, 销售额={sales_val}")
    ws_summary.append([filename, date_val, product_val, sales_val])

  • 记住,遇到报错不要慌,仔细阅读错误信息,它通常会告诉你问题出在哪里。按照上述步骤逐一排查,你很快就能让脚本顺利运行起来。

    让效率成为习惯

    当你第一次运行这段代码,看着进度条飞速走完,原本需要一下午才能搞定的工作瞬间完成时,那种成就感是无与伦比的。但这不仅仅是一次任务的完成,更是一种思维方式的转变。

    以前面对重复性工作,我们习惯性地忍受,觉得“这就是工作的一部分”。但现在,你有了另一种选择:停下来,花十分钟思考一下,这个流程能不能自动化?能不能写几行代码让它自己跑?

    Python 办公自动化并不是程序员的专利,它是每一个希望从机械劳动中解放出来的职场人的利器。你不需要成为算法专家,也不需要精通数据结构,只要掌握像 openpyxl 这样实用的库,理解基本的循环和逻辑判断,就能构建出属于自己的效率工具。

    今天的例子只是冰山一角。同样的逻辑,你可以用来批量重命名文件、自动发送邮件、从 Word 中提取表格、甚至生成 PPT 报告。关键在于迈出第一步。不妨现在就打开你的电脑,找一个让你头疼的重复性任务,试着用 Python 去解决它。哪怕最初代码写得不够优雅,哪怕需要不断调试报错,这个过程本身就是一种巨大的提升。

    当别人还在加班手动复制粘贴时,你已经喝完咖啡准备下班了。这,就是技术带给普通人的公平与红利。

    赞(0)
    未经允许不得转载:171主机测评 » Python办公自动化实战:用openpyxl十几行代码解放Excel批量汇总
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址