如何使用 Python openpyxl 套件操作 Excel 範圍?openpyxl CellRange 物件介紹

閱讀 19:00·字數 5700·發佈 
Youtube 頻道
訂閱 133

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-hant/openpyxl/ranges·codebeatme/office-programming·GitHub