URLhttps://learnscript.net/zh-hant/office-programming/openpyxl/ranges/
    複製連結移至說明  範例

    如何使用 openpyxl 處理 Excel 範圍?CellRange 物件介紹

    閱讀 17:23·字數 5216·更新 
    Youtube 頻道
    訂閱 375

    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_colmin_rowmax_colmax_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_colmin_rowmax_colmax_rowtitle,在未作出修改時,他們的值與傳遞給CellRange建構子的引數的值相同。

    CellRange 物件所表示的範圍的最大列和最大欄不能小於最小列和最小欄

    無論你是否為CellRange物件指定了參數range_stringCellRange物件的max_rowmax_col變數都不應該小於min_rowmin_col變數,否則可能會引發例外狀況ValueError: … must be greater than …

    Worksheet 物件的 move_range 方法將忽略 CellRange 物件的 title 變數

    CellRange物件的title變數,會被Worksheet物件的move_range方法忽視,這表示通過某個Worksheet物件來移動另一個工作表中的範圍是不可行的。

    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')

    取得 Excel 範圍的界限和位址

    CellRange物件的bounds屬性,可以取得CellRange物件所表示的 Excel 範圍的界限,其傳回值是一個依次包含變數min_colmin_rowmax_colmax_row的 Python 元組,即範圍的最小欄,最小列,最大欄,最大列。

    CellRange物件的topbottomleftright屬性,可以取得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

    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

    取得和設定 Excel 範圍的大小

    你可以簡單的通過CellRange物件的變數min_colmin_rowmax_colmax_row,來取得或設定CellRange物件所表示的 Excel 範圍的大小,不過,CellRange的以下特性可實作相同的效果。

    CellRange物件的size屬性,可以取得CellRange物件所表示的 Excel 範圍的大小(範圍包含的列和欄的個數),其傳回值是一個格式為{'columns':cs,'rows':rs}的 Python 字典物件,其中cs為範圍包含的欄的數量,rs為範圍包含的列的數量。

    cellrange.size

    CellRange物件的expandshrink方法,可用於改變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 參數

    downbottom參數為範圍最下方一列向外或向內移動的列數,設定為負數表示反向操作。

    left 參數

    left參數為範圍最左邊一欄向外或向內移動的欄數,設定為負數表示反向操作。

    up,top 參數

    uptop參數為範圍最上方一列向外或向內移動的列數,設定為負數表示反向操作。

    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

    周遊 Excel 範圍中的儲存格

    當然,要周遊 Excel 工作表中的儲存格,最好最簡便的方法是使用Worksheet物件的[]運算子,不過,你依然可以借助CellRange物件的rowscolscells屬性來完成相同的工作。

    不同於Worksheet物件的[]運算子,CellRange物件的rowscols屬性傳回的是一個可按照列或欄周遊儲存格位置的 Python 建置器物件,每一列或每一欄將作為一個 Python 串列存在,每個串列都包含一系列格式為(x,y)的元組,其中x表示儲存格位於哪一列,y表示儲存格位於哪一欄。

    CellRange物件的cells屬性的傳回值是一個itertools.product物件,該物件包含了 Excel 範圍內所有儲存格的位置資訊,這些位置資訊的順序與rows屬性相同,只不過他們不再按照列來進行劃分(每一列作為一個 Python 串列)。

    cellrange.rows
    cellrange.cols
    cellrange.cells

    工作表

    關於如何取得 Excel 儲存格,你可以檢視取得 Excel 儲存格一段。

    在下面的程式碼中,我們通過CellRange物件的rowscells屬性周遊了範圍內的儲存格,其中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

    移動 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_shiftrow_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會被移動到工作表之外,因此引發了例外狀況。

    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

    判斷 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的子集和超集,因為兩個範圍相同。

    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

    計算 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

    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