1. 程式人生 > >openpyxl讀取xlsx

openpyxl讀取xlsx

在做遊戲的時候,經常會使用到execel來做靜態配置表。之前我們使用讀取xls檔案的時候都是使用的xlrd庫。但是這個庫對於後來的xlsx的版本支援不算太好:
比如說:當你使用xlrd來載入xlsx檔案的時候,在程式碼中加入了
xlrd.open_workbook(filePath,formatting_info=True)
formatting_info=True
馬上會得到這個報錯提示:

Traceback (most recent call last):
  File "xxxxxxxx\test_read_excel_color.py", line 7, in <module>
    xlrd.open_workbook(r'./xxxxx.xlsx'
,formatting_info=True) File "C:\Python27\lib\site-packages\xlrd\__init__.py", line 422, in open_workbook ragged_rows=ragged_rows, File "C:\Python27\lib\site-packages\xlrd\xlsx.py", line 751, in open_workbook_2007_xml raise NotImplementedError("formatting_info=True not yet implemented") NotImplementedError: formatting_info=True
not yet implemented

新版本的xlsx的格式還沒有實現。
官網中formatting_info的解釋是:

> formatting_info –
The default is False, which saves memory. In this case, “Blank” cells, which are those with their own formatting information but no data, are treated as empty by ignoring the file’s BLANK and MULBLANK records. This cuts off any bottom or
right “margin” of rows of empty or blank cells. Only cell_value() and cell_type() are available.

這個option使用與節約記憶體的。在這個情況下,空的單元格,存在格式資訊但是沒有資料,將會被當成空來對待。這將會裁剪掉任何底部,右邊的“邊緣”空的表格。只有cell_value()和cell_type是有效的。
實際上在當關閉了這個option之後,當程式需要去載入cell中的顏色程式碼的時候將會存在下面的問題。

Traceback (most recent call last):
  File "xxxxx\test_read_execel_color1.py", line 10, in <module>
    xf_idx  = xws1.cell_xf_index(0,0)
  File "C:\Python27\lib\site-packages\xlrd\sheet.py", line 420, in cell_xf_index
    self.req_fmt_info()
  File "C:\Python27\lib\site-packages\xlrd\sheet.py", line 1664, in req_fmt_info
    raise XLRDError("Feature requires open_workbook(..., formatting_info=True)")
XLRDError: Feature requires open_workbook(..., formatting_info=True)

還不知道里面還存在一些啥其他的問題不。關閉了這個option之後,有些xlrd的程式碼就不能這麼寫了。還是很不爽。

後來去查了一下現在大概大家都會開始使用openpyxl庫來讀取配置表了。記錄一下當前掌握的一些基本用法。
在他主頁上直接這麼介紹:
A Python library to read/write Excel 2010 xlsx/xlsm files
在下面的文章中我們將會對比的來這兩者的程式碼編寫。

載入execel

openpyxl

from openpyxl import load_workbook
wb=load_workbook(filename = r'./mx_svr_list.xlsx')
ws1=wb.get_sheet_by_name("Sheet1")

xlrd

xwb=xlrd.open_workbook(r'./mx_svr_list.xls',formatting_info=True)
xws1=xwb.sheet_by_index(0)

讀取Sheet中的內容

openpyxl

print(ws1.cell(row=1,column=1).value)
    for sheet_name in wb.get_named_ranges():
        sheet=wb.get_sheet_by_name(sheet_name)
        for i in range(1,sheet.max_row+1):
            print(sheet.cell(row=i,column=1).value)

xlrd

    xwb=xlrd.open_workbook(filename = IP_CONFIG_FILE,formatting_info=True)
    sheet=xwb.sheet_by_index(0)
    for i in range(0,sheet.nrows):
        value=sheet.cell_value(i,0)

注意openpyxl的下標是從1開始的,xlrd的下標從0開始。

讀取cell中的顏色

openpyxl

c = ws1.cell(row=1,column=1)
fill = c.fill
front = c.font
print(c.value)
print(fill.start_color.rgb)
print(front.color.rgb)
伺服器名稱
FF00B050
FFFFFF00

這裡他的排列次序是:
[alpha通道:R:G:B]
這裡可以將單元格里面的字型顏色和背景顏色都打印出來。
對於openpyxl中的api介紹大家可以查閱這個文件

xlrd

xf_idx  = xws1.cell_xf_index(0,0)
xf_list = xwb.xf_list[xf_idx]
color   = xwb.colour_map[xf_list.background.pattern_colour_index]
print(color)
f = xwb.font_list[xf_list.font_index]
color = xwb.colour_map[f.colour_index]
print(color)
伺服器名稱
(0, 128, 0)
(255, 255, 0)

具體xlrd的api方法介紹可以查閱這裡
對比一下看這兩套庫的實現,openpyxl實現的要更加友好一些。他將最後的結果封裝成了類。而且這個格式裡面是支援alpha通道的。而xlrd庫使用就比較繁瑣了。他需要先到sheet裡面讀取到這個cell的xformatting的資訊,然後到book物件中的xf_list中讀取這個物件出來。字型的資訊還需要通過xformatting中font_index到book中的font_list中抓取出font物件,然後在book的colour_map中定位到這個RGB資訊,而且這個顏色中是沒有alpha通道資訊。xlrd條理還是算清晰。只是說操作起來比較繁瑣。
有個憂傷的故事,就是openpyxl是不支援xls版本的。

Traceback (most recent call last):
  File "F:\tmp\xls_read\MyTest.py", line 4, in <module>
    wb = load_workbook('./gonghuiMap.xls')
  File "C:\Python27\lib\site-packages\openpyxl\reader\excel.py", line 151, in load_workbook
    archive = _validate_archive(filename)
  File "C:\Python27\lib\site-packages\openpyxl\reader\excel.py", line 105, in _validate_archive
    raise InvalidFileException(msg)
InvalidFileException: openpyxl does not support the old .xls file format, please use xlrd to read this file, or convert it to the more recent .xlsx file format.