easyExcel單元格合并

環境

java 1.8
easyexcel 3.1.1

實現方式

自定義WriteHandler,實現AbstractMergeStrategy抽象類,實現merge 方法完成自定義的合并操作。
本測試代碼,實現了eques方法,用于判斷是否需要合并

核心代碼

實現AbstractMergeStrategy類的merge方法進行單元格合并
需要注意的是,單元格需要一次合并完成,合并了以后不能再次合并。所以判斷當前對象與前一個對象不相等時,才會對之前的對象進行合并操作


/*** 合并策略* @author dzh* @since 2025/4/17*/
public class MyMergeStrategy extends AbstractMergeStrategy {// 根據數據的下標判斷是否需要合并行private final Function<Integer, Boolean> eqBefore;// 根據列序號判斷該列列是否需要行合并,從0開始private final Function<Integer, Boolean> columnNeedMerge;public MyMergeStrategy(Function<Integer, Boolean> eqBefore, Function<Integer, Boolean> columnNeedMerge) {this.eqBefore = eqBefore;this.columnNeedMerge = columnNeedMerge;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {if (relativeRowIndex == null || relativeRowIndex <= 1) {return;}if (!columnNeedMerge.apply(cell.getColumnIndex())) {return;}if (!eqBefore.apply(relativeRowIndex) && eqBefore.apply(relativeRowIndex - 1)) {int endRow = cell.getRowIndex() - 1;int firstRow = getFirstRow(endRow, relativeRowIndex - 1);CellRangeAddress rangeAddress = new CellRangeAddress(firstRow, endRow, cell.getColumnIndex(), cell.getColumnIndex());sheet.addMergedRegion(rangeAddress);}}private int getFirstRow(int rowIndex, int dataIndex) {if (dataIndex == 0) {return rowIndex;}if (this.eqBefore.apply(dataIndex)) {return getFirstRow(rowIndex - 1, dataIndex - 1);}return rowIndex;}
}

測試代碼

測試代碼中定義的對象覆蓋了eques方法,通過該方法判斷多個對象如果相等則進行合并操作


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.google.common.collect.Sets;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;/*** @author dzh* @since 2023-06-28*/
public class ExportExcelTest {@Testpublic void template() throws IOException {InputStream in = new ClassPathResource("template.xlsx").getInputStream();File out = new File("c://temp/report.xlsx");List<Student> data = data();Function<Integer, Boolean> comp = (i) -> data.get(i - 1).equals(data.get(i));Function<Integer, Boolean> colMerge = (i) -> i < 2;MyMergeStrategy writeHandler = new MyMergeStrategy(comp, colMerge);ExcelWriterBuilder builder = EasyExcel.write(out).withTemplate(in).registerWriteHandler(writeHandler);try (ExcelWriter excelWriter = builder.build()) {WriteSheet writeSheet = EasyExcel.writerSheet().build();FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();excelWriter.fill(data, fillConfig, writeSheet);Map<String, Object> map = new HashMap<>();map.put("tableName", "成績報表");map.put("total", 886655);excelWriter.fill(map, writeSheet);} finally {in.close();}}@NotNullprivate static List<Student> data() {List<Student> list = new ArrayList<Student>() {{add(new Student("三年級一班", "lucy", "語文", 99));add(new Student("三年級一班", "lucy", "數學", 98));add(new Student("三年級一班", "lucy", "英語", 100));add(new Student("三年級一班", "jack", "語文", 87));add(new Student("三年級二班", "lucy", "語文", 78));add(new Student("三年級二班", "lily", "語文", 97));add(new Student("三年級二班", "lily", "數學", 79));add(new Student("三年級三班", "andy", "語文", 99));}};for (int i = 0; i < list.size(); i++) {Student cur = list.get(i);if (i == 0) {cur.setIndex(1);} else {Student pre = list.get(i - 1);if (pre.equals(cur)) {cur.setIndex(pre.getIndex());} else {cur.setIndex(pre.getIndex() + 1);}}}return list;}@Datastatic class Student {private Integer index;private String clas;private String name;private String subject;private Integer score;public Student(String clas, String name, String subject, Integer score) {this.clas = clas;this.name = name;this.subject = subject;this.score = score;}public boolean equals(Object obj) {Function<Student, Object> con = s -> String.join("-", s.getName(), s.getClas());Object a = con.apply(this);Object b = con.apply((Student) obj);System.out.println(a + "\t" + b);return a.equals(b);}}
}

模板

模板

導出效果

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901970.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901970.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901970.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jenkins 簡易使用記錄

一、Jenkins 核心功能與適用場景 核心功能&#xff1a; 持續集成&#xff08;CI&#xff09;&#xff1a;自動構建代碼、運行單元測試。持續交付&#xff08;CD&#xff09;&#xff1a;自動化部署到測試/生產環境。任務調度&#xff1a;定時執行任務&#xff08;如備份、清理&…

【HFP】藍牙HFP協議音頻連接核心技術深度解析

目錄 一、音頻連接建立的總體要求 1.1 發起主體與時機 1.2 前提條件 1.3 同步連接的建立 1.4 通知機制 二、不同主體發起的音頻連接建立流程 2.1 連接建立觸發矩陣 2.2 AG 發起的音頻連接建立 2.3 HF 發起的音頻連接建立 三、編解碼器連接建立流程 3.1 發起條件 3.…

【卡洛詩】成為平價市場中的標桿西餐廳

近年來&#xff0c;中國餐飲市場在消費分級趨勢下面臨結構性調整&#xff0c;消費者對“質價比”的追求催生了新賽道的崛起。在這一背景下&#xff0c;卡洛詩西餐憑借精準的定位與系統性創新&#xff0c;以“中式西餐”為核心理念&#xff0c;成功打破西餐高價壁壘&#xff0c;…

嵌入式設備網絡的動態ID分配機制實現

文章目錄 前言一、系統設計要點二、核心數據結構2.1 設備唯一標識(DeviceUID)2.2 節點信息(Node)2.3 節點管理器(NodeManager) 三、核心算法實現3.1 初始化與清理3.1.1 初始化節點管理器3.1.2 清理節點管理器 3.2 動態ID分配策略3.2.1 查找最小可用ID3.2.2 ID使用檢查 3.3 心跳…

WebSocket 雙向通信技術詳解

引言 在現代Web應用中&#xff0c;實時通信已經成為不可或缺的一部分。想象一下聊天應用、在線游戲、股票交易平臺或協作工具&#xff0c;這些應用都需要服務器能夠即時將更新推送給客戶端&#xff0c;而不僅僅是等待客戶端請求。WebSocket技術應運而生&#xff0c;它提供了一…

kafka菜鳥教程

一、kafka原理 1、kafka是一個高性能的消息隊列系統&#xff0c;能夠處理大規模的數據流&#xff0c;并提供低延遲的數據傳輸&#xff0c;它能夠以每秒數十萬條消息的速度進行讀寫操作。 二、kafka優點 1、服務解耦 &#xff08;1&#xff09;提高系統的可維護性? 通過服務…

SQLMap工具使用

一、SQLMap介紹 SQLMap 是一款強大的開源自動化 SQL 注入工具&#xff0c;用于檢測和利用 Web 應用程序中的 SQL 注入漏洞。其工作原理是SQLMap 通過向目標 URL 發送帶有特殊構造的 SQL 語句的請求&#xff0c;觀察目標應用程序的響應&#xff0c;來判斷是否存在 SQL 注入漏洞…

virtualbox安裝xp系統卡頓的解決

安裝virtualbox的增強功能即可。 先去下載 — Oracle VirtualBox下載 VirtualBox Guest Additions iso鏡像 然后在這里導入iso鏡像 再按照這幾步操作 virtualbox按鍵 強制關閉xp-cuckoo的虛擬機 VBoxManage controlvm "xp-cuckoo" poweroff

觀察者 ? 事件總線:一路走來的碎碎念

寫給未來的自己:每次手敲事件模型都要 Google,干脆把思路和踩坑一次性記清楚。文章很長,都是嘮叨,目的是讓自己看兩眼就能把設計理由找回來。 目錄 為什么我要折騰事件模型?V0 ─ 單一事件的觀察者模式V1 ─ 多事件同步總線(類型拆分)V2 ─ 訂閱者優先級(鏈式調用可控)…

windwos腳本 | 基于scrcpy,只投聲音、只投畫面

安裝scrcpy&#xff0c;scrcpy自帶adb 寫腳本命名為 .bat 結尾 注意這里的set "PATHD:\tools\scrcpy-win64-v3.2;%PATH%" 替換成scrcpy的安裝目錄 echo off :: 設置UTF-8編碼 chcp 65001 > nul :: 設置標題 title 手機投屏工具:: 添加 scrcpy 路徑到 PATH set &q…

Android device PCO (protocol configuration options) intro

術語 英文縮寫英文全稱中文PCOprotocol configuration options協議配置選項RILradio interface layer 無線電接口層PCO介紹 PCO(Protocol Configuration Options) 是 3GPP 標準協議(TS 24.008)中定義的核心概念,用于在 LTE/5G 網絡建立 PDN 連接時傳遞動態配置參數(如 D…

Spring Boot配置文件優先級全解析:如何優雅覆蓋默認配置?

&#x1f4da; 一、為什么需要了解配置文件優先級&#xff1f; 想象一下&#xff0c;你正在玩一個游戲&#x1f3ae;&#xff0c;游戲里有默認設置&#xff0c;但你可以通過不同的方式修改這些設置&#xff1a; 游戲內置的默認設置&#xff08;就像Spring Boot的默認配置&…

汽車行駛工況特征參數:從“速度曲線”到“駕駛DNA”的硬核解碼

作為新能源汽車行業的從業者&#xff0c;你是否曾困惑于這些問題&#xff1a; 為什么同一款電動車&#xff0c;不同用戶的實際續航差異高達30%&#xff1f;如何精準量化駕駛行為對電池壽命的影響&#xff1f;車企標定的“NEDC續航”與真實路況差距的根源是什么&#xff1f; 這…

HTTP 2.0 協議特性詳解

1. 使用二進制協議&#xff0c;簡化傳輸的復雜性&#xff0c;提高了效率 2. 支持一個 TCP 鏈接發起多請求&#xff0c;移除 pipeline HTTP/2 移除了 HTTP/1.1中的管道化&#xff08;pipeline&#xff09;機制&#xff0c;轉而采用多路復用&#xff08;Multiplexing&#xff0…

完美解決瀏覽器不能復制的問題(比如賽氪網的中題庫練習題)

僅供復制題庫題目進行打印學習使用&#xff01; 最近想把賽氪網題庫中的題目打印出來做練習&#xff0c;發現題庫中的題目不能復制&#xff0c;不能在試卷上勾畫標記太難受了&#xff0c;而且不能留作材料以后復習&#xff0c;故出此策。 而且CtrlP打印出的pdf會缺少題目。(我…

std::set (C++)

std::set 1. 概述定義特點 2. 內部實現3. 性能特征4. 常用 API5. 使用示例6. 自定義比較器7. 注意事項與優化8. 使用建議 1. 概述 定義 template<class Key,class Compare std::less<Key>,class Allocator std::allocator<Key> > class std::set;特點 有…

SSM省市區三級聯動和三表聯查附帶數據庫

SSM省市區三級聯動和三表聯查 ------附帶數據庫碼云地址&#xff1a;https://gitee.com/Mr_ZKC/NO1 數據庫在項目中

曲棍球·棒球1號位

中國女子曲棍球隊曾涌現過馬弋博、李紅俠等優秀選手&#xff0c;但“李紅”這一名字可能為信息誤差。以下為您系統介紹曲棍球&#xff0c;并結合棒球進行對比分析&#xff1a; 曲棍球&#xff08;Hockey&#xff09;核心特點 運動形式 分為草地曲棍球&#xff08;夏季奧運會項…

12芯束裝光纖不同包層線顏色之間的排列順序

為什么光纖線必須按照以下顏色順序進行排序&#xff1f;這其實是為了防止光污染的問題&#xff0c;不同顏色在傳遞光時從包層表皮漏光傳感到梳妝的其它纖芯上&#xff0c;會有光污染的問題&#xff0c;而為了減少并防止光污染的現象&#xff0c;所以在光通信之中&#xff0c;需…

c++程序的打包編譯cmake+make

c打包編譯 1 在不用系統中打包介紹1.1 linux中打包c程序的2種方式1.2 windows中打包c程序1.3 cmakeNinja和cmakemake的兩種方式對比1.3.1 Ninja是什么&#xff08;可以認為是make工具的一個替代產品&#xff09;1.3.2 cmakeNinja可以用于linux和windows系統中&#xff0c;編譯效…