Python 入门(四)- Openpyxl 操作 Excel 教程
以往我们处理 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 行交叉的单元格地址为 A1C 列和第 5 行交叉的单元格地址为 C5当你点击某个格子它周围会出现粗黑边框此时它就是“活动单元格”你可以直接输入数据Excel 工作界面PSOpenpyxl 的官方文档真是乱糟糟的连一个目录总览都没有全靠上一页下一页的挨个翻阅翻了半天也看不到头简直无力吐槽PS切换全屏CtrlShiftF1再次按取消全屏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()实例化的时候会自动创建一个工作表并自动生成默认表名SheetWorkbook.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 不兼容旧版本的 ExcelOffice2003 的xls格式旧版本可以用xlrd库进行 Excel 文件的读取并且xlrd库要指定1.2.0版本才能同时支持新旧 Excel 版本或者将旧版本的xsl转换为xlsx格式推荐我不想为了兼容旧版本的 Excel 去多学一个库所以我还是选择用 Openpyxl 库加载 Excel 文件使用load_workbook()函数打开现有的 Excel 文件from openpyxl import load_workbook wb load_workbook(filenamesample.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、…如果表名重复了它会自动加上数字123依此类推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)函数移动工作表的下标对其进行重新排序参数如下titleSheet 名称n负数表示向左移动正数表示向右移动数字表示移动几个位置from openpyxl import load_workbook wb load_workbook(filenamesample.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(filenamesample.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)