EasyExcel复杂表头导出(一对多)

您所在的位置:网站首页 easypoi读取第一行 EasyExcel复杂表头导出(一对多)

EasyExcel复杂表头导出(一对多)

2023-04-24 05:31| 来源: 网络整理| 查看: 265

一、前言

之前,写了 EasyExcel复杂表头导入(一对多)的博客,效果不错,好多网友留言让我再写一个导入的。盛情难却,就写了一个,发现问题很多。

现已通过自定义拦截器的形式完美解决了该博客的末尾的遗留问题,地址如下:

https://blog.csdn.net/qq_41057885/article/details/126411957

关于EasyPoi 框架的问题,在此不再赘述,参考我的另一篇博客,地址如下:

EasyExcel复杂表头导入(一对多)_间歇性悲伤患者的博客-CSDN博客_easyexcel复杂表头

实际上,官方文档和网上都没有详细的导出教程,需要自己参考官方去实现。我搞了半天只弄成功了一个半桶水的,十分惭愧,在此记录一下,方便回溯。

说明:EasyExcel无法处理List里面嵌套List的情况,我采用的方案是通过表格合并的来实现。

下面,先给出具体实现,然后再谈谈问题。

二、EasyExcel一对多导出的实现 2.1 Entity 对象 /** * 客户信息导出类,指明导出模板样式等。是真正和EasyPoi交互的类 */ @Data @EqualsAndHashCode @HeadRowHeight(30) @ContentRowHeight(20) @ColumnWidth(20) @HeadStyle(fillForegroundColor = 44) @NoArgsConstructor class Customer extends BaseRowModel implements Serializable { @ExcelProperty({"客户编号"}) private String userCode; @ExcelProperty({"客户名称"}) private String userName; @ColumnWidth(25) @ExcelProperty({"客户所在地址"}) private String address; @ExcelProperty({"联系人信息", "联系人姓名"}) private String personName; @ExcelProperty({"联系人信息", "联系电话"}) private String telephone; public Customer(CustomerInfo customerInfo) { this.userCode = customerInfo.getUserCode(); this.userName = customerInfo.getUserName(); this.address = customerInfo.getAddress(); this.personName = customerInfo.getPersonList().get(0).getPersonName(); this.telephone = customerInfo.getPersonList().get(0).getTelephone(); } public Customer(CustomerInfo.Person person) { this.personName = person.getPersonName(); this.telephone = person.getTelephone(); } } /** * 客户基本信息类,类比程序从service层拿到的信息 * 实际上,EasyPoi只能读取简单String、boolean、integer、float byte[] 等简单数据类型。无法处理List、Map等数据类型。 * 当前,你也可以只定义类型转换器Converter,具体见文章末尾的参考连接。 */ @Data @AllArgsConstructor @NoArgsConstructor class CustomerInfo { private String userCode; private String userName; private String address; private List personList; @Data @AllArgsConstructor @NoArgsConstructor static class Person { private String personName; private String telephone; } } 2.2 Controller 层 @IgnoreUserToken @GetMapping("/exportExcel") @ApiOperation("导出Excel") public void exportExcel(HttpServletResponse response) throws Exception { // 获取导出数据,模拟从service层拿到list数据。 List list = getData(); // 获取所有客户信息中,联系人最多的数量。并以此数量作为行合并的依据 int maxColNum = 1; for (CustomerInfo ele : list) { if (ele.getPersonList().size() > maxColNum) { maxColNum = ele.getPersonList().size(); } } // 整理,讲List包含List的数据格式,改成List的格式 final int finalMaxColNum = maxColNum; List result = list.stream() .flatMap(ele -> { List temp = new ArrayList(); // 获取当前客户联系人的数量 int len = ele.getPersonList().size(); // 先添加一条完整的客户信息 temp.add(new Customer(ele)); for (int i = 1; i < finalMaxColNum; i++) { if (i > len) { // 达不到maxColNum的,补null占位。 temp.add(new Customer()); } else { // 只添加联系人信息 temp.add(new Customer(ele.getPersonList().get(i))); } } return temp.stream(); }).collect(Collectors.toList()); // 设置excel表头样式 WriteSheet sheet = EasyExcel.writerSheet("客户信息").head(Customer.class).sheetNo(1).build(); // 设置excel表格样式 ExcelWriter writer = EasyExcel.write(response.getOutputStream()).needHead(true).excelType(ExcelTypeEnum.XLSX) .registerWriteHandler(new LoopMergeStrategy(maxColNum, 0)) // 设置第一列每maxColNum行合并 .registerWriteHandler(new LoopMergeStrategy(maxColNum, 1)) // 设置第二列每maxColNum行合并 .registerWriteHandler(new LoopMergeStrategy(maxColNum, 2)) // 设置第三列每maxColNum行合并 .build(); // 写入excel数据 writer.write(result, sheet); // 通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 response.setHeader("Content-disposition", "attachment;filename=" + new String("客户信息列表".getBytes("gb2312"), "ISO8859-1") + ".xlsx"); response.setContentType("multipart/form-data"); response.setCharacterEncoding("utf-8"); writer.finish(); } 2.3 getDate方法(用于模拟service层拿到的数据) public static List getData() { List data = new ArrayList(); CustomerInfo customer = new CustomerInfo(); customer.setUserCode("CT_jx001"); customer.setUserName("江西电信公司"); customer.setAddress("江西省南昌市青山湖区"); CustomerInfo.Person person1 = new CustomerInfo.Person("张三", "12345678910"); CustomerInfo.Person person2 = new CustomerInfo.Person("李四", "10987654321"); List personList = new ArrayList(); personList.add(person1); personList.add(person2); customer.setPersonList(personList); data.add(customer); CustomerInfo customer2 = new CustomerInfo(); customer2.setUserCode("CT_jx002"); customer2.setUserName("广东电信公司"); customer2.setAddress("广东省广州市花都区"); CustomerInfo.Person person12 = new CustomerInfo.Person("小明", "12345678910"); CustomerInfo.Person person22 = new CustomerInfo.Person("小红", "10987654321"); CustomerInfo.Person person23 = new CustomerInfo.Person("小王", "12345678910"); List personList2 = new ArrayList(); personList2.add(person12); personList2.add(person22); personList2.add(person23); customer2.setPersonList(personList2); data.add(customer2); return data; } 2.4 效果

接口是get类型的,浏览器直接访问,即可下载文件,效果如下。

扫描二维码关注公众号,回复: 14737282 查看本文章

顺便给出debug效果,方便理解。

 debug效果

三、问题及展望

从实现效果即可看出本方法的问题,就是会出现空行。

但是,这个空行避免不了,因为多行合并,只能按照最大值给,且不能动态调整。

这种方式,虽然可以实现复杂表头的导出,但显示不是令人满意的,主要是因为存在空行的问题。

我实在是找不出更好的解决方案,在此仅提供如下思路。

也你能通过EasyPoi的 自定义拦截器、数据格式转换器、模板写入、合并单元格、重复多次写入等功能实现。

四、参考链接

除官网地址外,参考如下文章。

Can not find ‘Converter‘ support class List问题解决_我取这个昵称总没被使用吧?的博客-CSDN博客问题描述com.alibaba.excel.exception.ExcelDataConvertException: Can not find ‘Converter’ support class List.问题解释EasyExcel开源框架中Converter接口的convertToExcelData只实现了转换BigDecimal、Bolean、Byte[]、btye[]、Byte、Date、Double、File、Float、InputStream、Integer、Long、Short、URL这些https://blog.csdn.net/qq_41049371/article/details/120156305EasyExcel ExcelDataConvertException:Can not find ‘Converter‘ support class ArrayList问题解决_旭东怪的博客-CSDN博客问题描述:com.alibaba.excel.exception.ExcelDataConvertException:Cannotfind'Converter'supportclassArrayList.问题分析:1、查看doWrite(List data)的源码时发现Converter接口的convertToExcelData只实现了转换BigDecimal、Bolean、Byte[]、btye[]、Byte、Date、Double、File、Float、InputStream、...https://blog.csdn.net/qq_38974638/article/details/116609844



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3