Excel 儲存格可能包含公式(如 =SUM(A1:A10))。Java 讀取時,需獲取公式計算後的結果值,而非公式字串。早期 Apache POI 正式版不支援此功能,開發者常面臨選型困境。
FormulaEvaluator,完整支援公式計算。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
public class PoiFormulaReader {
public static void main(String[] args) throws IOException {
try (FileInputStream fis = new FileInputStream("report.xlsx");
Workbook wb = new XSSFWorkbook(fis)) {
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
CellValue cellValue = evaluator.evaluate(cell);
switch (cellValue.getCellType()) {
case NUMERIC:
System.out.println(cell.getAddress() + " = " + cellValue.getNumberValue());
break;
case STRING:
System.out.println(cell.getAddress() + " = " + cellValue.getStringValue());
break;
case BOOLEAN:
System.out.println(cell.getAddress() + " = " + cellValue.getBooleanValue());
break;
case ERROR:
System.out.println(cell.getAddress() + " = ERROR: " +
FormulaError.forInt(cellValue.getErrorValue()).getString());
break;
default:
System.out.println(cell.getAddress() + " = (空白或不支援型別)");
}
}
}
}
}
}
Workbook.getCreationHelper().createFormulaEvaluator():建立評估器。FormulaEvaluator.evaluate(Cell):計算公式,返回 CellValue(不修改原儲存格)。FormulaEvaluator.evaluateAll():批次計算整個工作簿。FormulaEvaluator.evaluateInCell(Cell):計算並將結果寫回儲存格(修改檔案)。
import jxl.*;
import jxl.read.biff.BiffException;
import java.io.File;
import java.io.IOException;
public class JxlFormulaReader {
public static void main(String[] args) throws IOException, BiffException {
Workbook wb = Workbook.getWorkbook(new File("report.xls"));
Sheet sheet = wb.getSheet(0);
for (int row = 0; row < sheet.getRows(); row++) {
for (int col = 0; col < sheet.getColumns(); col++) {
Cell cell = sheet.getCell(col, row);
// jxl 直接返回計算後值(若支援該公式)
System.out.println(cell.getContents());
}
}
wb.close();
}
}
| 維度 | Apache POI | JExcelAPI (jxl) |
|---|---|---|
| 檔案格式支援 | .xls, .xlsx, .xlsm, .xlsb | .xls (Excel 95-2003) |
| 公式引擎 | 完整支援 300+ 函數、自訂函數、陣列公式 | 有限函數集,語言限制 |
| 效能/記憶體 | SXSSF 流式寫入支援大檔案 | 全載入記憶體,大檔案易 OOM |
| 維護狀態 | 活躍開發,頻繁釋出 | 停止更新(最後版本 2011 年) |
| 社群/生態 | 龐大,Spring、Hibernate 整合原生 | 極小,文檔稀缺 |
| Maven 坐標 | org.apache.poi:poi-ooxml:5.3.0 | net.sourceforge.jexcelapi:jxl:2.6.12 |
fastexcel (唯讀、流式、極快) 或 easyexcel (阿里開源、低記憶體)。
// 1. 重複使用評估器(執行緒不安全,單執行緒復用)
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
// 2. 強制重新計算所有公式(開啟檔案後首次)
evaluator.evaluateAll();
// 3. 處理外部連結公式(需實作 UDFFinder)
// evaluator.setupReferencedWorkbooks(Map);
// 4. 自訂函數(UDF)
// evaluator.getWorkbook().addToolPack(new MyCustomToolPack());
// 5. 錯誤處理
CellValue cv = evaluator.evaluate(cell);
if (cv.getCellType() == CellType.ERROR) {
FormulaError err = FormulaError.forInt(cv.getErrorValue());
// #N/A, #DIV/0!, #VALUE!, #REF!, #NAME?, #NUM!, #NULL!
}
Apache POI 早已解決「讀取公式計算值」難題,且持續進化支援最新 Excel 格式與複雜公式。JExcelAPI 因停止維護、格式受限,已不適合新專案。掌握 POI FormulaEvaluator 核心 API、流式處理 (SXSSF)、錯誤處理與自訂函數擴展,是 Java 處理 Excel 業務的必備技能。