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

Apache POI 實戰:多 Sheet Excel 報表生成(MySQL → Excel 完整範例)

     編輯:Java 綜合教學

Apache POI 實戰:多 Sheet Excel 報表生成(MySQL → Excel 完整範例)

本文提供一個完整的 Maven 專案範例,示範如何使用 Apache POI(HSSF/XSSF)從 MySQL 讀取「學校-學生」關聯資料,生成包含彙總 Sheet與多明細 Sheet的 Excel(.xls)檔案。涵蓋資料庫連線、VO 映射、POI 流式寫入、Sheet 動態創建、安全 Sheet 名稱處理等實務技巧。

一、專案結構與依賴

ExcelHandler/
├── src/
│   ├── main/
│   │   ├── java/com/b510/hongten/
│   │   │   ├── client/Client.java          # 入口
│   │   │   ├── common/Common.java          # 常數配置
│   │   │   ├── db/                         # DAO 與連線工具
│   │   │   ├── excel/WriteExcel.java       # POI 核心寫入邏輯
│   │   │   └── vo/School.java, Student.java
│   │   └── resources/log4j.xml
│   └── test/
├── lib/                     # POI、MySQL 驅動、Log4j JAR
└── pom.xml                  # Maven 依賴管理

關鍵依賴(pom.xml):

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version> <!-- 或 4.x/5.x 對應 XSSF -->
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

二、資料庫設計(MySQL)

-- 學校表
CREATE TABLE t_school (
    no INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50), `desc` VARCHAR(500), ranking INT, address VARCHAR(200)
);

-- 學生表
CREATE TABLE t_student (
    student_no INT, school_no INT,
    name VARCHAR(100), address VARCHAR(200), birthdate VARCHAR(15), phone VARCHAR(15),
    PRIMARY KEY (student_no, school_no),
    FOREIGN KEY (school_no) REFERENCES t_school(no)
);

三、核心寫入邏輯 WriteExcel.java

public class WriteExcel {
    private static final Logger log = Logger.getLogger(WriteExcel.class);

    public void writeExcel(List schools) {
        if (schools == null || schools.isEmpty()) return;

        Workbook wb = new HSSFWorkbook(); // .xls 格式;.xlsx 用 XSSFWorkbook
        // 1. 彙總 Sheet
        Sheet summarySheet = wb.createSheet(Common.SUMMARY); // "School Summary"
        summarySheet.setAutobreaks(true);
        createHeaderRow(summarySheet, Common.TITLES); // S/N, Name, Description, Ranking, Address

        int rowNum = 1;
        for (School school : schools) {
            Row row = summarySheet.createRow(rowNum++);
            fillSchoolRow(row, school);

            // 2. 每所學校一個明細 Sheet
            List students = school.getStudents();
            if (students != null && !students.isEmpty()) {
                // 安全 Sheet 名稱:移除非法字元
                String safeName = WorkbookUtil.createSafeSheetName(school.getName());
                Sheet stuSheet = wb.createSheet(safeName);
                stuSheet.setAutobreaks(true);
                createHeaderRow(stuSheet, Common.STUDENT_TITLE); // S/N, Name, Birth Date, Phone, Address
                int stuRow = 1;
                for (Student stu : students) {
                    Row r = stuSheet.createRow(stuRow++);
                    fillStudentRow(r, stu);
                }
            }
        }

        // 3. 輸出檔案
        try (FileOutputStream fos = new FileOutputStream(Common.TARGET_FILE_PATH)) {
            wb.write(fos);
            log.info("Excel 生成完成:" + Common.TARGET_FILE_PATH);
        } catch (IOException e) {
            log.error("寫入檔案失敗", e);
        }
    }

    // 輔助方法:建立標題列、填充資料列...
}

四、關鍵技術點解析

  1. Workbook/Sheet/Row/Cell 階層:Workbook → Sheet → Row → Cell,索引皆從 0 開始。
  2. 動態 Sheet 創建:wb.createSheet(name),名稱長度 ≤ 31 字元,不含 [\]:*?/\\。使用 WorkbookUtil.createSafeSheetName() 自動轉義。
  3. 資料類型寫入:cell.setCellValue(String/Number/Boolean/Date),POI 自動推斷 CellType。
  4. 大數據量優化:若超過 65535 列(.xls 限制)或記憶體敏感,改用 SXSSFWorkbook(流式寫入,僅保留近期行在記憶體)。
  5. 日期格式化:建立 CellStyle + DataFormat 統一日期顯示格式。

五、DAO 層:關聯查詢組裝 VO

public class SchoolDAO {
    public static List getSchools() {
        List schools = new ArrayList<>();
        try (Connection conn = ConnectionUtil.getConn();
             PreparedStatement ps = conn.prepareStatement("SELECT * FROM t_school ORDER BY no")) {
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                School school = mapSchool(rs);
                // 查詢該校學生
                try (PreparedStatement ps2 = conn.prepareStatement("SELECT * FROM t_student WHERE school_no = ?")) {
                    ps2.setInt(1, school.getNo());
                    ResultSet rs2 = ps2.executeQuery();
                    List students = new ArrayList<>();
                    while (rs2.next()) students.add(mapStudent(rs2));
                    school.setStudents(students);
                }
                schools.add(school);
            }
        } catch (SQLException e) { /* log & handle */ }
        return schools;
    }
}

六、常見問題與避坑

  • Sheet 名稱非法字元:必須用 WorkbookUtil.createSafeSheetName,否則 POI 拋 IllegalArgumentException。
  • .xls 列數限制:65536 行,超過必須用 .xlsx (XSSFWorkbook) 或 SXSSFWorkbook。
  • 數字儲存為文字:若 Excel 開啟顯示綠色三角,需設定 cell.setCellType(CellType.NUMERIC) 或寫入 Double 型別。
  • 資源釋放:Workbook 實作 Closeable,建議 try-with-resources 管理。

七、原始碼與測試資料下載

八、總結

Apache POI 提供豐富的 Excel 操作 API,配合合理的 VO 設計與分層架構,可快速構建企業級報表匯出功能。掌握 WorkbookUtil、SXSSF、CellStyle 等進階特性,能應對大數據量、複雜格式、多 Sheet 等實務挑戰。

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