首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java POI 操作 Excel 完全指南:.xls/.xlsx 區別、讀寫範例與常見坑

     編輯:Java 綜合教學

兩大格式核心區別 (決定 API 選擇)

特性.xls (Excel 97-2003).xlsx (Excel 2007+)
儲存格式BIFF (二進位)OOXML (XML + ZIP 壓縮)
檔頭魔數無固定PK\\x03\\x04 (ZIP)
行數上限65,536 (2^16)1,048,576 (2^20)
列數上限256 (IV)16,384 (XFD)
POI 類前綴HSSF (Horrible SpreadSheet Format)XSSF (XML SpreadSheet Format)
通用介面Workbook/Sheet/Row/Cell (SS 模型)

⚠️ **務必確認目標檔案格式再選擇 API**,混用會拋 InvalidFormatException。

通用 SS 介面 (推薦:格式無關代碼)

// 自動根據副檔名/檔頭判斷
Workbook wb = WorkbookFactory.create(new FileInputStream("data.xlsx")); // 或 .xls
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
String val = cell.getStringCellValue();

建立 Excel 檔案

1. 建立 Workbook

Workbook wb = new XSSFWorkbook(); // 或 new HSSFWorkbook()

2. 建立 Sheet (支援名稱合法性檢查)

Sheet sheet = wb.createSheet("報表");
String safe = WorkbookUtil.createSafeSheetName("[O'Brien's sales*?]"); // 自動轉義非法字符
Sheet sheet2 = wb.createSheet(safe);

3. 建立 Row/Cell 並寫入多型別數據

CreationHelper helper = wb.getCreationHelper();
Row row = sheet.createRow(0); // 索引從 0 開始

row.createCell(0).setCellValue(100);                    // 數值
row.createCell(1).setCellValue(3.14);
row.createCell(2).setCellValue(helper.createRichTextString("中文內容")); // 富文本
row.createCell(3).setCellValue(true);                   // 布林
row.createCell(4).setCellValue(new Date());             // 日期 (需配合 CellStyle)

4. 日期格式化 (關鍵)

CellStyle dateStyle = wb.createCellStyle();
dateStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
Cell dateCell = row.createCell(4);
dateCell.setCellValue(new Date());
dateCell.setCellStyle(dateStyle);

5. 輸出檔案

try (FileOutputStream out = new FileOutputStream("report.xlsx")) {
    wb.write(out);
}

讀取 Excel 檔案

try (InputStream in = new FileInputStream("report.xlsx")) {
    Workbook wb = WorkbookFactory.create(in);
    Sheet sheet = wb.getSheetAt(0);
    
    for (Row row : sheet) {
        if (row == null) continue;
        for (Cell cell : row) {
            if (cell == null) continue;
            switch (cell.getCellType()) {
                case STRING:  System.out.print(cell.getStringCellValue() + "\t"); break;
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) 
                        System.out.print(cell.getDateCellValue() + "\t");
                    else 
                        System.out.print(cell.getNumericCellValue() + "\t");
                    break;
                case BOOLEAN: System.out.print(cell.getBooleanCellValue() + "\t"); break;
                case FORMULA: System.out.print(cell.getCellFormula() + "\t"); break;
                default:      System.out.print("\t");
            }
        }
        System.out.println();
    }
}

大數據量優化:SXSSF (流式寫入)

XSSF 全載入記憶體,百萬行會 OOM。SXSSF 僅保留最近 N 行在記憶體,其餘刷盤。

SXSSFWorkbook wb = new SXSSFWorkbook(100); // 保留 100 行
// 後續 API 與 XSSF 完全一致
wb.write(out);
wb.dispose(); // 必須調用釋放臨時檔案

常見坑與解決

問題原因解決
數字讀成科學計數法NUMERIC 型別預設 toString用 DataFormatter 或 DecimalFormat 格式化
日期讀成數字Excel 日期本質是數字DateUtil.isCellDateFormatted(cell) 判斷後 getDateCellValue()
公式值為 nullPOI 不自動計算公式FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); evaluator.evaluate(cell)
中文亂碼編碼不一致確保檔案 UTF-8,POI 內部用 Unicode,通常無問題
合併儲存格讀取只在主儲存格有值sheet.getMergedRegions() 遍歷區域
SXSSF 寫完檔案為空未調用 dispose()必須在 write() 後調用 dispose()

Maven 依賴 (POI 5.2+)

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved