如何使用 Python openpyxl 套件操作 Excel 範圍?openpyxl CellRange 物件介紹
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_col
,min_row
,max_col
,max_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_col
,min_row
,max_col
,max_row
,title
,在未作出修改時,他們的值與傳遞給CellRange
建構子的引數的值相同。
openpyxl 套件的 CellRange 物件所表示的 Excel 範圍的最大列和最大欄不能小於最小列和最小欄
無論你是否為 Pythonopenpyxl
套件的CellRange
物件指定了參數range_string
,CellRange
物件的max_row
和max_col
變數都不應該小於min_row
和min_col
變數,否則可能會引發例外狀況ValueError: … must be greater than …
。
openpyxl 套件的 Worksheet 物件的 move_range 方法將忽略 CellRange 物件的 title 變數
Pythonopenpyxl
套件的CellRange
物件的title
變數,會被Worksheet
物件的move_range
方法忽視,這表示通過某個Worksheet
物件來移動另一個 Excel 工作表中的範圍是不可行的。
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')
取得 Python openpyxl 套件的 CellRange 物件所表示的 Excel 範圍的邊界和位址
Pythonopenpyxl
套件的CellRange
物件的bounds
屬性,可以取得CellRange
物件所表示的 Excel 範圍的邊界,其傳回值是一個依次包含變數min_col
,min_row
,max_col
和max_row
的 Python 元組,即範圍的最小欄,最小列,最大欄,最大列。
Pythonopenpyxl
套件的CellRange
物件的top
,bottom
,left
,right
屬性,可以取得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
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_col
,min_row
,max_col
,max_row
,來取得或設定CellRange
物件所表示的 Excel 範圍的大小,不過,CellRange
的以下特性可實作相同的效果。
Pythonopenpyxl
套件的CellRange
物件的size
屬性,可以取得CellRange
物件所表示的 Excel 範圍的大小(範圍包含的列和欄的個數),其傳回值是一個格式為{'columns':cs,'rows':rs}
的 Python 字典物件,其中cs
為 Excel 範圍包含的欄的數量,rs
為 Excel 範圍包含的列的數量。
cellrange.size
Pythonopenpyxl
套件的CellRange
物件的expand
和shrink
方法,可用於改變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 參數
down
或bottom
參數為 Excel 範圍最下方一列向外或向內移動的列數,設定為負數表示反向操作。- left 參數
left
參數為 Excel 範圍最左邊一欄向外或向內移動的欄數,設定為負數表示反向操作。- up,top 參數
up
或top
參數為 Excel 範圍最上方一列向外或向內移動的列數,設定為負數表示反向操作。
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
物件的rows
,cols
或cells
屬性來完成相同的任務。
不同於Worksheet
物件的[]
運算子,CellRange
物件的rows
,cols
屬性傳回的是一個可按照列或欄周遊儲存格位置的 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
物件的rows
和cells
屬性周遊了範圍內的 Excel 儲存格,其中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
移動 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_shift
或row_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
會被移動到工作表之外,因此引發了例外狀況。
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
的子集和超集,因為兩個範圍相同。
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
。
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