使用EasyExcel导出表格时合并单元格

这篇具有很好参考价值的文章主要介绍了使用EasyExcel导出表格时合并单元格。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

现在需要将一个导出列表数据到Excel表格的功能进行改造,将指定列相同数据自动合并单元格。
使用EasyExcel导出表格时合并单元格
如上图所示,指定A、B两列自动合并,如图所示(6、7),(8、9),(13、14、15)要自动合并单元格。

EasyExcel 介绍

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

EasyExcel相比其他Excel解析框架(Apache poi和jxl),拥有更好的内存消耗管理算法。特别是对07版Excel的解决,EasyExcel重写了底层解析逻辑,一个3M的Excel解析只需要几M内存,但是用poi解析可能需要100M左右的内存。EasyExcel提高了读取性能,64M内存20秒读取75M的Excel,还有更快的极速模式,但是消耗的内存会更多一些。

EasyExcel支持自定义策略合并单元格,可以方便快捷填充数据到模板中,有活跃的中文社区支持,完善的测试用例可以覆盖大部分业务场景的使用。

合并单元格案例讲解

使用EasyExcel导出Excel代码示例:

	@Test
    public void testWrite() throws IOException {
        List<DemoMergeData> resultList = new ArrayList<>();
        resultList.add(DemoMergeData.builder().id(1).sub("张胜男").date("12").build());
        resultList.add(DemoMergeData.builder().id(1).sub("李四").date("224").build());
        resultList.add(DemoMergeData.builder().id(3).sub("王五").date("224").build());
        resultList.add(DemoMergeData.builder().id(4).sub("赵柳").date("224").build());
        resultList.add(DemoMergeData.builder().id(5).sub("赵柳").date("224").build());
        resultList.add(DemoMergeData.builder().id(5).sub("赵柳").date("224").build());
        resultList.add(DemoMergeData.builder().id(8).sub("赵柳").date("224").build());
        resultList.add(DemoMergeData.builder().id(8).sub("赵柳").date("224").build());
        resultList.add(DemoMergeData.builder().id(9).sub("陈琪").date("224").build());
        resultList.add(DemoMergeData.builder().id(10).sub("小白").date("241").build());
        resultList.add(DemoMergeData.builder().id(11).sub("小黑").date("241").build());
        resultList.add(DemoMergeData.builder().id(12).sub("小黑").date("241").build());
        resultList.add(DemoMergeData.builder().id(12).sub("小黑").date("241").build());
        resultList.add(DemoMergeData.builder().id(12).sub("小黑").date("241").build());
        resultList.add(DemoMergeData.builder().id(13).sub("小黑").date("241").build());
        //  设置文件名称
        String fileName = "C:\\Users\\Administrator\\Downloads\\test\\t1.xlsx";
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
        }

        //  sheet名称
        EasyExcel.write(fileName, DemoMergeData.class)
                .autoCloseStream(Boolean.TRUE)
                .sheet("测试导出").doWrite(resultList);
    }

导出表格样式:
使用EasyExcel导出表格时合并单元格

自定义策略一:上下行数据相同合并单元格

自定义策略一代码示例:

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


    @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 columnIndex : mergeColumnIndex) {
                if (curColIndex == columnIndex) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }



    /**
     * 当前单元格向上合并
     *
     * @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);
            }
        }
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }
}

测试代码示例:

@Test
    public void testWrite() throws IOException {
        int[] mergeColumnIndex = {0,1};
	    // 需要从第几行开始合并
        int mergeRowIndex = 1;
        // 数据就不初始化了
        List<DemoMergeData> resultList = new ArrayList<>();
        // 设置文件名称
        String fileName = "C:\\Users\\Administrator\\Downloads\\test\\t1.xlsx";
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
        }

        //  sheet名称
        EasyExcel.write(fileName, DemoMergeData.class)
                .autoCloseStream(Boolean.TRUE)
                .registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex,mergeColumnIndex))
                .sheet("测试导出").doWrite(resultList);
    }

导出样式:
使用EasyExcel导出表格时合并单元格

自定义策略二:指定列数据都相同才合并单元格

自定义策略二代码示例:

public class MultiColumnMergeStrategy extends AbstractMergeStrategy {

    // 合并的列编号,从0开始,指定的index或自己按字段顺序数
    private Integer startCellIndex = 0;
    private Integer endCellIndex = 0;

    // 数据集大小,用于区别结束行位置
    private Integer maxRow = 0;

    // 禁止无参声明
    private MultiColumnMergeStrategy() {
    }


    public MultiColumnMergeStrategy(Integer maxRow, Integer startCellIndex, Integer endCellIndex) {
        this.startCellIndex = startCellIndex;
        this.endCellIndex = endCellIndex;
        this.maxRow = maxRow;
    }

    // 记录上一次合并的信息
    private final List<List<String>> dataList = new ArrayList<>();

    /**
     * 每行每列都会进入,循环注意条件限制
     */
    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex) {
        int currentCellIndex = cell.getColumnIndex();
        int currentRowIndex = cell.getRowIndex();

        // 判断该列是否需要合并
        if (currentCellIndex < startCellIndex || currentCellIndex > endCellIndex) {
            return;
        }

        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        String currentCellValue = curData.toString();

        List<String> rowList;
        if (dataList.size() > currentRowIndex - 1) {
            rowList = dataList.get(currentRowIndex - 1);
        } else {
            rowList = new ArrayList<>();
            dataList.add(rowList);
        }
        rowList.add(currentCellValue);

        // 结束的位置触发下最后一次没完成的合并
        if (relativeRowIndex == (maxRow - 1) && currentCellIndex == endCellIndex) {
            System.out.println(JSONObject.toJSONString(dataList));
            List<String> tempList = null;
            Integer tempIndex = null;
            for (int i = 0; i < dataList.size(); i++) {
                if (tempList == null) {
                    tempList = dataList.get(i);
                    tempIndex = i;
                    continue;
                }
                List<String> currList = dataList.get(i);
                if (tempList.equals(currList)) {
                    if (i >= dataList.size() - 1) {
                        // 结束的位置触发下最后一次没完成的合并
                        for (int j = 0; j < tempList.size(); j++) {
                            sheet.addMergedRegionUnsafe(new CellRangeAddress(tempIndex + 1, i + 1, startCellIndex + j, startCellIndex + j));
                        }
                    }
                    continue;
                }

                // 当前行数据和上一行数据不同且上面有多行相同数据时触发合并
                if (i - tempIndex > 1) {
                    for (int j = 0; j < tempList.size(); j++) {
                        sheet.addMergedRegionUnsafe(new CellRangeAddress(tempIndex + 1, i, startCellIndex + j, startCellIndex + j));
                    }
                }


                tempIndex = i;
                tempList = currList;


            }

        }
    }
}

测试代码示例:

@Test
    public void testWrite() throws IOException {
        // 数据就不初始化了
        List<DemoMergeData> resultList = new ArrayList<>();
        // 设置文件名称
        String fileName = "C:\\Users\\Administrator\\Downloads\\test\\t1.xlsx";
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
        }

        //  sheet名称
        EasyExcel.write(fileName, DemoMergeData.class)
                .autoCloseStream(Boolean.TRUE)
                .registerWriteHandler(new MultiColumnMergeStrategy(resultList.size(),0,1))
                .sheet("测试导出").doWrite(resultList);
    }

导出样式:
使用EasyExcel导出表格时合并单元格

总结

EasyExcel功能灵活强大,可以根据自身业务场景去自定义样式,也可以使用通过模板填充功能实现导出国际化语言等复杂功能。文章来源地址https://www.toymoban.com/news/detail-489465.html

到了这里,关于使用EasyExcel导出表格时合并单元格的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端vue+elementui导出复杂(单元格合并,多级表头)表格el-table转为excel导出

    需求 :前端对el-table表格导出 插件 : npm install xlsx -S npm install file-saver --save 原理 :直接导出el-table的表格里面的数据,这样就会存在缺点,只会导出当前页面的数据,如果需要导出全部数据,可以自己重新渲染一个全部数据不可见的el-table表格,来导出就可以了 扩展 :经过

    2024年02月04日
    浏览(54)
  • 使用EasyExcel实现Excel表格的导入导出

    Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。 easyexcel重

    2024年02月12日
    浏览(32)
  • EasyExcel合并单元格(同列相同数据合并)

    合并后效果如下: 合并策略代码: 使用: 主体代码来自网络,按自己业务修改,支持多列相同数据合并。

    2024年02月12日
    浏览(29)
  • EasyExcel合并单元格

    EasyExcel默认情况下写Excel是一行一行的,单元格不会自动合并,现在需求是合并这几列中相同的数据 开始自己也不想做过多改动代码,经过阅读EasyExce官方文档和大量博客之后总结了一个通用的工具类,重写接口中的merge方法,然后自己在写入Excel的时候指定实体类属性以及对

    2024年02月15日
    浏览(26)
  • easyexcel内容追加与单元格合并

        这里的需求是,如果表格不存在,则新建表格,并填入数据,如果表格存在,那么就追加内容,并且支持单元格合并。     内容追加,需要分两种方式插入,第一种就是没有表格,需要生成表头,并且插入内容,第二种就是已经有了表格,这个表格作为模板并,不用设置

    2023年04月22日
    浏览(25)
  • Java 导出Excel表格生成下拉框-EasyExcel

     

    2024年02月11日
    浏览(41)
  • 关于Unity使用Aspose.Words创建表格单元格垂直合并不生效情况说明

    👉一、前言 最近在使用Aspose.Words.dll实现创建表格功能时,遇到了一个让我费解了好几天的问题——单元格垂直合并失效。我都快要怀疑人生了都,关键是它水平合并没问题,而且创建别的表格垂直合并也没问题;况且经过我反复测试,代码逻辑也是没有问题的,你说这气不

    2023年04月11日
    浏览(43)
  • easyexcel根据模板导出Excel文件,表格自动填充问题

    同事在做easyexcel导出Excel,根据模板导出的时候,发现导出的表格,总会覆盖落款的内容。 这就很尴尬了,表格居然不能自动填充,直接怒喷工具,哈哈。 然后一起看了一下这个问题。 我找了自己的系统中关于表格导出的页面,导出了一下,发现可以正常扩充。 于是排查问

    2024年02月06日
    浏览(40)
  • easyExcel 模版导出 中间数据纵向延伸,并且对指定列进行合并

    备注 : 模板注意 用{} 来表示你要用的变量 如果本来就有\\\"{\\\",\\\"}\\\" 特殊字符 用\\\"{\\\",\\\"}\\\"代替 // {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list 合并策略代码 : 导出部分 : 官方文档 :  填充Excel | Easy Excel 合并代码参考 :  https://www.cnblogs.com/monianxd/p/16359369.html

    2024年04月11日
    浏览(24)
  • SpringBoot整合Easyexcel实现将数据导出为Excel表格的功能

    本文主要介绍基于SpringBoot +MyBatis-Plus+Easyexcel+Vue实现缺陷跟踪系统中导出缺陷数据的功能,实现效果如下图: EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。 本文

    2024年02月14日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包