EasyExcel导出合并单元格
生活随笔
收集整理的這篇文章主要介紹了
EasyExcel导出合并单元格
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
功能展示
功能類似這樣:
開題序言
當時網上的資料大部分都是上下行相同的數據合并,唯獨沒有左右列的單元格合并。因此找資料花了一點時間,但功夫不負有心人,終于看到有兩個和我要的功能差不多類似的文章。需要自取:
EasyExcel模板導出(行和列自動合并)_Lzfnemo2009的博客-CSDN博客_easyexcel模板導出
EasyExcel導出自定義合并單元格 策略 個人理解
寫這篇文章只是為了自己以后參考。?
以下進入正文:
1、導出的實體類,也就是表頭
@Data public class CityCapacityPo {@ExcelProperty(value = "時間",index = 0)private String time;@ExcelProperty(value = "出口",index = 1)private String export;@ExcelProperty(value = "地市",index = 2)private String direction;@ExcelProperty(value = "數據1",index = 3)private Double data1;@ExcelProperty(value = "數據2",index = 4)private Double data2;@ExcelProperty(value = "數據3",index = 5)private Double data3;@ExcelProperty(value = "數據4",index = 6)private Double data4;@ExcelProperty(value = "數據5",index = 7)private Double data5;@ExcelProperty(value = "數據6",index = 8)private Double data6;}2、行合并工具類
public class ExcelFillCellMergeStrategyUtils implements CellWriteHandler {/*** 需要合并列的下標,從0開始*/private int[] mergeColumnIndex;/*** 從第幾行開始合并,表頭下標為0*/private int mergeRowIndex;public ExcelFillCellMergeStrategyUtils(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {//當前行int curRowIndex = cell.getRowIndex();//當前列int curColIndex = cell.getColumnIndex();if (curRowIndex > mergeRowIndex) {for (int i = 0; i < mergeColumnIndex.length; i++) {if (curColIndex == mergeColumnIndex[i]) {mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);break;}}}}private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {//獲取當前行的當前列的數據和上一行的當前列列數據,通過上一行數據是否相同進行合并Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :cell.getNumericCellValue();Row preRow = cell.getSheet().getRow(curRowIndex - 1);if (preRow == null) {// 當獲取不到上一行數據時,使用緩存sheet中數據preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);}Cell preCell=preRow.getCell(curColIndex);Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :preCell.getNumericCellValue();// 比較當前行的第一列的單元格與上一行是否相同,相同合并當前單元格與上一行if (curData.equals(preData)) {Sheet sheet = writeSheetHolder.getSheet();List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();boolean isMerged = false;for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {CellRangeAddress cellRangeAddr = mergeRegions.get(i);// 若上一個單元格已經被合并,則先移出原有的合并單元,再重新添加合并單元if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {sheet.removeMergedRegion(i);cellRangeAddr.setLastRow(curRowIndex);sheet.addMergedRegion(cellRangeAddr);isMerged = true;}}// 若上一個單元格未被合并,則新增合并單元if (!isMerged) {CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,curColIndex);sheet.addMergedRegion(cellRangeAddress);}}}}3、列合并的工具類
@Data @AllArgsConstructor public class CellLineRange {/*** 起始列*/private int firstCol;/*** 結束列*/private int lastCol; } public class ExcelFillCelMergeStrategy implements CellWriteHandler {//自定義合并單元格的列 如果想合并 第4列和第5例 、第6列和第7例: [CellLineRange(firstCol=3, lastCol=4), CellLineRange(firstCol=5, lastCol=6)]private List<CellLineRange> cellLineRangeList;//自定義合并單元格的開始的行 一般來說填表頭行高0 表示從表頭下每列開始合并 :如表頭行高位為3則 int mergeRowIndex = 2 ;private int mergeRowIndex;public ExcelFillCelMergeStrategy(List<CellLineRange> cellLineRangeList, int mergeRowIndex) {this.cellLineRangeList=cellLineRangeList;this.mergeRowIndex=mergeRowIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {//當前單元格的行數int curRowIndex = cell.getRowIndex();// 當前單元格的列數int curColIndex = cell.getColumnIndex();if (curRowIndex > mergeRowIndex) {if (curRowIndex > mergeRowIndex) {for (int i = 0; i < cellLineRangeList.size(); i++) {if (curColIndex > cellLineRangeList.get(i).getFirstCol()&&curColIndex<=cellLineRangeList.get(i).getLastCol()) {//單元格數據處理mergeWithLeftLine(writeSheetHolder, cell, curRowIndex, curColIndex);break;}}}}}/*** @description 當前單元格向左合并*/private void mergeWithLeftLine(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {//當前單元格中數據Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();//獲取當前單元格的左面一個單元格Cell leftCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex - 1);//獲取當前單元格的左面一個單元格中的數據Object leftData = leftCell.getCellTypeEnum() == CellType.STRING ? leftCell.getStringCellValue() : leftCell.getNumericCellValue();// 將當前單元格數據與左側一個單元格數據比較if (leftData.equals(curData)) {//獲取當前sheet頁Sheet sheet = writeSheetHolder.getSheet();//得到所有的合并單元格List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();//是否合并boolean isMerged = false;for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {//CellRangeAddress POI合并單元格//CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)//例子:CellRangeAddress(2, 6000, 3, 3);//第2行起 第6000行終止 第3列開始 第3列結束。CellRangeAddress cellRangeAddr = mergeRegions.get(i);// cellRangeAddr.isInRange(int rowInd, int colInd)確定給定坐標是否在此范圍的范圍內。// 若左側一個單元格已經被合并,則先移出原有的合并單元,再重新添加合并單元if (cellRangeAddr.isInRange(curRowIndex, curColIndex - 1)) {sheet.removeMergedRegion(i);cellRangeAddr.setLastColumn(curColIndex);sheet.addMergedRegion(cellRangeAddr);isMerged = true;}}// 若左側一個單元格未被合并,則新增合并單元if (!isMerged) {CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex , curRowIndex, curColIndex- 1, curColIndex);sheet.addMergedRegion(cellRangeAddress);}}}}4、調用工具類,開始合并:
@PostMapping("/exportCityOutletCapacityList") @ApiOperation("導出Excel表") public void exportCityOutletCapacityList(@RequestBody OutletCapacityParam param, HttpServletResponse response) {//獲取需要導出的表數據List<CityCapacityPo> list=capacityFlowDao.selectCityOutletCapacityList(param);try {String fileName = "測試合并單元格";response.setContentType("application/octet-stream");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");CityCapacityPo capacityPo=new CityCapacityPo();capacityPo.setExport("匯總");capacityPo.setTime("匯總");capacityPo.setDirection("匯總");//遍歷列表,求各數據匯總capacityPo.setData1(list.stream().filter(Po-> Po.getData1()!=null).mapToDouble(CityCapacityPo::getData1).sum());capacityPo.setData2(list.stream().filter(Po-> Po.getData2()!=null).mapToDouble(CityCapacityPo::getData2).sum());capacityPo.setData3(list.stream().filter(Po-> Po.getData3()!=null).mapToDouble(CityCapacityPo::getData3).sum());capacityPo.setData4(list.stream().filter(Po-> Po.getData4()!=null).mapToDouble(CityCapacityPo::getData4).sum());capacityPo.setData5(list.stream().filter(Po-> Po.getData5()!=null).mapToDouble(CityCapacityPo::getData5).sum());capacityPo.setData6(list.stream().filter(Po-> Po.getData6()!=null).mapToDouble(CityCapacityPo::getData6).sum());list.add(capacityPo);ArrayList<CellLineRange> cellLineRanges=new ArrayList<>();//設置第幾列開始合并int[] mergeColumnIndex = {0, 1};//設置第幾行開始合并int mergeRowIndex = 1;cellLineRanges.add(new CellLineRange(0,2));EasyExcel.write(response.getOutputStream()) //設置行合并單元格.registerWriteHandler(new ExcelFillCellMergeStrategyUtils(mergeRowIndex,mergeColumnIndex))//設置行合并單元格.registerWriteHandler(new ExcelFillCelMergeStrategy(cellLineRanges,list.size()-1)).head(CityCapacityPo.class).sheet("sheet1").doWrite(list);} catch (Exception e) {e.printStackTrace();}}以上就是行和列的合并過程了,主要的內容就是行和列合并的工具類,網上的資料都差不多。其實很多我確實也沒參透,只是依樣畫葫蘆,碰巧實現了。
總結
以上是生活随笔為你收集整理的EasyExcel导出合并单元格的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Apifox测试Excel文件上传
- 下一篇: 3个难忘的老师