如何使用 Python openpyxl 包操作 Excel 区域?openpyxl CellRange 对象介绍

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

Python openpyxl 包中的 Excel 区域对象 CellRange

Pythonopenpyxl包中的CellRange类,属于模块openpyxl.worksheet.cell_range,表示 Excel 工作表中的区域,可以在移动区域的操作中指定需要移动的区域。openpyxl包中的MultiCellRange类,同样属于模块openpyxl.worksheet.cell_range,可表示 Excel 工作表中的多个区域。

Pythonopenpyxl包中的MergedCellRange类,属于模块openpyxl.worksheet.merge,继承自CellRange,可用于表示 Excel 工作表中被合并的单元格区域,他拥有本文讲述的CellRange对象的所有特性。

使用 Python openpyxl 包的 CellRange 对象创建 Excel 区域

你并不需要主动创建openpyxl包的CellRange对象,大多数情况下,使用 Excel 区域的地址可以达成相同的目标,比如,在移动某个区域时,将字符串'A1:C3'作为参数。如果确实需要 Pythonopenpyxl包的CellRange类的实例,那么其构造器如下。

CellRange(range_string=None, min_col=None, min_row=None, max_col=None, max_row=None, title=None)

range_string 参数

range_string参数为 Excel 区域的地址(表达式),如果该参数被省略或为None,那么需要提供参数min_colmin_rowmax_colmax_row

min_col 参数

min_col参数是一个整数,用于说明 Excel 区域开始于第几列,1表示第一列。

min_row 参数

min_row参数是一个整数,用于说明 Excel 区域开始于第几行,1表示第一行。

max_col 参数

max_col参数是一个整数,用于说明 Excel 区域结束于第几列,1表示第一列。

max_row 参数

max_row参数是一个整数,用于说明 Excel 区域结束于第几行,1表示第一行。

title 参数

title参数用于指定 Excel 区域所在的工作表,如果该参数被省略或为None,那么 Excel 区域属于当前工作表。

Python openpyxl 包的 CellRange 对象的变量

Pythonopenpyxl包的CellRange对象拥有变量min_colmin_rowmax_colmax_rowtitle,在未作出修改时,他们的值与传递给CellRange构造器的实参的值相同。

openpyxl 包的 CellRange 对象所表示的 Excel 区域的最大行和最大列不能小于最小行和最小列

无论你是否为 Pythonopenpyxl包的CellRange对象指定了参数range_stringCellRange对象的max_rowmax_col变量都不应该小于min_rowmin_col变量,否则可能会引发异常ValueError: … must be greater than …

openpyxl 包的 Worksheet 对象的 move_range 方法将忽略 CellRange 对象的 title 变量

Pythonopenpyxl包的CellRange对象的title变量,会被Worksheet对象的move_range方法忽视,这表示通过某个Worksheet对象来移动另一个 Excel 工作表中的区域是不可行的。

Excel 文件Data.xlsx包含了两个工作表FruitTrees,虽然在创建CellRange对象时,我们指定了参数title,但move_range方法并不会移动工作表Trees中的区域。

move.py
# 读取 Excel 文件 Data.xlsx 中的工作表 Fruit
from openpyxl import load_workbook
wb = load_workbook('Data.xlsx')
ws = wb['Fruit']

from openpyxl.worksheet.cell_range import CellRange # 创建区域 Trees!A1:B2,其中 Trees 不会发挥作用 range = CellRange(min_col=1, min_row=1, max_col=2, max_row=2, title='Trees') # 移动工作表 Fruit 的区域 A1:B2,而不是工作表 Trees ws.move_range(range, 1, 1)
wb.save('Move.xlsx')

获取 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域的边界和地址

Pythonopenpyxl包的CellRange对象的bounds属性,可以获取CellRange对象所表示的 Excel 区域的边界,其返回值是一个依次包含变量min_colmin_rowmax_colmax_row的 Python 元组,即区域的最小列,最小行,最大列,最大行。

Pythonopenpyxl包的CellRange对象的topbottomleftright属性,可以获取CellRange对象所表示的 Excel 区域的最上方的一行,最下方的一行,最左边的一列,最右边的一列的单元格的位置信息。他们的返回值是一个 Python 列表,列表中包含了一系列格式为(x,y)的元组,其中x表示单元格位于哪一行,y表示单元格位于哪一列。

cellrange.bounds
cellrange.top
cellrange.bottom
cellrange.left
cellrange.right

Pythonopenpyxl包的CellRange对象的coord属性,可以获取CellRange对象所表示的 Excel 区域的地址(比如,A1:C3),该地址不包含title变量所表示的 Excel 工作表名称。

cellrange.coord

range.py
from openpyxl.worksheet.cell_range import CellRange

# 创建区域 B2:D4 range = CellRange('B2:D4') # 显示区域的边界 print(range.bounds) print(f'最上方一行的单元格的位置信息 {range.top}') print(f'最下方一行的单元格的位置信息 {range.bottom}') print(f'最左边一行的单元格的位置信息 {range.left}') print(f'最右边一行的单元格的位置信息 {range.right}')
# 创建区域 C2:J4,工作表名称为 SheetA range = CellRange(min_col=3, min_row=2, max_col=10, max_row=4, title='SheetA') # 显示区域的地址 print(range.coord)
(2, 2, 4, 4)
最上方一行的单元格的位置信息 [(2, 2), (2, 3), (2, 4)]
最下方一行的单元格的位置信息 [(4, 2), (4, 3), (4, 4)]
最左边一行的单元格的位置信息 [(2, 2), (3, 2), (4, 2)]
最右边一行的单元格的位置信息 [(2, 4), (3, 4), (4, 4)]
C2:J4

获取和设置 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域的大小

你可以简单的通过CellRange对象的变量min_colmin_rowmax_colmax_row,来获取或设置CellRange对象所表示的 Excel 区域的大小,不过,CellRange的以下特性可实现相同的效果。

Pythonopenpyxl包的CellRange对象的size属性,可以获取CellRange对象所表示的 Excel 区域的大小(区域包含的行和列的个数),其返回值是一个格式为{'columns':cs,'rows':rs}的 Python 字典对象,其中cs为 Excel 区域包含的列的数量,rs为 Excel 区域包含的行的数量。

cellrange.size

Pythonopenpyxl包的CellRange对象的expandshrink方法,可用于改变CellRange对象所表示的 Excel 区域的大小,其中expand方法可以扩展 Excel 区域,shrink方法可以缩小 Excel 区域。

cellrange.expand(right=0, down=0, left=0, up=0)
cellrange.shrink(right=0, bottom=0, left=0, top=0)

right 参数

right参数为 Excel 区域最右边一列向外或向内移动的列数,设置为负数表示反向操作。

down,bottom 参数

downbottom参数为 Excel 区域最下方一行向外或向内移动的行数,设置为负数表示反向操作。

left 参数

left参数为 Excel 区域最左边一列向外或向内移动的列数,设置为负数表示反向操作。

up,top 参数

uptop参数为 Excel 区域最上方一行向外或向内移动的行数,设置为负数表示反向操作。

size.py
from openpyxl.worksheet.cell_range import CellRange

# 创建区域 B2:D4 range = CellRange('B2:D4') # 显示区域大小 print(range.size)
# 最右边列向内移动 1 列,最下边行向外移动 1 行,最左边列向外移动 1 列,最上边行向内移动 1 行 range.expand(-1, 1, 1, -1) print(range.coord) # 最右边列向外移动 1 列,最下边行向内移动 1 行,最左边列向内移动 1 列,最上边行向外移动 1 行 range.shrink(-1, 1, 1, -1) print(range.coord)
{'columns': 3, 'rows': 3}
A3:C5
B2:D4

遍历 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域中的单元格

当然,要遍历 Excel 工作表中的单元格,最好最简便的方法是使用openpyxl包的Worksheet对象的[]运算符,不过,你依然可以借助 Pythonopenpyxl包的CellRange对象的rowscolscells属性来完成相同的任务。

不同于Worksheet对象的[]运算符,CellRange对象的rowscols属性返回的是一个可按照行或列遍历单元格位置的 Python 生成器对象,每一行或每一列将作为一个 Python 列表存在,每个列表都包含一系列格式为(x,y)的元组,其中x表示单元格位于哪一行,y表示单元格位于哪一列。

openpyxl包的CellRange对象的cells属性的返回值是一个itertools.product对象,该对象包含了 Excel 区域内所有单元格的位置信息,这些位置信息的顺序与rows属性相同,只不过他们不再按照行来进行划分(每一行作为一个 Python 列表)。

cellrange.rows
cellrange.cols
cellrange.cells

工作表

关于如何获取 Excel 单元格,你可以查看使用 Python openpyxl 包的 Worksheet 对象获取 Excel 单元格一段。

在下面的代码中,我们通过CellRange对象的rowscells属性遍历了区域内的 Excel 单元格,其中cells不需要再次使用for语句。

iterate.py
# 读取 Excel 文件 Data.xlsx 中的工作表 Trees
from openpyxl import load_workbook
wb = load_workbook('Data.xlsx')
ws = wb['Trees']

from openpyxl.worksheet.cell_range import CellRange # 创建区域 A1:B2 range = CellRange('A1:B2')
# 借助 CellRange 的 row 属性遍历单元格 for row in range.rows: # x 和 y 分别表示单元格位于哪一行和哪一列 for x, y in row: c = ws.cell(x, y) print(f'{c.coordinate}={c.value}')
# 借助 CellRange 的 cells 属性遍历单元格 for x, y in range.cells: c = ws.cell(x, y) print(f'({x}, {y})={c.value}')
A1=苹果树
B1=10
A2=梨树
B2=20
(1, 1)=苹果树
(1, 2)=10
(2, 1)=梨树
(2, 2)=20

移动 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域的位置

Pythonopenpyxl包的CellRange对象的shift方法,可用于移动CellRange对象所表示的 Excel 区域。

cellrange.shift(col_shift=0, row_shift=0)

col_shift 参数

col_shift参数为 Excel 区域移动的列数,1表示向右移动一列,-1表示向左移动一列。

row_shift 参数

row_shift参数为 Excel 区域移动的行数,1表示向下移动一行,-1表示向上移动一行。

不能将 openpyxl 包的 CellRange 对象所表示的 Excel 区域移动到工作表之外

如果给出的col_shiftrow_shift参数会导致CellRange对象所表示的 Excel 区域被移动到工作表之外,那么shift方法将引发异常ValueError: Invalid shift value: col_shift=…, row_shift=…,Excel 区域不会被移动。

Python openpyxl 包的 CellRange 对象的 shift 方法不会移动 Excel 区域内的单元格

很明显的,CellRange对象的shift方法不会移动 Excel 区域内的单元格,他只是改变了区域的位置,如果你希望移动单元格,那么可以使用Worksheet对象的move_range方法。

工作表

关于如何移动 Excel 单元格,你可以查看使用 Python openpyxl 包的 Worksheet 对象移动 Excel 单元格一段。

在下面的代码中,第一次调用shift方法,区域B2:D4被移动至C3:E5,第二次调用shift方法,区域C3:E5会被移动到工作表之外,因此引发了异常。

shift.py
from openpyxl.worksheet.cell_range import CellRange

# 创建区域 B2:D4 range = CellRange('B2:D4') # 向右下方移动区域 range.shift(1, 1) print(range.coord)
# ERROR 移动后区域将超出工作表的范围 range.shift(row_shift=-3)
C3:E5

ValueError: Invalid shift value: col_shift=0, row_shift=-3

判断 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域之间的关系

Pythonopenpyxl包的CellRange对象的isdisjoint方法,可用于判断CellRange对象所表示的 Excel 区域与其他 Excel 区域的交集是否为空,即是否两个 Excel 区域没有相同地址的单元格。

Pythonopenpyxl包的CellRange对象的issubset方法,可用于判断CellRange对象所表示的 Excel 区域是否为其他 Excel 区域的子集,即是否等于或包含在其他 Excel 区域中。

Pythonopenpyxl包的CellRange对象的issuperset方法,可用于判断CellRange对象所表示的 Excel 区域是否为其他 Excel 区域的超集,即是否等于或包含了其他 Excel 区域。

cellrange.isdisjoint(other)
cellrange.issubset(other)
cellrange.issuperset(other)

other 参数

other参数为参与关系判断的其他 Excel 区域对应的CellRange对象。如果other对应的CellRange对象拥有有效的title变量,并且其值与原区域对应的CellRange对象的title变量的值不同,那么将引发异常ValueError: Cannot work with ranges from different worksheets

在下面的示例中,区域B2:D4是区域B2:D4的子集和超集,因为两个区域相同。

relationship.py
from openpyxl.worksheet.cell_range import CellRange

# 创建区域 B2:D4,然后判断他与其他区域的关系 range = CellRange('B2:D4') print(f'B2:D4 与 A1:B2 的交集为空?{range.isdisjoint(CellRange("A1:B2"))}') print(f'B2:D4 与 F4:H5 的交集为空?{range.isdisjoint(CellRange("F4:H5"))}')
print(f'B2:D4 是否为 A1:D4 的子集?{range.issubset(CellRange("A1:D4"))}') print(f'B2:D4 是否为 B2:D4 的子集?{range.issubset(CellRange("B2:D4"))}')
print(f'B2:D4 是否为 C3:C3 的超集?{range.issuperset(CellRange("C3:C3"))}') print(f'B2:D4 是否为 B2:D4 的超集?{range.issuperset(CellRange("B2:D4"))}')
B2:D4 与 A1:B2 的交集为空?False
B2:D4 与 F4:H5 的交集为空?True
B2:D4 是否为 A1:D4 的子集?True
B2:D4 是否为 B2:D4 的子集?True
B2:D4 是否为 A1:D4 的超集?True
B2:D4 是否为 C3:C3 的超集?True

计算 Python openpyxl 包的 CellRange 对象所表示的 Excel 区域

Pythonopenpyxl包的CellRange对象的intersection方法,可用于计算并返回一个新的CellRange对象,该对象表示的 Excel 区域为原区域与目标区域的交集。如果原区域与目标区域的交集为空,那么将引发异常ValueError: Range … doesn't intersect …

Pythonopenpyxl包的CellRange对象的union方法,可用于计算并返回一个新的CellRange对象(其title变量的值与原CellRange对象的title变量的值相同),该对象表示的 Excel 区域为原区域与目标区域的并集。

cellrange.intersection(other)
cellrange.union(other)

other 参数

other参数为参与计算的目标 Excel 区域对应的CellRange对象。对于union方法,如果other对应的CellRange对象拥有有效的title变量,并且其值与原区域对应的CellRange对象的title变量的值不同,那么将引发异常ValueError: Cannot work with ranges from different worksheets

calculate.py
from openpyxl.worksheet.cell_range import CellRange

# 创建区域 B2:D4,然后与其他区域进行计算 range = CellRange('B2:D4') print(f'B2:D4 与 A1:B2 的交集:{range.intersection(CellRange("A1:B2"))}')
print(f'B2:D4 与 A1:D4 的并集:{range.union(CellRange("A1:D4"))}') print(f'B2:D4 与 A1:A1 的并集:{range.union(CellRange("A1:A1"))}')
try: # ERROR 两个区域没有交集 range.intersection(CellRange('A1:A1')) except Exception as err: print(err)
try: # ERROR 目标区域的 title 有效并且与原区域不同 range.union(CellRange('A1:A1', title='Other')) except Exception as err: print(err)
B2:D4 与 A1:B2 的交集:B2
B2:D4 与 A1:D4 的并集:A1:D4
B2:D4 与 A1:A1 的并集:A1:D4
# 下面的第二个 B2:D4 应该是 A1:A1,这可能是 openpyxl 的一个 BUG
Range B2:D4 doesn't intersect B2:D4
Cannot work with ranges from different worksheets

源码

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