easyExcel导出包括相同列id相同合并单元格,明细导出

easyExcel导出明细

controller方法

复制代码
  /**
     * 导出流水明细
     *
     * @return
     */
    @PostMapping("/receipt/statement/detail/export")
    public void export(HttpServletResponse response, @RequestBody ExportDetailDto dto) throws ParseException {
        List<ExportFieldVo> exportField = dto.getExportField();
        List<String> names = exportField.stream().map(ExportFieldVo::getName).toList();
        //查询数据

        List<ExportDetailData> exportDetailData = receiptStatementDetailService.getExportData(dto);


        //  查询
        if (names.contains("明细表")) {
            try {

                int size = names.size() - 1;

                // 设置响应结果
                this.setExcelResponseProp(response, "流水明细");

                List<List<String>> list = generateHeadForDetail(names);
                List<List<Object>> dataList = new ArrayList<>();
                for (ExportDetailData detailData : exportDetailData) {
                    List<ContractInfo> contractInfoList = detailData.getContractInfoList();
                    // List<ProjectInfo> projectInfoList = detailData.getProjectInfoList();
                    if (CollUtil.isEmpty(contractInfoList)) {
                        List<Object> data1 = generateHeadCommon(names, detailData);
                        for (int i = 0; i < 10; i++) {
                            data1.add("");
                        }
                        dataList.add(data1);

                    } else {

                        setContractInfoData(names, dataList, detailData, contractInfoList);

                        // setProjectInfoData(names, dataList, detailData, projectInfoList);
                    }
                }


                WriteCellStyle writeCellStyle = new WriteCellStyle();
                writeCellStyle.setWrapped(true);

                // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
                // LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);

                HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                        new HorizontalCellStyleStrategy(null, writeCellStyle);

                // 调用合并单元格工具类,此工具类是根据工程名称相同则合并后面数据
                //需要合并的列
                //int[] mergeColumeIndex = {0, 1,2,3,4,5,6,7,8,9,10,11,12};

                //int[] index = generateArray(mergeColumeIndex, size);

                int[] mergeColumnIndex = new int[size];

                for (int i = 0; i < size; i++) {
                    mergeColumnIndex[i] = i;
                }

                //从第1列开始合并
                int mergeRowIndex = 0;
                ExcelMergeUtil excelFillCellMergeStrategy = new ExcelMergeUtil(mergeRowIndex, mergeColumnIndex);

                EasyExcel.write(response.getOutputStream())
                        .head(list)
                        .registerWriteHandler(horizontalCellStyleStrategy)
                        .registerWriteHandler(excelFillCellMergeStrategy)
                        .registerWriteHandler(new AutoColumnWidthHandler())
                        .excelType(ExcelTypeEnum.XLSX)
                        .sheet("流水明细")
                        .doWrite(dataList);
            } catch (IOException e) {
                throw new ServiceException(e);
            }
        } else {
            try {

                // 设置响应结果
                Map<String, String> headMap = new HashMap<>();
                this.setExcelResponseProp(response, "流水明细");
                List<List<String>> list = getHead(names, headMap);

                List<List<Object>> dataList = new ArrayList<>();
                for (ExportDetailData detailData : exportDetailData) {
                    setDataCommonExport(headMap, dataList, detailData);
                }


                WriteCellStyle writeCellStyle = new WriteCellStyle();
                writeCellStyle.setWrapped(true);

                HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                        new HorizontalCellStyleStrategy(null, writeCellStyle);

                EasyExcel.write(response.getOutputStream())
                        .head(list)
                        .registerWriteHandler(horizontalCellStyleStrategy)
                        .registerWriteHandler(new AutoColumnWidthHandler())
                        .excelType(ExcelTypeEnum.XLSX)
                        .sheet("流水明细")
                        .doWrite(dataList);
            } catch (IOException e) {
                throw new ServiceException(e);
            }
        }

    }

ExcelMergeUtil

package com.crfsdi.ocm.receipt.utils;

import com.alibaba.excel.metadata.Head;

import com.alibaba.excel.metadata.data.CellData;

import com.alibaba.excel.metadata.data.WriteCellData;

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 ExcelMergeUtil implements CellWriteHandler {

private int[] mergeColumnIndex;

private int mergeRowIndex;

复制代码
public ExcelMergeUtil() {
}

public ExcelMergeUtil(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) {

}


public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

}

@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    //当前行
    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);

    String stringCellValue = cell.getRow().getCell(0).getStringCellValue();

    String stringCellValue1 = cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue();

    //此处需要注意:因为我是按照工程名称确定是否需要合并的,所以获取每一行第二列数据和上一行第一列数据进行比较,如果相等合并,getCell里面的值,是工程名称所在列的下标
    Boolean bool = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue());
    System.out.println("A");
    if (dataBool && bool) {
        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);
        }
    }
}

}

表头设置方法

复制代码
    private static List<List<String>> getHead(List<String> names, Map<String, String> headMap) {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        if (names.contains("流水号")) {
            head0.add("流水号");
            list.add(head0);
            headMap.put("流水号", "流水号");
        }

        if (names.contains("金额(元)")) {
            List<String> head1 = new ArrayList<String>();
            head1.add("金额(元)");
            list.add(head1);
            headMap.put("金额(元)", "金额(元)");
        }

        if (names.contains("付款方")) {
            List<String> head2 = new ArrayList<String>();
            head2.add("付款方");
            list.add(head2);
            headMap.put("付款方", "付款方");
        }

        if (names.contains("用途")) {
            List<String> head3 = new ArrayList<String>();
            head3.add("用途");
            list.add(head3);
            headMap.put("用途", "用途");
        }
        if (names.contains("款项类别")) {
            List<String> head4 = new ArrayList<String>();
            head4.add("款项类别");
            list.add(head4);
            headMap.put("款项类别", "款项类别");
        }

        if (names.contains("到款时间")) {
            List<String> head5 = new ArrayList<String>();
            head5.add("到款时间");
            list.add(head5);
            headMap.put("到款时间", "到款时间");
        }

        if (names.contains("转至账户")) {
            List<String> head6 = new ArrayList<String>();
            head6.add("转至账户");
            list.add(head6);
            headMap.put("转至账户", "转至账户");
        }
        if (names.contains("款项类型")) {
            List<String> head7 = new ArrayList<String>();
            head7.add("款项类型");
            list.add(head7);
            headMap.put("款项类型", "款项类型");
        }

        if (names.contains("确认人")) {
            List<String> head8 = new ArrayList<String>();
            head8.add("确认人");
            list.add(head8);
            headMap.put("确认人", "确认人");
        }

        if (names.contains("单位名称")) {
            List<String> head9 = new ArrayList<String>();
            head9.add("单位名称");
            list.add(head9);
            headMap.put("单位名称", "单位名称");
        }

        if (names.contains("附件")) {
            List<String> head10 = new ArrayList<String>();
            head10.add("附件");
            list.add(head10);
            headMap.put("附件", "附件");
        }

        if (names.contains("当前节点")) {
            List<String> head11 = new ArrayList<String>();
            head11.add("当前节点");
            list.add(head11);
            headMap.put("当前节点", "当前节点");
        }

        if (names.contains("审批状态")) {
            List<String> head12 = new ArrayList<String>();
            head12.add("审批状态");
            list.add(head12);
            headMap.put("审批状态", "审批状态");
        }
        return list;
    }
相关推荐
me8323 小时前
【Java】解决Maven多模块父POM加载失败+IDEA无法新建Java类问题
java·maven·intellij-idea
亚马逊云开发者4 小时前
RAG 向量存储月费 800 刀?S3 Vectors 直接砍到 100 出头
java
2401_895521344 小时前
springboot集成onlyoffice(部署+开发)
java·spring boot·后端
zlpzlpzyd4 小时前
groovy学习
java·jvm·学习
程序员小假4 小时前
你分得清 Prompt、Agent、Function Call、Skill、MCP 吗?
java·后端
xuboyok24 小时前
【Spring Boot】统一数据返回
java·spring boot·后端
亚马逊云开发者4 小时前
你的 AI Agent 只有鱼的记忆?聊聊 Agent 记忆管理的正确姿势
java
燕山罗成4 小时前
JAVA多线程基础
java·开发语言
予枫的编程笔记4 小时前
【面试专栏|Java并发编程】拆解Java线程生命周期:从新建到终止,再讲清进程与线程的核心差异
java·多线程·java基础·java面试·进程与线程·面试干货·java线程生命周期
Yvonne爱编码5 小时前
JAVA数据结构 DAY7-二叉树
java·开发语言·数据结构