如何使用 openpyxl 處理 Excel 範圍?CellRange 物件介紹
訂閱 480
openpyxl Excel 範圍物件 CellRange
openpyxl套件中的CellRange類別,屬於模組openpyxl.worksheet.cell_range,表示 Excel 工作表中的範圍,可以在移動範圍的操作中指定需要移動的範圍。openpyxl套件中的MultiCellRange類別,同樣屬於模組openpyxl.worksheet.cell_range,可表示 Excel 工作表中的多個範圍。
openpyxl套件中的MergedCellRange類別,屬於模組openpyxl.worksheet.merge,繼承自CellRange,可用於表示 Excel 工作表中被合併的儲存格範圍,他擁有本文講述的CellRange物件的所有特性。
建立 Excel 範圍
你並不需要主動建立CellRange物件,大多數情況下,使用 Excel 範圍的位址可以達成相同的目標,比如,在移動某個範圍時,將字串'A1:C3'作為參數。如果確實需要CellRange類別的執行個體,那麽其建構子如下。
CellRange(range_string=None, min_col=None, min_row=None, max_col=None, max_row=None, title=None)
- range_string 參數
range_string參數為範圍的位址(運算式),如果該參數被省略或為None,那麽需要提供參數min_col,min_row,max_col,max_row。- min_col 參數
min_col參數是一個整數,用於說明範圍開始於第幾欄,1表示第一欄。- min_row 參數
min_row參數是一個整數,用於說明範圍開始於第幾列,1表示第一列。- max_col 參數
max_col參數是一個整數,用於說明範圍結束於第幾欄,1表示第一欄。- max_row 參數
max_row參數是一個整數,用於說明範圍結束於第幾列,1表示第一列。- title 參數
title參數用於指定範圍所在的工作表,如果該參數被省略或為None,那麽範圍屬於目前工作表。
CellRange 物件的變數
CellRange物件擁有變數min_col,min_row,max_col,max_row,title,在未作出修改時,他們的值與傳遞給CellRange建構子的引數的值相同。
CellRange 物件所表示的範圍的最大列和最大欄不能小於最小列和最小欄
無論你是否為CellRange物件指定了參數range_string,CellRange物件的max_row和max_col變數都不應該小於min_row和min_col變數,否則可能會引發例外狀況ValueError: … must be greater than …。
Worksheet 物件的 move_range 方法將忽略 CellRange 物件的 title 變數
CellRange物件的title變數,會被Worksheet物件的move_range方法忽視,這表示通過某個Worksheet物件來移動另一個工作表中的範圍是不可行的。
Excel 檔案Data.xlsx包含了兩個工作表Fruit和Trees,雖然在建立CellRange物件時,我們指定了參數title,但move_range方法並不會移動工作表Trees中的範圍。
# 讀取 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')取得 Excel 範圍的界限和位址
CellRange物件的bounds屬性,可以取得CellRange物件所表示的 Excel 範圍的界限,其傳回值是一個依次包含變數min_col,min_row,max_col和max_row的 Python 元組,即範圍的最小欄,最小列,最大欄,最大列。
CellRange物件的top,bottom,left,right屬性,可以取得CellRange物件所表示的 Excel 範圍的最上方的一列,最下方的一列,最左邊的一欄,最右邊的一欄的儲存格的位置資訊。他們的傳回值是一個 Python 串列,串列中包含了一系列格式為(x,y)的元組,其中x表示儲存格位於哪一列,y表示儲存格位於哪一欄。
cellrange.bounds
cellrange.top
cellrange.bottom
cellrange.left
cellrange.right
CellRange物件的coord屬性,可以取得CellRange物件所表示的 Excel 範圍的位址(比如,A1:C3),該位址不包含title變數所表示的工作表名稱。
cellrange.coord
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取得和設定 Excel 範圍的大小
你可以簡單的通過CellRange物件的變數min_col,min_row,max_col,max_row,來取得或設定CellRange物件所表示的 Excel 範圍的大小,不過,CellRange的以下特性可實作相同的效果。
CellRange物件的size屬性,可以取得CellRange物件所表示的 Excel 範圍的大小(範圍包含的列和欄的個數),其傳回值是一個格式為{'columns':cs,'rows':rs}的 Python 字典物件,其中cs為範圍包含的欄的數量,rs為範圍包含的列的數量。
cellrange.size
CellRange物件的expand和shrink方法,可用於改變CellRange物件所表示的 Excel 範圍的大小,其中expand方法可以擴展範圍,shrink方法可以縮小範圍。
cellrange.expand(right=0, down=0, left=0, up=0)
cellrange.shrink(right=0, bottom=0, left=0, top=0)
- right 參數
right參數為範圍最右邊一欄向外或向內移動的欄數,設定為負數表示反向操作。- down,bottom 參數
down或bottom參數為範圍最下方一列向外或向內移動的列數,設定為負數表示反向操作。- left 參數
left參數為範圍最左邊一欄向外或向內移動的欄數,設定為負數表示反向操作。- up,top 參數
up或top參數為範圍最上方一列向外或向內移動的列數,設定為負數表示反向操作。
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周遊 Excel 範圍中的儲存格
當然,要周遊 Excel 工作表中的儲存格,最好最簡便的方法是使用Worksheet物件的[]運算子,不過,你依然可以借助CellRange物件的rows,cols或cells屬性來完成相同的工作。
不同於Worksheet物件的[]運算子,CellRange物件的rows,cols屬性傳回的是一個可按照列或欄周遊儲存格位置的 Python 建置器物件,每一列或每一欄將作為一個 Python 串列存在,每個串列都包含一系列格式為(x,y)的元組,其中x表示儲存格位於哪一列,y表示儲存格位於哪一欄。
CellRange物件的cells屬性的傳回值是一個itertools.product物件,該物件包含了 Excel 範圍內所有儲存格的位置資訊,這些位置資訊的順序與rows屬性相同,只不過他們不再按照列來進行劃分(每一列作為一個 Python 串列)。
cellrange.rows
cellrange.cols
cellrange.cells
工作表
關於如何取得 Excel 儲存格,你可以檢視取得 Excel 儲存格一段。
在下面的程式碼中,我們通過CellRange物件的rows和cells屬性周遊了範圍內的儲存格,其中cells不需要再次使用for陳述式。
# 讀取 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移動 Excel 範圍的位置
CellRange物件的shift方法,可用於移動CellRange物件所表示的 Excel 範圍。
cellrange.shift(col_shift=0, row_shift=0)
- col_shift 參數
col_shift參數為範圍移動的欄數,1表示向右移動一欄,-1表示向左移動一欄。- row_shift 參數
row_shift參數為範圍移動的列數,1表示向下移動一列,-1表示向上移動一列。
不能將 CellRange 物件所表示的範圍移動到工作表之外
如果給出的col_shift或row_shift參數會導致CellRange物件所表示的範圍被移動到工作表之外,那麽shift方法將引發例外狀況ValueError: Invalid shift value: col_shift=…, row_shift=…,範圍不會被移動。
CellRange 物件的 shift 方法不會移動範圍內的儲存格
很明顯的,CellRange物件的shift方法不會移動範圍內的儲存格,他只是改變了範圍的位置,如果你希望移動儲存格,那麽可以使用Worksheet物件的move_range方法。
工作表
關於如何移動 Excel 儲存格,你可以檢視移動 Excel 儲存格一段。
在下面的程式碼中,第一次呼叫shift方法,範圍B2:D4被移動至C3:E5,第二次呼叫shift方法,範圍C3:E5會被移動到工作表之外,因此引發了例外狀況。
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判斷 Excel 範圍之間的關系
CellRange物件的isdisjoint方法,可用於判斷CellRange物件所表示的 Excel 範圍與其他範圍的交集是否為空,即是否兩個範圍沒有相同位址的儲存格。
CellRange物件的issubset方法,可用於判斷CellRange物件所表示的 Excel 範圍是否為其他範圍的子集,即是否等於或包含在其他範圍中。
CellRange物件的issuperset方法,可用於判斷CellRange物件所表示的 Excel 範圍是否為其他範圍的超集,即是否等於或包含了其他範圍。
cellrange.isdisjoint(other)
cellrange.issubset(other)
cellrange.issuperset(other)
- other 參數
other參數為參與關系判斷的其他範圍對應的CellRange物件。如果other對應的CellRange物件擁有有效的title變數,並且其值與原範圍對應的CellRange物件的title變數的值不同,那麽將引發例外狀況ValueError: Cannot work with ranges from different worksheets。
在下面的範例中,範圍B2:D4是範圍B2:D4的子集和超集,因為兩個範圍相同。
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計算 Excel 範圍
CellRange物件的intersection方法,可用於計算並傳回一個新的CellRange物件,該物件表示的 Excel 範圍為原範圍與目標範圍的交集。如果原範圍與目標範圍的交集為空,那麽將引發例外狀況ValueError: Range … doesn't intersect …。
CellRange物件的union方法,可用於計算並傳回一個新的CellRange物件(其title變數的值與原CellRange物件的title變數的值相同),該物件表示的 Excel 範圍為原範圍與目標範圍的並集。
cellrange.intersection(other)
cellrange.union(other)
- other 參數
other參數為參與計算的目標範圍對應的CellRange物件。對於union方法,如果other對應的CellRange物件擁有有效的title變數,並且其值與原範圍對應的CellRange物件的title變數的值不同,那麽將引發例外狀況ValueError: Cannot work with ranges from different worksheets。
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