如何使用 Python openpyxl 包读取和写入 Excel 文件

我被代码海扁署名-非商业-禁演绎
阅读 13:15·字数 3978·发布 
Bilibili 空间
关注 950

运行本节中的示例,需要安装 Python 包openpyxl,你可以查看安装 Python openpyxl 包一段来了解相关信息。

Python openpyxl 包支持的 Excel 文件格式

无论使用包中的哪个函数或类,Pythonopenpyxl包只能读取和写入以下 Microsoft Excel 文件格式,.xlsx.xlsm(启用了宏的 Excel 文件),.xltx(Excel 模板文件),.xltm(启用了宏的 Excel 模板文件)。

对于旧的 Excel 文件格式.xls,可以尝试采用 Python 包xlrdxlwt进行操作,或者将.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,他们位于同一目录中。

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函数的实参。

data_only.py
# 请将命令行跳转至 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 工作簿对象Workbooksave方法或对 Excel 单元格进行写入会导致异常,但并非所有的修改操作都是不可行的(比如,可以修改工作表的标题),只不过这些改变无法被保存。

下面,我们通过只读的方式来打开 Excel 文件Hello.xlsx,然后修改工作表的标题。

read_only.py
# 请将命令行跳转至 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,并不表示openpyxlWorkbook对象中的单元格会丢失全部样式,因为一些样式可能不属于富文本格式,不针对 Excel 单元格中的文本块(Text Block),比如,为整个单元格设置的文本颜色。

使用 Python openpyxl 包写入(保存)Excel 文件

使用 Python 模块openpyxl.writer.excelsave_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会被覆盖。

save.py
# 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对象两次。

write_only.py
# 导入函数 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 工作簿对象将拥有两个工作表,由于他们都是不可见的,因此保存将失败。

no_sheet.py
# 导入 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 文件。

close.py
# 请将命令行跳转至 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