EasyExcel:利用模板进行填充字段,生成公式处理,监听单元格填充后触发事件,相同日期单元格合并

您所在的位置:网站首页 带有公式的单元格求和 EasyExcel:利用模板进行填充字段,生成公式处理,监听单元格填充后触发事件,相同日期单元格合并

EasyExcel:利用模板进行填充字段,生成公式处理,监听单元格填充后触发事件,相同日期单元格合并

2023-11-14 18:53| 来源: 网络整理| 查看: 265

EasyExcel

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址:https://github.com/alibaba/easyexcel 官方文档:https://www.yuque.com/easyexcel/doc/easyexcel

1. 依赖引入 com.alibaba easyexcel 3.0.5 org.projectlombok lombok 1.18.22 provided cn.hutool hutool-all 5.7.18 com.github.xiaoymin knife4j-spring-boot-starter 2.0.8 官方单sheet填充示例 简单填充

https://www.yuque.com/easyexcel/doc/fill#437f2d89

填充列表

https://www.yuque.com/easyexcel/doc/fill#b68864a9

复杂填充

https://www.yuque.com/easyexcel/doc/fill#0b212861

多列表组合填充

https://www.yuque.com/easyexcel/doc/fill#EBYsX

存放Excle模板文件

我这里将excle模板文件放在resources/templates路径下 在这里插入图片描述

使用模板进行填充 多sheet填充 效果:

在这里插入图片描述

日期单元格合并 设置sheet注册监听 Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook(); //设置强制计算公式:不然公式会以字符串的形式显示在excel中 workbook.setForceFormulaRecalculation(true); // 这里writerSheet(3)说明设置的是第四个sheet工作表,注册监听器 WriteSheet sumExportSheet = EasyExcel.writerSheet(3).registerWriteHandler(new CustomDateWriteHandler()).build(); import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import lombok.extern.slf4j.Slf4j; import net.microcental.dcdrdatareported.constants.ReportConstant; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.springframework.context.annotation.Configuration; import java.util.List; /** * easyExcel-日期单元格监听合并 * * @author yunnuo * @since 2021-12-28 */ @Slf4j @Configuration public class CustomDateWriteHandler implements CellWriteHandler { // 这里方法表示单元格填充完成后 @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 日期单元格合并 final int dateColumnIndex = 0; if (Objects.equals(cell.getColumnIndex(), dateColumnIndex)) { CustomCellWriteHandler.mergeWithPrevRow(writeSheetHolder, cell, cell.getRowIndex(), cell.getColumnIndex()); } CellWriteHandler.super.afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead); } } import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import java.util.List; import java.util.Optional; /** * easyExcel-单元格向上合并监听 * * @author yunnuo * @since 2021-12-27 */ @Slf4j public class CustomCellWriteHandler { /** * 当前单元格向上合并(合并日期) * * @param writeSheetHolder sheet * @param cell 当前单元格 * @param curRowIndex 当前行 * @param curColIndex 当前列 * @author yunnuo * @date 2021-12-27 14:43 */ public static void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { // 获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并 Object curData = cell.getStringCellValue(); Optional.ofNullable(cell.getSheet()).flatMap(sheetOne -> Optional.ofNullable(sheetOne.getRow(curRowIndex - 1))).ifPresent(row -> { Cell preCell = row.getCell(curColIndex); Object preData = preCell.getStringCellValue(); // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行 if (curData.equals(preData)) { Sheet sheet = writeSheetHolder.getSheet(); List mergeRegions = sheet.getMergedRegions(); boolean isMerged = false; for (int i = 0; i sheet.removeMergedRegion(i); cellRangeAdder.setLastRow(curRowIndex); sheet.addMergedRegion(cellRangeAdder); isMerged = true; } } // 若上一个单元格未被合并,则新增合并单元 if (!isMerged) { CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); sheet.addMergedRegion(cellRangeAddress); } } }); } } 设置选择不同sheet区域公式填充 效果

在这里插入图片描述

汇总公式填充代码:

/** * 获取排放汇总导出列表对象

*

* 汇总逻辑如下:

* 1. 遍历赋值日期 - sumDto.getAllDate()

* 2. 对排放汇总导出dto进行赋值 - new DischargeSumExportDto().setDate(date)

* 1.2. 判断报表数据中的日期和sumDto中的日期

* 1.2.1. 获取相同日期的报表数据的size,进行SUM函数取区域

* 2. 返回sumExportDto

* * @param sumDto {@link DischargeSumDto} 排放汇总数据dto * @param workbook {@link Workbook} 工作簿 * @param reportTime {@link List} 导出报表日期时间列表数据 * @return {@link List} 获取排放汇总导出列表对象 * @author wxt.hexingtao * @date 2021-12-28 16:31 */ private List getDischargeSumExportDtoList(DischargeSumDto sumDto, Workbook workbook, List reportTime) { AtomicInteger sumIndex = new AtomicInteger(4); // 遍历赋值日期 return sumDto.getAllDate().stream().filter(Objects::nonNull).map(date -> { DischargeSumExportDto sumExportDto = new DischargeSumExportDto().setDate(date); // 判断是否有数据进行汇总计算 Optional.of(reportTime.stream().filter(reportDate -> Objects.equals(reportDate.getDate(), date)).collect(Collectors.toList())).ifPresent(reportDateList -> { int size = reportDateList.size(); if (size > 0) { // workbook.getSheetAt(2).getSheetName()获取第三个sheet表名 String windSystemSum = String.format("SUM('%s'!AE%d:AE%d)", workbook.getSheetAt(2).getSheetName(), sumIndex.get(), sumIndex.get() + size - 1); String pumpSystemSum = String.format("SUM('%s'!X%d:X%d)", workbook.getSheetAt(3).getSheetName(), sumIndex.get(), sumIndex.get() + size - 1); String gasRecycleSum = String.format("SUM('%s'!X%d:X%d)", workbook.getSheetAt(4).getSheetName(), sumIndex.get(), sumIndex.get() + size - 1); String gasVentSum = String.format("SUM('%s'!Y%d:Y%d)", workbook.getSheetAt(4).getSheetName(), sumIndex.get(), sumIndex.get() + size - 1); String gasNetAmountSum = String.format("SUM('%s'!Z%d:Z%d)", workbook.getSheetAt(4).getSheetName(), sumIndex.get(), sumIndex.get() + size - 1); sumExportDto.setWindSystemSum(windSystemSum) .setPumpSystemSum(pumpSystemSum) .setGasRecycleSum(gasRecycleSum) .setGasVentSum(gasVentSum) .setGasNetAmountSum(gasNetAmountSum); sumIndex.addAndGet(size); } }); return sumExportDto; }).collect(Collectors.toList()); } 但是这个如果这样的填充的话Excel会直接将这个公式识别为字符串,所以还需要注册一个监听器来完成公式填充

监听器代码:

import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import lombok.extern.slf4j.Slf4j; import net.microcental.dcdrdatareported.constants.ReportConstant; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.springframework.context.annotation.Configuration; import java.util.List; /** * easyExcel-汇总表监听 * * @author yunnuo * @since 2021-12-28 */ @Slf4j @Configuration public class CustomSumWriteHandler implements CellWriteHandler { @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 定义最大求和公式列 final int sumMaxColIndex = 6; if (cell.getColumnIndex() > 0 && StringUtils.isNotBlank(cell.getStringCellValue())) { log.info("汇总表-完成公式填写:{}:{},值:{}", cell.getRowIndex() + 1, cell.getColumnIndex() + 1, cell.getStringCellValue()); // cell.setCellFormula(cell.getStringCellValue()); 设置该单元格内容为公式格式,注意cell.getStringCellValue()中不能有=号,不然会报错 cell.setCellFormula(cell.getStringCellValue()); } } // 这里对汇总表中的一行数据进行公式填充 可以不要 if (cell.getColumnIndex() == sumMaxColIndex && StringUtils.isBlank(cell.getStringCellValue()) && StringUtils.isNotBlank(cell.getSheet().getRow(cell.getRowIndex()).getCell(cell.getColumnIndex() - 1).getStringCellValue())) { int rowIndex = cell.getRowIndex() + 1; // "总排放量" = B26 + C26 - F26 cell.setCellFormula(String.format("B%d+C%d-F%d", rowIndex, rowIndex, rowIndex)); } CellWriteHandler.super.afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead); } }

然后就可以进行生成报表了。



【本文地址】


今日新闻


推荐新闻


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