easyExcel合並數據導出(一對多)


語言 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;
}
View Code

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);
            }
        }
    }

}
View Code

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);
    }
}
View Code

4.服務層,持久層略去一千行....

....


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM