1. 什么是 OpenPyXL? #
OpenPyXL 是 Python 中最流行的 Excel 文件处理库之一,专门用于读写 Excel 2007 及更高版本的文件格式(.xlsx、.xlsm、.xltx、.xltm)。它支持创建、读取、修改 Excel 文件,还能设置样式、添加公式、插入图表等功能。
为什么要用 OpenPyXL?
想象一下,你需要批量处理 Excel 文件、生成报表、或者从 Excel 中提取数据进行分析。手动操作太慢且容易出错,而 OpenPyXL 提供了强大的 Python API,可以自动化完成这些任务。
OpenPyXL 的优势:
- 功能强大:支持读写、样式、公式、图表等所有常见操作
- 纯 Python 实现:不需要安装 Microsoft Excel
- 跨平台:Windows、macOS、Linux 都可以使用
- 易于学习:API 设计简洁直观,文档完善
- 兼容性好:支持 Excel 2007 及以上版本
前置知识补充:
- Excel 文件结构:Excel 文件(.xlsx)由工作簿(Workbook)组成,每个工作簿可以包含多个工作表(Worksheet),每个工作表由单元格(Cell)组成。单元格是行和列的交集,比如 A1、B2 等。
- 坐标系统:Excel 使用字母(A、B、C...)表示列,使用数字(1、2、3...)表示行。比如 A1 表示第一行第一列的单元格,B2 表示第二行第二列的单元格。
- 工作表(Worksheet):一个工作簿可以包含多个工作表,每个工作表可以独立编辑。在 Excel 中,你可以在底部看到多个工作表标签。
- 工作簿(Workbook):整个 Excel 文件就是一个工作簿,它包含所有的工作表和数据。
2. 环境准备 #
在学习 OpenPyXL 之前,需要确保你的 Python 环境已经准备好。OpenPyXL 支持 Python 3.7 及以上版本。
2.1 检查 Python 版本 #
在安装之前,先检查一下你的 Python 版本是否符合要求。
# Windows PowerShell:查看 Python 版本
python --version# macOS 终端:查看 Python 版本
python3 --version2.2 安装 OpenPyXL #
OpenPyXL 可以直接通过 pip 安装。安装过程会自动下载所需的依赖包。
# 说明:Windows PowerShell 安装 OpenPyXL
# 先升级 pip 到最新版本,确保能正常安装依赖
python -m pip install --upgrade pip
# 安装 openpyxl 库
python -m pip install openpyxl# 说明:macOS / Linux 终端安装 OpenPyXL
# 先升级 pip 到最新版本
python3 -m pip install --upgrade pip
# 安装 openpyxl 库
python3 -m pip install openpyxl网络加速提示:如果从 PyPI 下载较慢,可以使用国内镜像:
- Windows:
python -m pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple- macOS:
python3 -m pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple
安装问题提示:
- 如果安装失败,可能是因为网络问题。可以尝试使用镜像源,或者检查网络连接。
- macOS 用户如果遇到权限问题,可以在命令前加
sudo(不推荐),或者使用虚拟环境。
2.3 验证安装 #
安装完成后,验证一下是否安装成功。
# -*- coding: utf-8 -*-
# 说明:验证 OpenPyXL 是否安装成功
# 说明:导入 openpyxl 库
# openpyxl 是用于处理 Excel 文件的核心库
import openpyxl
# 说明:打印 OpenPyXL 版本信息
# __version__ 属性返回库的版本号
print(f"OpenPyXL 版本:{openpyxl.__version__}")
# 说明:测试创建工作簿
# Workbook() 创建一个新的空工作簿对象
wb = openpyxl.Workbook()
# 说明:获取默认工作表
# active 属性返回当前活动的工作表
ws = wb.active
# 说明:在工作表中写入一个测试值
# 通过坐标(如 A1)直接赋值可以写入数据
ws["A1"] = "测试"
# 说明:读取单元格的值
# 同样可以通过坐标读取单元格的值
value = ws["A1"].value
# 说明:打印结果,验证安装是否成功
print("安装成功!单元格 A1 的值:", value)
# 说明:如果没有报错并输出了"测试",说明安装成功3. 核心概念 #
在使用 OpenPyXL 之前,需要理解几个核心概念。这些概念是理解 OpenPyXL 的基础。
3.1 Workbook(工作簿) #
Workbook 是 Excel 文件的对象表示,相当于整个 Excel 文件。你可以通过 Workbook() 创建新的工作簿,或通过 load_workbook() 加载已有的工作簿。
3.2 Worksheet(工作表) #
Worksheet 是工作簿中的一个工作表,类似于 Excel 中的标签页。一个工作簿可以包含多个工作表,每个工作表都可以独立编辑。
3.3 Cell(单元格) #
Cell 是工作表中的一个单元格,是数据存储的基本单位。每个单元格都有一个唯一的坐标,如 A1、B2 等。
3.4 坐标系统 #
OpenPyXL 使用 Excel 的坐标系统:列用字母(A、B、C...)表示,行用数字(1、2、3...)表示。你也可以使用数字坐标,列从 1 开始。
4. 快速体验:创建和读取工作簿 #
让我们通过一个最简单的例子来快速体验 OpenPyXL 的强大功能。
4.1 创建工作簿 #
本代码块中使用的 OpenPyXL 方法:
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
Workbook() |
创建一个新的空工作簿 | 无 | Workbook 对象 |
.active |
获取当前活动的工作表 | 无(属性) | Worksheet 对象 |
.title |
获取或设置工作表的名称 | 无(属性),可直接赋值 | 字符串 |
ws[坐标] |
通过坐标访问单元格 | 坐标:如 "A1" |
Cell 对象 |
.save() |
保存工作簿到文件 | filename:文件路径 |
无 |
# -*- coding: utf-8 -*-
# 说明:快速体验 OpenPyXL - 创建工作簿
# 说明:导入 openpyxl 库
# 从 openpyxl 导入 Workbook 类,用于创建新工作簿
from openpyxl import Workbook
# 说明:创建一个新的空工作簿
# Workbook() 函数创建一个新的 Excel 工作簿对象
wb = Workbook()
# 说明:获取默认工作表
# active 属性返回当前活动的工作表(通常是第一个工作表)
ws = wb.active
# 说明:设置工作表的名称
# title 属性可以读取或设置工作表的名称
ws.title = "销售数据"
# 说明:在工作表中写入数据
# 通过坐标(如 "A1")可以直接访问单元格并赋值
# A1 表示第一行第一列的单元格
ws["A1"] = "月份"
ws["B1"] = "收入"
# 说明:使用 append() 方法添加一行数据
# append() 方法在表的末尾添加一行数据
# 参数是一个列表,列表中的每个元素对应一列
ws.append(["一月", 1000])
ws.append(["二月", 1500])
ws.append(["三月", 1200])
# 说明:保存工作簿到文件
# save() 方法将工作簿保存到指定的文件路径
# 如果文件已存在,会被覆盖;如果不存在,会创建新文件
wb.save("quick_start.xlsx")
# 说明:打印成功消息
print("工作簿已创建:quick_start.xlsx")
print(f"工作表名称:{ws.title}")4.2 读取工作簿 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
load_workbook() |
加载已有的工作簿文件 | filename:文件路径,read_only:是否只读(可选),data_only:是否只读取值(可选) |
Workbook 对象 |
.sheetnames |
获取所有工作表的名称列表 | 无(属性) | 字符串列表 |
.value |
获取单元格的值 | 无(属性) | 单元格的值 |
# -*- coding: utf-8 -*-
# 说明:快速体验 OpenPyXL - 读取工作簿
# 说明:导入 openpyxl 库
# 从 openpyxl 导入 load_workbook 函数,用于加载已有工作簿
from openpyxl import load_workbook
# 说明:加载已有的工作簿文件
# load_workbook() 函数从文件路径加载一个 Excel 工作簿
# 返回 Workbook 对象
wb = load_workbook("quick_start.xlsx")
# 说明:获取所有工作表的名称
# sheetnames 属性返回工作簿中所有工作表名称的列表
sheet_names = wb.sheetnames
print("所有工作表名称:", sheet_names)
# 说明:通过名称获取工作表
# 可以通过工作表名称访问特定的工作表
ws = wb["销售数据"]
# 说明:读取单元格的值
# 通过坐标访问单元格,然后使用 value 属性获取单元格的值
month = ws["A1"].value
revenue = ws["B1"].value
print(f"\n标题行:{month} | {revenue}")
# 说明:遍历并读取多行数据
# 可以通过坐标范围(如 "A2:B4")访问多个单元格
print("\n数据内容:")
for row in ws["A2:B4"]:
# 说明:row 是一个包含多个 Cell 对象的元组
# row[0] 是第一列的单元格,row[1] 是第二列的单元格
month_value = row[0].value
revenue_value = row[1].value
print(f" {month_value}:{revenue_value}")
# 说明:关闭工作簿(可选,但推荐)
# 如果不再需要访问工作簿,可以关闭它以释放资源
wb.close()5. 工作簿与工作表管理 #
在实际应用中,你可能需要创建多个工作表、复制工作表或删除工作表。本节介绍如何管理工作表。
5.1 创建和删除工作表 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.create_sheet() |
创建新工作表 | title:工作表名称,index:插入位置(可选,0 表示最前面) |
Worksheet 对象 |
.remove() |
删除工作表 | worksheet:要删除的工作表对象 |
无 |
# -*- coding: utf-8 -*-
# 说明:演示如何创建和删除工作表
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建一个新的工作簿
wb = Workbook()
# 说明:获取默认工作表
# active 属性返回当前活动的工作表
ws_main = wb.active
# 说明:设置默认工作表的名称
ws_main.title = "主表"
# 说明:在末尾创建新工作表
# create_sheet() 方法创建新的工作表
# 如果只提供 title 参数,新工作表会被添加到末尾
ws_summary = wb.create_sheet("汇总表")
# 说明:在最前面插入新工作表
# create_sheet() 的 index 参数指定插入位置
# index=0 表示插入到最前面
ws_first = wb.create_sheet("报表头", 0)
# 说明:在新工作表中写入数据
# 可以在新创建的工作表中直接写入数据
ws_summary["A1"] = "这是汇总表"
ws_first["A1"] = "这是报表头"
# 说明:打印所有工作表名称
# sheetnames 属性返回所有工作表名称的列表
print("创建后的工作表:", wb.sheetnames)
# 说明:删除工作表
# remove() 方法删除指定的工作表
# 参数是要删除的工作表对象
wb.remove(ws_summary)
# 说明:打印删除后的工作表名称
print("删除后的工作表:", wb.sheetnames)
# 说明:保存工作簿
wb.save("sheets_manage.xlsx")
print("\n工作簿已保存:sheets_manage.xlsx")5.2 复制工作表 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.copy_worksheet() |
复制工作表 | worksheet:要复制的工作表对象 |
新创建的 Worksheet 对象 |
# -*- coding: utf-8 -*-
# 说明:演示如何复制工作表
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
# 说明:获取默认工作表
ws_main = wb.active
# 说明:设置工作表名称
ws_main.title = "主表"
# 说明:在主表中写入一些数据
ws_main["A1"] = "姓名"
ws_main["A2"] = "张三"
ws_main["A3"] = "李四"
# 说明:复制工作表
# copy_worksheet() 方法复制指定的工作表
# 参数是要复制的工作表对象
# 返回新创建的工作表对象(包含所有数据和格式)
ws_copy = wb.copy_worksheet(ws_main)
# 说明:设置副本的名称
# 复制后的工作表需要设置新名称
ws_copy.title = "主表副本"
# 说明:在副本中修改数据(验证是独立的副本)
ws_copy["A2"] = "王五"
# 说明:打印所有工作表名称
print("所有工作表:", wb.sheetnames)
# 说明:验证主表和副本的数据不同
print(f"\n主表 A2 的值:{ws_main['A2'].value}")
print(f"副本 A2 的值:{ws_copy['A2'].value}")
# 说明:保存工作簿
wb.save("sheets_copy.xlsx")
print("\n工作簿已保存:sheets_copy.xlsx")6. 单元格读写:多种方式访问单元格 #
OpenPyXL 提供了多种方式来访问和操作单元格。理解这些方法可以提高代码的可读性和灵活性。
6.1 通过坐标访问单元格 #
本代码块中使用的 OpenPyXL 方法:
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
ws[坐标] |
通过坐标访问单元格 | 坐标:如 "A1" |
Cell 对象 |
.value |
获取或设置单元格的值 | 无(属性),可直接赋值 | 单元格的值 |
.cell() |
通过行号和列号访问单元格 | row:行号(从 1 开始),column:列号(从 1 开始),value:值(可选) |
Cell 对象 |
# -*- coding: utf-8 -*-
# 说明:演示多种方式访问和操作单元格
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:方法1:通过坐标字符串直接访问(最常用)
# 使用类似 "A1"、"B2" 这样的字符串坐标
# 这种方式最直观,类似于 Excel 中的单元格引用
ws["A1"] = "姓名"
ws["B1"] = "成绩"
# 说明:方法2:使用 cell() 方法通过行号和列号访问
# cell() 方法的第一个参数是行号(从 1 开始),第二个参数是列号(从 1 开始)
# 列号也可以用数字:1=A, 2=B, 3=C...
# 这种方式适合在循环中使用
ws.cell(row=2, column=1, value="张三")
ws.cell(row=2, column=2, value=95)
# 说明:方法3:先获取单元格对象,再设置值
# 可以先获取 Cell 对象,然后单独设置其 value 属性
cell_a3 = ws.cell(row=3, column=1)
cell_a3.value = "李四"
cell_b3 = ws["B3"]
cell_b3.value = 88
# 说明:读取单元格的值
# 使用 value 属性可以读取单元格的值
name_a2 = ws["A2"].value
score_b2 = ws["B2"].value
print(f"A2 单元格的值:{name_a2}")
print(f"B2 单元格的值:{score_b2}")
# 说明:保存工作簿
wb.save("cells_basic.xlsx")
print("\n工作簿已保存:cells_basic.xlsx")6.2 批量添加数据 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.append() |
在工作表末尾添加一行数据 | row:包含一行数据的列表或元组 |
无 |
# -*- coding: utf-8 -*-
# 说明:演示如何批量添加数据
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:设置标题行
ws["A1"] = "姓名"
ws["B1"] = "成绩"
ws["C1"] = "等级"
# 说明:方法1:逐行添加数据
# append() 方法在表的末尾添加一行数据
# 参数是一个列表,列表中的每个元素对应一列
ws.append(["张三", 95, "优秀"])
ws.append(["李四", 88, "良好"])
ws.append(["王五", 76, "及格"])
# 说明:方法2:使用循环批量添加
# 如果你有一个包含多行数据的列表,可以使用循环逐行添加
students = [
["赵六", 92, "优秀"],
["钱七", 85, "良好"],
["孙八", 70, "及格"],
]
# 说明:遍历学生列表,逐行添加
for student in students:
ws.append(student)
# 说明:读取所有数据
# 可以通过坐标范围访问多个单元格
print("所有学生数据:")
for row in ws["A1:C6"]:
# 说明:row 是一个包含多个 Cell 对象的元组
# 遍历每行的单元格并打印值
row_values = [cell.value for cell in row]
print(" ", row_values)
# 说明:保存工作簿
wb.save("cells_append.xlsx")
print("\n工作簿已保存:cells_append.xlsx")6.3 遍历单元格 #
本代码块中使用的 OpenPyXL 方法:
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
ws[范围] |
通过范围访问多个单元格 | 范围:如 "A1:C3" |
包含 Cell 对象的元组的元组 |
.iter_rows() |
遍历指定范围的行 | min_row:最小行号,max_row:最大行号,min_col:最小列号,max_col:最大列号,values_only:是否只返回值(可选) |
迭代器,返回行 |
.coordinate |
获取单元格的坐标 | 无(属性) | 字符串,如 "A1" |
# -*- coding: utf-8 -*-
# 说明:演示如何遍历单元格
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿并写入测试数据
wb = Workbook()
ws = wb.active
# 说明:写入一些测试数据
ws.append(["姓名", "年龄", "城市"])
ws.append(["张三", 25, "北京"])
ws.append(["李四", 30, "上海"])
ws.append(["王五", 28, "广州"])
# 说明:方法1:通过坐标范围遍历
# 使用类似 "A1:C4" 的字符串指定范围
print("方法1:通过坐标范围遍历")
for row in ws["A1:C4"]:
# 说明:row 是一个包含多个 Cell 对象的元组
# 遍历每行的单元格
row_values = []
for cell in row:
# 说明:coordinate 属性返回单元格的坐标(如 "A1")
# value 属性返回单元格的值
row_values.append(f"{cell.coordinate}:{cell.value}")
print(" ", " | ".join(row_values))
# 说明:方法2:使用 iter_rows() 方法遍历
# iter_rows() 方法返回一个迭代器,可以遍历指定范围的行
# values_only=True 表示只返回值,不返回 Cell 对象
print("\n方法2:使用 iter_rows() 遍历(只返回值)")
for row in ws.iter_rows(min_row=1, max_row=4, min_col=1, max_col=3, values_only=True):
# 说明:row 是一个包含值的元组(不再是 Cell 对象)
print(" ", row)
# 说明:方法3:使用 iter_rows() 返回 Cell 对象
print("\n方法3:使用 iter_rows() 遍历(返回 Cell 对象)")
for row in ws.iter_rows(min_row=1, max_row=4, min_col=1, max_col=3):
# 说明:row 是一个包含 Cell 对象的元组
row_values = []
for cell in row:
# 说明:可以访问 Cell 对象的属性
row_values.append(f"{cell.coordinate}={cell.value}")
print(" ", " | ".join(row_values))
# 说明:保存工作簿
wb.save("cells_iterate.xlsx")
print("\n工作簿已保存:cells_iterate.xlsx")7. 样式设置:美化工作表 #
OpenPyXL 支持丰富的样式设置,包括字体、颜色、对齐、边框等。本节介绍常用的样式设置。
7.1 字体和颜色 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
Font() |
创建字体对象 | name:字体名称,size:字体大小,bold:是否粗体,color:字体颜色(RGB 十六进制) |
Font 对象 |
PatternFill() |
创建填充对象 | fill_type:填充类型(如 "solid"),fgColor:前景色(RGB 十六进制) |
PatternFill 对象 |
.font |
设置单元格的字体 | 无(属性),可赋值为 Font 对象 | 无 |
.fill |
设置单元格的填充 | 无(属性),可赋值为 PatternFill 对象 | 无 |
# -*- coding: utf-8 -*-
# 说明:演示如何设置字体和颜色
# 说明:导入 openpyxl 库和相关样式类
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入标题行数据
ws.append(["姓名", "部门", "绩效"])
ws.append(["张三", "研发", "A"])
ws.append(["李四", "市场", "B"])
ws.append(["王五", "销售", "A"])
# 说明:创建字体对象
# Font() 函数创建字体对象,可以设置字体名称、大小、颜色、粗体等属性
# bold=True 表示粗体
# color="FFFFFF" 表示白色(RGB 十六进制颜色码,FFFFFF 表示白色)
title_font = Font(
name="微软雅黑", # 字体名称(Windows)
size=12, # 字体大小
bold=True, # 是否粗体
color="FFFFFF" # 字体颜色(白色)
)
# 说明:创建填充对象
# PatternFill() 函数创建填充对象,可以设置单元格的背景色
# fill_type="solid" 表示纯色填充
# fgColor="4F81BD" 表示蓝色背景(RGB 十六进制颜色码)
title_fill = PatternFill(
fill_type="solid",
fgColor="4F81BD"
)
# 说明:设置标题行的样式
# 遍历第一行的所有单元格
for cell in ws[1]:
# 说明:font 属性设置单元格的字体
cell.font = title_font
# 说明:fill 属性设置单元格的填充(背景色)
cell.fill = title_fill
# 说明:设置数据行的样式(示例:设置绩效为 A 的行)
# 遍历第 2 到 4 行
for row_num in range(2, 5):
# 说明:获取绩效列(C 列)的单元格
performance_cell = ws.cell(row=row_num, column=3)
# 说明:如果绩效是 A,设置特殊样式
if performance_cell.value == "A":
# 说明:创建绿色填充
green_fill = PatternFill(fill_type="solid", fgColor="C6EFCE")
performance_cell.fill = green_fill
# 说明:创建粗体字体
bold_font = Font(bold=True)
performance_cell.font = bold_font
# 说明:保存工作簿
wb.save("styled_font.xlsx")
print("工作簿已保存:styled_font.xlsx")
print("已设置标题行样式(蓝色背景、白色粗体)")
print("已设置绩效 A 的样式(绿色背景、粗体)")7.2 对齐和边框 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
Alignment() |
创建对齐对象 | horizontal:水平对齐("left"、"center"、"right"),vertical:垂直对齐("top"、"center"、"bottom") |
Alignment 对象 |
Border() |
创建边框对象 | left、right、top、bottom:四个方向的边框线 |
Border 对象 |
Side() |
创建边框线对象 | style:边框样式("thin"、"medium"、"thick" 等) |
Side 对象 |
.alignment |
设置单元格的对齐 | 无(属性),可赋值为 Alignment 对象 | 无 |
.border |
设置单元格的边框 | 无(属性),可赋值为 Border 对象 | 无 |
# -*- coding: utf-8 -*-
# 说明:演示如何设置对齐和边框
# 说明:导入 openpyxl 库和相关样式类
from openpyxl import Workbook
from openpyxl.styles import Alignment, Border, Side
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入数据
ws.append(["姓名", "年龄", "工资"])
ws.append(["张三", 25, 8000])
ws.append(["李四", 30, 12000])
ws.append(["王五", 28, 10000])
# 说明:创建对齐对象
# Alignment() 函数创建对齐对象
# horizontal="center" 表示水平居中
# vertical="center" 表示垂直居中
center_align = Alignment(
horizontal="center", # 水平对齐:left(左)、center(中)、right(右)
vertical="center" # 垂直对齐:top(上)、center(中)、bottom(下)
)
# 说明:创建边框线对象
# Side() 函数创建边框线对象
# style="thin" 表示细线(其他选项:medium、thick 等)
thin_side = Side(style="thin")
# 说明:创建边框对象
# Border() 函数创建边框对象
# 可以设置四个方向的边框线:left(左)、right(右)、top(上)、bottom(下)
thin_border = Border(
left=thin_side, # 左边框
right=thin_side, # 右边框
top=thin_side, # 上边框
bottom=thin_side # 下边框
)
# 说明:设置所有单元格的对齐和边框
# 遍历所有有数据的行(1 到 4 行)
for row_num in range(1, 5):
# 说明:遍历每行的所有列(1 到 3 列)
for col_num in range(1, 4):
# 说明:获取单元格
cell = ws.cell(row=row_num, column=col_num)
# 说明:设置对齐
cell.alignment = center_align
# 说明:设置边框
cell.border = thin_border
# 说明:保存工作簿
wb.save("styled_align_border.xlsx")
print("工作簿已保存:styled_align_border.xlsx")
print("已设置所有单元格居中对齐和细边框")7.3 行高和列宽 #
本代码块中使用的 OpenPyXL 方法:
| 方法/属性 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.column_dimensions |
访问列尺寸对象 | 列字母(如 "A") | ColumnDimension 对象 |
.row_dimensions |
访问行尺寸对象 | 行号(如 1) | RowDimension 对象 |
.width |
设置列宽 | 无(属性),可直接赋值为数字 | 无 |
.height |
设置行高 | 无(属性),可直接赋值为数字 | 无 |
# -*- coding: utf-8 -*-
# 说明:演示如何设置行高和列宽
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入数据
ws.append(["姓名", "部门", "职位", "工资"])
ws.append(["张三", "研发部", "高级工程师", 15000])
ws.append(["李四", "市场部", "市场经理", 18000])
ws.append(["王五", "销售部", "销售总监", 20000])
# 说明:设置列宽
# column_dimensions[列字母] 访问指定列的尺寸对象
# width 属性设置列宽(数字表示字符宽度)
ws.column_dimensions["A"].width = 10 # A 列宽度为 10 个字符
ws.column_dimensions["B"].width = 12 # B 列宽度为 12 个字符
ws.column_dimensions["C"].width = 15 # C 列宽度为 15 个字符
ws.column_dimensions["D"].width = 10 # D 列宽度为 10 个字符
# 说明:设置行高
# row_dimensions[行号] 访问指定行的尺寸对象
# height 属性设置行高(数字表示磅值,约 72 磅 = 1 英寸)
ws.row_dimensions[1].height = 30 # 第一行(标题行)高度为 30 磅
ws.row_dimensions[2].height = 25 # 第二行高度为 25 磅
ws.row_dimensions[3].height = 25 # 第三行高度为 25 磅
ws.row_dimensions[4].height = 25 # 第四行高度为 25 磅
# 说明:批量设置列宽
# 可以使用循环批量设置多列的宽度
for col_letter in ["A", "B", "C", "D"]:
# 说明:如果列宽小于 12,设置为 12
if ws.column_dimensions[col_letter].width < 12:
ws.column_dimensions[col_letter].width = 12
# 说明:保存工作簿
wb.save("styled_dimensions.xlsx")
print("工作簿已保存:styled_dimensions.xlsx")
print("已设置列宽和行高")8. 公式计算 #
OpenPyXL 支持在单元格中写入 Excel 公式。当你在 Excel 中打开文件时,公式会自动计算。
8.1 基本公式 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
ws[坐标] |
访问单元格 | 坐标:如 "A1" |
Cell 对象 |
.value |
设置单元格的值(可以是公式字符串) | 无(属性),可直接赋值 | 无 |
# -*- coding: utf-8 -*-
# 说明:演示如何在工作表中写入公式
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入标题行
ws.append(["月份", "产品A", "产品B", "产品C", "总计"])
# 说明:写入数据行
# 第一行数据
ws.append(["一月", 1000, 800, 600])
# 说明:在总计列(E 列)写入公式
# 公式字符串以 "=" 开头,类似于 Excel 中的公式
# SUM(B2:D2) 表示对 B2 到 D2 的单元格求和
ws["E2"] = "=SUM(B2:D2)"
# 说明:第二行数据
ws.append(["二月", 1200, 950, 700])
ws["E3"] = "=SUM(B3:D3)"
# 说明:第三行数据
ws.append(["三月", 900, 1100, 800])
ws["E3"] = "=SUM(B3:D3)"
# 说明:在末尾添加平均行
# 使用 AVERAGE 函数计算平均值
ws.append(["平均值", "=AVERAGE(B2:B4)", "=AVERAGE(C2:C4)", "=AVERAGE(D2:D4)", "=AVERAGE(E2:E4)"])
# 说明:保存工作簿
wb.save("formula_basic.xlsx")
print("工作簿已保存:formula_basic.xlsx")
print("已写入公式:SUM(求和)和 AVERAGE(平均值)")
print("在 Excel 中打开文件时,公式会自动计算")8.2 常用公式示例 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
.value |
设置单元格的值(可以是公式字符串) | 无(属性),可直接赋值 | 无 |
# -*- coding: utf-8 -*-
# 说明:演示更多常用公式
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入学生成绩数据
ws.append(["姓名", "语文", "数学", "英语", "总分", "平均分", "最高分", "最低分"])
ws.append(["张三", 85, 90, 88, None, None, None, None])
ws.append(["李四", 92, 95, 90, None, None, None, None])
ws.append(["王五", 78, 85, 80, None, None, None, None])
# 说明:为每行添加公式
# 遍历第 2 到 4 行(数据行)
for row_num in range(2, 5):
# 说明:计算总分(SUM 函数)
ws.cell(row=row_num, column=5).value = f"=SUM(B{row_num}:D{row_num})"
# 说明:计算平均分(AVERAGE 函数)
ws.cell(row=row_num, column=6).value = f"=AVERAGE(B{row_num}:D{row_num})"
# 说明:计算最高分(MAX 函数)
ws.cell(row=row_num, column=7).value = f"=MAX(B{row_num}:D{row_num})"
# 说明:计算最低分(MIN 函数)
ws.cell(row=row_num, column=8).value = f"=MIN(B{row_num}:D{row_num})"
# 说明:在最后一行添加统计信息
ws.append(["统计", "=AVERAGE(B2:B4)", "=AVERAGE(C2:C4)", "=AVERAGE(D2:D4)", "=SUM(E2:E4)", "=AVERAGE(F2:F4)", None, None])
# 说明:保存工作簿
wb.save("formula_advanced.xlsx")
print("工作簿已保存:formula_advanced.xlsx")
print("已写入多种公式:")
print(" - SUM:求和")
print(" - AVERAGE:平均值")
print(" - MAX:最大值")
print(" - MIN:最小值")9. 读取大文件:优化性能 #
当处理大型 Excel 文件时,需要考虑性能问题。OpenPyXL 提供了只读模式和写入模式来优化性能。
9.1 只读模式读取 #
本代码块中使用的 OpenPyXL 方法:
| 方法 | 功能说明 | 常用参数 | 返回值 |
|---|---|---|---|
load_workbook() |
加载工作簿 | filename:文件路径,read_only:是否只读(True/False) |
Workbook 对象 |
.close() |
关闭工作簿 | 无 | 无 |
.iter_rows() |
遍历行 | values_only:是否只返回值(True/False) |
迭代器 |
# -*- coding: utf-8 -*-
# 说明:演示如何使用只读模式读取大文件
# 说明:导入 openpyxl 库
from openpyxl import Workbook, load_workbook
# 说明:先创建一个较大的测试文件
print("创建测试文件...")
wb_test = Workbook()
ws_test = wb_test.active
# 说明:写入标题行
ws_test.append(["ID", "姓名", "年龄", "城市"])
# 说明:写入大量测试数据(1000 行)
for i in range(1, 1001):
ws_test.append([i, f"用户{i}", 20 + (i % 50), f"城市{i % 10}"])
# 说明:保存测试文件
wb_test.save("large_file.xlsx")
print("测试文件已创建:large_file.xlsx(1000 行数据)")
# 说明:方法1:使用只读模式读取(推荐用于大文件)
# load_workbook() 的 read_only=True 参数开启只读模式
# 只读模式会显著降低内存占用,提高读取速度
print("\n方法1:只读模式读取")
wb_readonly = load_workbook("large_file.xlsx", read_only=True)
ws_readonly = wb_readonly.active
# 说明:使用 iter_rows() 遍历行
# values_only=True 表示只返回值,不返回 Cell 对象,进一步减少内存占用
count = 0
for row in ws_readonly.iter_rows(values_only=True):
count += 1
# 说明:只读取前 5 行作为示例
if count <= 5:
print(f" 第 {count} 行:{row}")
# 说明:如果只读模式,不能修改工作表
# 只能读取数据
# 说明:关闭工作簿(只读模式必须手动关闭)
wb_readonly.close()
print(f"\n总共读取 {count} 行数据")
# 说明:方法2:普通模式读取(适用于小文件)
print("\n方法2:普通模式读取(前 5 行)")
wb_normal = load_workbook("large_file.xlsx")
ws_normal = wb_normal.active
# 说明:普通模式可以修改数据
for row_num in range(1, 6):
row_values = []
for col_num in range(1, 5):
cell_value = ws_normal.cell(row=row_num, column=col_num).value
row_values.append(cell_value)
print(f" 第 {row_num} 行:{tuple(row_values)}")
# 说明:普通模式需要手动关闭(虽然 Python 垃圾回收会处理,但推荐手动关闭)
wb_normal.close()
print("\n性能建议:")
print(" - 大文件读取:使用 read_only=True")
print(" - 需要修改数据:使用普通模式")
print(" - 只读取值:使用 values_only=True")10. 实战案例:销售报表生成器 #
下面是一个完整的实战案例,综合运用前面学到的知识,创建一个销售报表生成器。
本代码块中使用的 OpenPyXL 方法总结:
| 方法/属性 | 功能说明 |
|---|---|
Workbook() |
创建工作簿 |
.active |
获取活动工作表 |
.title |
设置工作表名称 |
ws.append() |
添加行数据 |
ws[坐标] |
访问单元格 |
Font() |
创建字体对象 |
PatternFill() |
创建填充对象 |
Alignment() |
创建对齐对象 |
.save() |
保存工作簿 |
# -*- coding: utf-8 -*-
# 说明:实战案例 - 销售报表生成器
# 综合运用前面学到的所有知识,创建一个完整的销售报表
# 说明:导入所需的库
from datetime import datetime
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
def build_sales_report(filename: str) -> None:
"""
生成销售报表
参数:
filename (str): 输出文件名
"""
# 说明:准备销售数据
# 数据格式:(月份, 产品A销量, 产品B销量, 产品C销量)
sales_data = [
("一月", 1000, 1500, 800),
("二月", 1200, 1600, 900),
("三月", 1100, 1700, 850),
("四月", 1300, 1800, 950),
("五月", 1250, 1750, 900),
]
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
ws.title = "销售报表"
# 说明:设置标题行
headers = ["月份", "产品A", "产品B", "产品C", "总计", "平均"]
ws.append(headers)
# 说明:创建样式对象
# 标题行字体:白色、粗体
header_font = Font(name="微软雅黑", size=12, bold=True, color="FFFFFF")
# 标题行填充:深蓝色背景
header_fill = PatternFill(fill_type="solid", fgColor="1F4E78")
# 居中对齐
center_align = Alignment(horizontal="center", vertical="center")
# 细边框
thin_border = Border(
left=Side(style="thin"),
right=Side(style="thin"),
top=Side(style="thin"),
bottom=Side(style="thin")
)
# 说明:设置标题行样式
for cell in ws[1]:
cell.font = header_font
cell.fill = header_fill
cell.alignment = center_align
cell.border = thin_border
# 说明:写入数据行并添加公式
for idx, row_data in enumerate(sales_data, start=2):
# 说明:写入月份和三个产品的销量
ws.append([row_data[0], row_data[1], row_data[2], row_data[3], None, None])
# 说明:添加总计公式(E 列)
ws.cell(row=idx, column=5).value = f"=SUM(B{idx}:D{idx})"
# 说明:添加平均公式(F 列)
ws.cell(row=idx, column=6).value = f"=AVERAGE(B{idx}:D{idx})"
# 说明:设置数据行样式
for col_num in range(1, 7):
cell = ws.cell(row=idx, column=col_num)
cell.alignment = center_align
cell.border = thin_border
# 说明:添加总计行
total_row = len(sales_data) + 2
ws.cell(row=total_row, column=1).value = "总计"
ws.cell(row=total_row, column=2).value = f"=SUM(B2:B{total_row-1})"
ws.cell(row=total_row, column=3).value = f"=SUM(C2:C{total_row-1})"
ws.cell(row=total_row, column=4).value = f"=SUM(D2:D{total_row-1})"
ws.cell(row=total_row, column=5).value = f"=SUM(E2:E{total_row-1})"
ws.cell(row=total_row, column=6).value = f"=AVERAGE(F2:F{total_row-1})"
# 说明:设置总计行样式(突出显示)
total_font = Font(bold=True)
total_fill = PatternFill(fill_type="solid", fgColor="D9E1F2")
for col_num in range(1, 7):
cell = ws.cell(row=total_row, column=col_num)
cell.font = total_font
cell.fill = total_fill
cell.alignment = center_align
cell.border = thin_border
# 说明:设置列宽
ws.column_dimensions["A"].width = 12
ws.column_dimensions["B"].width = 10
ws.column_dimensions["C"].width = 10
ws.column_dimensions["D"].width = 10
ws.column_dimensions["E"].width = 10
ws.column_dimensions["F"].width = 10
# 说明:设置标题行高度
ws.row_dimensions[1].height = 25
# 说明:保存工作簿
wb.save(filename)
print(f"✓ 报表已生成:{filename}")
# 说明:主程序入口
if __name__ == "__main__":
# 说明:生成带时间戳的文件名
today = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"sales_report_{today}.xlsx"
# 说明:调用函数生成报表
build_sales_report(filename)
print("\n报表包含:")
print(" - 标题行(深蓝色背景、白色粗体)")
print(" - 数据行(包含公式计算总计和平均)")
print(" - 总计行(突出显示)")
print(" - 样式美化(边框、对齐、列宽)")11. 常见问题与排查 #
在使用 OpenPyXL 时,可能会遇到一些常见问题。本节提供解决方案。
11.1 文件损坏问题 #
问题:保存后的文件无法打开或提示损坏。
原因:通常是文件被其他程序占用,或者在写入过程中程序异常退出。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示如何避免文件损坏问题
# 说明:导入 openpyxl 库
from openpyxl import Workbook
import os
# 说明:方法1:使用 try-except 确保文件正确关闭
wb = Workbook()
ws = wb.active
ws["A1"] = "测试"
try:
# 说明:保存文件
wb.save("safe_save.xlsx")
print("文件已保存:safe_save.xlsx")
except Exception as e:
# 说明:如果保存失败,捕获异常
print(f"保存失败:{e}")
# 说明:方法2:检查文件是否被占用
def is_file_locked(filepath: str) -> bool:
"""
检查文件是否被占用
参数:
filepath (str): 文件路径
返回:
bool: 如果文件被占用返回 True,否则返回 False
"""
if not os.path.exists(filepath):
return False
try:
# 说明:尝试以写入模式打开文件
with open(filepath, "r+b"):
return False
except IOError:
# 说明:如果无法打开,说明文件被占用
return True
# 说明:使用示例
filepath = "test_file.xlsx"
if is_file_locked(filepath):
print(f"文件 {filepath} 被占用,请先关闭 Excel")
else:
# 说明:文件未被占用,可以安全保存
wb = Workbook()
ws = wb.active
ws["A1"] = "测试"
wb.save(filepath)
print("文件已安全保存")11.2 中文字体显示问题 #
问题:设置的中文字体不生效或显示异常。
原因:字体名称在系统中不存在。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示如何正确设置中文字体
# 说明:导入 openpyxl 库
from openpyxl import Workbook
from openpyxl.styles import Font
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入中文内容
ws["A1"] = "这是中文测试"
ws["A2"] = "Hello World"
# 说明:Windows 系统常用中文字体
# 如果字体不存在,OpenPyXL 会使用默认字体
windows_fonts = [
"微软雅黑", # Windows 默认中文字体
"宋体", # 传统中文字体
"黑体", # 粗体中文字体
]
# 说明:macOS 系统常用中文字体
macos_fonts = [
"PingFang SC", # macOS 默认中文字体
"STSong", # 宋体
"STHeiti", # 黑体
]
# 说明:尝试设置字体(根据系统选择)
# 在实际使用中,你需要根据运行环境选择合适的字体
try:
# 说明:Windows 用户可以使用
font = Font(name="微软雅黑", size=12)
except:
# 说明:macOS 用户可以使用
font = Font(name="PingFang SC", size=12)
# 说明:应用字体
ws["A1"].font = font
# 说明:保存文件
wb.save("font_test.xlsx")
print("文件已保存:font_test.xlsx")
print("提示:如果字体显示异常,请检查系统是否安装了该字体")11.3 公式不计算问题 #
问题:写入的公式在 Excel 中不自动计算。
原因:OpenPyXL 只写入公式字符串,Excel 会在打开文件时自动计算。
解决方案:
# -*- coding: utf-8 -*-
# 说明:说明公式计算的问题和解决方案
# 说明:导入 openpyxl 库
from openpyxl import Workbook
# 说明:创建新工作簿
wb = Workbook()
ws = wb.active
# 说明:写入数据
ws.append(["数字1", "数字2", "求和"])
ws.append([10, 20, "=SUM(A2:B2)"])
ws.append([30, 40, "=SUM(A3:B3)"])
# 说明:保存文件
wb.save("formula_test.xlsx")
print("文件已保存:formula_test.xlsx")
print("\n重要说明:")
print(" - OpenPyXL 只写入公式字符串,不会计算结果")
print(" - 当你用 Excel 打开文件时,公式会自动计算")
print(" - 如果需要立即得到计算结果,可以在 Python 中手动计算:")
# 说明:如果需要立即得到计算结果,可以手动计算
result = 10 + 20
ws["C2"].value = result # 直接写入计算结果而不是公式
print(f" - 例如:10 + 20 = {result}")
print(" - 可以直接写入计算结果而不是公式")11.4 性能优化建议 #
问题:处理大文件时速度慢或内存占用高。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示性能优化技巧
# 说明:导入 openpyxl 库
from openpyxl import Workbook, load_workbook
print("性能优化建议:")
print("\n1. 读取大文件时使用只读模式:")
print(" wb = load_workbook('large.xlsx', read_only=True)")
print("\n2. 遍历时使用 values_only=True:")
print(" for row in ws.iter_rows(values_only=True):")
print("\n3. 批量写入数据,避免逐个单元格操作:")
print(" # 好的方式:")
print(" ws.append([value1, value2, value3])")
print(" # 避免:")
print(" ws['A1'] = value1")
print(" ws['B1'] = value2")
print(" ws['C1'] = value3")
print("\n4. 完成后及时关闭工作簿:")
print(" wb.close()")
print("\n5. 如果只是读取值,使用 data_only=True:")
print(" wb = load_workbook('file.xlsx', data_only=True)")
# 说明:性能对比示例
print("\n性能对比示例:")
# 说明:慢的方式(逐个单元格写入)
print("\n慢的方式(逐个单元格):")
wb_slow = Workbook()
ws_slow = wb_slow.active
import time
start = time.time()
for i in range(1, 101):
ws_slow.cell(row=i, column=1, value=i)
ws_slow.cell(row=i, column=2, value=i*2)
slow_time = time.time() - start
print(f" 时间:{slow_time:.4f} 秒")
# 说明:快的方式(批量写入)
print("\n快的方式(批量写入):")
wb_fast = Workbook()
ws_fast = wb_fast.active
start = time.time()
for i in range(1, 101):
ws_fast.append([i, i*2])
fast_time = time.time() - start
print(f" 时间:{fast_time:.4f} 秒")
print(f" 提速:{slow_time/fast_time:.2f} 倍")