Hutool Java 工具类库导出 Excel并合并数据,全网最详细!
ps:基于HuTool工具类ExcelWriter合并单元格并且使用 jdk1.8 lambda表达式
一、原始数据模板
二、合并后的数据
按照班级名称、班级分数、小组名称、小组得分、人物名称、人物总分进行单元格合并
合并后效果:
三、导入依赖
ps:pom依赖版本不合适可以换其他版本
导出是项目中最常见的功能,例如考勤记录导出,账单明细导出,订单记录导出等等。导出的工具类有许多种,目前常见的有poi,easypoi,poi...,今天我要说的是基于hutool-poi的导出,hutool-poi是将poi做了封装,简化了大量的代码编写。 使用方式: maven 在项目的pom.xml中引入gradle 在项目的build.gradle中引入 compile 'cn.hutool:hutool-all:5.7.3' cn.hutool hutool-all 4.5.1
四、代码逻辑
1.查找数据库返回数据voList;
2.设置导出表头数据;
3.用lambda表达式获取字段分组数据;
4.遍历数据,设置合并规则;
5.将数据保存在list中;
6.ExcelWriter导出excel文件
五、代码
1.需实现将人物信息导出到excel文件中并且还要按照班级名称,小组名称,人物名称动态合并单元格,所以先创建人物对象:
@Data @AllArgsConstructor //生成所有参数的构造器 public class Person { //班级名称 private String className; //班级分数 private double classScore; //小组名称 private String groupName; //小组分数 private double groupScore; //人物姓名 private String personName; //人物总分 private double personScore; //学科名称 private String subjectName; //学科分数 private double subjectScore; }
2.导出核心代码:
@Slf4j @RestController @RequestMapping("/person") public class PersonController { /** * 将页面的数据导出并合并单元格 * @param response */ @ApiOperation(value = "导出数据到excel") @ApiImplicitParams({ @ApiImplicitParam(name = "response", value = "响应体对象", dataType = "HttpServletResponse") }) @GetMapping("/export") public void export(HttpServletResponse response)throws Exception{ //1.模拟一些人物对象数据(工作中从数据库查出来) Listlist = new ArrayList<>(); list.add(new Person("一班",90,"一组",89,"孙悟空",89,"语文",89)); list.add(new Person("一班",90,"一组",89,"孙悟空",89,"数学",98)); list.add(new Person("一班",90,"一组",89,"唐僧",78,"语文",98)); list.add(new Person("一班",90,"一组",89,"唐僧",78,"数学",78)); list.add(new Person("一班",90,"二组",90,"沙悟净",90,"语文",90)); list.add(new Person("一班",90,"二组",90,"沙悟净",90,"数学",90)); list.add(new Person("二班",91,"一组",97,"鲁智深",98,"语文",89)); list.add(new Person("二班",91,"一组",97,"鲁智深",98,"数学",98)); list.add(new Person("二班",91,"二组",89,"宋江",89,"语文",98)); list.add(new Person("二班",91,"二组",89,"宋江",89,"数学",78)); list.add(new Person("二班",91,"二组",89,"林冲",88,"语文",90)); list.add(new Person("二班",91,"二组",89,"林冲",88,"数学",90)); //2.定义基础数据 List rowHead = CollUtil.newArrayList("班级名称","班级分数","小组名称","小组分数","角色姓名","角色总分","学科名称","学科分数"); //3.通过ExcelUtil.getBigWriter()创建Writer对象,BigExcelWriter用于大数据量的导出,不会引起溢出; ExcelWriter writer = ExcelUtil.getBigWriter(); //4.写入标题 writer.writeHeadRow(rowHead); ServletOutputStream out = null; //5.实现核心逻辑 try { //6.定义容器保存人物数据 List > rows = new LinkedList<>(); //7.按照班级进行分组 LinkedHashMap
> classList = list.stream().collect(Collectors.groupingBy(item -> item.getClassName(), LinkedHashMap::new, Collectors.toList())); //8.定义起始行(方便分组后合并时从哪一行开始) //因为标题已经占了一行,所以数据从第二行开始写(excel第一行索引为0) //因需要合并到人物分数单元格所以需定义如下起始坐标 int indexClassName = 1; //班级名称起始行 int indexClassScore = 1; int indexGroupName = 1; int indexGroupScore = 1; int indexPersonName = 1; int indexPersonScore = 1; //9.遍历按班级名分组后的list(用entrySet效率比keySet效率高) for (Map.Entry > classNameListEntry : classList.entrySet()) { //10.获取按照班级名分组后的集合 List classValue = classNameListEntry.getValue(); //11.计算此集合的长度 int classSize = classValue.size(); //12.如果只有一行数据不能调用merge方法合并数据,否则会报错 if (classSize == 1){ indexClassName += classSize; indexClassScore += classSize; indexGroupName += classSize; indexGroupScore += classSize; indexPersonName += classSize; indexPersonScore += classSize; }else{ //13.根据班级名称进行合并单元格 //合并行,第一个参数是合并行的开始行号(行号从0开始),第二个参数是合并行的结束行号,第三个参数是合并的列号开始(列号从0开始), //第四个参数是合并的列号结束,第五个参数是合并后的内容,null不设置,第六个参数指是否支持设置样式,true指的是。 writer.merge(indexClassName, indexClassName + classSize - 1, 0, 0, null, true); //14.合并完后起始索引移到下一个合并点 indexClassName += classSize; //15.因为班级分数与班级名称相关联,所以不需要对班级分数分组,直接在此基础上对班级分数合并 writer.merge(indexClassScore, indexClassScore + classSize - 1, 1, 1, null, true); indexClassScore += classSize; //16.按照小组名进行分组(以下分组与班级名合并类似) LinkedHashMap > groupList = classValue.stream().collect(Collectors.groupingBy(item -> item.getGroupName(), LinkedHashMap::new, Collectors.toList())); for (Map.Entry > groupListEntry : groupList.entrySet()) { List groupValue = groupListEntry.getValue(); int groupSize = groupValue.size(); if (groupSize == 1){ indexGroupName += groupSize; indexGroupScore += groupSize; indexPersonName += groupSize; indexPersonScore += groupSize; }else{ //合并小组 writer.merge(indexGroupName, indexGroupName + groupSize - 1, 2, 2, null, true); indexGroupName += groupSize; //合并小组分数 writer.merge(indexGroupScore, indexGroupScore + groupSize - 1, 3, 3, null, true); indexGroupScore += groupSize; //17.按照人物名称进行分组 LinkedHashMap > personList = groupValue.stream().collect(Collectors.groupingBy(item -> item.getPersonName(), LinkedHashMap::new, Collectors.toList())); for (Map.Entry > personListEntry : personList.entrySet()) { List personValue = personListEntry.getValue(); int personSize = personValue.size(); if (personSize == 1){ indexPersonName += personSize; indexPersonScore += personSize; }else{ //合并人物 writer.merge(indexPersonName, indexPersonName + personSize - 1, 4, 4, null, true); indexPersonName += personSize; //合并人物总分 writer.merge(indexPersonScore, indexPersonScore + personSize - 1, 5, 5, null, true); indexPersonScore += personSize; } } } } } //18.保存数据 classValue.forEach( sList->{ List
六、测试
1.使用postman测试
2.结果:
借鉴地址:
https://juejin.cn/post/6982853657679101982
https://blog.csdn.net/zqy_CSDN_name/article/details/119643968