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

Apache POI 导出 Excel 通用工具类:支持多 Sheet、标题合并、样式、日期格式与反射泛型

     編輯:Java 綜合教學

工具类特性

  • 基于 HSSFWorkbook (xls) / SXSSFWorkbook (大数据流式)。
  • 泛型 <T> + 反射,自动映射实体属性到列。
  • 支持**分 Sheet 导出**(单 Sheet 行数超限自动拆分)。
  • 支持**标题行合并单元格**、表头冻结、自定义单元格样式(边框、字体、居中)。
  • 日期类型自动格式化为 yyyy-MM-dd HH:mm:ss。
  • 配置驱动:List headersParams 格式 "表头=属性名"。

核心依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version> <!-- 或 4.x/5.x -->
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.15</version>
</dependency>

核心代码结构

public class NextExcelUtil {

    // 常量
    private static final int MAX_MSG_BODY_SIZE = 1020; // 示例常量,实际工具类中无此常量

    /** 单 Sheet 导出入口 */
    public static  Workbook getWorkbook(String title, List headersParams, List dataList) { ... }

    /** 多 Sheet 分页导出入口 */
    public static  Workbook getWorkbook(String title, List headersParams, List dataList, int sheetMaxCount) { ... }

    // 内部:拆分大 List
    private static  List> getSplitList(List dataList, int sheetMaxCount) { ... }

    // 内部:反射获取 getter 方法名
    private static String getMethodName(String fieldName) {
        return "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
    }

    // 内部:单元格样式构建(标题、表头、数据行)
    private static CellStyle getStyle(Workbook wb) { ... }
    private static CellStyle getTitleStyle(Workbook wb) { ... }
    private static CellStyle getColumnTopStyle(Workbook wb) { ... }
    private static CellStyle getCellStyle(Workbook wb) { ... }
}

关键实现细节

1. 多 Sheet 拆分逻辑

int page = (count % sheetMaxCount > 0) ? count/sheetMaxCount + 1 : count/sheetMaxCount;
List> splitList = getSplitList(dataList, sheetMaxCount);
for (int i = 0; i < page; i++) {
    Sheet sheet = wb.createSheet();
    if (title != null) wb.setSheetName(i, title + (i+1));
    // ... 写标题、表头、数据 ...
}

2. 标题合并单元格

// 占用前两行
for (int j = 0; j < 2; j++) {
    Row titleRow = sheet.createRow(j);
    for (int k = 0; k < headersParams.size(); k++) {
        Cell cell = titleRow.createCell(k);
        cell.setCellStyle(titleStyle);
        if (j == 0 && k == 0) cell.setCellValue(title); // 仅左上角写值
    }
}
// 合并区域:起始行0,终止行1,起始列0,终止列最后一列
sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, headersParams.size()-1));

3. 反射填充数据

Class clazz = dataList.get(0).getClass();
for (int i = 0; i < dataList.size(); i++) {
    Row row = sheet.createRow(i + 1 + headerOffset);
    for (int j = 0; j < params.length; j++) {
        Field field = clazz.getDeclaredField(params[j]);
        Method method = clazz.getMethod(getMethodName(params[j]));
        Object val = method.invoke(dataList.get(i));
        
        Cell cell = row.createCell(j);
        // 日期特殊处理
        if (val instanceof Date) {
            CellStyle dateStyle = wb.createCellStyle();
            dateStyle.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
            cell.setCellStyle(dateStyle);
            cell.setCellValue((Date) val);
        } else {
            cell.setCellValue(val != null ? val.toString() : "");
        }
    }
}

4. 样式封装

统一定义边框、居中、字体加粗等 CellStyle,避免重复创建导致样式数量超限(HSSF 限制 4000 个)。

使用示例

List users = userService.findAll();
List headers = Arrays.asList("姓名=name", "年龄=age", "注册时间=createTime");
Workbook wb = NextExcelUtil.getWorkbook("用户导出", headers, users, 50000); // 每 Sheet 5万行

try (FileOutputStream fos = new FileOutputStream("users.xls")) {
    wb.write(fos);
}

注意事项

  • 实体类必须提供标准 Getter 方法。
  • 大数据量(>10万行)建议使用 SXSSFWorkbook (POI 3.8+),内存占用极低。
  • 导出后需手动 wb.close() 释放临时文件(SXSSF)。
  • 样式对象尽量复用,防止 Style records exceed 4000 错误。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved