左右列的单元格合并

╰+攻爆jí腚メ 2024-02-05 16:51 126阅读 0赞

EasyExcel导出合并单元格,左右列的单元格合并
1、导出的实体类,也就是表头

  1. @Data
  2. public class CityCapacityPo {
  3. @ExcelProperty(value = "时间",index = 0)
  4. private String time;
  5. @ExcelProperty(value = "出口",index = 1)
  6. private String export;
  7. @ExcelProperty(value = "地市",index = 2)
  8. private String direction;
  9. @ExcelProperty(value = "数据1",index = 3)
  10. private Double data1;
  11. @ExcelProperty(value = "数据2",index = 4)
  12. private Double data2;
  13. @ExcelProperty(value = "数据3",index = 5)
  14. private Double data3;
  15. @ExcelProperty(value = "数据4",index = 6)
  16. private Double data4;
  17. @ExcelProperty(value = "数据5",index = 7)
  18. private Double data5;
  19. @ExcelProperty(value = "数据6",index = 8)
  20. private Double data6;
  21. }

2、行合并工具类

  1. public class ExcelFillCellMergeStrategyUtils implements CellWriteHandler {
  2. /**
  3. * 需要合并列的下标,从0开始
  4. */
  5. private int[] mergeColumnIndex;
  6. /**
  7. * 从第几行开始合并,表头下标为0
  8. */
  9. private int mergeRowIndex;
  10. public ExcelFillCellMergeStrategyUtils(int mergeRowIndex, int[] mergeColumnIndex) {
  11. this.mergeRowIndex = mergeRowIndex;
  12. this.mergeColumnIndex = mergeColumnIndex;
  13. }
  14. @Override
  15. public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
  16. }
  17. @Override
  18. public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  19. }
  20. @Override
  21. public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  22. }
  23. @Override
  24. public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  25. //当前行
  26. int curRowIndex = cell.getRowIndex();
  27. //当前列
  28. int curColIndex = cell.getColumnIndex();
  29. if (curRowIndex > mergeRowIndex) {
  30. for (int i = 0; i < mergeColumnIndex.length; i++) {
  31. if (curColIndex == mergeColumnIndex[i]) {
  32. mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
  33. break;
  34. }
  35. }
  36. }
  37. }
  38. private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
  39. //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
  40. Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
  41. cell.getNumericCellValue();
  42. Row preRow = cell.getSheet().getRow(curRowIndex - 1);
  43. if (preRow == null) {
  44. // 当获取不到上一行数据时,使用缓存sheet中数据
  45. preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
  46. }
  47. Cell preCell=preRow.getCell(curColIndex);
  48. Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
  49. preCell.getNumericCellValue();
  50. // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
  51. if (curData.equals(preData)) {
  52. Sheet sheet = writeSheetHolder.getSheet();
  53. List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
  54. boolean isMerged = false;
  55. for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
  56. CellRangeAddress cellRangeAddr = mergeRegions.get(i);
  57. // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
  58. if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
  59. sheet.removeMergedRegion(i);
  60. cellRangeAddr.setLastRow(curRowIndex);
  61. sheet.addMergedRegion(cellRangeAddr);
  62. isMerged = true;
  63. }
  64. }
  65. // 若上一个单元格未被合并,则新增合并单元
  66. if (!isMerged) {
  67. CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
  68. curColIndex);
  69. sheet.addMergedRegion(cellRangeAddress);
  70. }
  71. }
  72. }
  73. }

3、列合并的工具类

  1. @Data
  2. @AllArgsConstructor
  3. public class CellLineRange {
  4. /**
  5. * 起始列
  6. */
  7. private int firstCol;
  8. /**
  9. * 结束列
  10. */
  11. private int lastCol;
  12. }
  13. public class ExcelFillCelMergeStrategy implements CellWriteHandler {
  14. //自定义合并单元格的列 如果想合并 第4列和第5例 、第6列和第7例: [CellLineRange(firstCol=3, lastCol=4), CellLineRange(firstCol=5, lastCol=6)]
  15. private List<CellLineRange> cellLineRangeList;
  16. //自定义合并单元格的开始的行 一般来说填表头行高0 表示从表头下每列开始合并 :如表头行高位为3则 int mergeRowIndex = 2 ;
  17. private int mergeRowIndex;
  18. public ExcelFillCelMergeStrategy(List<CellLineRange> cellLineRangeList, int mergeRowIndex) {
  19. this.cellLineRangeList=cellLineRangeList;
  20. this.mergeRowIndex=mergeRowIndex;
  21. }
  22. @Override
  23. public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
  24. }
  25. @Override
  26. public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  27. }
  28. @Override
  29. public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  30. }
  31. @Override
  32. public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
  33. //当前单元格的行数
  34. int curRowIndex = cell.getRowIndex();
  35. // 当前单元格的列数
  36. int curColIndex = cell.getColumnIndex();
  37. if (curRowIndex > mergeRowIndex) {
  38. if (curRowIndex > mergeRowIndex) {
  39. for (int i = 0; i < cellLineRangeList.size(); i++) {
  40. if (curColIndex > cellLineRangeList.get(i).getFirstCol()&&curColIndex<=cellLineRangeList.get(i).getLastCol()) {
  41. //单元格数据处理
  42. mergeWithLeftLine(writeSheetHolder, cell, curRowIndex, curColIndex);
  43. break;
  44. }
  45. }
  46. }
  47. }
  48. }
  49. /**
  50. * @description 当前单元格向左合并
  51. */
  52. private void mergeWithLeftLine(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
  53. //当前单元格中数据
  54. Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
  55. //获取当前单元格的左面一个单元格
  56. Cell leftCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex - 1);
  57. //获取当前单元格的左面一个单元格中的数据
  58. Object leftData = leftCell.getCellTypeEnum() == CellType.STRING ? leftCell.getStringCellValue() : leftCell.getNumericCellValue();
  59. // 将当前单元格数据与左侧一个单元格数据比较
  60. if (leftData.equals(curData)) {
  61. //获取当前sheet页
  62. Sheet sheet = writeSheetHolder.getSheet();
  63. //得到所有的合并单元格
  64. List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
  65. //是否合并
  66. boolean isMerged = false;
  67. for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
  68. //CellRangeAddress POI合并单元格
  69. //CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)
  70. //例子:CellRangeAddress(2, 6000, 3, 3);
  71. //第2行起 第6000行终止 第3列开始 第3列结束。
  72. CellRangeAddress cellRangeAddr = mergeRegions.get(i);
  73. // cellRangeAddr.isInRange(int rowInd, int colInd)确定给定坐标是否在此范围的范围内。
  74. // 若左侧一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
  75. if (cellRangeAddr.isInRange(curRowIndex, curColIndex - 1)) {
  76. sheet.removeMergedRegion(i);
  77. cellRangeAddr.setLastColumn(curColIndex);
  78. sheet.addMergedRegion(cellRangeAddr);
  79. isMerged = true;
  80. }
  81. }
  82. // 若左侧一个单元格未被合并,则新增合并单元
  83. if (!isMerged) {
  84. CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex , curRowIndex, curColIndex- 1, curColIndex);
  85. sheet.addMergedRegion(cellRangeAddress);
  86. }
  87. }
  88. }
  89. }

4、调用工具类,开始合并:

  1. @PostMapping("/exportCityOutletCapacityList")
  2. @ApiOperation("导出Excel表")
  3. public void exportCityOutletCapacityList(@RequestBody OutletCapacityParam param, HttpServletResponse response) {
  4. //获取需要导出的表数据
  5. List<CityCapacityPo> list=capacityFlowDao.selectCityOutletCapacityList(param);
  6. try {
  7. String fileName = "测试合并单元格";
  8. response.setContentType("application/octet-stream");
  9. response.setCharacterEncoding("utf-8");
  10. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  11. CityCapacityPo capacityPo=new CityCapacityPo();
  12. capacityPo.setExport("汇总");
  13. capacityPo.setTime("汇总");
  14. capacityPo.setDirection("汇总");
  15. //遍历列表,求各数据汇总
  16. capacityPo.setData1(list.stream().filter(Po-> Po.getData1()!=null).mapToDouble(CityCapacityPo::getData1).sum());
  17. capacityPo.setData2(list.stream().filter(Po-> Po.getData2()!=null).mapToDouble(CityCapacityPo::getData2).sum());
  18. capacityPo.setData3(list.stream().filter(Po-> Po.getData3()!=null).mapToDouble(CityCapacityPo::getData3).sum());
  19. capacityPo.setData4(list.stream().filter(Po-> Po.getData4()!=null).mapToDouble(CityCapacityPo::getData4).sum());
  20. capacityPo.setData5(list.stream().filter(Po-> Po.getData5()!=null).mapToDouble(CityCapacityPo::getData5).sum());
  21. capacityPo.setData6(list.stream().filter(Po-> Po.getData6()!=null).mapToDouble(CityCapacityPo::getData6).sum());
  22. list.add(capacityPo);
  23. ArrayList<CellLineRange> cellLineRanges=new ArrayList<>();
  24. //设置第几列开始合并
  25. int[] mergeColumnIndex = {
  26. 0, 1};
  27. //设置第几行开始合并
  28. int mergeRowIndex = 1;
  29. cellLineRanges.add(new CellLineRange(0,2));
  30. EasyExcel.write(response.getOutputStream())
  31. //设置行合并单元格
  32. .registerWriteHandler(new ExcelFillCellMergeStrategyUtils(mergeRowIndex,mergeColumnIndex))
  33. //设置行合并单元格
  34. .registerWriteHandler(new ExcelFillCelMergeStrategy(cellLineRanges,list.size()-1))
  35. .head(CityCapacityPo.class)
  36. .sheet("sheet1")
  37. .doWrite(list);
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. }
  41. }

发表评论

表情:
评论列表 (有 0 条评论,126人围观)

还没有评论,来说两句吧...

相关阅读