easyexcel复杂导出,合并单元格,无对象生成easyexcel动态表头

1.首先理解一下无对象生成表头,就需要添加head属性,自己在Java代码中手动书写表头信息,然后添加到head中,如果是动态的,则用代码循环

2.因为自己代码逻辑多一些,就多用文字表述来说一下,里面有我的业务逻辑,不建议直接粘贴,其实很简单,理解为主

3.首先看一下官方文档https://www.yuque.com/easyexcel/doc/write#avjBv

主要参考的是:不创建对象写

 一:首先是创建表头

 /**
     * 设置表头
     *
     * @param exportList
     * @return
     */
    public List<List<String>> head(List<ExportHour> exportList) {
        String time = exportList.get(0).getMonth();
        String year = time.substring(0, 4);
        String month = time.substring(5, 7);
        //初始化第一行表头
        String bigTitle = "表头名字" + year + "年度" + month + "月工时分摊表";
        //创建表头集合
        List<List<String>> head = new ArrayList<>();
        //这里的每一个list都是代表一列,按照顺序来,相同的名称会自动合并单元格,比如说两个序号,
        //就是把第第一列的第二第三格合并到了一起
        //然后行单元格合并是同理的,可以看到bigTitle每一个list都有,都是在第一个,说明每一列的
        //第一个单元格都是这个值,所以最终的效果就是你生成的表格第一行全部合并,然后可以展示大表                  
        //头,
        //第一列
        List<String> title = new ArrayList<>(Arrays.asList(bigTitle, "序号", "序号", "序号"));
        head.add(title);
        //第二列
        List<String> title1 = new ArrayList<>(Arrays.asList(bigTitle, "技术人员", "技术人员", "技术人员"));
        head.add(title1);
        //第三列
        List<String> title2 = new ArrayList<>(Arrays.asList(bigTitle, "月总工时", "月总工时", "月总工时"));
        head.add(title2);
        //动态生成列,也就是说这一部分的表头是动态生成的,
        for (ExportHour exportHour : exportList) {
            List<String> title3 = new ArrayList<>(Arrays.asList(bigTitle, "月工时", exportHour.getProjectName(), exportHour.getProjectName()));
            head.add(title3);
        }
        //列
        List<String> title7 = new ArrayList<>(Arrays.asList(bigTitle, "月工时", "合计工时", "合计工时"));
        head.add(title7);
        //列
        List<String> title5 = new ArrayList<>(Arrays.asList(bigTitle, "", "核验", "核验"));
        head.add(title5);
        //最后直接把这些生成的表头集合返回就行了
        return head;
    }

二:填充数据

看一下我写的,其实很简单,只是有我的业务逻辑在而已,这个是参考

/**
     * 写数据
     *
     * @param exportList
     * @param
     * @return
     */
    private List data(List<ExportHour> exportList) {
        int i = 1;
        List<List<String>> list = ListUtils.newArrayList();
        Integer size = getDates(exportList.get(0).getMonth()).size();
        Integer sumHour = size * 8;
//        获取指定月份下的所有项目所涉及的人员
        List<String> strings = projectHourService.queryUserList();
        List<String> list1 = strings.stream().distinct().collect(Collectors.toList());
        for (String userId : list1) {
            List<String> head = ListUtils.newArrayList();
//            序号
            head.add(i + "");
            i++;
            head.add(userService.selectUserById(Long.valueOf(userId)).getNickName());
//            月总工时
            head.add(sumHour + "");
            BigDecimal sumhour = BigDecimal.ZERO;
            for (ExportHour exportHour : exportList) {
                List<ProjectHorsInfo> userInfo = exportHour.getExportList();
                List<ProjectHorsInfo> info = userInfo.stream().filter(a -> a.getUserId().toString().equals(userId))
                        .collect(Collectors.toList());
                if (info.size() > 0) {
                    sumhour = sumhour.add(info.get(0).getSumUserHors());
//                    个人项目工时
                    head.add(info.get(0).getSumUserHors().toString());
                } else {
                    head.add("");
                }
            }
            //                合计工时
            head.add(sumhour.toString());
            BigDecimal result = sumhour.subtract(new BigDecimal(size * 8));
            head.add(result + "");
            list.add(head);
        }

        return list;
    }

其实跟创建表头的思路是一样的,用同样的方法,一次次创建表头,只不过是每一列只填一个数据,把你需要填充的数据添加到一个个的head里就行了,只不过这次是填充的数据而已,这么说懂吧

三:写数据

现在表头和数据都准备好了,那就是写入数据

/**
     * 项目详情导出
     *
     * @return
     */
    @PostMapping("/export")
    @PreAuthorize("@ss.hasPermi('system:project:stat:query')")
    @ApiOperation("导出")
    public void export(HttpServletResponse response, @RequestBody BaseProjectDto baseProjectDto) throws IOException {
        String fileName = URLEncoder.encode("projectWorkingHour", "UTF-8").concat(".xlsx");
        //response输出文件流
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
        List<ResultExport> list = projectHourService.queryProjectHors(baseProjectDto);

        //导出对象,输出数据流,CustomCellWriteHandler()是我写的简单的一个拦截器,下面会贴
        //可以看一下,不需要拦截器的话,把registerWriteHandler去掉就行了
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(new CustomCellWriteHandler())
                .build();
        int i = 0;
        for (ResultExport export : list) {
            if (export.getDateResults().size() > 0) {
//                创建sheet页,设置sheet页名称,同时写入表头信息
                WriteSheet writeSheet = EasyExcel.writerSheet(i, export.getDateTime())
                        .head(head(list.get(i).getDateResults()))
                        .build();
//                写入数据,并将sheet页对象传入
                excelWriter.write(data(list.get(i).getDateResults()), writeSheet);
            }
            i++;
        }
        //这一步很关键,不然文件会损坏
        excelWriter.finish();
    }

response就不用说了把,这些请求头参数不用动,直接拿过来就行了,不想用,百度也行

注意:文件名必须是英文,不要是中文,否则会报错,文件名字是啥无所谓,下载的时候前端给指定就行了,sheet页可以是中文。

JDK不要是简易版的,不然没有数据流出来,简易版的jdk后面带-slim这个后缀

到这里的话,就可以进行导出了,应该是没啥问题了,可以试一下

四:定制格式

我这里只是简单的定制格式,更复杂的,请问度娘或者谷歌


/**
 * @author: zbh19
 * @date: 2022/5/5 1:57
 * @description: 表头样式拦截器
 */

@Slf4j
@Component
public class CustomCellWriteHandler implements CellWriteHandler {
    @Override
    public void afterCellDataConverted(CellWriteHandlerContext context) {

    }

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        WriteCellData<?> cellData = context.getFirstCellData();
        int rowNum = context.getRow().getRowNum();
        Integer columnIndex = context.getColumnIndex();
        Sheet sheet = context.getWriteSheetHolder().getSheet();
        Cell cell = context.getCell();

        if (BooleanUtils.isTrue(context.getHead())) {
            WriteCellStyle writeCellStyle = cellData.getWriteCellStyle();
            //字体
            WriteFont writeFont = writeCellStyle.getWriteFont();
            //背景颜色
            writeCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            //字体大小
            writeFont.setFontHeightInPoints((short) 16);
            //字体加粗
            writeFont.setBold(true);
            writeCellStyle.setWriteFont(writeFont);
            //列宽,行高
            sheet.setColumnWidth(cell.getColumnIndex(), 4000);
            sheet.setDefaultRowHeight((short) 400);
        }
    }
}

最后来个我的效果图:

好了,完事了,就这吧!~~~

  • 5
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清石小猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值