开发者

基于Java POI实现动态列Excel导出的通用方法

目录
  • 一、核心功能特性
    • 1. 动态列处理
    • 2. 多级表头支持
    • 3. 数据统计功能
    • 4. 样式与布局优化
  • 二、关键代码解析
    • 1. 列集合初始化
    • 2. 多级表头生成
    • 3. 数据行与合计行
    • 4. 单元格样式设置
  • 三、使用示例
    • 1. 方法参数说明
    • 2. 调用示例
    • 3. 表头命名规范
  • 四、优化与扩展建议
    • 1. 类型适配优化
    • 2. 样式扩展
    • 3. 性能优化
    • 4. 错误处理增强
  • 五、总结

    一、核心功能特性

    1. 动态列处理

    • 支持从前端接收​​List<String>​​​类型的列名集合(​​cellList​​​),结合固定列数组(​​strCloumnAry​​)动态拼接最终列集合
    • 使用​​LinkedHashMap​​维护列顺序,确保导出列与传入顺序一致

    2. 多级表头支持

    • 通过​​headerNum​​参数控制表头层级(1-3 级)
    • 表头名称通过​​||​​​分隔(如​​"船舶信息||完船日期||吨位"​js​),自动解析为多级结构

    3. 数据统计功能

    • 自动识别数值型列(​​Number​​​类型),生成​​totalMap​​存储列求和结果
    • 支持在导出数据末尾添加 "合计" 行,并合并单元格显示

    4. 样式与布局优化

    • 统一设置单元格边框、居中对齐、字体大小
    • 自动调整列宽适应内容
    • 多级表头行合并相同标题单元格,提升可读性

    二、关键代码解析

    1. 列集合初始化

    LinkedHashMap<String, Integer> allColumn = new LinkedHashMap<>();
    // 先添加固定列
    for (int i = 0; i < strCloumnAry.length; i++) {
        allColumn.putIfAbsent(javascriptstrCloumnAry[i], i);
    }
    // 再添加动态列(避免重复)
    int i = strCloumnAry.length;
    for (String key : cellList) {
        if (!allColumn.containsKey(key)) {
            allColumn.put(key, i++);
        }
    }
    
    • 使用​​LinkedHashMap​​保持顺序,固定列在前,动态列在后
    • 通过​​putIfAbsent​​避免重复列名导致的索引冲突

    2. 多级表头生成

    if (headerNum == 2) { // 二级表头处理
        for (String key : allColumn.keySet()) {
            String[] parts = key.split("\|\|"); // 按||拆分
            if (parts.length == 2) {
                // 一级表头行
                Cell cell1 = headerRow1.createCell(allColumn.get(key));
                cell1.setCellValue(parts[0]);
                // 二级表头行
                Cell cell2 = headerRow2.createCell(allColumn.get(key));
                cell2.setCellValue(parts[1]);
            }
      js  }
    }
    
    • 通过​​split("\|\|")​​解析多级表头名称
    • 根据​​headerNum​​创建对应行数的表头行(1-3 级)
    • 同一列的多级表头单元格共享相同列索引

    3. 数据行与合计行

    // 写入数据行
    int row = headerNum; // 表头行下方开始写数据
    for (Map<String, Object> data : datas) {
        Row dataRow = sheet.createRow(row++);
        for (Map.Entry<String, Integer> entry : allColumn.entrySet()) {
            Cell cell = dataRow.createCell(entry.getValue());
            cell.setCellValue(data.get(entry.getKey()) != null ? data.get(entry.getKey()).toString() : "");
        }
    }
    
    // 写入合计行
    Row totalRow = sheet.createRow(row);
    totalRow.createCell(0).setCellValue("合计");
    for (Map.Entry<String, Object> entry : totalMap.entrySet()) {
        int colIndex = allColumn.get(entry.getKey());
        Cell cell = totalRow.createCell(colIndex);
        cell.setCellValue(entry.getValue() != null ? entry.getValue().toString() : "");
    }
    // 合并合计行标题单元格
    sheet.addMergedRegion(new CellRangeAddress(row, row, 0, maxSp));
    
    • ​totalMap​​通过遍历数据行自动计算数值列总和
    • 合计行标题 "合计" 通过​​CellRangeAddress​​合并多个列单元格
    • ​maxSp​​变量动态计算需要合并的列范围

    4. 单元格样式设置

    // 创建通用样式
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setAlignment(HorizontalAlignment.CENTER);
    cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    cellStyle.setBorderTop(BorderStyle.THIN);
    cellStyle.setBorderBottom(BorderStyle.THIN);
    cellStyle.setBorderLeft(BorderStyle.THIN);
    cellStyle.setBorderRight(BorderStyle.THIN);
    
    // 表头字体设置
    Font headerFont = workbook.createFont();
    headerFont.setFontHeightInPoints((short) 10);
    cellStyle.setFont(headerFont);
    
    • 统一设置水平 / 垂直居中对齐
    • 添加细边框样式
    • 表头使用 10 号字体

    三、使用示例

    1. 方法参数说明

    参数名类型说明
    responseHttpServletResponseServlet 响应对象,用于输出文件流
    datasList<Map<String,Object>>导出数据集合,每个 Map 代表一行数据
    cellListList动态列名集合(如前端勾选的列)
    baseFileNameString基础文件名(不含时间戳)
    strAryString[]固定列显示名称数组(与 strCloumnAry 对应)
    strCloumnAryString[]固定列字段名数组(如数据库字段名)
    headerNumint表头层级(1-3 级)

    2. 调用示例

    // 假设前端传入动态列名为["price","quantity"]
    List<String> cellList = Arrays.asList("price", "quantity");
    // 固定列字段名与显示名
    String[] strCloumnAry = {"name", "date"};
    String[] strAry = {"商品名称", "日期"};
    
    // 构造模拟数据
    List<Map<String, Object>> datas = new ArrayList<>();
    Map<String, Object> data1 = new HashMap<>();
    data1.put("name", "苹果");
    data1.put("date", "2023-10-01");
    data1.put("price", 5.99);
    data1.put("quantity", 100);
    datas.add(data1);
    
    // 调用导出方法(二级表头示例)
    exportDynamicExcel(response, datas, cellList, "商品销售报表", strAry, strCloumnAry, 2);
    

    3. 表头命名规范

    多级表头通过​​||​​分隔,如:

    • 一级表头:​​"销售额"​
    • 二级表头:​​"季度数据||销售额"​
    • 三级表头:​​"年度汇总||季度数据||销售额"​

    四、优化与扩展建议

    1. 类型适配优化

    当前代码仅处理​​Number​​类型数值求和,可扩展支持:

    • ​String​​类型数值转换(需校验格式)
    • ​LocalDate​​​/​​LocalDateTime​​类型日期格式化显示

    2. 样式扩展

    • 添加条件格式(如数值超过阈值时标红)
    • 支持不同背景色区分奇偶行
    • 表头行添加自动筛选功能

    3. 性能优化

    • 大数据量场景可改用​​SXSSFWorkbook​​(基于磁盘缓存的流式处理)
    • 合并单元格操作可批量处理,减少​​sheet.addMergedRegion​​调用次数

    4. 错误处理增强

    • 添加参数校验(如​​cellList​​​与​​strCloumnAry​​重复校验)
    • 提供更友好的异常提示信息(如字段名不存在)

    五、总结

    本文提供的动态列 Excel 导出方法通过灵活的参数设计,实现python了:

    • 动态列与固定列的混合展示
    • 1-3 级多级表头的自动解析
    • 数值列自动求和与合计行生成
    • 统一的单元格样式与布局优化

    适用于需要根据用户选择动态展示列的管理系统(如数据报表、权限控制场景)。实际使用中可根据业务需求进一步扩展类型适配、样式定制等功能,提升导出文件的实用性与美观性。

    以上就是基于Java POI实现动态列Exceandroidl导出的通用方法的详细内容,更多关于Java POI动态列Excel导出的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜