如何使用 Python openpyxl 套件操作 Excel 活頁簿?openpyxl Workbook 物件介紹

閱讀 17:33·字數 5269·發佈 
Youtube 頻道
訂閱 133

本節並不包含 Microsoft Excel 檔案的讀取和寫入,如果你想了解相關內容,可以檢視如何使用 Python openpyxl 套件讀取和寫入 Excel 檔案一節。

此外,本節內容也不涉及與 Excel 樣式,計算或圖表相關的內容。

Python openpyxl 套件中的 Excel 活頁簿物件 Workbook

Pythonopenpyxl套件中的Workbook類別,對應了我們通常所說的 Excel 活頁簿,使用Workbook物件可以取得 Excel 活頁簿的相關資訊,或對其中的內容進行操作。

如果正確呼叫了openpyxl套件的load_workbook函式,那麽其傳回值將是一個Workbook物件。

使用 Python openpyxl 套件的 Workbook 物件建立 Excel 活頁簿

當你希望建立一個新的 Excel 活頁簿時,就需要使用 Pythonopenpyxl套件的Workbook類別的建構子。

Workbook(write_only=False, iso_dates=False)

write_only 參數

write_only參數表示被建立的 Excel 活頁簿是否是唯寫的,唯寫活頁簿僅支援整列資料的寫入,不支援對單個儲存格的操作,預設為False(不是唯寫的),如果設定為True,那麽僅能對Workbook物件執行一次儲存操作。

iso_dates 參數

iso_dates參數對應的屬性iso_dates,被官方標記為尚未完成。

使用建構子建立的 Python openpyxl 套件的 Workbook 物件可能不包含工作表 Sheet

在預設情況下,使用建構子建立的openpyxlWorkbook物件將擁有一個名稱為Sheet的 Excel 工作表。當建構子參數write_onlyTrue時,唯寫Workbook物件不會包含任何工作表,如果在Workbook物件執行儲存操作時依然如此,那麽openpyxl將嘗試為Workbook物件新增一個 Excel 工作表。

create_workbook.py
from openpyxl import Workbook

# 建立一個新的活頁簿,預設包含 Sheet 工作表 workbook = Workbook() print(workbook['Sheet'])
# 唯寫活頁簿不包含任何工作表 write_only_workbook = Workbook(True) print(write_only_workbook.worksheets)
<Worksheet "Sheet">
[]

使用 Python openpyxl 套件的 Workbook 物件取得和設定目前使用中的 Excel 工作表

Pythonopenpyxl套件的Workbook物件的active屬性,可用於取得或設定 Excel 活頁簿目前使用中的工作表,在取得目前使用中的工作表時,active屬性的傳回值可能是空值None

workbook.active
workbook.active = worksheet

worksheet 值

worksheet是需要設定為使用中的Worksheet物件或 Excel 工作表的索引(int整數型別),0表示第一個工作表,-1表示倒數第一個工作表。

為 Python openpyxl 套件的 Workbook 物件設定的目前使用中 Excel 工作表需要存在且可見

如果將Worksheet物件設定為目前使用中的 Excel 工作表,那麽Worksheet對應的工作表應該存在於 Excel 活頁簿中,並且是可見的,否則會擲回例外狀況ValueError: Worksheet is not in the workbookValueError: Only visible sheets can be made active。如果通過工作表索引設定目前使用中的 Excel 工作表,則不存在擲回例外狀況的情況,但可能導致openpyxlWorkbook物件的active屬性傳回空值None,因為索引指示的位置沒有 Excel 工作表。

在 Microsoft Excel 檔案School.xlsx中,工作表ClassAClassBClassC依次排列。

active.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import load_workbook
workbook = load_workbook('School.xlsx')
print(f'目前使用中 {workbook.active}')

# 將倒數第一個工作表設定為目前使用中的工作表 workbook.active = -1 print(f'目前使用中 {workbook.active}') # 將 ClassB 設定為目前使用中的工作表 workbook.active = workbook['ClassB'] print(f'目前使用中 {workbook.active}')
# 沒有索引為 100 的工作表 workbook.active = 100 print(f'目前使用中 {workbook.active}')
目前使用中 <Worksheet "ClassA">
目前使用中 <Worksheet "ClassC">
目前使用中 <Worksheet "ClassB">
目前使用中 None

使用 Python openpyxl 套件的 Workbook 物件取得 Excel 工作表

Pythonopenpyxl套件的Workbook物件實作了__getitem__方法,你可以方便的使用[]運算子並傳遞工作表的名稱(不支援傳遞工作表索引),來取得 Excel 活頁簿中特定的工作表。如果指定的工作表在 Excel 活頁簿中不存在,那麽將導致例外狀況KeyError: 'Worksheet … does not exist.'

如果需要通過索引或配量運算式,來取得活頁簿中的某個或某些工作表,那麽可以使用openpyxl套件的Workbook物件的worksheets屬性,該屬性傳回一個包含所有工作表物件的 Python 串列。

workbook.worksheets[slice]

slice 值

slice為需要取得的某個 Excel 工作表的索引,或表示某些 Excel 工作表的配量運算式。

由於可以采用[]運算子,因此openpyxl已取代Workbook類別的get_sheet_by_name方法。

get_sheets.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
import openpyxl
workbook = openpyxl.load_workbook('School.xlsx')

# 取得工作表 ClassA sheet = workbook['ClassA'] print(sheet) # 取得第二個和其之後的所有工作表 sheets = workbook.worksheets[1:] print(sheets)
<Worksheet "ClassA">
[<Worksheet "ClassB">, <Worksheet "ClassC">]

使用 Python openpyxl 套件的 Workbook 物件建立 Excel 工作表

Pythonopenpyxl套件的Workbook物件的create_sheet方法,可用於為 Excel 活頁簿建立新的 Excel 工作表,並將其插入到指定位置,原本位於該位置的工作表將向後移動,如果他存在的話。create_sheet方法的傳回值是新工作表對應的Worksheet物件。

workbook.create_sheet(title=None, index=None)

title 參數

title參數為新 Excel 工作表的名稱(標題),如果省略或設定為None,則openpyxl會將新工作表命名為Sheet。需要指出,工作表的名稱可能擁有一個數值尾碼,用於確保其不與其他名稱重複。

index 參數

index參數為新 Excel 工作表在活頁簿的插入位置,0表示插入到目前第一個工作表之前,-1表示插入到目前最後一個工作表之前(新的 Excel 工作表將位於倒數第二)。如果該參數被省略或設定為None,則openpyxl會將新工作表放置於末尾,如果該參數表示的插入位置不存在工作表,則新的 Excel 工作表會出現在開頭,當index參數為負數時,或出現在末尾,當index參數為正數時。

由於被建立的Workbook物件,預設擁有一個名稱為Sheet的 Excel 工作表,因此,在未指定名稱的情況下,方法create_sheet建立的新工作表將被命名為Sheet1Sheet2Sheet3等。

create_sheet.py
import openpyxl
workbook = openpyxl.Workbook()

# 由於已經存在 Sheet,因此新工作表名稱為 Sheet1,他將被放置在末尾 new_sheet1 = workbook.create_sheet() print(f'新工作表名稱 {new_sheet1.title}') print(f'最後一個工作表的名稱 {workbook.worksheets[-1].title}')
# 新工作表名稱為 Sheet2,他將被放置在開頭 workbook.create_sheet(index=0) print(f'第一個工作表的名稱 {workbook.worksheets[0].title}')
# 新工作表名稱為 New,他將被放置在目前倒數第二個工作表 Sheet 之前 new = workbook.create_sheet('New', -2) print(workbook.worksheets)
新工作表名稱 Sheet1
最後一個工作表的名稱 Sheet1
第一個工作表的名稱 Sheet2
[<Worksheet "Sheet2">, <Worksheet "New">, <Worksheet "Sheet">, <Worksheet "Sheet1">]

使用 Python openpyxl 套件的 Workbook 物件複製 Excel 工作表

Pythonopenpyxl套件的Workbook物件的copy_worksheet方法,可用於複製 Excel 活頁簿中的 Excel 工作表,並將得到的工作表復本新增至 Excel 活頁簿的末尾,復本的名稱通常以Copy結尾。copy_worksheet方法的傳回值是 Excel 工作表復本對應的Worksheet物件。

workbook.copy_worksheet(from_worksheet)

from_worksheet 參數

from_worksheet參數為被複製的 Excel 工作表對應的Worksheet物件。

Python openpyxl 套件僅能複製 Workbook 物件自身擁有的 Excel 工作表

openpyxlWorkbook物件的copy_worksheet方法,僅能複製包含在Workbook物件中的 Excel 工作表,嘗試將其他 Excel 活頁簿物件的工作表傳遞給參數from_worksheet,會導致例外狀況ValueError: Cannot copy between worksheets from different workbooks

copy_sheet.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
import openpyxl
workbook = openpyxl.load_workbook('School.xlsx')

# 複製工作表 ClassA workbook.copy_worksheet(workbook['ClassA']) print(f'ClassA 復本的名稱為 {workbook.worksheets[-1].title}')
# 嘗試複製其他活頁簿的工作表 newbook = openpyxl.Workbook() # ERROR 無法複製自身不擁有的工作表 workbook.copy_worksheet(newbook['Sheet'])
ClassA 復本的名稱為 ClassA Copy

ValueError: Cannot copy between worksheets from different workbooks

使用 Python openpyxl 套件的 Workbook 物件移動 Excel 工作表

Pythonopenpyxl套件的Workbook物件的move_sheet方法,可用於移動 Excel 活頁簿中的工作表,從而改變工作表之間的順序。事實上,openpyxl通過先刪除後插入來完成工作表的移動,他會計算被移動的 Excel 工作表的插入位置,並將其放置在插入位置對應的工作表之前。

workbook.move_sheet(sheet, offset=0)

sheet 參數

sheet參數為需要移動的 Excel 工作表的名稱或其對應的Worksheet物件。

offset 參數

offset參數為 Excel 工作表插入位置與原索引之間的位移值,1表示插入位置為原索引加1-1表示插入位置為原索引減1,使用0的效果相當於不移動。如果插入位置最終為負數,那麽移動的效果可能並非你的預期,比如,當 Excel 活頁簿擁有多個工作表時,對索引為0的第一個工作表使用-1,他會被放置在倒數第二的位置,而不是倒數第一,這與使用create_sheet方法所產生的效果類似。

在移動 Excel 工作表ClassA之後,工作表ClassB將位於開頭,此時指定參數offset-1,會使ClassB被移動至倒數第二的位置,因為計算的插入位置為-1,即倒數第一的ClassA之前。

move_sheet.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import open
workbook = open('School.xlsx')
print(workbook.worksheets)

# 工作表 ClassA 將位於末尾 workbook.move_sheet('ClassA', 100) print(workbook.worksheets) # 目前第一個工作表 ClassB 將被移動至倒數第二的位置 b = workbook['ClassB'] workbook.move_sheet(b, -1) print(workbook.worksheets)
[<Worksheet "ClassA">, <Worksheet "ClassB">, <Worksheet "ClassC">]
[<Worksheet "ClassB">, <Worksheet "ClassC">, <Worksheet "ClassA">]
[<Worksheet "ClassC">, <Worksheet "ClassB">, <Worksheet "ClassA">]

使用 Python openpyxl 套件的 Workbook 物件移除 Excel 工作表

使用 Pythonopenpyxl套件的Workbook物件的remove方法,或使用del關鍵字和[]運算子,並給出工作表的名稱,可移除 Excel 活頁簿中的工作表。

workbook.remove(worksheet)
del workbook[name]

worksheet 參數

worksheet參數為需要移除的 Excel 工作表對應的Worksheet物件。

name 值

name為需要移除的 Excel 工作表的名稱。

openpyxl已取代Workbook類別的remove_sheet方法。

remove_sheet.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import open
workbook = open('School.xlsx')

# 刪除工作表 ClassA,ClassB del workbook['ClassA'] workbook.remove(workbook['ClassB']) print(workbook.worksheets)
[<Worksheet "ClassC">]

使用 Python openpyxl 套件的 Workbook 物件取得 Excel 工作表的名稱和索引

Pythonopenpyxl套件的Workbook物件的sheetnames屬性,傳回一個包含所有 Excel 工作表名稱的 Python 串列。

workbook.sheetnames[slice]

slice 值

slice為需要取得名稱的某個或某些 Excel 工作表的索引或配量運算式。

openpyxl已取代Workbook類別的get_sheet_names方法。

Pythonopenpyxl套件的Workbook物件的index方法,可用於取得指定 Excel 工作表在活頁簿中的索引,第一個工作表的索引為0

workbook.index(worksheet)

worksheet 參數

worksheet參數為需要取得索引的 Excel 工作表對應的Worksheet物件。

openpyxl已取代Workbook類別的get_index方法。

name_and_index.py
# 請將命令列跳躍至 School.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import load_workbook
workbook = load_workbook('School.xlsx')

# 取得工作表的名稱和索引 print(f'第二個工作表的名稱 {workbook.sheetnames[1]}') print(f'工作表 ClassC 的索引 {workbook.index(workbook["ClassC"])}')
第二個工作表的名稱 ClassB
工作表 ClassC 的索引 2

使用 Python openpyxl 套件的 Workbook 物件取得 Excel 活頁簿的日期系統

Pythonopenpyxl套件的Workbook物件的excel_base_date屬性或epoch屬性,可用於取得 Excel 活頁簿日期系統的開始日期。

workbook.excel_base_date

什麽是 Excel 活頁簿的日期系統?

每一個 Excel 活頁簿都指定了自己的日期系統,不同的日期系統具有不同的開始日期,Excel 會將日期計算為相對於開始日期的位移值,因此,同一日期在不同日期系統中儲存的資料並不相同。

date_system.py
# 請將命令列跳躍至 1904.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import load_workbook
workbook = load_workbook('1904.xlsx')

# 取得活頁簿的日期系統 print(workbook.excel_base_date)
1904-01-01 00:00:00

使用 Python openpyxl 套件的 Workbook 物件判斷 Excel 活頁簿是否為範本

Pythonopenpyxl套件的Workbook擁有類別變數template和執行個體變數is_template,他們的值始終為True,官方似乎沒有闡明其具體作用,因此templateis_template不能用於判斷 Excel 活頁簿是否是一個範本,你需要使用Workbook物件的mime_type屬性來完成此目標,該屬性用來說明 Excel 活頁簿的 MIME 類型,當其包含template時,可將活頁簿視為範本。

workbook.mime_type

is_template.py
# 請將命令列跳躍至 Hello.xltx 所在的目錄,然後執行此腳本檔案
from openpyxl import load_workbook
workbook = load_workbook('Hello.xltx')

# 活頁簿是否為範本? print('template' in workbook.mime_type)
True

Python openpyxl 套件的 Workbook 物件的其他特性

以下是與openpyxlWorkbook物件相關,但不太重要的一些特性,這些特性可能並非從 Microsoft Excel 檔案取得,只是由openpyxl套件給出了固定值。

encoding 變數

Workbook物件的encoding變數用於表示 Excel 活頁簿的編碼,他由openpyxl指定為'utf-8'

path 變數

Pythonopenpyxl套件所處理的 Excel 檔案本身是一個壓縮檔案,Workbook物件的path變數表示其在壓縮檔案中的路徑,他由openpyxl指定為'/xl/workbook.xml'

vba_archive 變數

Workbook物件的vba_archive變數是一個ZipFile物件,表示與 VBA 相關的壓縮檔案,該壓縮檔案包含在 Excel 檔案中,通常的名稱為vbaProject.bin

data_only,read_only,write_only 屬性

Workbook物件的data_onlyread_onlywrite_only屬性是唯讀的,他們由讀取 Excel 檔案或建立openpyxlWorkbook物件時給出的引數來決定,由於相關文章已經進行了講解,這裏不再累述。

程式碼

src/zh-hant/openpyxl/workbooks·codebeatme/office-programming·GitHub