Python操作Excel工作簿的示例代碼(\*.xlsx)
前言
Excel 作為流行的個人計算機數(shù)據(jù)處理軟件,混跡于各個領(lǐng)域,在程序員這里也是常常被處理的對象,可以處理 Excel 格式文件的 Python 庫還是挺多的,比如 xlrd、xlwt、xlutils、openpyxl、xlwings 等等,但是每個庫處理 Excel 的方式不同,有些庫在處理時還會有一些局限性。
接下來對比一下幾個庫的不同,然后主要記錄一下 xlwings 這個庫的使用,目前這是個人感覺使用起來比較方便的一個庫了,其他的幾個庫在使用過程中總是有這樣或那樣的問題,不過在特定情況下使用也是挺不錯的。
EXCEL文件
Excel 被稱為電子表格,其實際可以保存的格式分為很多種,但是“Excel 工作簿(*.xlsx)”和“Excel 97-2003 工作簿(*.xls)”是其中比較常用的兩種,可以認(rèn)為 .xls 格式的表格是 03版Excel 之前常用的格式,而 .xlsx 是 03版之后,一般指 07版Excel 之后常用的格式。
一般的 Excel 程序?qū)τ谏鲜龅膬煞N格式都可以打開編輯,也可以相互轉(zhuǎn)化存儲,不過還是建議在沒有特殊要求的情況下使用新版本的格式,一方面新的穩(wěn)定版本可能會修復(fù)之前的一些BUG,同時也會帶來進(jìn)行一些優(yōu)化。
我也是在寫這篇總結(jié)之前才發(fā)現(xiàn),一個空的 .xlsx 格式的文件大小有 7KB,而一個空的 .xls 格式的文件大小有 24KB,當(dāng)我分別寫入一個相同的漢字后,兩個文件大小變成了 10KB 和 30KB,差距還是不小的,還有一個問題就是在將 .xlsx 格式的文件另存為 .xls 格式時還會有兼容性提示,提醒用戶有些設(shè)置可能會丟失,所以能選新版本還是盡量用新版本吧。
測試環(huán)境
因為很多應(yīng)用程序是不斷迭代的,相對應(yīng)的 Python 庫也是不斷迭代的,這里盡可能的給出版本號,不同的版本可能會有不同的問題:
- 操作系統(tǒng): Windows 10 隨意版
- Python: 3.75
- xlrd: 1.2.0
- xlwt: 1.3.0
- xlutils: 2.0.0
- openpyxl: 3.0.3
- xlwings: 0.18.0
以上各個程序庫使用之前自行安裝就行,安裝方法就不贅述了,不過可以提供一個可以快速安裝鏡像源,使用 pip install -i https://pypi.doubanio.com/simple 庫名
可以盡可能解決下載安裝緩慢的問題。
Excel具體操作
關(guān)于使用 Python 具體操作 Excel 的方法可以分為三組,配合使用 xlrd、xlwt、xlutils 操作作為第一組,使用庫 openpyxl 作為第二組,而 xlwings 作為第三組,這篇總結(jié)重點總結(jié) xlwings 的使用,其他兩組簡單了解。
xlrd、xlwt、xlutils
這一組操作 Excel 的庫名字很形象,一個讀、一個寫、一個小工具,湊到一起就可以對 Excel 肆意妄為了,下面做個小練習(xí),打開一個 Excel 文件然后修改第一個單元格的值,再另存為一個新文件,代碼如下:
import xlrd import xlwt import xlutils.copy def save_as_new_file(file_name, new_file_name): # 打開Excel文件 rb = xlrd.open_workbook(file_name) # 創(chuàng)建一個可寫入的副本 wb = xlutils.copy.copy(rb) # 獲得第一個sheet頁簽 ws = wb.get_sheet(0) # 第一個單元格寫入測試值 ws.write(0, 0, 'test value') # 另存為一個新文件 wb.save(new_file_name)
上述代碼無論是操作 .xlsx 文件還是操作 .xls 文件都不會報錯,但是另存為的 .xlsx 格式的文件會打不開,同時你會發(fā)現(xiàn)正常存儲的 .xls 文件打開后格式全都沒了,怎么辦,改個參數(shù)試試,將打開文件的代碼修改如下:
rb = xlrd.open_workbook(file_name, formatting_info=True)
其中參數(shù) formatting_info=True 就表示打開Excel時保留原有的格式,但是這是相對于 .xls 格式的文件,對于 .xlsx 格式的文件直接跑出異常 raise NotImplementedError("formatting_info=True not yet implemented"),就因為處理不了 .xlsx 格式的文件,我暫時沒有使用這幾個庫操作 Excel。
還有一點,這幾個庫操作單元格時,行和列的索引是從0開始的。
openpyxl
首先說這個庫主要用來操作 .xlsx 格式的文件,對于 .xls 格式的文件無法打開,會報 openpyxl does not support the old .xls file format 這樣的錯誤,但是可以存儲成這樣的格式,再次打開時會有格式不匹配的警告,但是基礎(chǔ)的數(shù)據(jù)還在,所以還是優(yōu)先用來操作 .xls 格式的文件吧。
寫一個新文件的常見用法:
from openpyxl import Workbook from openpyxl import load_workbook from openpyxl.styles import Font, Fill, Alignment, PatternFill def write_new_excel(file_name): # 創(chuàng)建一個excel文檔 wb = Workbook() # 獲得當(dāng)前激活的sheet對象 ws = wb.active # 給A2單元格賦值 ws['A2'] = 'This is A2 cell' # 一行添加多列數(shù)據(jù) ws.append([1, 2, 'hello']) # 添加新的sheet ws = wb.create_sheet(title='NewInfo',index=0) # 設(shè)置單元格的值 ws['A1'] = 'This is new sheet' # 保存excel wb.save(file_name)
讀取和改寫一個原有文件的常見用法:
def read_update_excel(file_name): # 加載Excel表 wb = load_workbook(file_name) # 打印sheet數(shù)量 print('sheet count:', len(wb.sheetnames)) # 打印所有sheet名字 print('sheet name list:', wb.sheetnames) # 獲取第一個sheet對象 ws = wb[wb.sheetnames[0]] # 打印sheet表行數(shù)和列數(shù) print('rows count:', ws.max_row, 'cols count:', ws.max_column) # 更新單元格A1的內(nèi)容 ws['A1'] = 'this is A1' # 在第二行位置插入一行 ws.insert_rows(2) # 刪除第五行 ws.delete_rows(5) # 獲取單元格對象,對應(yīng)B2單元格 cell = ws.cell(2,2) # 設(shè)置單元格內(nèi)容 cell.value = 'this is B2' # 修改字體格式為粗體 cell.font = Font(bold=True) # 修改單元格格式 cell.fill = PatternFill("solid", fgColor="F0CDCD") # 保存原文件或另存一個文件 wb.save(file_name)
使用這個庫遇到的情況,存儲帶有樣式的數(shù)據(jù)沒有發(fā)現(xiàn)問題,但是當(dāng)加入一個計算公式后,另存為一個文件時明顯文件尺寸變小了,但是數(shù)據(jù)和公式?jīng)]有發(fā)現(xiàn)有問題。
有資料說處理速度真的很慢,因為我處理的文件比較小,但是沒有發(fā)現(xiàn)這方面的問題,還有一個問題就是說Excel中的宏全部丟失,這個測試的時候確實是丟了,只不過這個好像和文件格式有關(guān),要想保存宏需要存儲為 .xlsm 格式,但是 openpyxl 使用來操作 .xlsx 文件的,存儲時會導(dǎo)致宏丟失,強行存儲為 .xlsm 格式會導(dǎo)致最終的文件打不開。
還有一點,這個庫操作單元格時,行和列的索引是從1開始的。
xlwings
這個庫在操作的首先要創(chuàng)建一個 App,通過這個創(chuàng)建出來的 App 對象來操作 Excel,非常像把 Excel 的各種操作 api 封裝到一起,然后通過這個 App 對象來調(diào)用,如果在創(chuàng)建 App 的時候不設(shè)置隱藏參數(shù),是會正常打開 Excel 程序的。
使用 xlwings 的基本方式:
import xlwings as xw # 設(shè)置Excel程序不可見 app = xw.App(visible=False, add_book=False) # 通過 app 操作 Excel文件 # app.bala bala bala ..... # app.bala bala bala ..... # 優(yōu)雅的退出 app.quit()
創(chuàng)建一個新的 Excel 文件并寫入數(shù)據(jù):
def write_new_excel(app, file_name): # 創(chuàng)建新的 Excel 表 wb = app.books.add() # 獲取當(dāng)前活動的sheet ws = wb.sheets.active # 初始化二維區(qū)域的值 arr_data = [[1, 2, 3], [4, 5, 6], [7, 8, 'end']] # 設(shè)置到新建的Excel中 ws.range('A1:B3').value=arr_data # 設(shè)置單獨一個單元格的值 ws.range('A4').value='this is A4' # 設(shè)置單獨一個單元格的值 ws[3,1].value='this is B4' # 保存Excel文件 wb.save(file_name) wb.close()
需要注意的是通過行索引和列索引修改單元格時,起始索引是0。
讀入已有 Excel 表格并修改
def read_update_excel(app, file_name): # 加載已有的表格 load_wb = app.books.open(file_name) # 獲取Excel表中第一個sheet load_ws = load_wb.sheets[0] # 打印sheet的名字 print(load_ws.name) # 根據(jù)sheet名字獲取sheet對象 load_ws = load_wb.sheets[load_ws.name] # 獲取當(dāng)前活動的sheet load_ws = load_wb.sheets.active # 獲取存在數(shù)據(jù)的行數(shù)和列數(shù) rows = load_ws.api.UsedRange.Rows.count cols = load_ws.api.UsedRange.Columns.count print('rows count:', rows, 'cols count:', cols) # 修改指定單元格數(shù)據(jù)(A1單元格) load_ws[0,0].value='this is A1' # 有空行或空列時獲取準(zhǔn)確的行列數(shù)量 print(load_ws.used_range.shape) # 從A1單元格開始擴展到非空行空列,最后的行數(shù)和列數(shù) print((load_ws.range('A1').expand().last_cell.row, load_ws.range('A1').expand().last_cell.column)) # 從A1單元格開始擴展到非空行空列,最后的行數(shù)和列數(shù) print((load_ws.range('A1').expand().last_cell.row, load_ws.range('A1').expand().last_cell.column)) # 從A1單元格開始擴展到非空行空列,最后形狀 print(load_ws.range(1,1).expand().shape) # 從A1單元格開始擴展到非空行空列,最后的行數(shù)和列數(shù) print((load_ws.range('A1').expand('table').rows.count, load_ws.range('A1').expand('table').columns.count)) # 保存修改后的Excel load_wb.save(file_name) load_wb.close()
Excel 增加刪除行和列
def insert_delete_rowscols(app, file_name): # 加載已有的表格 load_wb = app.books.open(file_name) # 獲取當(dāng)前活動的sheet load_ws = load_wb.sheets.active # 從第2行開始插入4行,也就是說2-5行變成新插入的空行 load_ws.api.rows('2:5').insert # 刪除第6行和第7行 load_ws.api.rows('6:7').delete # 插入一個單元格,實際測試效果是B列從B2開始向下移動,B2為新添加的單元格 load_ws.range('B2').api.insert # 插入新的一列 load_ws.api.columns('B').insert # 刪除一列 load_ws.api.columns('C').delete # 保存修改后的Excel load_wb.save(file_name) load_wb.close()
單元格寬高查詢設(shè)置與合并
def cell_operation(app, file_name): # 加載已有的表格 load_wb = app.books.open(FILE_PATH_ROOT + file_name) # 獲取當(dāng)前活動的sheet load_ws = load_wb.sheets.active # 合并單元格 load_ws.range('A2:A3').api.merge #獲取單元格 cell = xw.Range('B2') # 打印單元格所在的行和列 print("row is:", cell.row, "col is:", cell.column) # 打印當(dāng)前格子的高度和寬度 print("cell.width:", cell.width, "cell.height:", cell.height) # 設(shè)置當(dāng)前格子的高度和寬度 cell.row_height = 32 cell.column_width = 64 # 指定單元格的高度和寬度自適應(yīng) cell.columns.autofit() cell.rows.autofit() # 再次打印當(dāng)前格子的高度和寬度 print("cell.width:", cell.width, "cell.height:", cell.height) # 保存修改后的Excel load_wb.save(file_name) load_wb.close()
幾個庫支持情況對比
雖然前面寫了這么多方法,但是遇到一個實際的問題時還是會猶豫,到底用哪種方式呢?下面做一個簡單的對比,只是根據(jù)我做的實驗來簡單對比,如果有不準(zhǔn)確甚至是錯誤的地方,歡迎大家指出來,我會盡快改正的。
情景/庫 | xlrd、xlwt、xlutils | openpyxl | xlwings |
---|---|---|---|
讀取.xls | 可以帶有樣式讀取 | 不支持 | 可以讀取 |
保存.xls | 可以帶有樣式保存 | 可以保存,但是提示文件擴展名不匹配,可以看到原始數(shù)據(jù) | 可以保存,但是提示文件擴展名不匹配,可以看到原始數(shù)據(jù) |
讀取.xlsx | 可以讀取,但沒有樣式 | 可以帶有樣式讀取 | 可以帶有樣式讀取 |
保存.xlsx | 保存后打不開 | 可以帶有樣式保存 | 可以帶有樣式保存 |
讀取.xlsm | 可以讀取,但沒有樣式和宏 | 可以讀取,但沒有宏 | 可以讀取包含宏的表格 |
保存.xlsm | 保存后打不開,存成 .xls 格式宏丟失 | 保存后打不開,存成 .xls想 格式宏丟失 | 存儲后宏還在 |
增刪行和列 | 沒有直接方法 | 支持 | 支持 |
另存后大小 | .xls 文件沒有變化 | .xlsx 文件會變小 | .xls、.xlsx 文件沒有變化 |
使用建議 | 只操作.xls文件可以考慮 | 只操作.xlsx文件可以考慮,不能帶有宏 | 一個比較好的選擇,使用時感覺速度稍微有點慢 |
總結(jié)
- Excel 表格程序經(jīng)過版本的更替發(fā)生了很大的變化,出現(xiàn)了相同內(nèi)容時 .xls 比 .xlsx 格式的文件大很多的情況
- 基于上一點考慮,如果能使用的新版的表格,那么就放棄舊的格式的吧
- 還有一個神奇的情況,一個帶有少量數(shù)據(jù)的 .xlsx 格式的表格要比一個空表格還要小,這是什么情況,暫時沒弄明白怎么回事,求知道的大神告知一二
到此這篇關(guān)于Python操作Excel工作簿的示例代碼(\*.xlsx)的文章就介紹到這了,更多相關(guān)Python操作Excel工作簿內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python利用re模塊實現(xiàn)簡易分詞(tokenization)
分詞(tokenization)任務(wù)是Python字符串處理中最為常見任務(wù)了。本文將利用re模塊實現(xiàn)簡易tokenizer,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-04-04Python 3.x基于Xml數(shù)據(jù)的Http請求方法
今天小編就為大家分享一篇Python 3.x基于Xml數(shù)據(jù)的Http請求方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12Python網(wǎng)絡(luò)請求模塊urllib與requests使用介紹
網(wǎng)絡(luò)爬蟲的第一步就是根據(jù)URL,獲取網(wǎng)頁的HTML信息。在Python3中,可以使用urllib和requests進(jìn)行網(wǎng)頁數(shù)據(jù)獲取,這篇文章主要介紹了Python網(wǎng)絡(luò)請求模塊urllib與requests使用2022-10-10Python中實現(xiàn)定時任務(wù)常見的幾種方式
在Python中,實現(xiàn)定時任務(wù)是一個常見的需求,無論是在自動化腳本、數(shù)據(jù)處理、系統(tǒng)監(jiān)控還是其他許多應(yīng)用場景中,Python提供了多種方法來實現(xiàn)定時任務(wù),包括使用標(biāo)準(zhǔn)庫、第三方庫以及系統(tǒng)級別的工具,本文將詳細(xì)介紹幾種常見的Python定時任務(wù)實現(xiàn)方式2024-08-08pandas.dataframe按行索引表達(dá)式選取方法
今天小編就為大家分享一篇pandas.dataframe按行索引表達(dá)式選取方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10Python畫柱狀統(tǒng)計圖操作示例【基于matplotlib庫】
這篇文章主要介紹了Python畫柱狀統(tǒng)計圖操作,結(jié)合實例形式分析了Python基于matplotlib庫實現(xiàn)圖形繪制的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07