Python 原生 xlrd/xlwt/openpyxl 處理含圖表的 Excel 極其困難。本文展示透過 JPype 啟動 JVM、載入 Java 庫 SmartXLS,實現讀取、修改、寫入 Excel 並完整保留圖表的跨語言整合方案。
核心依賴與環境
- JPype:Python 嵌入 JVM 橋接器(
pip install jpype1)
- SmartXLS:Java Excel 操作庫(需
SX.jar)
- JDK:需安裝並設定
JAVA_HOME
完整實作程式碼
# -*- coding: utf8 -*-
"""
使用 Java 模組 SmartXLS 和 JPype 修改 Excel
優勢:可生成和保持圖表(xlrd/xlwt 無法做到)
"""
from __future__ import print_function, division
import os
import jpype
# os.environ['JAVA_HOME'] = "/usr/lib64/jvm/default-java" # 若未設定環境變數需啟用
# 啟動 JVM,指定 classpath
jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.class.path=SX.jar')
# 載入 Java 類別
WorkBook = jpype.JClass('com.smartxls.WorkBook')
w = WorkBook()
# 讀取、修改、寫入
w.read("b.xls")
w.setNumber(0, 2, 0, 20.0) # sheet索引, 行, 列, 值
w.write("c.xls")
# 關閉 JVM(程式結束自動關閉,良好習慣顯式調用)
jpype.shutdownJVM()
關鍵 API 對照
| 操作 | SmartXLS (Java) | openpyxl (Python) |
| 讀取檔案 | wb.read("file.xls") | load_workbook() |
| 寫入數值 | wb.setNumber(sheet, row, col, val) | ws.cell(row, col).value = val |
| 寫入公式 | wb.setFormula(sheet, row, col, "=A1+B1") | ws.cell(row, col).value = "=A1+B1" |
| 保留圖表 | 完整支援 | 不支援(圖表會遺失) |
| 儲存 | wb.write("out.xls") | wb.save("out.xlsx") |
常見坑點與解決
- JVM 啟動失敗:確認
JAVA_HOME、JDK 版本(建議 JDK 8/11)、SX.jar 路徑正確
- 記憶體不足:
jpype.startJVM(..., '-Xmx512m') 調整堆大小
- 執行緒安全:JPype 不支援多執行緒並發調用,需鎖序列化
- 版本相容:
jpype1 (PyPI) 非舊版 jpype,API 有差異
替代方案對比
| 方案 | 圖表支援 | 複雜度 | 效能 |
| JPype + SmartXLS | ✅ 完整 | 高(需 JVM) | 中(JNI 開銷) |
| openpyxl | ❌ 遺失 | 低 | 高 |
| xlwings (Windows/Mac) | ✅ 透過 Excel 應用程式 | 中 | 低(需安裝 Office) |
| LibreOffice headless 轉換 | ✅ 間接 | 高 | 低 |
適用場景建議
- 模板含圖表,需資料填充後保留圖表 → 首選 SmartXLS
- 純資料處理、無圖表 → openpyxl 原生更簡單
- 需 Excel 計算引擎(公式重算) → xlwings 或 LibreOffice