以往我们处理 Excel 文件,只能手动打开 Excel 文件进行操作。如果碰到大量且重复性高的任务,一个个编辑文件就特别费时费力。这时我们可以借助Python 读取和写入 Excel 文件的库来进行文件的批量以及自动化处理。Python 提供了好几个能够操作 Excel 的库。本篇文章选择Openpyxl库作为教程。
考虑到有的朋友可能对 Excel 不太熟悉,我先在开头简单回顾一下Excel 的基础概念:
层级关系工作簿(Workbook) ├── 工作表(Worksheet) │ ├── 单元格(Cell) │ ├── 单元格(Cell) │ └── ... ├── 工作表(Worksheet) └── ...一个工作簿包含多个工作表,每个工作表又由无数个单元格组成,单元格是 Excel 最小的数据存储单位
工作簿(Workbook)工作簿是 Excel 官方的叫法,它其实就是一个 Excel 文件,通常以 .xlsx 或 .xls 为扩展名
文件扩展名:
.xls —— 普通 Excel 工作簿(Excel 早期版本:1997–2003) .xlsx —— 普通 Excel 工作簿(Excel 2007 及之后版本) .xlsm —— 带宏的工作簿 .xlsb —— 二进制的工作簿创建工作簿的时候会自动生成 1 个工作表
工作表(Worksheet)工作表是工作簿内部的一张张独立表格。工作表的名称默认为“Sheet1”、“Sheet2”、“Sheet3” 依次递增,也可自行修改
工作表用于分类存放数据。例如一个名为“2026年财务报表”的工作簿,可以包含“1月”、“2月”等多个工作表
每个工作表是由行(Rows:从 1 开始编号,如 1, 2, 3…)和列(Columns:用字母表示A, B, C…)组成
单元格(Cell)单元格就是工作表上的一个个小格子。它是存储数据的最小单位,用来输入文本(字符串),数值(数字),日期 / 时间,公式(以 = 开头)
每个单元格都有唯一的地址标识,由「列标(字母) + 行号(数字)」组成。例如 A 列和第 1 行交叉的单元格,地址为 A1;C 列和第 5 行交叉的单元格,地址为 C5
当你点击某个格子,它周围会出现粗黑边框,此时它就是“活动单元格”,你可以直接输入数据
Excel 工作界面:
PS:Openpyxl 的官方文档真是乱糟糟的,连一个目录总览都没有,全靠上一页下一页的挨个翻阅,翻了半天也看不到头,简直无力吐槽
PS:切换全屏:Ctrl+Shift+F1,再次按取消全屏
2. 安装
我使用 uv 作为 python 包管理工具。为了节省文章篇幅,安装 uv、使用 uv 安装 python 以及创建项目、创建虚拟环境等步骤略过。不会 uv 的同学可以看我的另一篇文章:
📝 《Python 入门(一)- 用 UV 管理 Python》:juejin.cn/post/760585…
安装 openpyxl 库
uv add openpyxl
安装后会在pyproject.toml文件写入 openpyxl 依赖
以及在uv.lock文件锁定 openpyxl 包的版本
3. 工作簿(Excel 文件)
3.1 工作簿创建
Workbook()实例化的时候会自动创建一个工作表,并自动生成默认表名"Sheet"
Workbook.save()方法将工作簿保存到磁盘上的文件中。如果文件不存在将创建文件,如果文件存在则进行内容覆盖
注意!覆盖 Excel 内容的时候,需要将当前打开的 Excel 文件关闭才能执行代码,否则 Excel 文件被占用,执行Workbook.save()方法会报错
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 print("wb:", wb) wb.save("sample.xlsx") # 保存 excel print("创建成功!")
成功创建工作簿,并默认创建了一个名为 "Sheet" 的工作表
也可以指定路径创建,我这里将创建的 excel 文件放在 D 盘的 xlsx 文件夹下面
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 print("wb:", wb) wb.save("D:\\xlsx\\sample.xlsx") # 保存 excel print("创建成功!")
注意!路径(xlsx 文件夹)需要存在,否则会报错
3.2 工作簿加载
注意,Openpyxl 不兼容旧版本的 Excel(Office2003 的xls格式)!旧版本可以用xlrd库进行 Excel 文件的读取,并且xlrd库要指定1.2.0版本才能同时支持新旧 Excel 版本;或者将旧版本的xsl转换为xlsx格式(推荐)
我不想为了兼容旧版本的 Excel 去多学一个库,所以我还是选择用 Openpyxl 库加载 Excel 文件
使用load_workbook()函数打开现有的 Excel 文件
from openpyxl import load_workbook wb = load_workbook(filename="sample.xlsx") # 获取所有工作表名称 print(wb.sheetnames)
打印出工作表的名称证明加载成功
3.3 工作簿删除
使用os库的remove()方法删除工作簿
import os os.remove("sample.xlsx") print("工作簿删除成功!")
也可以使用os库的path.exists()方法加一个判断提升代码健壮性:如果文件存在才删除,否则提示不存在
import os # 删除工作簿文件 file_path = "sample.xlsx" if os.path.exists(file_path): os.remove(file_path) print(f"已删除文件: {file_path}") else: print("文件不存在")
3.4 合并工作薄
我们可以将多个结构相同的 Excel 工作薄合并为一个
具体操作:略
3.5 拆分工作薄
我们也可以将结构相同的 Excel 工作薄拆分为多个
具体操作:略
4. 工作表
4.1 修改工作表的名称
Workbook()实例化的时候会自动创建一个工作表,并自动生成默认表名。可以使用Workbook.title属性更改工作表的名称
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 ws = wb.active # 获取当前活跃的工作表 ws.title = "工资表" # 修改当前工作表的名称 wb.save("sample.xlsx") # 保存 excel print("创建成功!")
表名被成功修改为“工资表”
4.2 创建新的工作表
create_sheet()函数共有两个参数:
title(表名):若不指定工作表的名称,将按顺序递增自动生成(Sheet、Sheet1、Sheet2、…);如果表名重复了,它会自动加上数字1,2,3依此类推
index(索引值):正数从 0 开始从前往后生成工作表,负数从 -1 开始从后往前生成工作表,索引不指定时追加到最右侧
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 ws2 = wb.create_sheet("天", 0) # 正数索引:从0开始,指定插入位置 ws2 = wb.create_sheet("青", 1) ws2 = wb.create_sheet("色", 2) ws2 = wb.create_sheet("等", 3) ws2 = wb.create_sheet("烟", 4) ws2 = wb.create_sheet("等", -1) # 负数索引:从末尾开始计数 ws2 = wb.create_sheet("在", -2) ws2 = wb.create_sheet("我", -3) ws2 = wb.create_sheet("而", -4) ws2 = wb.create_sheet("雨", -5) wb.save("sample.xlsx") # 保存 excel print("创建成功!")
我们按照歌词“天青色等烟雨而我在等”的顺序创建工作表
表名重复了,有两个等,所以第二个等被自动加上了数字1
默认创建的 Sheet 因为没加索引,所以默认排在最后
现在我们加上一行ws1 = wb.create_sheet("你")代码,索引为空将表插入到末尾
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 ws1 = wb.create_sheet("你") # 索引为空:插入到末尾 ws2 = wb.create_sheet("天", 0) # 正数索引:从0开始,指定插入位置 ws2 = wb.create_sheet("青", 1) ws2 = wb.create_sheet("色", 2) ws2 = wb.create_sheet("等", 3) ws2 = wb.create_sheet("烟", 4) ws2 = wb.create_sheet("等", -1) # 负数索引:从末尾开始计数 ws2 = wb.create_sheet("在", -2) ws2 = wb.create_sheet("我", -3) ws2 = wb.create_sheet("而", -4) ws2 = wb.create_sheet("雨", -5) wb.save("sample.xlsx") # 保存 excel print("创建成功!")
注意看!神奇的事情发生了
表名你,索引为空所以插入到末尾,这个很好理解
但是默认创建的 Sheet 跑到了中间,这又是咋回事?
我的理解是插入到末尾已经被表名你给占用了,所以默认创建的 Sheet 只能放在不属于这些带有索引下标的位置-也就是中间
所以大家创建多个表的时候,建议每个表都指定下标索引,避免排序混乱
4.3 查看所有工作表的名称
Workbook.sheetname()函数查看工作簿中所有工作表的名称
在前面的 3.2 工作簿加载 章节已经用过此方法了,不再赘述
4.4 移动工作表(下标)
move_sheet(title, n)函数移动工作表的下标,对其进行重新排序,参数如下:
title:Sheet 名称
n:负数表示向左移动,正数表示向右移动,数字表示移动几个位置
from openpyxl import load_workbook wb = load_workbook(filename="sample.xlsx") print(wb.sheetnames) # 获取所有工作表名称 wb.move_sheet("Sheet", 1) # -1 负数表示向左移动,正数表示向右移动,数字表示移动几个位置 print(wb.sheetnames) # 获取所有工作表名称
加载刚才创建的工作簿,然后将默认创建的 Sheet 向右移动了一个位置
需要保存 excel 的话,在最后调用wb.save("sample.xlsx")函数即可
4.5 复制工作表
Workbook.copy_worksheet(sheet):在当前工作簿复制指定的工作表并返回复制后的工作表对象
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 ws = wb.active # 获取当前活跃的工作表 ws.title = "工资表" # 修改当前工作表的名称 new_worksheet = wb.copy_worksheet(ws) # 复制工作表 wb.save("sample.xlsx") # 保存 excel print("创建成功!")
不指定复制指定的工作表的名字的话,默认会在表名后加上Copy
如果想指定名字的话加上new_worksheet.title = "复制的工资表"这句代码即可
4.6 删除工作表
del wb['SheetName']:在当前工作簿中删除指定的工作表
wb是已加载的工作簿对象
SheetName是想要删除的表名
from openpyxl import load_workbook wb = load_workbook(filename="sample.xlsx") print(wb.sheetnames) # 获取所有工作表名称 del wb["工资表 Copy"] # 删除工作表 print(wb.sheetnames) # 获取所有工作表名称
加载刚才创建的工作簿,然后将名为"工资表 Copy"的工作表删除
需要保存 excel 的话,在最后调用wb.save("sample.xlsx")函数即可
注意:旧的remove_sheet()删除工作表方法已被废弃
5. 单元格
5.1 单元格的内容写入
5.1.1 通过工作表的键
通过工作表的键填写单元格内容
from openpyxl import Workbook wb = Workbook() # 实例化 excel 工作簿对象 ws = wb.active # 获取当前活跃的工作表 ws.title = "工资表" # 修改当前工作表的名称 ws["A1"] = "姓名" # 给单元格填写值(通过工作表的键) wb.save("sample.xlsx") # 保存 excel print("创建成功!")
也可以加上 .value
# 给单元格填写值(通过工作表的键) ws["A1"].value = "工资表"
通过工作表的键获取单元格内容
print(ws["A1"].value)