ToB企服应用市场:ToB评测及商务社交产业平台

标题: easyExcel 填充写时,动态合并单位格 [打印本页]

作者: 科技颠覆者    时间: 2024-8-30 23:41
标题: easyExcel 填充写时,动态合并单位格
1、定义合并单位格策略获取方法

  1. /**
  2.      * @description: 获取第二个表格的合并策略
  3.      * @param secondTablelist  
  4.      * @return: java.util.List<com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy>
  5.      * @author 30864
  6.      * @date: 2024/8/24 20:27
  7.      */
  8.     public static List<OnceAbsoluteMergeStrategy> getSecondMergeStrategy(List<ProjectContractExpenditureStatisticDto> secondTablelist) {
  9.         int baseRowIndex = 3;
  10.         //合并开始行
  11.         int startRowIndex = 0;
  12.         //合并结束行
  13.         int endRowIndex = 0;
  14.         //合并开始列
  15.         int colStartIndex = 0;
  16.         //合并结束列
  17.         int colEndIndex = 0;
  18.         List<OnceAbsoluteMergeStrategy> strategyList = new ArrayList<>();
  19.         //       取出string列的数据
  20.         List<String> contractNoList = secondTablelist.stream().map(ProjectContractExpenditureStatisticDto::getContractNo).collect(Collectors.toList());
  21.         //       前后添加两个不计入合并的元素 , 类似链表中哨兵,简化索引越界的判断
  22.         contractNoList.add(0, "开始节点不计入合并");
  23.         contractNoList.add(contractNoList.size(), "结束节点不计入合并");
  24.         List<Integer> mergeColIndexList = Arrays.asList(0,1,2,3,4,5,6,13,14,15);
  25.         for (int index = 1; index < contractNoList.size() - 1; index++) {
  26.             // 当前的元素和数组中前一个元素是否相等
  27.             boolean equalsPrevious = Objects.equals(contractNoList.get(index), contractNoList.get(index - 1));
  28.             // 当前的元素和数组中后一个元素是否相等
  29.             boolean equalsAfter = Objects.equals(contractNoList.get(index), contractNoList.get(index + 1));
  30. //            如果找到一个元素和不等于前面,但是等于后面,则这个元素的索引就是一个OnceAbsoluteMergeStrategy的开始行
  31.             if (!equalsPrevious && equalsAfter) {
  32.                 startRowIndex = index;
  33.                 //            如果找到一个元素和等于前面,但是不等于后面,则这个元素的索引就是一个OnceAbsoluteMergeStrategy的结束结束行
  34.             } else if (equalsPrevious && !equalsAfter) {
  35.                 endRowIndex = index;
  36.                 // 无合同号,不进行合并
  37.                 if (StringUtils.equals(secondTablelist.get(startRowIndex).getContractName(), Constansts.NOT_HAS_CONTRACT_CONTENT) ){
  38.                     continue;
  39.                 }
  40. //              创建单个合并策略,并添加到策略列表里面去
  41.                 for (int colIndex : mergeColIndexList) {
  42.                     OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(baseRowIndex + startRowIndex, baseRowIndex + endRowIndex, colIndex, colIndex);
  43.                     strategyList.add(strategy);
  44.                 }
  45.             }
  46.         }
  47.         return strategyList;
  48.     }
复制代码
表明: 需求:根据合同编码判断是否要合并,雷同合同合并单位格
1、根据待写入数据纪录的聚集list, 获取合同编号聚集
2、取当前纪录及其前一条纪录,判断当前纪录的合同号  = 前一条纪录合同号 ?
如果不相称,则当然前纪录就是待合并单位格的起始行
3、取当前纪录及其后一条纪录,判断当前纪录的合同号 = 后一条纪录合同号 ? 
如果不相称,则当前纪录就是待合并单位格的竣事行
4、起始结尾行号确定了,需要确定起始结尾的列号,由于每列内容不一样,所以合同属性涉及的列号,都要一一合并,(这里涉及的列号 List<Integer> mergeColIndexList=Arrays.asList(0,1,2,3,4,5,6,13,14,15);)所以这里把涉及的列号定义了一个聚集,然后其中的每一列都按照 起始行、竣事行去合并。

2、写入时将合并策略注册到ExcelWriterSheetBuilder

  1. /**
  2.      * @param project
  3.      * @description: 导出项目
  4.      * @return: void
  5.      * @author 30864
  6.      * @date: 2024/8/1 9:05
  7.      */
  8.     @Override
  9.     public void export(Project project, HttpServletResponse response) throws IOException {
  10.         Project dbProject = projectMapper.selectProjectByNo(project.getProjectNo());
  11.         String fileName = String.format("%s【%s】报告", dbProject.getProjectName(), dbProject.getProjectNo()) + System.currentTimeMillis() + ".xlsx";
  12.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  13.         response.setCharacterEncoding("utf-8");
  14.         // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
  15.         fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  16.         response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
  17.         OutputStream os = response.getOutputStream();
  18.         String templateFileName = "template/template-project-report-new.xlsx";
  19.         InputStream templateFileIos = getClass().getClassLoader().getResourceAsStream(templateFileName);
  20.         if (null == templateFileIos) {
  21.             throw new ServiceException("找不到模板文件");
  22.         }
  23.         try (ExcelWriter excelWriter = EasyExcel.write(os).withTemplate(templateFileIos).build()) {
  24.             ExcelWriterSheetBuilder excelWriterSheetBuilder1 =   EasyExcel.writerSheet("项目执行情况-汇总");
  25.             ExcelWriterSheetBuilder excelWriterSheetBuilder2 =   EasyExcel.writerSheet("项目执行情况-明细");
  26.             ExcelWriterSheetBuilder excelWriterSheetBuilder3 =   EasyExcel.writerSheet("项目执行情况-审定数据");
  27.             StatisticFirstTableDataDto firstTableDataDto = firstTableData(project);
  28.             StatisticSecondTableDataDto secondTableDataDto = secondTableData(project);
  29.             StatisticThirdTableDataDto thirdTableDataDto = thirdTableData(project);
  30.             // 第二个表格添加合并单元格策略
  31.             List<OnceAbsoluteMergeStrategy> secondMergeStrategyList = getSecondMergeStrategy(secondTableDataDto.getExpenditureList());
  32.             for (OnceAbsoluteMergeStrategy secondMergeStrategy : secondMergeStrategyList ) {
  33.                 excelWriterSheetBuilder2.registerWriteHandler(secondMergeStrategy);
  34.             }
  35.             // 第三个表格添加合并单元格策略
  36.             List<OnceAbsoluteMergeStrategy> thirdMergeStrategyList = getThirdMergeStrategy(thirdTableDataDto.getAuditList());
  37.             for (OnceAbsoluteMergeStrategy thirdMergeStrategy : thirdMergeStrategyList ) {
  38.                 excelWriterSheetBuilder3.registerWriteHandler(thirdMergeStrategy);
  39.             }
  40.             WriteSheet writeSheet1 = excelWriterSheetBuilder1.build();
  41.             WriteSheet writeSheet2 = excelWriterSheetBuilder2.build();
  42.             WriteSheet writeSheet3 = excelWriterSheetBuilder3.build();
  43.             /** 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。
  44.              * 默认 是false,会直接使用下一行,如果没有则创建。 forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用 */
  45.             // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 totalData,warnList 然后多个list必须用 FillWrapper包裹
  46.             // HORIZONTAL 横向填充 , VERTICAL 纵向填充
  47.             // 第一个表格合同维度列表统计
  48.             FillConfig contractListConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build();
  49.             excelWriter.fill(new FillWrapper("firstTableData", firstTableDataDto.getContractList()), contractListConfig, writeSheet1);
  50.             // 第二个表格支出维度,列表统计
  51.             FillConfig secordTableConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build();
  52.             excelWriter.fill(new FillWrapper("secondTableData", secondTableDataDto.getExpenditureList()), secordTableConfig, writeSheet2);
  53.             // 第三个表格概算类型维度,列表统计
  54.             FillConfig thirdTableConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build();
  55.             excelWriter.fill(new FillWrapper("thirdTableData", thirdTableDataDto.getAuditList()), thirdTableConfig, writeSheet3);
  56.             // 填充其他非列表数据
  57.             Map<String, Object> data = new HashMap<>();
  58.             // 项目名称
  59.             data.put("projectName", dbProject.getProjectName());
  60.             data.put("projectNo", dbProject.getProjectNo());
  61.             // 第一个表格总计
  62.             data.put("firstTableTotal_totalPayMoney", firstTableDataDto.getTotalPayMoney());
  63.             data.put("firstTableTotal_totalUnpaidAmount", firstTableDataDto.getTotalUnpaidAmount());
  64.             // 第二个表格总计
  65.             data.put("secondTableTotal_totalPayMoney", secondTableDataDto.getTotalPayMoney());
  66.             data.put("secondTableTotal_unpaidAmount", secondTableDataDto.getUnpaidAmount());
  67.             // 第三个表格总计
  68.             data.put("thirdTableTotal_totalPayMoney", thirdTableDataDto.getTotalPayMoney());
  69.             data.put("thirdTableTotal_unpaidAmount", thirdTableDataDto.getUnpaidAmount());
  70.             data.put("thirdTableTotal_estimateAmount", thirdTableDataDto.getEstimateAmount());
  71.             excelWriter.fill(data, writeSheet1);
  72.             excelWriter.fill(data, writeSheet2);
  73.             excelWriter.fill(data, writeSheet3);
  74.             excelWriter.finish();
  75.         }
  76.     }
复制代码
表明: 这里涉及三个sheet的写入,只需关注 excelWriterSheetBuilder2 即可

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4