如何使用 Python openpyxl 套件讀取和寫入 Excel 檔案
執行本節中的範例,需要安裝 Python 套件openpyxl
,你可以檢視安裝 Python openpyxl 套件一段來了解相關資訊。
Python openpyxl 套件支援的 Excel 檔案格式
無論使用套件中的哪個函式或類別,Pythonopenpyxl
套件只能讀取和寫入以下 Microsoft Excel 檔案格式,.xlsx
,.xlsm
(啟用了巨集的 Excel 檔案),.xltx
(Excel 範本檔案),.xltm
(啟用了巨集的 Excel 範本檔案)。
對於舊的 Excel 檔案格式.xls
,可以嘗試采用 Python 套件xlrd
和xlwt
進行操作,或者將.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
,他們位於同一目錄中。
# 請將命令列跳躍至 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
函式的引數。
# 請將命令列跳躍至 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 活頁簿物件Workbook
的save
方法或對 Excel 儲存格進行寫入會導致例外狀況,但並非所有的修改操作都是不可行的(比如,可以修改工作表的標題),只不過這些改變無法被儲存。
下面,我們通過唯讀的方式來開啟 Excel 檔案Hello.xlsx
,然後修改工作表的標題。
# 請將命令列跳躍至 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
,並不表示openpyxl
的Workbook
物件中的儲存格會丟失全部樣式,因為一些樣式可能不屬於豐富文字格式,不針對 Excel 儲存格中的文字區塊(Text Block),比如,為整個儲存格設定的文字色彩。
使用 Python openpyxl 套件寫入(儲存)Excel 檔案
使用 Python 模組openpyxl.writer.excel
的save_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
會被覆蓋。
# 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
物件兩次。
# 匯入函式 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 活頁簿物件將擁有兩個工作表,由於他們都是不可見的,因此儲存將失敗。
# 匯入 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 檔案。
# 請將命令列跳躍至 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