如何使用 Python openpyxl 套件讀取和寫入 Excel 檔案

閱讀 13:25·字數 4027·發佈 
Youtube 頻道
訂閱 133

執行本節中的範例,需要安裝 Python 套件openpyxl,你可以檢視安裝 Python openpyxl 套件一段來了解相關資訊。

Python openpyxl 套件支援的 Excel 檔案格式

無論使用套件中的哪個函式或類別,Pythonopenpyxl套件只能讀取和寫入以下 Microsoft Excel 檔案格式,.xlsx.xlsm(啟用了巨集的 Excel 檔案),.xltx(Excel 範本檔案),.xltm(啟用了巨集的 Excel 範本檔案)。

對於舊的 Excel 檔案格式.xls,可以嘗試采用 Python 套件xlrdxlwt進行操作,或者將.xls轉換為.xlsx格式的 Excel 檔案。

使用 Python openpyxl 套件讀取 Excel 檔案

你可以使用 Pythonopenpyxl套件中的load_workbook函式或其別名open(非 Python 內建函式open),來讀取 Excel 檔案中的資料,該函式的傳回值是一個可操作 Excel 資料的活頁簿物件Workbook

load_workbook(filename, read_only=False, keep_vba=KEEP_VBA, data_only=False, keep_links=True, rich_text=False)

filename 參數

filename參數為需要讀取的 Excel 檔案的路徑(絕對路徑或相對路徑),或者與 Excel 檔案相關並采用了二進位模式的file-like(類檔案)物件。比如,呼叫 Python 內建函式open(非load_workbook的別名),並采用rb模式建立的file-like物件。

read_only 參數

read_only參數預設為False,用來指示load_workbook函式傳回的openpyxl活頁簿物件Workbook是否是唯讀的。如果設定為True,那麽你將無法通過Workbook物件儲存對 Excel 資料的改動,這可能會改進一些效能,因為與寫入相關的邏輯以及一些複雜的內容(比如,Excel 儲存格中的超連結)將被忽略。

keep_vba 參數

在非測試環境下,keep_vba參數的預設值為False,表示不會讀取 Excel 檔案中與 VBA(Visual Basic for Applications)有關的內容。如果設定為True,那麽 Excel 檔案中關於 VBA 的內容將被openpyxl讀取到Workbook物件中,當然,這並不意味著你可以通過 Pythonopenpyxl套件執行 VBA 中的程式碼,或使用 VBA 所實作的功能。

data_only 參數

data_only參數(預設值為False)用於指示是讀取 Excel 儲存格的公式的計算結果,還是讀取 Excel 儲存格的公式,當openpyxl讀取的 Excel 檔案包含具有公式的儲存格時。如果設定為True,那麽openpyxl將讀取公式的計算結果,這意味著Workbook物件中的相關 Excel 儲存格不再擁有公式。

keep_links 參數

keep_links參數的預設值為True,用於指示在 Pythonopenpyxl套件讀取 Excel 檔案時,是否讀取 Excel 外部連結資料的快取,比如,另一個 Excel 檔案的工作表的某個儲存格的值。如果設定為False,那麽外部連結資料的快取不會被讀取到Workbook物件中,當快取過大時,這種做法將是有效的。

rich_text 參數

rich_text參數用於指示在 Pythonopenpyxl套件讀取 Excel 檔案時,是否保留儲存格中的豐富文字格式(Rich Text Formatting,RFT),其預設值為False(不保留豐富文字格式),這意味著Workbook物件中相關 Excel 儲存格的豐富文字格式將丟失。當rich_text參數為True時,儲存Workbook物件可能會失敗。

下面,我們準備了名稱為Hello.xlsx的 Excel 檔案,以及讀取 Excel 檔案的 Python 腳本檔案read.py,他們位於同一目錄中。

read.py
# 請將命令列跳躍至 Hello.xlsx 所在的目錄,然後執行此腳本檔案
# 匯入函式 load_workbook
from openpyxl import load_workbook

# 讀取 Excel 檔案 workbook = load_workbook('Hello.xlsx')
# 取得工作表 1.1班 中的儲存格 A1,B1,C1,B4,C4 並顯示 worksheet = workbook['1.1班'] name = worksheet['A1'].value age = worksheet['B1'].value score = worksheet['C1'].value print(f'第一個學生 {name} {age} {score}') avg_age = worksheet['B4'].value avg_score = worksheet['C4'].value print(f'平均值公式 {avg_age} {avg_score}')
第一個學生 小小 13 100
平均值公式 =AVERAGE(B1:B3) =AVERAGE(C1:C3)

Python openpyxl 套件通過 read 特性來判斷 filename 參數是否為 file-like 物件

在讀取 Excel 檔案的過程中,openpyxl會檢查load_workbook函式的參數filename是否具有特性read,如果具有,那麽filename參數將被視為 Pythonfile-like物件,read特性將作為方法被呼叫,以取得 Excel 檔案的二進位格式資料。

在下面的程式碼中,我們使用open函式開啟了 Excel 檔案Hello.xlsx,並將傳回的物件作為load_workbook函式的引數。

data_only.py
# 請將命令列跳躍至 Hello.xlsx 所在的目錄,然後執行此腳本檔案
# 匯入函式 load_workbook
from openpyxl import load_workbook

# 使用 open 函式開啟 Excel 檔案 xlsx = open('Hello.xlsx', 'rb') workbook = load_workbook(xlsx, data_only=True)
# 讀取儲存格 B4,C4 的公式計算結果並顯示 worksheet = workbook['1.1班'] avg_age = worksheet['B4'].value avg_score = worksheet['C4'].value print(f'平均值 {avg_age} {avg_score}')
平均值 13 96.3333333333333

將 read_only 參數設定為 True 後,Workbook 及其相關物件依然可以進行某些修改操作

雖然將load_workbook函式的read_only參數設定為True後,執行 Excel 活頁簿物件Workbooksave方法或對 Excel 儲存格進行寫入會導致例外狀況,但並非所有的修改操作都是不可行的(比如,可以修改工作表的標題),只不過這些改變無法被儲存。

下面,我們通過唯讀的方式來開啟 Excel 檔案Hello.xlsx,然後修改工作表的標題。

read_only.py
# 請將命令列跳躍至 Hello.xlsx 所在的目錄,然後執行此腳本檔案
# 匯入套件 openpyxl
import openpyxl

# 以唯讀方式開啟 Excel 檔案,並修改工作表標題 workbook = openpyxl.open('Hello.xlsx', True) worksheet = workbook['1.1班'] worksheet.title = '1.2班'
# ERROR 唯讀的 Workbook 物件不能修改儲存格的值 worksheet['A1'].value = '一個好人'
AttributeError: Cell is read only

rich_text 參數為 False 不意味著 Workbook 物件中的相關 Excel 儲存格會丟失全部樣式

load_workbook函式的rich_text參數為False,並不表示openpyxlWorkbook物件中的儲存格會丟失全部樣式,因為一些樣式可能不屬於豐富文字格式,不針對 Excel 儲存格中的文字區塊(Text Block),比如,為整個儲存格設定的文字色彩。

使用 Python openpyxl 套件寫入(儲存)Excel 檔案

使用 Python 模組openpyxl.writer.excelsave_workbook函式,或Workbook物件的save方法,可以將Workbook物件儲存為 Microsoft Excel 檔案。

save_workbook(workbook, filename)
save(filename)

workbook 參數

workbook參數為需要進行儲存的Workbook物件。

filename 參數

filename參數為 Excel 檔案的絕對路徑或相對路徑,如果路徑指向的檔案已經存在,那麽他將被覆蓋。

下面,我們嘗試在修改 Excel 儲存格A1後,再次將Workbook物件儲存為檔案Overwrite.xlsx,原有的Overwrite.xlsx會被覆蓋。

save.py
# Overwrite.xlsx 會被儲存至命令列的目前工作目錄
# 匯入套件 openpyxl
import openpyxl

# 建立 Workbook 並先後儲存兩次 workbook = openpyxl.Workbook() workbook.save('Overwrite.xlsx') workbook['Sheet']['A1'].value = '你好!' workbook.save('Overwrite.xlsx')

write_only 屬性為 True 的 Workbook 物件僅能被儲存一次

當你直接建立 Pythonopenpyxl套件的Workbook物件,並將其建構子的write_only參數設定為True時,被建立的Workbook物件將是唯寫的(write_only屬性為True),對於唯寫的Workbook物件,只能呼叫其save方法或使用save_workbook函式儲存一次,多次儲存將導致例外狀況。

在下面的例子中,我們嘗試儲存唯寫的Workbook物件兩次。

write_only.py
# 匯入函式 save_workbook 和類別 Workbook
from openpyxl.writer.excel import save_workbook
from openpyxl import Workbook

# 建立 Workbook 物件並儲存 workbook = Workbook(True) workbook.save('New.xlsx') # ERROR 只能儲存一次 save_workbook(workbook, 'New.xlsx')

被儲存為 Excel 檔案的 Workbook 物件需要擁有至少一個可見的工作表

無論是使用openpyxl.writer.excel模組的save_workbook函式,還是Workbook物件的save方法,Pythonopenpyxl套件要求 Excel 活頁簿物件擁有至少一個可見的工作表,即至少一個sheet_state屬性為'visible'Worksheet物件,否則,儲存為 Excel 檔案將是不可行的,例外狀況IndexError: At least one sheet must be visible會被擲回。

在下面的程式碼中,Excel 活頁簿物件將擁有兩個工作表,由於他們都是不可見的,因此儲存將失敗。

no_sheet.py
# 匯入 Workbook 類別
from openpyxl import Workbook

# 建立一個 Workbook 物件,將其中的工作表設定為隱藏 workbook = Workbook() workbook['Sheet'].sheet_state = 'hidden' workbook.create_sheet().sheet_state = 'hidden' # ERROR 無法儲存沒有可見工作表的 Workbook 物件 workbook.save('nosheet.xlsx')
IndexError: At least one sheet must be visible

關閉 Python openpyxl 套件開啟的 Excel 檔案

如果你在使用 Pythonopenpyxl套件的load_workbook函式時,將read_only參數設定為True,取得了唯讀的Workbook物件,那麽呼叫Workbook物件的close方法,可以關閉與 Excel 活頁簿相關的ZipFile物件,此後,讀取 Excel 工作表中的儲存格將是不可行的,但工作表自身的一些相關資訊依然可以存取,比如工作表的名稱(標題)。

close 方法對 write_only 屬性為 True 的 Workbook 物件的影響不明顯

雖然在官方的說明中,close方法會對唯寫的Workbook物件產生影響,但這種影響並不明顯(似乎是不存在的),你可以將一列資料寫入呼叫了close方法的Workbook物件,並通過save方法儲存他們。

在對Workbook物件呼叫close方法之前或之後,寫入資料均沒有問題,並可以呼叫save方法將Workbook物件儲存為 Excel 檔案。

close.py
# 請將命令列跳躍至 Hello.xlsx 所在的目錄,然後執行此腳本檔案
from openpyxl import Workbook, load_workbook

# 建立唯寫的活頁簿 w_workbook = Workbook(True) w_workbook.create_sheet() w_workbook['Sheet'].append(['Hello', 'World']) # 呼叫 close 方法之後,再次寫入一列資料,並儲存 w_workbook.close() w_workbook['Sheet'].append(['你好', '世界']) w_workbook.save('Close.xlsx')
# 建立唯讀的活頁簿 r_workbook = load_workbook('Hello.xlsx', True) print(r_workbook['1.1班']['A1'].value) # 呼叫 close 方法之後,讀取儲存格 A1 r_workbook.close() # ERROR 無法讀取 A1 儲存格 print(r_workbook['1.1班']['A1'])
小小

ValueError: Attempt to use ZIP archive that was already closed

程式碼

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

講解影片

如何使用 Python openpyxl 套件讀取 Excel 活頁簿檔案的工作表,取得和設定 Excel 儲存格的值,以及儲存 Excel 活頁簿檔案·YouTube