easyExcel合并单元格策略

Ruoyi框架使用easyExcel实现单元格合并 / 你也可以在创建行的时候进行拦截,也可以在创建单元格的时候拦截,不同功能实现不同的接口 public class TableHeadHandler implements SheetWriteHandler {// 基础的excel操作,可以在此处添加表头的样式 Workbook workbook = writeWorkbookHolder . getWorkbook();row0 . createCell(0) . setCellValue("第一行"); 阅读详情

合并行:

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 lombok.Data;
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;

/**
 * 合并单元格
 */
@Data
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 integer, Integer integer1, Boolean aBoolean) {

    }

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

    }


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

    }

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

合并列:

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.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 自定义合并某行某列
 */
public class ExcelFillCellMergePrevCol implements CellWriteHandler {

    /**
     * 合并字段的下标
     */
    private int[] mergeColumnIndex;

    //合并哪一行
    private int row;

    //合并多少列
    private  int num;

    public ExcelFillCellMergePrevCol(int[] mergeColumnIndex, int row, int num) {
        this.mergeColumnIndex = mergeColumnIndex;
        this.row = row;
        this.num = num;
    }

    @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) {

    }

    @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 == row) {

            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    // 合并最后一行 ,列
                    mergeWithPrevCol(writeSheetHolder, cell, curRowIndex, curColIndex);
                }
            }

        }
    }
    private void mergeWithPrevCol(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        Sheet sheet = writeSheetHolder.getSheet();
        CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex, curRowIndex, curColIndex, curColIndex + num);
        sheet.addMergedRegion(cellRangeAddress);
    }

}

easyexcel复杂模板导出(合并行列,列统计汇总) easyexcel复杂模板导出 阅读详情

相关推荐

实战演练,如何用Easyexcel合并单元格,设置字体、边框样式,并在尾行加入备注

,实现效果如下:1、多级表头合并2、表头底纹+表格边框3、合并相同数据单元格4、尾行加入备注。

Su7148的博客 1万+

easyExcel自动合并单元格

来源EasyExcel(根据条件动态合并单元格的重复数据) package com.ustcinfo.fn.comp.complain.util; 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

weixin_43891731的博客 4514

EasyExcel导出自定义合并单元格的策略

需求概述 项目中需要导出的Excel如下所示: 目前的列表是查询出所有行的数据,前端再去按主键进行合并的。所以,导出时只要Excel下一行的主键相同,就合并框红的区域。 目前网上找到的EasyExcel自定义合并单元格都是ExcelFillCellMergeStrategy,这个工具类只要下一行的cell和上一行的cell内容相同就会合并,不符合目前的需求。本例也是在此基础上进行逻辑修改。 参考链接。 测试代码 引入相关依赖: <dependencies> <dependency

我可能在扯淡 6548

EasyExcel合并单元格,通过注解方式实现自定义合并策略

今天博主探讨如何实现EasyExcel自定义实现单元格合并策略,考虑需要抽象代码、适用于更多的业务场景,提供了两个工具类,参考过很多博主的方案,并整合优化了一下。

q1468051413的博客 6594

一篇讲透:豆包、元宝、DeepSeek、Kimi、WorkBuddy,职场里到底怎么分工

这篇文章深入分析了当前主流AI工具(WorkBuddy、豆包、腾讯元宝、DeepSeek、Kimi)的特点和使用场景,帮助读者根据不同工作需求选择合适的AI助手。核心观点包括: AI工具各有所长:豆包适合快速创作初稿,元宝擅长信息检索整理,DeepSeek强于逻辑分析,Kimi专精文本处理,WorkBuddy则更适合任务推进和成果交付。 使用前需明确需求:是要创意发散、信息整理,还是任务执行?不同阶段应选用不同工具组合。 提供了6个具体职场场景的解决方案,包括文章创作、课程设计、会议纪要等,并给出详细的操作

weixin_39284145的博客 1万+

吉林大学2016级唐班c语言期末考试B卷

` #include<stdio.h> #include<stdlib.h> //双指针法,每次从a,b中选一个最大的数,从后向前一次放在数组a中 int merge(int *a,int m,int *b,int n){ int i=m-1,j=n-1,k=m+n-1; while(i>=0&&j>=0){ if(a[i]>b[j])a[...

weixin_42339173的博客 1195

EasyExcel导出动态合并单元格策略

EasyExcel导出动态合并单元格策略 1.导入依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency> 2.合并单元格工具类 import com.alibaba.

weixin_50067580的博客 6674

Cesium体渲染实战:从医学CT到气象数据的3D可视化全攻略

本文详细介绍了如何利用Cesium体渲染技术实现医学CT和气象数据的3D可视化。从数据预处理到交互式渲染,涵盖了DICOM和NetCDF格式的处理技巧,以及性能优化的实战策略,帮助开发者高效处理复杂的三维数据集。

weixin_28717431的博客 420

EasyExcel进阶:从零封装动态合并单元格策略

本文详细介绍了如何使用EasyExcel实现动态合并单元格策略,解决复杂报表导出中的重复数据问题。通过封装通用合并策略,支持多级合并规则和动态配置,大幅提升Excel导出的灵活性和效率。特别适用于电商订单、财务报表等需要多维度合并的场景。

weixin_29250573的博客 343

DRM遇到的实际问题及领悟(3)

DRM遇到的实际问题及领悟(3)

phmatthaus的专栏 636

零基础 ABAP 学习教程系列文章的目录

曾几何时,ABAP 就是 SAP 的代名词。ABAP 这门编程语言造就了 SAP 名噪一时的 R/3 产品,同时也是如今 SAP 旗舰级产品,SAP S/4HANA 底层的实现语言。 ABAP 不仅代表着 SAP 这家公司在企业级管理软件市场辉煌的过去,ABAP 自身也在不断地进化着。SAP 不仅在本地部署(On-Premise)领域继续保持着自己绝对的统治地位,而且在云应用领域(Software-as-a-Service, 简称 SaaS), 也推出了自己的解决方案,比如 SAP S/4HANA Clo

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2万+

easyExcel实现动态表头的数据导出,合并单元格,列宽策略

easyExcel导出(非注解) 思路:先拿到表头数据,再去封装表数据。 一.动态表头 List<List<String>> headTitles = Lists.newArrayList();//表头数据    说明:外层list表示的表头接口,内层list表示的是表头每一列的数据,而内层list的每一位元素,代表这该行的数据,位序为0的是第一行数据,位序为1的是第二行数据,依次往下。 下面展示一些 代码片段。 List<List<St

qq_37293674的博客 8623

ORB-SLAM3算法2之EuRoc开源数据集运行ORB-SLAM3生成轨迹并用evo工具评估轨迹

ORB-SLAM3算法1 已成功编译安装ORB-SLAM3到本地,本篇目的是用EuRoc开源数据来运行ORB-SLAM3,并生成轨迹,最后用evo评估工具来评估ORB-SLAM3生成的轨迹和真值轨迹。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 3762

easyexcel 动态合并单元格

easyexcel 动态合并单元格 目前操作excel文档的底层都是用poi来进行的,在早期工作开发过程中,是基于poi,然后对每一个数据单元格进行操作代码编写,后面有一些比较好的开源项目,像easyexcel、easypoi、hutool等,由于身处电商之都,就选择了阿里开源的easyexcel来做二次开发,源码相对来说并没有那么枯燥,有兴趣可以细细研读一番,对抽象能力,编码规范等一些重要的编程功底都有所帮助的。 单元格的动态合并 在实际项目开发过程中,不可避免地会有生成excel文档的需求,同时也不可避

jianghuafeng0的博客 2万+

【AirPlay】苹果认证MFI学习

配件认证是一个过程,通过这个过程,可验证其配件符合MFi技术规范,并通过苹果指定的任何认证测试。MFi门户中的产品计划 "认证 "页面将指导你完成特定配件所需的认证步骤,并指出何时完成所有要求。在完成所有MFi认证要求之前,你不得制造、分发或销售任何配件。在开始MFi认证过程之前,你必须测试你的配件,以确保它符合最新的MFi技术规范,通过产品计划 "测试计划 "上的所有适用测试,并与它将声称具有兼容性的每个苹果设备兼容。

天天的博客 2276

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

EasyExcel导出自定义合并单元格策略

EasyExcel导出自定义合并单元格策略 调用方式 //引用自定义合并单元格 ExcelWriter excelWriter = EasyExcel.write(outputStream) .withTemplate(getTemplateInputStream("excel_templates/xxx.xlsx")) .regi...

weixin_43693334的博客 8512

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

easyexcel导出&自定义策略合并单元格

easyExcel导出&excel单元格合并策略

weixin_44673447的博客 3939

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

EasyExcel导出自定义合并单元格

EasyExcel导出自定义合并单元格

weixin_45817985的博客 2221

Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略)

Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略) 适用于多张表(只查单表数据就用创建对象那种方法) Controller @RequestMapping(value = "/downloadPlanList", method = RequestMethod.GET) @ApiOperation(value = "下载") public void exportExcel(HttpServletResponse response) throws IOException {

Nicole_0488的博客 2299

EasyExcel动态合并单元格实战:基于RowWriteHandler与CellWriteHandler的双策略实现

本文深入探讨了使用EasyExcel实现动态合并单元格的两种核心策略。基于RowWriteHandler的注解驱动方案,通过在实体类字段上标注@CustomMerge注解,实现声明式合并,适合规则固定的场景。基于CellWriteHandler的数据驱动方案,通过预先分组数据并传入处理器,实现更灵活的编程式合并,适合动态规则。文章对比了两种方案的优劣,并提供了详细的实战代码与避坑指南。

weixin_29255731的博客 640

EasyExcel合并单元格策略样例

自定义EasyExcel单元格合并策略,动态合并单元格。

ohCCa的博客 2628

EasyExcel 模板导出数据 + 自定义策略(合并单元格)

Excel导出功能,主要特点包括:1)通过SQL联查主表(exception_case_summary)和明细表(exception_case_sorting_item)数据;2)使用EasyExcel框架实现导出;3)采用自定义合并策略(CustomRowMergeStrategy)合并主表数据单元格;4)支持模板导出模式;5)包含序号生成和居中样式处理功能。其中关键点包括:通过@CustomRowMerge注解标记需要合并的字段

wys0127的博客 841

EasyExcel左右合并单元格策略

【代码】EasyExcel左右合并单元格策略。

Chuk 638

效率爆表!EasyExcel合并单元格这样实现才是yyds

来源:juejin.cn/post/7322156759443095561???? 欢迎加入小哈的星球,你将获得:专属的项目实战 /1v1 提问/Java 学习路线 /学习打卡/每月赠书/社群讨论新项目:《从零手撸:仿小红书(微服务架构)》正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,点击查看项目介绍;《...

犬小哈 4371
上一篇: java-easyExcel导出-合并单元格
下一篇: Nginx安装
UID_UUID
博客等级 码龄5年 352粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值