如何使用 Python openpyxl 套件操作 Excel 活頁簿?openpyxl Workbook 物件介紹
本節並不包含 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
在預設情況下,使用建構子建立的openpyxl
Workbook
物件將擁有一個名稱為Sheet
的 Excel 工作表。當建構子參數write_only
為True
時,唯寫Workbook
物件不會包含任何工作表,如果在Workbook
物件執行儲存操作時依然如此,那麽openpyxl
將嘗試為Workbook
物件新增一個 Excel 工作表。
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 workbook
或ValueError: Only visible sheets can be made active
。如果通過工作表索引設定目前使用中的 Excel 工作表,則不存在擲回例外狀況的情況,但可能導致openpyxl
Workbook
物件的active
屬性傳回空值None
,因為索引指示的位置沒有 Excel 工作表。
在 Microsoft Excel 檔案School.xlsx
中,工作表ClassA
,ClassB
,ClassC
依次排列。
# 請將命令列跳躍至 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
方法。
# 請將命令列跳躍至 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
建立的新工作表將被命名為Sheet1
,Sheet2
,Sheet3
等。
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 工作表
openpyxl
Workbook
物件的copy_worksheet
方法,僅能複製包含在Workbook
物件中的 Excel 工作表,嘗試將其他 Excel 活頁簿物件的工作表傳遞給參數from_worksheet
,會導致例外狀況ValueError: Cannot copy between worksheets from different workbooks
。
# 請將命令列跳躍至 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
之前。
# 請將命令列跳躍至 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
方法。
# 請將命令列跳躍至 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
方法。
# 請將命令列跳躍至 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 會將日期計算為相對於開始日期的位移值,因此,同一日期在不同日期系統中儲存的資料並不相同。
# 請將命令列跳躍至 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
,官方似乎沒有闡明其具體作用,因此template
和is_template
不能用於判斷 Excel 活頁簿是否是一個範本,你需要使用Workbook
物件的mime_type
屬性來完成此目標,該屬性用來說明 Excel 活頁簿的 MIME 類型,當其包含template
時,可將活頁簿視為範本。
workbook.mime_type
# 請將命令列跳躍至 Hello.xltx 所在的目錄,然後執行此腳本檔案
from openpyxl import load_workbook
workbook = load_workbook('Hello.xltx')
# 活頁簿是否為範本?
print('template' in workbook.mime_type)
True
Python openpyxl 套件的 Workbook 物件的其他特性
以下是與openpyxl
Workbook
物件相關,但不太重要的一些特性,這些特性可能並非從 Microsoft Excel 檔案取得,只是由openpyxl
套件給出了固定值。
- encoding 變數
Workbook
物件的encoding
變數用於表示 Excel 活頁簿的編碼,他由openpyxl
指定為'utf-8'
。- path 變數
Python
openpyxl
套件所處理的 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_only
,read_only
,write_only
屬性是唯讀的,他們由讀取 Excel 檔案或建立openpyxl
Workbook
物件時給出的引數來決定,由於相關文章已經進行了講解,這裏不再累述。
程式碼
src/zh-hant/openpyxl/workbooks·codebeatme/office-programming·GitHub