一、前言:Excel 與 Python 的不解之緣
在數據處理與辦公自動化領域,Excel 文件(.xls / .xlsx) 一直是最常見的數據載體。
而在 Python 世界中,圍繞 Excel 操作的生態非常龐大,其中最經典、最輕量級的讀文件庫之一便是 —— xlrd。
xlrd 是一個專門用於讀取 Excel 文件內容的 Python 庫,它支持從 Excel 工作簿中提取工作表(Sheet)、單元格內容、數據類型等信息。
雖然在新版本中它僅支持舊格式 .xls 文件,但憑藉其簡潔、高效和穩定的特點,xlrd 依然在許多老系統與數據遷移任務中被廣泛使用。
二、庫的起源與演變:從萬能到專一
在早期的 Python Excel 生態中,xlrd 和 xlwt(寫入)是一對黃金搭檔,配合使用可以輕鬆實現 Excel 的讀寫操作。
- xlrd(read):讀取 Excel 文件內容。
- xlwt(write):寫入
.xls文件。 - xlutils:基於二者實現的高級操作庫(複製、修改工作表等)。
然而,自 xlrd 2.0.0
🚫 不再支持
.xlsx文件讀取,僅支持 Excel 97-2003 格式.xls。
主要原因包括:
- Excel 2007 之後的
.xlsx文件是基於 XML + ZIP 的複雜結構,解析成本高; - 已有更現代的庫如
openpyxl和pandas提供更好的支持; - 維護者希望
xlrd聚焦舊格式的穩定讀取。
這也導致了後期許多項目遷移至 openpyxl 或 pandas.read_excel()。
不過,如果你面對的是歷史系統、銀行報表、政府舊數據,xlrd 仍然是最輕量可靠的解決方案。
三、安裝與環境要求
1. 安裝方式
pip install xlrd
2. 版本建議
如果你的 Excel 文件是 .xlsx 格式,請務必使用舊版本(≤1.2.0):
pip install xlrd==1.2.0
否則會遇到如下錯誤:
XLRDError: Excel xlsx file; not supported
3. 基本依賴
xlrd 只依賴標準庫和 zipfile 模塊,因此即使在嵌入式系統(如樹莓派、Jetson Nano)上也能輕鬆運行。
四、核心對象結構分析
xlrd 的內部設計採用了典型的分層數據結構,理解這點有助於掌握其靈活性:
|
層級
|
對象名稱
|
描述
|
|
1
|
Book |
Excel 文件對象(工作簿)
|
|
2
|
Sheet |
每個工作表
|
|
3
|
Cell |
單元格對象(包含值與類型)
|
|
4
|
XFRecord |
樣式記錄對象(字體、邊框、格式等)
|
這種結構類似於文檔樹(Document Object Model),讀取 Excel 時,xlrd 會逐級解析:
import xlrd
workbook = xlrd.open_workbook("data.xls")
sheet = workbook.sheet_by_index(0)
value = sheet.cell_value(0, 0)
print(value)
執行結果:
員工編號
五、主要API與使用方法詳解
1. 打開 Excel 文件
import xlrd
book = xlrd.open_workbook("report.xls")
支持參數:
filename: 文件路徑file_contents: 二進制字節流encoding_override: 指定編碼(如 GBK)on_demand: 是否懶加載(節省內存)ragged_rows: 是否允許行列不對齊
2. 獲取工作表
# 通過索引
sheet = book.sheet_by_index(0)
# 通過名稱
sheet = book.sheet_by_name('銷售數據')
# 獲取所有表名
print(book.sheet_names())
3. 獲取單元格內容與屬性
value = sheet.cell_value(1, 2) # 第二行第三列
ctype = sheet.cell_type(1, 2) # 數據類型
常見的 ctype 類型:
|
類型編號
|
類型名
|
含義
|
|
0
|
XL_CELL_EMPTY
|
空單元格
|
|
1
|
XL_CELL_TEXT
|
字符串
|
|
2
|
XL_CELL_NUMBER
|
數值
|
|
3
|
XL_CELL_DATE
|
日期
|
|
4
|
XL_CELL_BOOLEAN
|
布爾值
|
|
5
|
XL_CELL_ERROR
|
錯誤
|
4. 遍歷所有數據
for row_idx in range(sheet.nrows):
row = sheet.row_values(row_idx)
print(row)
或者使用 get_rows():
for row in sheet.get_rows():
print([cell.value for cell in row])
5. 日期類型的處理
Excel 內部使用浮點數存儲日期,需要藉助 xlrd.xldate_as_datetime() 進行轉換:
from datetime import datetime
date_value = sheet.cell_value(2, 3)
date_obj = xlrd.xldate_as_datetime(date_value, book.datemode)
print(date_obj.strftime("%Y-%m-%d"))
六、實戰案例:Excel 數據提取與分析
下面通過一個實際案例展示如何利用 xlrd 實現報表數據分析。
案例背景
某公司每月導出一份 sales_2024.xls 銷售報表,包含以下字段:
|
日期
|
產品
|
銷量
|
單價
|
地區
|
|
2024-01-01
|
A類產品
|
120
|
30
|
上海
|
|
2024-01-02
|
B類產品
|
80
|
25
|
北京
|
目標
- 計算各產品的總銷售額
- 輸出每個地區的總銷售額分佈
步驟1:讀取數據
import xlrd
book = xlrd.open_workbook('sales_2024.xls')
sheet = book.sheet_by_index(0)
data = []
for row_idx in range(1, sheet.nrows):
row = sheet.row_values(row_idx)
data.append(row)
步驟2:計算彙總
from collections import defaultdict
product_sales = defaultdict(float)
region_sales = defaultdict(float)
for row in data:
product = row[1]
sales = row[2] * row[3]
region = row[4]
product_sales[product] += sales
region_sales[region] += sales
print("按產品統計:", dict(product_sales))
print("按地區統計:", dict(region_sales))
輸出結果:
按產品統計: {'A類產品': 3600.0, 'B類產品': 2000.0}
按地區統計: {'上海': 3600.0, '北京': 2000.0}
步驟3:可視化展示(與 Matplotlib 結合)
import matplotlib.pyplot as plt
plt.bar(product_sales.keys(), product_sales.values())
plt.title("產品銷售額對比")
plt.xlabel("產品")
plt.ylabel("銷售額(元)")
plt.show()
這展示了 xlrd 在數據提取階段的強大能力,與現代可視化庫完美兼容。
七、性能優化與大文件讀取
當 Excel 文件行數超過 10 萬行時,內存開銷會顯著上升。
以下技巧可幫助提升性能:
1. 啓用按需加載
book = xlrd.open_workbook('large.xls', on_demand=True)
僅在訪問某個 Sheet 時加載數據,可顯著節省內存。
2. 避免重複讀取單元格對象
使用 row_values() 一次性獲取整行數據,而非多次調用 cell_value()。
3. 文件格式轉換
若文件超過幾百 MB,建議先用命令行或 pandas 轉為 CSV 再分析:
import pandas as pd
df = pd.read_excel('large.xls', engine='xlrd')
df.to_csv('large.csv', index=False)
八、與其他庫的比較
|
功能點
|
xlrd
|
openpyxl
|
pandas
|
|
支持文件格式
|
|
|
|
|
讀取速度
|
快(小文件)
|
稍慢
|
中等
|
|
內存佔用
|
較低
|
較高
|
中等
|
|
寫入能力
|
無
|
有
|
有
|
|
API 難度
|
簡單
|
中等
|
簡單
|
|
適合場景
|
老系統兼容、輕量提取
|
現代 Excel 操作
|
分析任務
|
總結:
- 如果你只需讀取
.xls文件:選xlrd。 - 如果需要寫入或支持
.xlsx:用openpyxl。 - 如果需要快速分析:用
pandas.read_excel()。
九、深入源碼:xlrd 的解析機制
xlrd 的核心邏輯位於 book.py 與 sheet.py 模塊。其工作流程大致為:
- 打開文件 → 識別格式(OLE2 vs XML)
- 解析 Workbook → Sheet → Cell
- 建立數據緩存與索引表
- 提供 Pythonic API 封裝訪問
核心函數結構如下:
def open_workbook(filename=None, file_contents=None, encoding_override=None, ...):
bk = Book()
bk.load(filename)
return bk
Book 類中維護 sheets 列表,每個 Sheet 又包含 _cell_values 數組和 _cell_types 數組,用於快速索引。
這種結構雖然不如 pandas 靈活,但勝在內存可控和結構清晰。
十、版本兼容與遷移策略
1. xlrd >= 2.0 不支持 .xlsx
對於 .xlsx 文件,請使用:
import pandas as pd
df = pd.read_excel('file.xlsx', engine='openpyxl')
2. 向下兼容舊系統
若必須兼容 .xls 與 .xlsx:
try:
book = xlrd.open_workbook('data.xlsx')
except Exception:
import openpyxl
wb = openpyxl.load_workbook('data.xlsx')
3. 推薦替代方案
- 讀取
.xls:xlrd - 寫入
.xls:xlwt - 讀取/寫入
.xlsx:openpyxl - 分析型任務:
pandas
十一、實際應用案例:自動報表系統
在許多中小企業中,日報/週報 Excel 報表往往手動彙總。使用 xlrd 可實現自動提取並生成彙總結果。
示例流程:
- 掃描
./reports文件夾下所有.xls文件 - 讀取每個文件中的“銷售額”數據
- 彙總後生成一份統計表(通過
xlwt寫出)
import os, xlrd, xlwt
summary = xlwt.Workbook()
sheet_sum = summary.add_sheet('彙總')
row_index = 0
for file in os.listdir('./reports'):
if file.endswith('.xls'):
wb = xlrd.open_workbook(os.path.join('./reports', file))
sh = wb.sheet_by_index(0)
total = sum(sh.col_values(2)[1:]) # 第三列為銷售額
sheet_sum.write(row_index, 0, file)
sheet_sum.write(row_index, 1, total)
row_index += 1
summary.save('彙總結果.xls')
這就是最典型的辦公自動化應用之一。
十二、常見錯誤與排查
|
錯誤類型
|
説明
|
解決方法
|
|
|
新版本不支持 |
降級至 |
|
|
文件路徑錯誤
|
檢查路徑、使用絕對路徑
|
|
|
Sheet 索引錯誤
|
確認工作表存在
|
|
|
編碼問題
|
指定 |
十三、與 Pandas 的結合:批量數據分析
pandas 的 read_excel() 默認會使用 xlrd(舊版本),因此你可以結合兩者快速分析數據:
import pandas as pd
df = pd.read_excel('report.xls', engine='xlrd')
print(df.describe())
對於 .xlsx 文件:
df = pd.read_excel('report.xlsx', engine='openpyxl')
十四、總結與展望
xlrd 雖然是一個“老派”庫,但它依然具備以下優勢:
✅ 輕量級、穩定性高
✅ 適合服務器端、嵌入式環境
✅ 兼容老式 Excel 格式
✅ 代碼簡單易嵌入腳本
在現代 Python 數據分析生態中,xlrd 更多地扮演**“穩定讀取引擎”**的角色,而非“通用 Excel 工具”。
對於大多數歷史數據處理、Excel 自動化遷移任務而言,它仍然是一款值得信賴的老朋友。
參考資源
- 官方文檔:https://github.com/python-excel/xlrd
- 兼容庫:openpyxl
- 高級分析:pandas.read_excel()