如何使用 Python openpyxl 包读取和写入 Excel 文件
运行本节中的示例,需要安装 Python 包openpyxl
,你可以查看安装 Python openpyxl 包一段来了解相关信息。
Python openpyxl 包支持的 Excel 文件格式
无论使用包中的哪个函数或类,Pythonopenpyxl
包只能读取和写入以下 Microsoft Excel 文件格式,.xlsx
,.xlsm
(启用了宏的 Excel 文件),.xltx
(Excel 模板文件),.xltm
(启用了宏的 Excel 模板文件)。
对于旧的 Excel 文件格式.xls
,可以尝试采用 Python 包xlrd
和xlwt
进行操作,或者将.xls
转换为.xlsx
格式的 Excel 文件。
使用 Python openpyxl 包读取 Excel 文件
你可以使用 Pythonopenpyxl
包中的load_workbook
函数或其别名open
(非 Python 内置函数open
),来读取 Excel 文件中的数据,该函数的返回值是一个可操作 Excel 数据的工作簿对象Workbook
。
load_workbook(filename, read_only=False, keep_vba=KEEP_VBA, data_only=False, keep_links=True, rich_text=False)
- filename 参数
filename
参数为需要读取的 Excel 文件的路径(绝对路径或相对路径),或者与 Excel 文件相关并采用了二进制模式的file-like
(类文件)对象。比如,调用 Python 内置函数open
(非load_workbook
的别名),并采用rb
模式创建的file-like
对象。- read_only 参数
read_only
参数默认为False
,用来指示load_workbook
函数返回的openpyxl
工作簿对象Workbook
是否是只读的。如果设置为True
,那么你将无法通过Workbook
对象保存对 Excel 数据的改动,这可能会改进一些性能,因为与写入相关的逻辑以及一些复杂的内容(比如,Excel 单元格中的超链接)将被忽略。- keep_vba 参数
在非测试环境下,
keep_vba
参数的默认值为False
,表示不会读取 Excel 文件中与 VBA(Visual Basic for Applications)有关的内容。如果设置为True
,那么 Excel 文件中关于 VBA 的内容将被openpyxl
读取到Workbook
对象中,当然,这并不意味着你可以通过 Pythonopenpyxl
包执行 VBA 中的代码,或使用 VBA 所实现的功能。- data_only 参数
data_only
参数(默认值为False
)用于指示是读取 Excel 单元格的公式的计算结果,还是读取 Excel 单元格的公式,当openpyxl
读取的 Excel 文件包含具有公式的单元格时。如果设置为True
,那么openpyxl
将读取公式的计算结果,这意味着Workbook
对象中的相关 Excel 单元格不再拥有公式。- keep_links 参数
keep_links
参数的默认值为True
,用于指示在 Pythonopenpyxl
包读取 Excel 文件时,是否读取 Excel 外部链接数据的缓存,比如,另一个 Excel 文件的工作表的某个单元格的值。如果设置为False
,那么外部链接数据的缓存不会被读取到Workbook
对象中,当缓存过大时,这种做法将是有效的。- rich_text 参数
rich_text
参数用于指示在 Pythonopenpyxl
包读取 Excel 文件时,是否保留单元格中的富文本格式(Rich Text Formatting,RFT),其默认值为False
(不保留富文本格式),这意味着Workbook
对象中相关 Excel 单元格的富文本格式将丢失。当rich_text
参数为True
时,保存Workbook
对象可能会失败。
下面,我们准备了名称为Hello.xlsx
的 Excel 文件,以及读取 Excel 文件的 Python 脚本文件read.py
,他们位于同一目录中。
# 请将命令行跳转至 Hello.xlsx 所在的目录,然后运行此脚本文件
# 导入函数 load_workbook
from openpyxl import load_workbook
# 读取 Excel 文件
workbook = load_workbook('Hello.xlsx')
# 获取工作表 1.1班 中的单元格 A1,B1,C1,B4,C4 并显示
worksheet = workbook['1.1班']
name = worksheet['A1'].value
age = worksheet['B1'].value
score = worksheet['C1'].value
print(f'第一个学生 {name} {age} {score}')
avg_age = worksheet['B4'].value
avg_score = worksheet['C4'].value
print(f'平均值公式 {avg_age} {avg_score}')
第一个学生 小小 13 100
平均值公式 =AVERAGE(B1:B3) =AVERAGE(C1:C3)
Python openpyxl 包通过 read 特性来判断 filename 参数是否为 file-like 对象
在读取 Excel 文件的过程中,openpyxl
会检查load_workbook
函数的参数filename
是否具有特性read
,如果具有,那么filename
参数将被视为 Pythonfile-like
对象,read
特性将作为方法被调用,以获取 Excel 文件的二进制格式数据。
在下面的代码中,我们使用open
函数打开了 Excel 文件Hello.xlsx
,并将返回的对象作为load_workbook
函数的实参。
# 请将命令行跳转至 Hello.xlsx 所在的目录,然后运行此脚本文件
# 导入函数 load_workbook
from openpyxl import load_workbook
# 使用 open 函数打开 Excel 文件
xlsx = open('Hello.xlsx', 'rb')
workbook = load_workbook(xlsx, data_only=True)
# 读取单元格 B4,C4 的公式计算结果并显示
worksheet = workbook['1.1班']
avg_age = worksheet['B4'].value
avg_score = worksheet['C4'].value
print(f'平均值 {avg_age} {avg_score}')
平均值 13 96.3333333333333
将 read_only 参数设置为 True 后,Workbook 及其相关对象依然可以进行某些修改操作
虽然将load_workbook
函数的read_only
参数设置为True
后,执行 Excel 工作簿对象Workbook
的save
方法或对 Excel 单元格进行写入会导致异常,但并非所有的修改操作都是不可行的(比如,可以修改工作表的标题),只不过这些改变无法被保存。
下面,我们通过只读的方式来打开 Excel 文件Hello.xlsx
,然后修改工作表的标题。
# 请将命令行跳转至 Hello.xlsx 所在的目录,然后运行此脚本文件
# 导入包 openpyxl
import openpyxl
# 以只读方式打开 Excel 文件,并修改工作表标题
workbook = openpyxl.open('Hello.xlsx', True)
worksheet = workbook['1.1班']
worksheet.title = '1.2班'
# ERROR 只读的 Workbook 对象不能修改单元格的值
worksheet['A1'].value = '一个好人'
AttributeError: Cell is read only
rich_text 参数为 False 不意味着 Workbook 对象中的相关 Excel 单元格会丢失全部样式
load_workbook
函数的rich_text
参数为False
,并不表示openpyxl
的Workbook
对象中的单元格会丢失全部样式,因为一些样式可能不属于富文本格式,不针对 Excel 单元格中的文本块(Text Block),比如,为整个单元格设置的文本颜色。
使用 Python openpyxl 包写入(保存)Excel 文件
使用 Python 模块openpyxl.writer.excel
的save_workbook
函数,或Workbook
对象的save
方法,可以将Workbook
对象保存为 Microsoft Excel 文件。
save_workbook(workbook, filename)
save(filename)
- workbook 参数
workbook
参数为需要进行保存的Workbook
对象。- filename 参数
filename
参数为 Excel 文件的绝对路径或相对路径,如果路径指向的文件已经存在,那么他将被覆盖。
下面,我们尝试在修改 Excel 单元格A1
后,再次将Workbook
对象保存为文件Overwrite.xlsx
,原有的Overwrite.xlsx
会被覆盖。
# Overwrite.xlsx 会被保存至命令行的当前工作目录
# 导入包 openpyxl
import openpyxl
# 创建 Workbook 并先后保存两次
workbook = openpyxl.Workbook()
workbook.save('Overwrite.xlsx')
workbook['Sheet']['A1'].value = '你好!'
workbook.save('Overwrite.xlsx')
write_only 属性为 True 的 Workbook 对象仅能被保存一次
当你直接创建 Pythonopenpyxl
包的Workbook
对象,并将其构造器的write_only
参数设置为True
时,被创建的Workbook
对象将是只写的(write_only
属性为True
),对于只写的Workbook
对象,只能调用其save
方法或使用save_workbook
函数保存一次,多次保存将导致异常。
在下面的例子中,我们尝试保存只写的Workbook
对象两次。
# 导入函数 save_workbook 和类 Workbook
from openpyxl.writer.excel import save_workbook
from openpyxl import Workbook
# 创建 Workbook 对象并保存
workbook = Workbook(True)
workbook.save('New.xlsx')
# ERROR 只能保存一次
save_workbook(workbook, 'New.xlsx')
被保存为 Excel 文件的 Workbook 对象需要拥有至少一个可见的工作表
无论是使用openpyxl.writer.excel
模块的save_workbook
函数,还是Workbook
对象的save
方法,Pythonopenpyxl
包要求 Excel 工作簿对象拥有至少一个可见的工作表,即至少一个sheet_state
属性为'visible'
的Worksheet
对象,否则,保存为 Excel 文件将是不可行的,异常IndexError: At least one sheet must be visible
会被抛出。
在下面的代码中,Excel 工作簿对象将拥有两个工作表,由于他们都是不可见的,因此保存将失败。
# 导入 Workbook 类
from openpyxl import Workbook
# 创建一个 Workbook 对象,将其中的工作表设置为隐藏
workbook = Workbook()
workbook['Sheet'].sheet_state = 'hidden'
workbook.create_sheet().sheet_state = 'hidden'
# ERROR 无法保存没有可见工作表的 Workbook 对象
workbook.save('nosheet.xlsx')
IndexError: At least one sheet must be visible
关闭 Python openpyxl 包打开的 Excel 文件
如果你在使用 Pythonopenpyxl
包的load_workbook
函数时,将read_only
参数设置为True
,获取了只读的Workbook
对象,那么调用Workbook
对象的close
方法,可以关闭与 Excel 工作簿相关的ZipFile
对象,此后,读取 Excel 工作表中的单元格将是不可行的,但工作表自身的一些相关信息依然可以访问,比如工作表的名称(标题)。
close 方法对 write_only 属性为 True 的 Workbook 对象的影响不明显
虽然在官方的说明中,close
方法会对只写的Workbook
对象产生影响,但这种影响并不明显(似乎是不存在的),你可以将一行数据写入调用了close
方法的Workbook
对象,并通过save
方法保存他们。
在对Workbook
对象调用close
方法之前或之后,写入数据均没有问题,并可以调用save
方法将Workbook
对象保存为 Excel 文件。
# 请将命令行跳转至 Hello.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import Workbook, load_workbook
# 创建只写的工作簿
w_workbook = Workbook(True)
w_workbook.create_sheet()
w_workbook['Sheet'].append(['Hello', 'World'])
# 调用 close 方法之后,再次写入一行数据,并保存
w_workbook.close()
w_workbook['Sheet'].append(['你好', '世界'])
w_workbook.save('Close.xlsx')
# 创建只读的工作簿
r_workbook = load_workbook('Hello.xlsx', True)
print(r_workbook['1.1班']['A1'].value)
# 调用 close 方法之后,读取单元格 A1
r_workbook.close()
# ERROR 无法读取 A1 单元格
print(r_workbook['1.1班']['A1'])
小小
…
ValueError: Attempt to use ZIP archive that was already closed
源码
src/zh/openpyxl/excel_files·codebeatme/office-programming·GitHub
讲解视频
使用 Python openpyxl 包读取 Excel 工作簿文件的工作表,获取和设置 Excel 单元格的值,以及保存 Excel 工作簿文件·BiliBili