【EasyExcel】解决模板导出时,合并单元格样式丢失

解决使用EasyExcel 模板导出时,列表中的合并单元格列,自动新增时样式异常,不会自动合并。

导出模板

在导出示例中,不给备注列设值。

示例代码:

java 复制代码
package easyExcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: DaBing
 * @Create_Date: 2025/11/6 16:36
 */
@Slf4j
@SpringBootTest
public class EasyExcelDemo {

    /**
     * 复杂的填充
     *
     * @since 2.1.1
     */
    @Test
    public void complexFill() {
        //模板路径
        String templateFileName = "模板路径";
        //导出文件保存路径
        String fileName = "导出文件保存路径";

        List<Map> dataList = this.getDataList();

        ExcelWriter excelWriter = EasyExcel.write(fileName)
                .registerWriteHandler(new MyHandler())  //设置策略
                .withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
        // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
        // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
        // 如果数据量大 list不是最后一行 参照下一个
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(dataList, fillConfig, writeSheet);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("date", "2019年10月9日13:28:28");
        map.put("total", 1000);
        excelWriter.fill(map, writeSheet);
        excelWriter.finish();
    }
    @Test
    public void complexFill1() {
        PrintSuper printSuper = new PrintSuper();
        List dataList = printSuper.getPrintData();
        Object o = dataList.get(0);
        System.out.println(JSON.toJSONString(o));

        Field[] fields = o.getClass().getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            System.out.println(">>>> " + name);
        }

    }

    public class PrintSuper {


        public List<PrintData> getPrintData() {
            List<PrintData> printDataList = new ArrayList<>();
            for (int i = 0; i < 10; i ++) {
                PrintData printData = new PrintData();
                printData.setIndex(i);
//                printData.setName("name" + i);
                printDataList.add(printData);
            }
            return printDataList;
        }

        private class PrintData {
            private int index;

            private String name;

            public int getIndex() {
                return index;
            }

            public void setIndex(int index) {
                this.index = index;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }
        }
    }

    private static List<Map> getDataList() {
        List<Map> dataList = new ArrayList<>();
        for (int i = 0; i < 5; i ++) {
            Map temp = new HashMap();
            temp.put("index", i);
            temp.put("name", "名称" + i);
            temp.put("number", i * 10);
            temp.put("remarks", "");
            dataList.add(temp);
        }

        return dataList;
    }

    /**
     * 单元格合并策略1
     */
    public class MyHandler extends AbstractMergeStrategy {

        @Override
        protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
            if(relativeRowIndex==null ||relativeRowIndex==0){
                return;
            }

            int rowIndex = cell.getRowIndex();
            int colIndex = cell.getColumnIndex();

            log.debug(">>> 处理第 {} 行数据,第 {} 列数据", rowIndex, colIndex);

            sheet=cell.getSheet();
            Row preRow = sheet.getRow(rowIndex - 1);
            Cell preCell = preRow.getCell(colIndex);//获取上一行的该格
            List<CellRangeAddress> rangeAddressList = sheet.getMergedRegions();
            for (int i = 0; i < rangeAddressList.size(); i++) {
                CellRangeAddress cellRangeAddress = rangeAddressList.get(i);

                if (cellRangeAddress.containsRow(preCell.getRowIndex()) && cellRangeAddress.containsColumn(preCell.getColumnIndex()))  {
                    int firstColIndex = cellRangeAddress.getFirstColumn();
                    int lastColIndex = cellRangeAddress.getLastColumn();
                    int firstRowIndex = cellRangeAddress.getFirstRow();

                    log.debug(">>> 第 {} 行 {},第 {} 列至第 {} 列合并。", rowIndex, firstRowIndex, firstColIndex, lastColIndex);

                    CellRangeAddress cra;
                    cra = new CellRangeAddress(rowIndex, rowIndex, firstColIndex, lastColIndex);
                    sheet.addMergedRegion(cra);

                    //设置合并区域cra的边框
                    RegionUtil.setBorderBottom(BorderStyle.THIN, cra, sheet);
                    RegionUtil.setBorderLeft(BorderStyle.THIN, cra, sheet);
                    RegionUtil.setBorderRight(BorderStyle.THIN, cra, sheet);
                    RegionUtil.setBorderTop(BorderStyle.THIN, cra, sheet);
                    return;
                }
            }
        }
    }
}

代码执行结果:

相关推荐
一叶飘零_sweeeet18 天前
Java+EasyExcel 打造学习平台视频学习时长统计系统
java·报表·easyexcel
老友@20 天前
Java Excel 导出:EasyExcel 使用详解
java·开发语言·excel·easyexcel·excel导出
装不满的克莱因瓶20 天前
【项目亮点】基于EasyExcel + 线程池解决POI文件导出时的内存溢出及超时问题
java·jvm·excel·线程池·async·虚拟机·easyexcel
TangKenny1 个月前
基于EasyExcel的动态列映射读取方案
java·easyexcel
暗武逢天1 个月前
Java导出写入固定Excel模板数据
java·导出数据·easyexcel·excel固定模板导出
kangaroo.2 个月前
基于EasyExcel、FastExcel封装spring boot starter
spring boot·easyexcel·fastexcel
FenceRain3 个月前
EasyExcel 实现国际化导入导出
java·spring boot·easyexcel
带刺的坐椅3 个月前
老码农教你:Solon + EasyExcel 导出工具
java·excel·solon·easyexcel
假客套5 个月前
2025 Java EasyExcel 基于Excel模板填充数据 SpringBoot+Mybatis-Flex
java·spring boot·mybatis·easyexcel