語言 java
框架 ssm
需求 :看圖 也是導出效果
數據庫查詢為(關系為一對多) 一個學生對應多個課程
實現步驟
1.實體類配置, 建議單獨寫個實體用來導出使用()
學生信息字段正常配置 , 課程表字段 使用 @ExcelProperty({"學生和選課中間表","學生編號"})
StudentExcel.java

package com.example.mybatisplus.pojo; import com.alibaba.excel.annotation.ExcelProperty; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * easy_excel導出 * @author three * @date 2021/8/23 16:13 */ @ApiModel("easy_excel導出實體類") @Data public class StudentExcel implements Serializable { private static final long serialVersionUID = 1L; // ----學生信息表( 一 ) @ExcelProperty("學生姓名") @ApiModelProperty("學生姓名") private String sname; @ExcelProperty("性別") @ApiModelProperty("性別") private String sgender; @ExcelProperty("出生年月") @ApiModelProperty("出生年月") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date sbirth; //----學生和選課中間表(多)---- @ExcelProperty({"學生和選課中間表","學生編號"}) @ApiModelProperty("學生編號") private Integer sno; @ExcelProperty({"學生和選課中間表","課程編號"}) @ApiModelProperty("課程編號") private String cno; @ExcelProperty({"學生和選課中間表","分數"}) @ApiModelProperty("分數") private String score; }
2.代碼 工具類 ExcelFillCellMergeStrategy.java

package com.example.mybatisplus.utils; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import java.util.List; public class ExcelFillCellMergeStrategy implements CellWriteHandler { private int[] mergeColumnIndex; private int mergeRowIndex; public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) { this.mergeRowIndex = mergeRowIndex; this.mergeColumnIndex = mergeColumnIndex; } @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { } @Override public 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; } } } } /** * 當前單元格向上合並 * * @param writeSheetHolder * @param cell 當前單元格 * @param curRowIndex 當前行 * @param curColIndex 當前列 */ private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); // 將當前單元格數據與上一個單元格數據比較 Boolean dataBool = preData.equals(curData); if (dataBool) { 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. EasyExcelController.java
3.1 int[] mergeColumeIndex = {0,1,2}; 數據重復部分會合並成一個單元格,只需標出需要合並的列數
3.2 int mergeRowIndex = 0; 標出合並的開始列數 從0開始

package com.example.mybatisplus.controller; import com.alibaba.excel.EasyExcel; import com.example.mybatisplus.pojo.StudentExcel; import com.example.mybatisplus.pojo.StudentinfoEntity; import com.example.mybatisplus.service.StudentinfoService; import com.example.mybatisplus.utils.ExcelFillCellMergeStrategy; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.util.List; /** * EasyExcel test * 測試地址 http://localhost:8088/easy-excel/export * 傳輸數據 [1,2,3] * @author zou * @date 2021/8/23 15:51 */ @Api(tags = "easy-excel的使用") @RestController @RequestMapping("/easy-excel") public class EasyExcelController { @Resource private StudentinfoService studentinfoService; @PostMapping("/export") @ApiOperation("導出excel(一對多關系)") public void excel(HttpServletResponse response,@RequestBody Integer[] sno) throws IOException { List<StudentExcel> studentinfoEntities = studentinfoService.studentToElectives(sno); // 設置響應格式 response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); //需要合並的列 int[] mergeColumeIndex = {0,1,2}; // 從那一列開始合並 int mergeRowIndex = 0; String fileName = URLEncoder.encode("one-to-many", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), StudentExcel.class) .sheet("one-to-many") .registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex)) .doWrite(studentinfoEntities); } }
4.服務層,持久層略去一千行....
....