參考:https://juejin.cn/post/7322156759443095561?searchId=202405262043517631094B7CCB463FDA06
https://juejin.cn/post/7322156759443095561?searchId=202405262043517631094B7CCB463FDA06
準備條件
依賴
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version></dependency>
工具類
package co.yixiang.exam.listener;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() {}public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}@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;}}}}/*** 當前單元格向上合并** @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();// 比較當前行的第一列的單元格與上一行是否相同,相同合并當前單元格與上一行//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);}}}}
ServiceImpl層應用
sql 數據的重復數據,合并單元格
SELECTeq.id,eq.question_title,eo.options_content,eq.options_correct,eq.question_answer,eq.question_score,eq.question_subject,eq.question_title_zi,eq.question_type
FROMex_question eq
LEFT JOINex_options eoon eq.id = eo.question_id where eq.is_del = 0 and eo.is_del = 0;
@Overridepublic R exportExQuestionOptions(HttpServletResponse response) throws IOException {// 定義導出的Excel文件名String fileName = "test.xlsx";// 設置響應的內容類型為二進制流,這是文件下載的標準設置response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 設置響應頭的Content-Disposition,使用"attachment"指示瀏覽器這是一個需要下載的文件response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()));// 查詢需要導出的數據 (包含復雜數據)List<ExExcelQuestionOptionsDto> questionsOptionsAll = exQuestionMapper.getQuestionsOptionsAll();// 假設我們要合并第1行和第2列到第4列的數據(索引從0開始)int mergeRowIndex = 0; // 行索引 int[] mergeColumnIndex = new int[]{0,1,2,3,4,5,6}; // 列索引數組 要合并的列ExcelFillCellMergeStrategy excelFillCellMergeStrategy = new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumnIndex);EasyExcel.write(response.getOutputStream(), ExExcelQuestionOptionsDto.class).registerWriteHandler(excelFillCellMergeStrategy).sheet("測試").doWrite(questionsOptionsAll);return R.success();}