EasyExcel 导出数据,无模版,动态多级表头。

EasyExcel 导出数据,无模版,动态多级表头。

效果图

我这个表前六列是写死的,后面全都是动态的,支持无限横竖扩容。
在这里插入图片描述
核心代码

    public void listExport(HttpServletResponse response) throws IOException {
		response.setCharacterEncoding("utf-8");
        response.setContentType("application/vnd.ms-excel");
        String fileName = URLEncoder.encode(EVALUATION_DATA_EXPORT + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")) + ".xls", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        //内容样式策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //垂直居中,水平居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        contentWriteCellStyle.setShrinkToFit(Boolean.TRUE);
        //设置 自动换行
        contentWriteCellStyle.setWrapped(true);
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 12);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //头策略使用默认
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();

        //表头
        List<List<String>> lists = new ArrayList<>();
        getMyEvaluationHeader(myEvaluationScoreResultModel.getMyEvaluationHeader(), lists);

        //数据
        List<List<String>> myEvaluationData = getMyEvaluationData(myEvaluationScoreResultModel);

        EasyExcel.write(response.getOutputStream())
                .head(lists)
                .excelType(ExcelTypeEnum.XLS)
                .needHead(true)
                .sheet("data")
                .registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle))
                .useDefaultStyle(true)
                .doWrite(myEvaluationData);
    }

	private void getMyEvaluationHeader(List<PerformanceItemModel> myEvaluationHeader, List<List<String>> lists) {
        lists.add(Stream.of("姓名").collect(Collectors.toList()));
        lists.add(Stream.of("工号").collect(Collectors.toList()));
        lists.add(Stream.of("年级").collect(Collectors.toList()));
        lists.add(Stream.of("学科").collect(Collectors.toList()));
        lists.add(Stream.of("评估模版").collect(Collectors.toList()));
        lists.add(Stream.of("自评状态").collect(Collectors.toList()));
        List<List<String>> allPaths = getAllPaths(myEvaluationHeader);
        lists.addAll(allPaths);
        int maxSize = -1;
        for (List<String> allPath : allPaths) {
            if(allPath.size() > maxSize){
                maxSize = allPath.size();
            }
        }
        for (List<String> allPath : lists) {
            int size = maxSize - allPath.size();
            String indexName = allPath.get(allPath.size() - 1);
            for (int i = 0; i < size; i++) {
                allPath.add(indexName);
            }
        }
    }
    
	public static List<List<String>> getAllPaths(List<PerformanceItemModel> tree) {
        List<List<String>> paths = new ArrayList<>();
        List<String> currentPath = new ArrayList<>();
        traverseTree(tree, currentPath, paths);
        return paths;
    }

    private static void traverseTree(List<PerformanceItemModel> tree, List<String> currentPath, List<List<String>> paths) {
        if (tree == null || tree.isEmpty()) {
            return;
        }

        for (PerformanceItemModel node : tree) {
            currentPath.add(node.getItemName()); // 添加当前节点到路径中

            if (node.getPerformanceItemModelList() != null && !node.getPerformanceItemModelList().isEmpty()) {
                traverseTree(node.getPerformanceItemModelList(), currentPath, paths); // 递归遍历子节点
            } else {
                paths.add(new ArrayList<>(currentPath)); // 当到达叶子节点时,添加路径
            }

            currentPath.remove(currentPath.size() - 1); // 回溯以探索其他路径
        }
    }

主要是使用 .head(lists) 实现动态表头 .doWrite(myEvaluationData) 填充数据。数据和表头都要包装成二维数组 List<List>。

其中表头格式会复杂一点,我这里的原始表头数据是树形结构,需要转化为二维数组,二维数组的高是树的高度。二维数组的宽是列的数量。

核心代码是 getAllPaths() 方法,这个方法会遍历树的所有路径,并返回 所有路径的 List<List> allPaths。然后测量树的高度,填充二维数组 allPaths 的空缺位置(这个很重要,这是合并单元格的关键)。

这是debug的截图,结合理解下。

表头:

在这里插入图片描述

[[姓名, 姓名, 姓名, 姓名], 
[工号, 工号, 工号, 工号], 
[年级, 年级, 年级, 年级], 
[学科, 学科, 学科, 学科], 
[评估模版, 评估模版, 评估模版, 评估模版], 
[自评状态, 自评状态, 自评状态, 自评状态], 
[备课, 早上备课, 早上备课, 早上备课], 
[备课, 中午备课, 中午备课, 中午备课], 
[备课, 下午备课, 下午备课, 下午备课], 
[备课, 晚上备课, 晚上备课, 晚上备课], 
[备课, 单项小计, 单项小计, 单项小计], 
[吃饭, 吃早饭, 吃包子, 吃酸菜包], 
[吃饭, 吃早饭, 吃包子, 单项小计], 
[吃饭, 吃早饭, 单项小计, 单项小计], 
[吃饭, 吃午饭, 吃午饭, 吃午饭], 
[吃饭, 单项小计, 单项小计, 单项小计]]

数据:

在这里插入图片描述

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于使用 EasyExcel 导出数据时设置多级表头,你可以按照以下步骤进行操作: 1. 创建一个 WriteSheet 对象,用于设置导出的 sheet。 2. 使用 WriteSheet 的 setRelativeHeadRowIndex 方法,设置相对于数据起始行的表头行索引。如果数据起始行是第 1 行,设置为 1,以此类推。 3. 使用 WriteSheet 的 setNeedHead 方法,设置是否需要表头。如果需要表头,则设置为 true;否则设置为 false。 4. 创建一个 List<List<String>> 对象,用于存储多级表头数据。 5. 按照多级表头的层级关系,将每个层级的表头数据存储在 List<String> 中,并将其添加到 List<List<String>> 对象中。 6. 使用 WriteSheet 的 setHead 方法,将 List<List<String>> 对象设置为导出表头数据。 7. 使用 EasyExcel 的 write 方法,将数据写入 Excel 文件。 以下是一个示例代码: ```java // 创建一个 WriteSheet 对象 WriteSheet writeSheet = EasyExcel.writerSheet().build(); // 设置相对于数据起始行的表头行索引 writeSheet.setRelativeHeadRowIndex(1); // 设置是否需要表头 writeSheet.setNeedHead(true); // 创建一个 List<List<String>> 对象,用于存储多级表头数据 List<List<String>> headList = new ArrayList<>(); // 添加第一级表头数据 List<String> firstLevelHead = new ArrayList<>(); firstLevelHead.add("A"); firstLevelHead.add("B"); headList.add(firstLevelHead); // 添加第二级表头数据 List<String> secondLevelHead = new ArrayList<>(); secondLevelHead.add("C"); secondLevelHead.add("D"); headList.add(secondLevelHead); // 设置导出表头数据 writeSheet.setHead(headList); // 使用 EasyExcel 的 write 方法,将数据写入 Excel 文件 EasyExcel.write("output.xlsx").sheet().doWrite(dataList); ``` 在上述示例代码中,dataList 是要导出数据列表。你可以根据实际需求修改表头的层级关系和数据内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值