如何使用 Python openpyxl 包操作 Excel 工作簿?openpyxl Workbook 对象介绍

我被代码海扁署名-非商业-禁演绎
阅读 17:19·字数 5196·发布 
Bilibili 空间
关注 960

本节并不包含 Microsoft Excel 文件的读取和写入,如果你想了解相关内容,可以查看如何使用 Python openpyxl 包读取和写入 Excel 文件一节。

此外,本节内容也不涉及与 Excel 样式,计算或图表相关的内容。

Python openpyxl 包中的 Excel 工作簿对象 Workbook

Pythonopenpyxl包中的Workbook类,对应了我们通常所说的 Excel 工作簿,使用Workbook对象可以获取 Excel 工作簿的相关信息,或对其中的内容进行操作。

如果正确调用了openpyxl包的load_workbook函数,那么其返回值将是一个Workbook对象。

使用 Python openpyxl 包的 Workbook 对象创建 Excel 工作簿

当你希望创建一个新的 Excel 工作簿时,就需要使用 Pythonopenpyxl包的Workbook类的构造器。

Workbook(write_only=False, iso_dates=False)

write_only 参数

write_only参数表示被创建的 Excel 工作簿是否是只写的,只写工作簿仅支持整行数据的写入,不支持对单个单元格的操作,默认为False(不是只写的),如果设置为True,那么仅能对Workbook对象执行一次保存操作。

iso_dates 参数

iso_dates参数对应的属性iso_dates,被官方标记为尚未完成。

使用构造器创建的 Python openpyxl 包的 Workbook 对象可能不包含工作表 Sheet

在默认情况下,使用构造器创建的openpyxlWorkbook对象将拥有一个名称为Sheet的 Excel 工作表。当构造器参数write_onlyTrue时,只写Workbook对象不会包含任何工作表,如果在Workbook对象执行保存操作时依然如此,那么openpyxl将尝试为Workbook对象添加一个 Excel 工作表。

create_workbook.py
from openpyxl import Workbook

# 创建一个新的工作簿,默认包含 Sheet 工作表 workbook = Workbook() print(workbook['Sheet'])
# 只写工作簿不包含任何工作表 write_only_workbook = Workbook(True) print(write_only_workbook.worksheets)
<Worksheet "Sheet">
[]

使用 Python openpyxl 包的 Workbook 对象获取和设置当前活动的 Excel 工作表

Pythonopenpyxl包的Workbook对象的active属性,可用于获取或设置 Excel 工作簿当前活动的工作表,在获取当前活动的工作表时,active属性的返回值可能是空值None

workbook.active
workbook.active = worksheet

worksheet 值

worksheet是需要设置为活动的Worksheet对象或 Excel 工作表的索引(int整数类型),0表示第一个工作表,-1表示倒数第一个工作表。

为 Python openpyxl 包的 Workbook 对象设置的当前活动 Excel 工作表需要存在且可见

如果将Worksheet对象设置为当前活动的 Excel 工作表,那么Worksheet对应的工作表应该存在于 Excel 工作簿中,并且是可见的,否则会抛出异常ValueError: Worksheet is not in the workbookValueError: Only visible sheets can be made active。如果通过工作表索引设置当前活动的 Excel 工作表,则不存在抛出异常的情况,但可能导致openpyxlWorkbook对象的active属性返回空值None,因为索引指示的位置没有 Excel 工作表。

在 Microsoft Excel 文件School.xlsx中,工作表ClassAClassBClassC依次排列。

active.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import load_workbook
workbook = load_workbook('School.xlsx')
print(f'当前活动 {workbook.active}')

# 将倒数第一个工作表设置为当前活动的工作表 workbook.active = -1 print(f'当前活动 {workbook.active}') # 将 ClassB 设置为当前活动的工作表 workbook.active = workbook['ClassB'] print(f'当前活动 {workbook.active}')
# 没有索引为 100 的工作表 workbook.active = 100 print(f'当前活动 {workbook.active}')
当前活动 <Worksheet "ClassA">
当前活动 <Worksheet "ClassC">
当前活动 <Worksheet "ClassB">
当前活动 None

使用 Python openpyxl 包的 Workbook 对象获取 Excel 工作表

Pythonopenpyxl包的Workbook对象实现了__getitem__方法,你可以方便的使用[]运算符并传递工作表的名称(不支持传递工作表索引),来获取 Excel 工作簿中特定的工作表。如果指定的工作表在 Excel 工作簿中不存在,那么将导致异常KeyError: 'Worksheet … does not exist.'

如果需要通过索引或切片表达式,来获取工作簿中的某个或某些工作表,那么可以使用openpyxl包的Workbook对象的worksheets属性,该属性返回一个包含所有工作表对象的 Python 列表。

workbook.worksheets[slice]

slice 值

slice为需要获取的某个 Excel 工作表的索引,或表示某些 Excel 工作表的切片表达式。

由于可以采用[]运算符,因此openpyxl已弃用Workbook类的get_sheet_by_name方法。

get_sheets.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
import openpyxl
workbook = openpyxl.load_workbook('School.xlsx')

# 获取工作表 ClassA sheet = workbook['ClassA'] print(sheet) # 获取第二个和其之后的所有工作表 sheets = workbook.worksheets[1:] print(sheets)
<Worksheet "ClassA">
[<Worksheet "ClassB">, <Worksheet "ClassC">]

使用 Python openpyxl 包的 Workbook 对象创建 Excel 工作表

Pythonopenpyxl包的Workbook对象的create_sheet方法,可用于为 Excel 工作簿创建新的 Excel 工作表,并将其插入到指定位置,原本位于该位置的工作表将向后移动,如果他存在的话。create_sheet方法的返回值是新工作表对应的Worksheet对象。

workbook.create_sheet(title=None, index=None)

title 参数

title参数为新 Excel 工作表的名称(标题),如果省略或设置为None,则openpyxl会将新工作表命名为Sheet。需要指出,工作表的名称可能拥有一个数字后缀,用于确保其不与其他名称重复。

index 参数

index参数为新 Excel 工作表在工作簿的插入位置,0表示插入到当前第一个工作表之前,-1表示插入到当前最后一个工作表之前(新的 Excel 工作表将位于倒数第二)。如果该参数被省略或设置为None,则openpyxl会将新工作表放置于末尾,如果该参数表示的插入位置不存在工作表,则新的 Excel 工作表会出现在开头,当index参数为负数时,或出现在末尾,当index参数为正数时。

由于被创建的Workbook对象,默认拥有一个名称为Sheet的 Excel 工作表,因此,在未指定名称的情况下,方法create_sheet创建的新工作表将被命名为Sheet1Sheet2Sheet3等。

create_sheet.py
import openpyxl
workbook = openpyxl.Workbook()

# 由于已经存在 Sheet,因此新工作表名称为 Sheet1,他将被放置在末尾 new_sheet1 = workbook.create_sheet() print(f'新工作表名称 {new_sheet1.title}') print(f'最后一个工作表的名称 {workbook.worksheets[-1].title}')
# 新工作表名称为 Sheet2,他将被放置在开头 workbook.create_sheet(index=0) print(f'第一个工作表的名称 {workbook.worksheets[0].title}')
# 新工作表名称为 New,他将被放置在目前倒数第二个工作表 Sheet 之前 new = workbook.create_sheet('New', -2) print(workbook.worksheets)
新工作表名称 Sheet1
最后一个工作表的名称 Sheet1
第一个工作表的名称 Sheet2
[<Worksheet "Sheet2">, <Worksheet "New">, <Worksheet "Sheet">, <Worksheet "Sheet1">]

使用 Python openpyxl 包的 Workbook 对象复制 Excel 工作表

Pythonopenpyxl包的Workbook对象的copy_worksheet方法,可用于复制 Excel 工作簿中的 Excel 工作表,并将得到的工作表副本添加至 Excel 工作簿的末尾,副本的名称通常以Copy结尾。copy_worksheet方法的返回值是 Excel 工作表副本对应的Worksheet对象。

workbook.copy_worksheet(from_worksheet)

from_worksheet 参数

from_worksheet参数为被复制的 Excel 工作表对应的Worksheet对象。

Python openpyxl 包仅能复制 Workbook 对象自身拥有的 Excel 工作表

openpyxlWorkbook对象的copy_worksheet方法,仅能复制包含在Workbook对象中的 Excel 工作表,尝试将其他 Excel 工作簿对象的工作表传递给参数from_worksheet,会导致异常ValueError: Cannot copy between worksheets from different workbooks

copy_sheet.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
import openpyxl
workbook = openpyxl.load_workbook('School.xlsx')

# 复制工作表 ClassA workbook.copy_worksheet(workbook['ClassA']) print(f'ClassA 副本的名称为 {workbook.worksheets[-1].title}')
# 尝试复制其他工作簿的工作表 newbook = openpyxl.Workbook() # ERROR 无法复制自身不拥有的工作表 workbook.copy_worksheet(newbook['Sheet'])
ClassA 副本的名称为 ClassA Copy

ValueError: Cannot copy between worksheets from different workbooks

使用 Python openpyxl 包的 Workbook 对象移动 Excel 工作表

Pythonopenpyxl包的Workbook对象的move_sheet方法,可用于移动 Excel 工作簿中的工作表,从而改变工作表之间的顺序。事实上,openpyxl通过先删除后插入来完成工作表的移动,他会计算被移动的 Excel 工作表的插入位置,并将其放置在插入位置对应的工作表之前。

workbook.move_sheet(sheet, offset=0)

sheet 参数

sheet参数为需要移动的 Excel 工作表的名称或其对应的Worksheet对象。

offset 参数

offset参数为 Excel 工作表插入位置与原索引之间的偏移值,1表示插入位置为原索引加1-1表示插入位置为原索引减1,使用0的效果相当于不移动。如果插入位置最终为负数,那么移动的效果可能并非你的预期,比如,当 Excel 工作簿拥有多个工作表时,对索引为0的第一个工作表使用-1,他会被放置在倒数第二的位置,而不是倒数第一,这与使用create_sheet方法所产生的效果类似。

在移动 Excel 工作表ClassA之后,工作表ClassB将位于开头,此时指定参数offset-1,会使ClassB被移动至倒数第二的位置,因为计算的插入位置为-1,即倒数第一的ClassA之前。

move_sheet.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import open
workbook = open('School.xlsx')
print(workbook.worksheets)

# 工作表 ClassA 将位于末尾 workbook.move_sheet('ClassA', 100) print(workbook.worksheets) # 当前第一个工作表 ClassB 将被移动至倒数第二的位置 b = workbook['ClassB'] workbook.move_sheet(b, -1) print(workbook.worksheets)
[<Worksheet "ClassA">, <Worksheet "ClassB">, <Worksheet "ClassC">]
[<Worksheet "ClassB">, <Worksheet "ClassC">, <Worksheet "ClassA">]
[<Worksheet "ClassC">, <Worksheet "ClassB">, <Worksheet "ClassA">]

使用 Python openpyxl 包的 Workbook 对象移除 Excel 工作表

使用 Pythonopenpyxl包的Workbook对象的remove方法,或使用del关键字和[]运算符,并给出工作表的名称,可移除 Excel 工作簿中的工作表。

workbook.remove(worksheet)
del workbook[name]

worksheet 参数

worksheet参数为需要移除的 Excel 工作表对应的Worksheet对象。

name 值

name为需要移除的 Excel 工作表的名称。

openpyxl已弃用Workbook类的remove_sheet方法。

remove_sheet.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import open
workbook = open('School.xlsx')

# 删除工作表 ClassA,ClassB del workbook['ClassA'] workbook.remove(workbook['ClassB']) print(workbook.worksheets)
[<Worksheet "ClassC">]

使用 Python openpyxl 包的 Workbook 对象获取 Excel 工作表的名称和索引

Pythonopenpyxl包的Workbook对象的sheetnames属性,返回一个包含所有 Excel 工作表名称的 Python 列表。

workbook.sheetnames[slice]

slice 值

slice为需要获取名称的某个或某些 Excel 工作表的索引或切片表达式。

openpyxl已弃用Workbook类的get_sheet_names方法。

Pythonopenpyxl包的Workbook对象的index方法,可用于获取指定 Excel 工作表在工作簿中的索引,第一个工作表的索引为0

workbook.index(worksheet)

worksheet 参数

worksheet参数为需要获取索引的 Excel 工作表对应的Worksheet对象。

openpyxl已弃用Workbook类的get_index方法。

name_and_index.py
# 请将命令行跳转至 School.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import load_workbook
workbook = load_workbook('School.xlsx')

# 获取工作表的名称和索引 print(f'第二个工作表的名称 {workbook.sheetnames[1]}') print(f'工作表 ClassC 的索引 {workbook.index(workbook["ClassC"])}')
第二个工作表的名称 ClassB
工作表 ClassC 的索引 2

使用 Python openpyxl 包的 Workbook 对象获取 Excel 工作簿的日期系统

Pythonopenpyxl包的Workbook对象的excel_base_date属性或epoch属性,可用于获取 Excel 工作簿日期系统的开始日期。

workbook.excel_base_date

什么是 Excel 工作簿的日期系统?

每一个 Excel 工作簿都指定了自己的日期系统,不同的日期系统具有不同的开始日期,Excel 会将日期计算为相对于开始日期的偏移值,因此,同一日期在不同日期系统中存储的数据并不相同。

date_system.py
# 请将命令行跳转至 1904.xlsx 所在的目录,然后运行此脚本文件
from openpyxl import load_workbook
workbook = load_workbook('1904.xlsx')

# 获取工作簿的日期系统 print(workbook.excel_base_date)
1904-01-01 00:00:00

使用 Python openpyxl 包的 Workbook 对象判断 Excel 工作簿是否为模板

Pythonopenpyxl包的Workbook拥有类变量template和实例变量is_template,他们的值始终为True,官方似乎没有阐明其具体作用,因此templateis_template不能用于判断 Excel 工作簿是否是一个模板,你需要使用Workbook对象的mime_type属性来完成此目标,该属性用来说明 Excel 工作簿的 MIME 类型,当其包含template时,可将工作簿视为模板。

workbook.mime_type

is_template.py
# 请将命令行跳转至 Hello.xltx 所在的目录,然后运行此脚本文件
from openpyxl import load_workbook
workbook = load_workbook('Hello.xltx')

# 工作簿是否为模板? print('template' in workbook.mime_type)
True

Python openpyxl 包的 Workbook 对象的其他特性

以下是与openpyxlWorkbook对象相关,但不太重要的一些特性,这些特性可能并非从 Microsoft Excel 文件获取,只是由openpyxl包给出了固定值。

encoding 变量

Workbook对象的encoding变量用于表示 Excel 工作簿的编码,他由openpyxl指定为'utf-8'

path 变量

Pythonopenpyxl包所处理的 Excel 文件本身是一个压缩文件,Workbook对象的path变量表示其在压缩文件中的路径,他由openpyxl指定为'/xl/workbook.xml'

vba_archive 变量

Workbook对象的vba_archive变量是一个ZipFile对象,表示与 VBA 相关的压缩文件,该压缩文件包含在 Excel 文件中,通常的名称为vbaProject.bin

data_only,read_only,write_only 属性

Workbook对象的data_onlyread_onlywrite_only属性是只读的,他们由读取 Excel 文件或创建openpyxlWorkbook对象时给出的实参来决定,由于相关文章已经进行了讲解,这里不再累述。

源码

src/zh/openpyxl/workbooks·codebeatme/office-programming·GitHub