怎么用Python实现Excel自动化办公?实战案例教程

何川
何川
发布时间:2026-09-17 | 3人浏览过
原创

用Python实现Excel自动化,核心并不是“用代码重新做一遍Excel”,而是把那些需要重复打开文件、复制数据、填写公式、汇总结果和设置格式的操作交给程序。对于普通的 .xlsx 文件,可以使用 openpyxl 直接读取和修改工作簿;遇到数据量较大的清洗、筛选和统计任务,再配合 pandas 会更方便。

下面不只演示几个零散函数,而是从一个实际办公场景出发:读取销售明细表,自动计算销售额、汇总各部门数据、生成新的统计工作表并设置基础格式。掌握这个流程之后,日报、月报、库存表、财务汇总表等任务都可以采用类似的方法处理。

一、先弄清楚Python自动化Excel的处理流程

假设每天都会收到一份名为 sales.xlsx 的销售明细,其中包含日期、部门、商品、单价和数量。人工处理时,通常要增加销售额列,再按照部门汇总,最后整理成一份适合查看的报表。

Python可以把整个过程固定下来:

SVG 配图 1
图1:一个典型的Python Excel自动化任务,从原始数据一直处理到最终报表。

这里有一个很重要的思路:尽量让原始数据保持规则,例如第一行固定是字段名称,每一行表示一条记录,不要大量使用合并单元格。数据结构越稳定,自动化程序越容易长期复用。

二、准备Python环境和Excel示例文件

下面主要使用 openpyxl。它适合直接读取、创建和修改 .xlsx 工作簿,而且可以控制单元格内容、公式、颜色、字体、边框、列宽等。

在终端、PowerShell或命令提示符中安装:

python -m pip install openpyxl

如果后面还需要进行更复杂的数据筛选和统计,可以一起安装 pandas:

python -m pip install pandas openpyxl

本例假设当前目录有一个 sales.xlsx,其中工作表名称为“销售明细”,数据结构如下:

日期 部门 商品 单价 数量
2026-09-01 华东 产品A 120 5
2026-09-01 华南 产品B 80 12
2026-09-02 华东 产品C 150 3

程序文件可以命名为 excel_report.py,目录结构保持简单:

excel_demo/
├── sales.xlsx
└── excel_report.py
注意:不要把脚本文件命名成 openpyxl.py 或 pandas.py,否则导入对应库时可能发生名称冲突。

三、第一步:用Python读取Excel工作簿

先完成最基础的工作:打开文件、选择工作表,并确认程序确实读取到了数据。

from openpyxl import load_workbook

file_path = "sales.xlsx"

wb = load_workbook(file_path)
ws = wb["销售明细"]

print("工作表:", ws.title)
print("数据行数:", ws.max_row)
print("数据列数:", ws.max_column)

for row in ws.iter_rows(min_row=2, values_only=True):
    print(row)

load_workbook() 会加载现有工作簿,wb["销售明细"] 用于选择指定工作表。由于第一行是表头,所以遍历数据时从 min_row=2 开始。

按照前面的示例文件,可能看到类似结果:

示例输出:
工作表: 销售明细
数据行数: 4
数据列数: 5
(datetime.datetime(2026, 9, 1, 0, 0), '华东', '产品A', 120, 5)
(datetime.datetime(2026, 9, 1, 0, 0), '华南', '产品B', 80, 12)
(datetime.datetime(2026, 9, 2, 0, 0), '华东', '产品C', 150, 3)

Excel中的日期可能会被读取成Python日期或日期时间对象,这是正常现象。后续如果只是把它继续保存到Excel,一般不需要手工转成字符串。

四、第二步:自动计算每条记录的销售额

现在给原表增加一列“销售额”。销售额的计算规则很直接:

销售额 = 单价 × 数量

按照当前表格结构,D列是单价,E列是数量,因此可以把结果写入F列。

from openpyxl import load_workbook

file_path = "sales.xlsx"

wb = load_workbook(file_path)
ws = wb["销售明细"]

ws["F1"] = "销售额"

for row in range(2, ws.max_row + 1):
    price = ws.cell(row=row, column=4).value
    quantity = ws.cell(row=row, column=5).value

    if price is None or quantity is None:
        amount = 0
    else:
        amount = price * quantity

    ws.cell(row=row, column=6, value=amount)

wb.save("sales_processed.xlsx")

执行完成后,原始的 sales.xlsx 不会被覆盖,而是生成新的 sales_processed.xlsx。这种做法比较适合办公自动化,因为程序出现逻辑错误时仍然保留原始文件。

按照示例数据,新增列应该得到:

商品 单价 数量 销售额
产品A 120 5 600
产品B 80 12 960
产品C 150 3 450
SVG 配图 2
图2:程序逐行读取单价和数量,计算销售额后写回同一行。

五、第三步:自动按部门汇总销售数据

只增加销售额还不够,办公报表更常见的要求是“按部门汇总”。可以使用一个字典保存每个部门累计的销售额。

summary = {}

for row in range(2, ws.max_row + 1):
    department = ws.cell(row=row, column=2).value
    amount = ws.cell(row=row, column=6).value

    if not department:
        continue

    if amount is None:
        amount = 0

    summary[department] = summary.get(department, 0) + amount

print(summary)

使用前面的三条示例数据,结果为:

{'华东': 1050, '华南': 960}

summary.get(department, 0) 的意思是:如果部门已经出现过,就取出原来的累计金额;如果第一次出现,则从0开始。这样无论有几十条还是几万条记录,都可以采用同样的逻辑累加。

六、第四步:创建“部门汇总”工作表

接下来把统计结果写回Excel,而不是只打印在终端中。

if "部门汇总" in wb.sheetnames:
    del wb["部门汇总"]

summary_ws = wb.create_sheet("部门汇总")

summary_ws.append(["部门", "销售总额"])

for department, total in summary.items():
    summary_ws.append([department, total])

这里先检查工作簿中是否已经存在“部门汇总”。如果脚本重复运行,而旧工作表仍然存在,直接再次创建同名工作表会带来不必要的问题,所以先删除旧表再重新生成。

SVG 配图 3
图3:明细表中的多条记录按照部门分组,再累计为一张汇总表。

七、第五步:自动设置Excel报表格式

程序生成的Excel如果只是写入数据,通常还不够方便阅读。可以继续设置表头、数字格式、列宽和冻结窗格。

先引入需要的样式:

from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

然后设置原始明细表:

header_fill = PatternFill("solid", fgColor="52677D")
header_font = Font(color="FFFFFF", bold=True)
thin_border = Border(
    bottom=Side(style="thin", color="D9E0E6")
)

for cell in ws[1]:
    cell.fill = header_fill
    cell.font = header_font
    cell.alignment = Alignment(horizontal="center", vertical="center")

for row in ws.iter_rows(min_row=2, max_row=ws.max_row):
    for cell in row:
        cell.border = thin_border

for row in range(2, ws.max_row + 1):
    ws.cell(row=row, column=4).number_format = '#,##0.00'
    ws.cell(row=row, column=6).number_format = '#,##0.00'

ws.column_dimensions["A"].width = 14
ws.column_dimensions["B"].width = 12
ws.column_dimensions["C"].width = 18
ws.column_dimensions["D"].width = 12
ws.column_dimensions["E"].width = 10
ws.column_dimensions["F"].width = 15

ws.freeze_panes = "A2"

freeze_panes = "A2" 表示冻结第一行。数据比较多时向下滚动,字段名称仍然会保留在顶部,这比仅调整颜色更有实际使用价值。

汇总表也可以使用相同的表头样式:

for cell in summary_ws[1]:
    cell.fill = header_fill
    cell.font = header_font
    cell.alignment = Alignment(horizontal="center")

for row in range(2, summary_ws.max_row + 1):
    summary_ws.cell(row=row, column=2).number_format = '#,##0.00'

summary_ws.column_dimensions["A"].width = 18
summary_ws.column_dimensions["B"].width = 18

八、把前面的步骤合成一个完整脚本

实际办公时不会分别运行几段代码,通常会把读取、计算、汇总、格式设置和保存组合成一个脚本。下面给出可以直接对应本案例的完整版本。

from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

INPUT_FILE = "sales.xlsx"
OUTPUT_FILE = "sales_processed.xlsx"
DETAIL_SHEET = "销售明细"
SUMMARY_SHEET = "部门汇总"

# 1. 打开Excel
wb = load_workbook(INPUT_FILE)

if DETAIL_SHEET not in wb.sheetnames:
    raise ValueError(f"找不到工作表:{DETAIL_SHEET}")

ws = wb[DETAIL_SHEET]

# 2. 添加销售额字段
ws["F1"] = "销售额"

summary = {}

for row in range(2, ws.max_row + 1):
    department = ws.cell(row=row, column=2).value
    price = ws.cell(row=row, column=4).value
    quantity = ws.cell(row=row, column=5).value

    if price is None or quantity is None:
        amount = 0
    else:
        amount = price * quantity

    ws.cell(row=row, column=6, value=amount)

    if department:
        summary[department] = summary.get(department, 0) + amount

# 3. 删除旧汇总表并重新创建
if SUMMARY_SHEET in wb.sheetnames:
    del wb[SUMMARY_SHEET]

summary_ws = wb.create_sheet(SUMMARY_SHEET)
summary_ws.append(["部门", "销售总额"])

for department, total in summary.items():
    summary_ws.append([department, total])

# 4. 定义基础样式
header_fill = PatternFill("solid", fgColor="52677D")
header_font = Font(color="FFFFFF", bold=True)
thin_border = Border(
    bottom=Side(style="thin", color="D9E0E6")
)

# 5. 明细表格式
for cell in ws[1]:
    cell.fill = header_fill
    cell.font = header_font
    cell.alignment = Alignment(
        horizontal="center",
        vertical="center"
    )

for row_cells in ws.iter_rows(
    min_row=2,
    max_row=ws.max_row,
    min_col=1,
    max_col=6
):
    for cell in row_cells:
        cell.border = thin_border

for row in range(2, ws.max_row + 1):
    ws.cell(row=row, column=4).number_format = '#,##0.00'
    ws.cell(row=row, column=6).number_format = '#,##0.00'

ws.column_dimensions["A"].width = 14
ws.column_dimensions["B"].width = 12
ws.column_dimensions["C"].width = 18
ws.column_dimensions["D"].width = 12
ws.column_dimensions["E"].width = 10
ws.column_dimensions["F"].width = 15
ws.freeze_panes = "A2"

# 6. 汇总表格式
for cell in summary_ws[1]:
    cell.fill = header_fill
    cell.font = header_font
    cell.alignment = Alignment(horizontal="center")

for row in range(2, summary_ws.max_row + 1):
    summary_ws.cell(row=row, column=2).number_format = '#,##0.00'

summary_ws.column_dimensions["A"].width = 18
summary_ws.column_dimensions["B"].width = 18

# 7. 保存为新文件
wb.save(OUTPUT_FILE)

print(f"处理完成:{OUTPUT_FILE}")

在脚本所在目录执行:

python excel_report.py

正常完成后,会生成:

sales_processed.xlsx

打开该文件,应当能确认三件事:销售明细中出现了“销售额”列;工作簿增加了“部门汇总”工作表;表头、数字格式、列宽和冻结首行已经应用。

SVG 配图 4
图4:从准备原始文件到验证输出结果的完整操作步骤。

九、数据量较大时,可以用pandas处理再写回Excel

openpyxl 的优势是能够直接控制工作簿和单元格,但如果任务主要是筛选、分组、合并、统计数据,pandas 的写法通常更简洁。

例如同样的部门销售汇总,可以这样处理:

import pandas as pd

df = pd.read_excel(
    "sales.xlsx",
    sheet_name="销售明细"
)

df["销售额"] = df["单价"].fillna(0) * df["数量"].fillna(0)

summary = (
    df.groupby("部门", as_index=False)["销售额"]
      .sum()
      .rename(columns={"销售额": "销售总额"})
)

with pd.ExcelWriter(
    "sales_pandas.xlsx",
    engine="openpyxl"
) as writer:
    df.to_excel(
        writer,
        sheet_name="销售明细",
        index=False
    )

    summary.to_excel(
        writer,
        sheet_name="部门汇总",
        index=False
    )

这里的 groupby("部门") 就完成了按部门分组,随后对“销售额”求和。对于需要按地区、员工、产品、日期等多个条件统计的表格,这种方式会比手工遍历单元格更容易维护。

可以简单理解:

需求 更合适的工具
修改指定单元格、字体、颜色、边框、公式 openpyxl
筛选、分组、排序、统计大量表格数据 pandas
既要统计数据,又要精细调整最终Excel格式 pandas + openpyxl

十、进一步实现批量处理多个Excel文件

真正能明显减少重复劳动的场景,往往不是处理一个文件,而是一个文件夹里每天、每周或者每个部门各有一份Excel。

例如目录中存在:

reports/
├── 华东销售.xlsx
├── 华南销售.xlsx
├── 华北销售.xlsx
└── 西南销售.xlsx

可以利用Python的 pathlib 扫描目录:

from pathlib import Path
from openpyxl import load_workbook

folder = Path("reports")

for file_path in folder.glob("*.xlsx"):
    print("正在处理:", file_path.name)

    wb = load_workbook(file_path)
    ws = wb["销售明细"]

    ws["F1"] = "销售额"

    for row in range(2, ws.max_row + 1):
        price = ws.cell(row=row, column=4).value or 0
        quantity = ws.cell(row=row, column=5).value or 0

        ws.cell(
            row=row,
            column=6,
            value=price * quantity
        )

    output_path = file_path.with_name(
        file_path.stem + "_处理后.xlsx"
    )

    wb.save(output_path)

这样脚本会查找 reports 目录中的所有 .xlsx 文件,并分别生成带“_处理后”后缀的新文件。

需要特别处理临时文件:如果目录中的Excel正在被桌面版Excel打开,有时会出现以 ~$ 开头的临时文件。批量脚本可以增加判断,跳过这类文件:
if file_path.name.startswith("~$"):
    continue

十一、实际办公自动化中最容易出错的地方

1. Excel列位置发生变化

前面的程序假设“部门”固定在B列、“单价”固定在D列。如果有人把“单价”移动到E列,程序仍然读取D列,就会产生错误结果。

更稳妥的方式是根据表头寻找列,而不是把列号完全写死。例如:

headers = {}

for cell in ws[1]:
    headers[cell.value] = cell.column

price_col = headers["单价"]
quantity_col = headers["数量"]
department_col = headers["部门"]

后面的代码再使用 price_col、quantity_col 和 department_col。这样即使列顺序变化,只要表头名称没有变,程序仍然能够找到正确字段。

2. 单元格中存在空值或文本

实际表格不一定像示例这么整齐。某一行的单价可能为空,也可能误填成“待确认”。如果直接执行乘法,会出现异常。

需要先验证数据类型:

if isinstance(price, (int, float)) and isinstance(quantity, (int, float)):
    amount = price * quantity
else:
    amount = 0

正式业务中是否应该把异常值当作0,要根据实际规则决定。很多情况下,更合适的做法不是默默改成0,而是把异常行记录下来,等待人工确认。

3. 不要一开始就覆盖原始文件

如果直接:

wb.save("sales.xlsx")

原始文件会被新结果替换。程序逻辑尚未经过验证时,更建议输出到新文件,例如:

wb.save("sales_processed.xlsx")

等脚本稳定以后,再根据业务需要决定是否覆盖原文件。

4. 公式和公式结果不是一回事

Excel中可以存在公式,例如:

=D2*E2

openpyxl 可以读取和写入公式,但它本身不是Excel的完整公式计算引擎。也就是说,把公式写入工作簿并不等于Python已经重新计算出了所有Excel公式结果。

如果自动化任务需要立即得到计算结果,最可靠的方式之一是直接在Python中完成相应计算,然后把数值写入单元格。

5. 合并单元格适合展示,不适合原始数据

如果一张表大量使用合并单元格来表示部门、地区或分类,从人的视觉角度看可能比较整齐,但对程序来说会增加读取难度。

用于自动处理的原始表最好保持“一行一条记录、每列一个字段”。最终生成给人阅读的报表时,再根据需要增加展示格式。

十二、什么时候适合用Python做Excel自动化

并不是所有Excel操作都值得写程序。只有偶尔修改三五个单元格,直接使用Excel通常更快。Python更适合具有明显重复性的任务,例如:

  • 每天都要把相同格式的数据整理成日报;
  • 几十个Excel文件需要执行相同的计算或格式调整;
  • 需要按照部门、地区、产品等字段自动统计;
  • 需要把多个表格合并成一份总表;
  • 需要批量检查空值、重复数据或异常数据;
  • 需要定期生成结构固定的Excel报表。

判断是否值得自动化,可以看一个很简单的条件:操作规则是否明确并且会重复出现。规则越固定、重复次数越多,Python脚本的价值越明显。

SVG 配图 5
图5:建立Excel自动化脚本时,真正需要固定下来的四个关键环节。

十三、完整思路总结

用Python实现Excel自动化办公,可以先从一个非常具体的重复任务开始,而不是一开始就尝试建立复杂的办公系统。本例的过程就是一个可以复用的基本模板:读取 sales.xlsx,逐行计算销售额,按照部门汇总数据,创建新的汇总工作表,再设置必要的Excel格式并输出新文件。

如果任务重点是修改工作簿结构、单元格和格式,使用 openpyxl 比较直接;如果重点是大量数据的筛选、分组和统计,可以先用 pandas 处理,再根据需要使用 openpyxl 调整最终报表。

真正开始用于日常工作后,还应逐步处理三个问题:不要过度依赖固定列号,要检查空值和异常数据,并且在脚本经过验证之前保留原始文件。做到这些之后,原本每天都需要手工重复的Excel整理流程,就可以变成“放入新数据、运行脚本、检查结果”这样相对稳定的自动化过程。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表