Apache POI 是 Java 操作 Microsoft Office 文件的標準庫。本文示範使用 HSSF 元件讀取舊版 .xls (BIFF8) 格式,完整處理字串、數值、日期、公式、布林、空白、錯誤等七種儲存格型別,並正確格式化輸出。
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.3.0</version> <!-- 請使用最新版 -->
</dependency>
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExcelReader {
public static void readExcel(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath);
POIFSFileSystem fs = new POIFSFileSystem(fis);
HSSFWorkbook wb = new HSSFWorkbook(fs)) {
HSSFSheet sheet = wb.getSheetAt(0);
for (int rowIdx = 0; rowIdx <= sheet.getLastRowNum(); rowIdx++) {
HSSFRow row = sheet.getRow(rowIdx);
if (row == null) continue; // 空白列
for (short colIdx = 0; colIdx < row.getLastCellNum(); colIdx++) {
HSSFCell cell = row.getCell(colIdx);
String value = parseCell(cell);
System.out.println(rowIdx + "," + colIdx + ":" + value);
}
}
}
}
private static String parseCell(HSSFCell cell) {
if (cell == null) return "";
// 關鍵:設定編碼避免中文亂碼 (HSSF 專用)
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
return cell.getStringCellValue();
case HSSFCell.CELL_TYPE_NUMERIC:
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
return (date != null) ? new SimpleDateFormat("yyyy-MM-dd").format(date) : "";
} else {
// 避免科學記號,去除小數點後無意義的 0
return new DecimalFormat("0.######").format(cell.getNumericCellValue());
}
case HSSFCell.CELL_TYPE_FORMULA:
// 公式儲存格可能有快取值或字串形式
try {
String strVal = cell.getStringCellValue();
return strVal.isEmpty() ? String.valueOf(cell.getNumericCellValue()) : strVal;
} catch (IllegalStateException e) {
return String.valueOf(cell.getNumericCellValue());
}
case HSSFCell.CELL_TYPE_BOOLEAN:
return cell.getBooleanCellValue() ? "Y" : "N";
case HSSFCell.CELL_TYPE_ERROR:
return "ERROR:" + cell.getErrorCellValue();
case HSSFCell.CELL_TYPE_BLANK:
default:
return "";
}
}
public static void main(String[] args) throws IOException {
readExcel("F:/1.xls");
}
}
| 項目 | 說明 |
|---|---|
cell.setEncoding(ENCODING_UTF_16) | HSSF (.xls) 必須設定,否則中文會亂碼;XSSF (.xlsx) 不需要 |
HSSFDateUtil.isCellDateFormatted() | 判斷數值儲存格是否為日期格式(Excel 內部以數值儲存日期) |
DecimalFormat("0.######") | 避免 1.0 輸出為 1,保留必要小數位 |
| 公式儲存格處理 | 可能無快取值,需同時嘗試 getStringCellValue 與 getNumericCellValue |
| 空白列/儲存格 | getRow 可能回傳 null,getCell 回傳 null 或型別為 BLANK |
若需同時支援 .xls 與 .xlsx,建議使用 WorkbookFactory.create(inputStream) 自動偵測:
try (Workbook wb = WorkbookFactory.create(new FileInputStream(file))) {
// 後續程式碼相同,介面為統一的 Workbook/Sheet/Row/Cell
}
SXSSF (串流式寫入) 或 XSSF 的 EventModel (SAX 模式讀取)。Workbook.close() 被呼叫,釋放臨時檔案。此範例涵蓋 .xls 讀取的完整型別處理邏輯,可直接整合至資料匯入、報表產生等實務專案中。