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

Apache POI (HSSF/XSSF) 純 Java 操作 Excel 完整指南:從入門到生產級應用

     編輯:Java 程式設計入門

專案背景

企業級系統常需「導出 Excel 報表」「匯入 Excel 資料」。Apache POI 是純 Java 實現、無需 Office 安裝、跨平台的標杆庫。本文涵蓋 HSSF (Excel 97-2003 `.xls`) 與 XSSF (Excel 2007+ `.xlsx`) 核心 API、樣式、大數據流式處理、中文支援、遷移建議。

Maven 依賴 (POI 5.3.0)

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>5.3.0</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>5.3.0</version>
</dependency>

核心物件模型

介面/類對應 Excel 概念HSSF 實現XSSF 實現
`Workbook`整個活頁簿`HSSFWorkbook``XSSFWorkbook`
`Sheet`工作表`HSSFSheet``XSSFSheet`
`Row`列`HSSFRow``XSSFRow`
`Cell`儲存格`HSSFCell``XSSFCell`
`CellStyle`儲存格樣式`HSSFCellStyle``XSSFCellStyle`
`Font`字型`HSSFFont``XSSFFont`
`DataFormat`資料格式 (日期、貨幣等)`HSSFDataFormat``XSSFDataFormat`

寫入 Excel 完整範例 (.xlsx)

try (XSSFWorkbook wb = new XSSFWorkbook();
     FileOutputStream fos = new FileOutputStream("report.xlsx")) {

    XSSFSheet sheet = wb.createSheet("銷售報表");

    // 1. 樣式定義
    XSSFCellStyle headerStyle = wb.createCellStyle();
    XSSFFont headerFont = wb.createFont();
    headerFont.setBold(true);
    headerFont.setFontHeightInPoints((short) 12);
    headerStyle.setFont(headerFont);
    headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    headerStyle.setBorderBottom(BorderStyle.THIN);
    headerStyle.setAlignment(HorizontalAlignment.CENTER);

    XSSFCellStyle dataStyle = wb.createCellStyle();
    dataStyle.setBorderBottom(BorderStyle.THIN);
    dataStyle.setDataFormat(wb.createDataFormat().getFormat("#,##0.00"));

    // 2. 表頭
    Row header = sheet.createRow(0);
    String[] cols = {"產品", "單價", "數量", "金額", "日期"};
    for (int i = 0; i < cols.length; i++) {
        Cell cell = header.createCell(i);
        cell.setCellValue(cols[i]);
        cell.setCellStyle(headerStyle);
    }

    // 3. 資料列 (模擬 10000 列)
    for (int r = 1; r <= 10000; r++) {
        Row row = sheet.createRow(r);
        row.createCell(0).setCellValue("商品" + r);
        row.createCell(1).setCellValue(100 + r * 0.5);
        row.createCell(2).setCellValue(r % 100);
        Cell amt = row.createCell(3);
        amt.setCellFormula("B" + (r+1) + "*C" + (r+1));
        amt.setCellStyle(dataStyle);
        Cell dt = row.createCell(4);
        dt.setCellValue(new java.util.Date());
        dt.setCellStyle(dataStyle);
    }

    // 4. 自動欄寬
    for (int i = 0; i < cols.length; i++) sheet.autoSizeColumn(i);

    wb.write(fos);
}

讀取 Excel (事件驅動 SAX 模式,低記憶體)

// 僅示意 XSSF SAX 解析器
OPCPackage pkg = OPCPackage.open("big.xlsx");
XSSFReader reader = new XSSFReader(pkg);
StylesTable styles = reader.getStylesTable();
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);

XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(new XSSFSheetXMLHandler(styles, strings, new SheetContentsHandler() {
    @Override
    public void startRow(int rowNum) { /* 新列 */ }
    @Override
    public void cell(String cellRef, String formattedValue, XSSFComment comment) {
        System.out.println(cellRef + " = " + formattedValue);
    }
    @Override
    public void endRow(int rowNum) { /* 列結束 */ }
}, false));

parser.parse(new InputSource(reader.getSheetsData().next()));

中文支援關鍵設定

  • **字型註冊** (PDF/圖片導出需):`Font font = wb.createFont(); font.setFontName("Microsoft YaHei");` 需系統安裝該字型。
  • **編碼**:POI 內部使用 Unicode,讀寫 `.xlsx` 無編碼問題;`.xls` (HSSF) 需 `wb = new HSSFWorkbook();` 直接支援雙位元組字符。
  • **公式計算**:`FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); evaluator.evaluateAll();`

大數據量優化策略 (百萬列+)

策略適用場景記憶體佔用
SXSSF (Streaming)僅寫入、不需隨機讀取~100MB (固定視窗)
XSSF SAX 事件解析僅讀取、不需修改~50MB
分批寫入 + 定期 flush需隨機修改視批次大小
// SXSSF 範例:保留最近 100 行在記憶體,其餘刷入磁碟
try (SXSSFWorkbook wb = new SXSSFWorkbook(100)) {
    Sheet sheet = wb.createSheet();
    for (int i = 0; i < 1_000_000; i++) {
        Row row = sheet.createRow(i);
        row.createCell(0).setCellValue("Row " + i);
    }
    wb.write(new FileOutputStream("huge.xlsx"));
}

常見坑與避雷指南

坑點症狀修正
CellStyle 重複建立樣式表超過 64k 限制 (`.xls`) / 檔案膨脹統一建立樣式對象,複用;或用 `CellUtil.getCellStyle()`
日期顯示為數字未設定 DataFormat`style.setDataFormat(wb.createDataFormat().getFormat("yyyy-mm-dd"))`
公式不計算Excel 開啟顯示 0寫入前呼叫 `evaluator.evaluateAll()` 或開啟時手動重新計算
合併儲存格邊框缺失僅第一格有邊框對合併區域所有儲存格單獨套用邊框樣式

現代化替代庫對比

庫授權特點
Apache POIApache 2.0功能最全、社群最大、支援 .xls/.xlsx/圖表/樞紐分析表
EasyExcel (Alibaba)Apache 2.0基於 POI 封裝、記憶體友好、註解驅動、適合導入導出業務
JExcelApi (jxl)LGPL僅支援 .xls、已停更、不建議新專案使用
FastexcelApache 2.0純寫入、極速、無樣式支援、適合超大報表

建議:**新專案首選 EasyExcel** (業務導入導出) 或 **POI SXSSF** (複雜報表);避開 JXL。

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