用 Python 处理 Excel:openpyxl 实战

把重复的表格工作交给代码

作者 sunhao666 · 2026年9月29日 · 约 7 分钟

什么场景需要它#

每个学期都会有这样的表格工作: 把几十份学生成绩表汇总成一张总表、按班级拆分成多个文件、 批量计算总分和排名。手工做一次要半小时,还容易出错。

这种结构固定、重复度高的工作,正是代码最擅长的。

安装#

pip install openpyxl

一、读取表格#

from openpyxl import load_workbook

# data_only=True 表示读取公式的计算结果,而不是公式本身
wb = load_workbook("成绩表.xlsx", data_only=True)

# 按名称获取工作表
ws = wb["Sheet1"]

# 用 iter_rows 逐行读取,values_only=True 直接拿到值而不是单元格对象
for row in ws.iter_rows(min_row=2, values_only=True):  # 跳过标题行
    name, chinese, math, english = row[0], row[1], row[2], row[3]
    print(name, chinese, math, english)

小技巧:ws.max_row 和 ws.max_column 能拿到表格的行列数, 但注意如果表格中间有空行,这两个值可能不准。

二、写入表格#

from openpyxl import Workbook

wb = Workbook()          # 新建工作簿
ws = wb.active
ws.title = "成绩汇总"     # 重命名默认工作表

# 写标题行:append 会自动往后找空行
ws.append(["姓名", "语文", "数学", "英语", "总分"])

# 写数据行,顺便算总分
students = [("张三", 88, 92, 85), ("李四", 76, 95, 80)]
for name, c, m, e in students:
    ws.append([name, c, m, e, c + m + e])

wb.save("汇总结果.xlsx")
print("已生成 汇总结果.xlsx")

三、加一点格式#

数据能看懂的前提是排版清晰。

from openpyxl.styles import Font, Alignment, PatternFill
from openpyxl.utils import get_column_letter

# 标题行加粗、加底色、居中
header_font = Font(bold=True, color="FFFFFF")
header_fill = PatternFill("solid", fgColor="0085A1")

for cell in ws[1]:                    # ws[1] 就是第一行
    cell.font = header_font
    cell.fill = header_fill
    cell.alignment = Alignment(horizontal="center")

# 自动调整列宽
# get_column_letter(1) 把数字 1 转成字母 "A"
for i in range(1, ws.max_column + 1):
    letter = get_column_letter(i)
    ws.column_dimensions[letter].width = 12

四、实用的完整例子:按班级拆分表格#

from openpyxl import load_workbook, Workbook
from collections import defaultdict

wb = load_workbook("全年级成绩.xlsx", data_only=True)
ws = wb.active

# 按班级分组:defaultdict 的好处是不用先判断 key 存在不存在
groups = defaultdict(list)

# 假设第一列是班级,第二列是姓名,后面是各科分数
for row in ws.iter_rows(min_row=2, values_only=True):
    if row[0] is None:
        continue                       # 跳过空行
    class_name = str(row[0]).strip()
    groups[class_name].append(row[1:])

# 每个班级写一个文件
for class_name, rows in groups.items():
    new_wb = Workbook()
    new_ws = new_wb.active
    new_ws.title = class_name
    new_ws.append(["姓名", "语文", "数学", "英语"])
    for r in rows:
        new_ws.append(r)
    new_wb.save(f"{class_name}_成绩.xlsx")
    print(f"{class_name}: {len(rows)} 人")

这段代码把「手工复制粘贴几十次」压缩成了 20 行。

常见报错#

报错 原因 解决
FileNotFoundError 文件路径不对 检查文件名,注意扩展名是 .xlsx 不是 .xls
KeyError: 'Sheet1' 工作表名不对 用 wb.sheetnames 看真实的工作表名
PermissionError 文件正被 Excel 打开 先关掉 Excel 再运行

注意:openpyxl 不支持老式的 .xls 格式。 遇到 .xls 要先在 Excel 里另存为 .xlsx。

课堂思考题#

  1. 为什么读取时要用 data_only=True?不加会有什么后果?
  2. 如果表格有几万行,一次性读进内存会有问题吗?有没有更省内存的写法?