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

Apache POI 讀取 Excel 2007 格式檔案無反應的解決方案

     編輯:程式設計綜合問答

問題現象

使用 WorkbookFactory.create(FileInputStream) 讀取 Excel 2003 (.xls) 正常,但讀取 Excel 2007 (.xlsx) 時程式卡住,既不拋出異常也讀不出資料。

根本原因

Excel 2003 與 2007 採用完全不同的檔案格式:

  • .xls (BIFF8):二進位格式,對應 HSSFWorkbook
  • .xlsx (OOXML):基於 ZIP 的 XML 格式,對應 XSSFWorkbook

WorkbookFactory 雖支援自動識別,但某些版本或環境下對 .xlsx 支援不穩定,特別是缺少 ooxml 相關依賴時。

解決方案

方案一:顯式指定工作簿類型(推薦)

// 根據副檔名判斷
String filePath = "data.xlsx";
FileInputStream fis = new FileInputStream(filePath);
Workbook workbook;

if (filePath.endsWith(".xlsx")) {
    workbook = new XSSFWorkbook(fis); // Excel 2007+
} else if (filePath.endsWith(".xls")) {
    workbook = new HSSFWorkbook(fis); // Excel 2003
} else {
    throw new IllegalArgumentException("不支援的檔案格式");
}

方案二:確保依賴完整

Maven 專案需同時引入:

<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>

方案三:使用 WorkbookFactory 但加強錯誤處理

try (FileInputStream fis = new FileInputStream(file)) {
    Workbook wb = WorkbookFactory.create(fis);
    // 立即驗證是否成功載入
    if (wb.getNumberOfSheets() == 0) {
        throw new IOException("工作簿為空或格式不支援");
    }
    // 後續處理...
} catch (Exception e) {
    log.error("讀取 Excel 失敗: {}", file.getName(), e);
    throw new RuntimeException("Excel 解析異常", e);
}

完整讀取範例

public List<Map<String, String>> readExcel(File file) {
    List<Map<String, String>> data = new ArrayList<>();
    try (FileInputStream fis = new FileInputStream(file)) {
        Workbook wb = WorkbookFactory.create(fis);
        Sheet sheet = wb.getSheetAt(0);
        Row headerRow = sheet.getRow(0);
        int colNum = headerRow.getPhysicalNumberOfCells();
        
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row == null) continue;
            
            Map<String, String> rowData = new HashMap<>();
            for (int j = 0; j < colNum; j++) {
                Cell cell = row.getCell(j);
                String key = getCellValueAsString(headerRow.getCell(j));
                String value = getCellValueAsString(cell);
                rowData.put(key, value);
            }
            data.add(rowData);
        }
    } catch (Exception e) {
        throw new RuntimeException("Excel 讀取失敗", e);
    }
    return data;
}

常見坑點提醒

  • 大檔案使用 SXSSFWorkbook (串流模式) 避免 OOM
  • 儲存格類型判斷:cell.getCellType() 需處理 NUMERIC、STRING、BOOLEAN、FORMULA 等
  • 日期儲存格需用 DateUtil.isCellDateFormatted(cell) 判斷
  • 合併儲存格需額外處理 sheet.getMergedRegions()

參考資源

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved