雖然 Apache POI 是目前主流選擇,但 JXL(jexcelapi)作為純 Java 實現、不依賴 Windows 環境、體積輕量的特性,在 Linux 服務器、嵌入式設備、舊系統維護等場景仍有獨特價值。本文詳細講解 JXL 讀取 Excel 核心 API 與實戰代碼。
jxl.jar:官方站點| 類 | 職責 | 關鍵方法 |
|---|---|---|
Workbook | 整個工作簿 | getWorkbook(File), getSheet(int), close() |
Sheet | 單個工作表 | getCell(int col, int row), getRows(), getColumns() |
Cell | 單個儲存格 | getContents(), getType(), getRow(), getColumn() |
座標系統:(列, 行),均從 0 開始,列對應 x(水平),行對應 y(垂直)。合併儲存格以左上角座標為準。
import java.io.File;
import jxl.*;
public class ExcelReaderDemo {
public static void main(String[] args) {
String filePath = "t.xls"; // 僅支援 .xls 格式
try {
// 1. 獲取 Workbook
Workbook workbook = Workbook.getWorkbook(new File(filePath));
// 2. 獲取第一個 Sheet(索引 0)
Sheet sheet = workbook.getSheet(0);
// 3. 讀取標題儲存格 (0,0)
Cell titleCell = sheet.getCell(0, 0);
System.out.println("標題:" + titleCell.getContents());
// 4. 逐行讀取數據(假設第 0 行是標題,從第 1 行開始)
int row = 1;
while (true) {
Cell cell0 = sheet.getCell(0, row); // 第 1 列
Cell cell1 = sheet.getCell(1, row); // 第 2 列
Cell cell2 = sheet.getCell(2, row); // 第 3 列
// 遇到第一列為空視為結束
if (cell0.getContents().isEmpty()) break;
System.out.println(cell0.getContents() + "\t" +
cell1.getContents() + "\t" +
cell2.getContents());
row++;
}
// 5. 關鍵:釋放資源
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.io.File;
import java.util.*;
import jxl.*;
public class JxlUtils {
/**
* 讀取 Excel 為 List<Map<String, String>>,首行作為標題
*/
public static List<Map<String, String>> readSheet(File file, int sheetIndex) {
List<Map<String, String>> result = new ArrayList<>();
Workbook workbook = null;
try {
workbook = Workbook.getWorkbook(file);
Sheet sheet = workbook.getSheet(sheetIndex);
int cols = sheet.getColumns();
int rows = sheet.getRows();
if (rows == 0) return result;
// 讀取標題行
String[] headers = new String[cols];
for (int c = 0; c < cols; c++) {
headers[c] = sheet.getCell(c, 0).getContents().trim();
}
// 讀取數據行
for (int r = 1; r < rows; r++) {
Map<String, String> rowMap = new LinkedHashMap<>();
boolean allEmpty = true;
for (int c = 0; c < cols; c++) {
String value = sheet.getCell(c, r).getContents().trim();
rowMap.put(headers[c], value);
if (!value.isEmpty()) allEmpty = false;
}
if (allEmpty) continue; // 跳過全空行
result.add(rowMap);
}
} catch (Exception e) {
throw new RuntimeException("讀取 Excel 失敗: " + file.getName(), e);
} finally {
if (workbook != null) workbook.close();
}
return result;
}
}
| 限制 | 影響 | 替代方案 |
|---|---|---|
| 僅支援 .xls (BIFF 格式) | 無法讀取 .xlsx | 遷移至 Apache POI (支援 .xls/.xlsx) |
| 不支援公式計算 | 只能讀取公式結果值 | POI 提供 FormulaEvaluator |
| 大文件記憶體佔用高 | 全量載入內存 | POI SXSSF / EasyExcel 流式讀取 |
| 項目停止維護 (2012 年最後更新) | 無安全更新、無新特性 | 生產環境強烈建議遷移 POI |
// JXL
Workbook wb = Workbook.getWorkbook(file);
Sheet s = wb.getSheet(0);
String v = s.getCell(0,0).getContents();
// POI (HSSF - .xls)
Workbook wb = new HSSFWorkbook(new FileInputStream(file));
Sheet s = wb.getSheetAt(0);
String v = s.getRow(0).getCell(0).getStringCellValue();
// POI (XSSF - .xlsx)
Workbook wb = new XSSFWorkbook(file); // 或 FileInputStream
// 後續 API 相同
wb.close();
finally { workbook.close() } 防止句柄洩漏DateCell/NumberCell 正確解析,避免 getContents() 格式問題