Java整合EasyExcel实战——3(上下列相同合并单元格策略)

参考:https://juejin.cn/post/7322156759443095561?searchId=202405262043517631094B7CCB463FDA06icon-default.png?t=N7T8https://juejin.cn/post/7322156759443095561?searchId=202405262043517631094B7CCB463FDA06

准备条件

依赖

        <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version></dependency>

工具类

package co.yixiang.exam.listener;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.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 ExcelFillCellMergeStrategy implements CellWriteHandler {private int[] mergeColumnIndex;private int mergeRowIndex;public ExcelFillCellMergeStrategy() {}public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic 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;}}}}/*** 当前单元格向上合并** @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();// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行//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);}}}}

ServiceImpl层应用

sql 数据的重复数据,合并单元格

SELECTeq.id,eq.question_title,eo.options_content,eq.options_correct,eq.question_answer,eq.question_score,eq.question_subject,eq.question_title_zi,eq.question_type
FROMex_question eq
LEFT JOINex_options eoon eq.id = eo.question_id where eq.is_del = 0 and eo.is_del = 0;
    @Overridepublic R exportExQuestionOptions(HttpServletResponse response) throws IOException {// 定义导出的Excel文件名String fileName = "test.xlsx";// 设置响应的内容类型为二进制流,这是文件下载的标准设置response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 设置响应头的Content-Disposition,使用"attachment"指示浏览器这是一个需要下载的文件response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()));// 查询需要导出的数据 (包含复杂数据)List<ExExcelQuestionOptionsDto> questionsOptionsAll = exQuestionMapper.getQuestionsOptionsAll();// 假设我们要合并第1行和第2列到第4列的数据(索引从0开始)int mergeRowIndex = 0; // 行索引 int[] mergeColumnIndex = new int[]{0,1,2,3,4,5,6}; // 列索引数组 要合并的列ExcelFillCellMergeStrategy excelFillCellMergeStrategy = new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumnIndex);EasyExcel.write(response.getOutputStream(), ExExcelQuestionOptionsDto.class).registerWriteHandler(excelFillCellMergeStrategy).sheet("测试").doWrite(questionsOptionsAll);return R.success();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/339924.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud学习笔记(Nacos):Nacos持久化(未完成)

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 1、Overview2、单机使用MySQL 1、Overview 我们关闭单机下的Nacos后&#xff0c;再重新启动会发现之前配置的内容没有被删除。这时因为Nacos有内嵌的数据库derby&#xff0c;会自己持久化。 但是在集群的情况下…

大模型应用框架-LangChain

LangChain的介绍和入门 &#x1f4a5; 什么是LangChain LangChain由 Harrison Chase 创建于2022年10月&#xff0c;它是围绕LLMs&#xff08;大语言模型&#xff09;建立的一个框架&#xff0c;LLMs使用机器学习算法和海量数据来分析和理解自然语言&#xff0c;GPT3.5、GPT4是…

如何卸载ollama

文章目录 一 概述二 卸载2.1 Windows平台卸载 ollama2.2 Linux 平台卸载 ollama2.3 Docker 平台卸载 ollama 参考链接 一 概述 本文档主要讲述 ollama 如何卸载&#xff0c;适用范围包括 Windows Linux 以及 Docker 等平台的安装方式。 二 卸载 2.1 Windows平台卸载 ollama …

【SAP HANA 33】前端参数多选情况下HANA如何使用in来匹配?

场面描述: 在操作界面经常会出现某个文本框需要多选的情况,然后后台需要根据多选的值进行匹配搜索。 一般处理的情况是: 1、在Java后端动态生成SQL 2、不改变动态SQL的情况,直接当做一个正常的参数进行传递 本次方案是第二个,直接当做一个正常的字符串参数进行传递即…

36【Aseprite 作图】蒸笼盖——拆解

1 蒸笼盖框架 里圈和外圈的形状都是一样的 扶手处&#xff0c;2 1 2 2 2&#xff08;最好都是2&#xff0c;拐角处用1&#xff09; 2 上色 中间的波浪&#xff0c;是2 2 2 上&#xff08;再 2 2 2 下&#xff09; 下方阴影&#xff0c;左边的阴影&#xff0c;右边的阴影颜色…

音视频开发—FFmpeg播放YUV文件,YUV转换为JPEG操作

文章目录 1.使用命令行播放YUV数据1.1命令解析1.2参数说明 2.使用C语言实现将YUV数据转为JPEG图片格式2.1需求分析2.2读取YUV源文件2.3将YUV数据封装为AVFrame2.4将NV12 转换为YUV420平面格式2.5初始化MJPEG编码器2.6将YUV420P编码为JPEG2.7将编码数据写入图片文件2.8完整代码 …

Python 图书馆管理系统 有GUI界面 【含Python源码 MX_031期】

使用python3&#xff0c;PyQt5&#xff0c;Sqlite3数据库搭建 数据库版本为MySQL&#xff1a;Python 图书馆管理系统&#xff08;MySQL数据库&#xff09; 有GUI界面 【含Python源码 MX_032期】-CSDN博客 主要功能&#xff1a; 用户注册、登录、修改密码、用户管理存储图书信…

详解Java反序列化漏洞

001&#xff1a;序列化基本概念 序列化&#xff1a;将对象写入IO流中反序列化&#xff1a;从IO流中恢复对象意义&#xff1a;序列化机制允许将实现序列化的Java对象转换位字节序列&#xff0c;这些字节序列可以保存在磁盘上&#xff0c;或通过网络传输&#xff0c;以达到以后恢…

C++多线程同步

C使用多线程必须包含头文件 #include <thread> 来实现 当多个线程同事访问一个对象的时候&#xff0c;会产生数据竞争现象。 这个时候&#xff0c;就可以加锁&#xff0c;同步资源&#xff0c;解决数据竞争。 最简单就是互斥锁mutex 上代码&#xff0c;计算一个数自增到1…

python常见数据分析函数

apply DataFrame.apply(func, axis0, broadcastFalse, rawFalse, reduceNone, args(), **kwds) 第一个参数是函数 可以在Series或DataFrame上执行一个函数 支持对行、列或单个值进行处理 import numpy as np import pandas as pdf lambda x: x.max()-x.min()df pd.DataFrame(…

韩顺平0基础学java——第15天

p303-326 重写override 和重载做个对比 注&#xff1a;但子类可以扩大范围&#xff0c;比如父类是protected&#xff0c;子类可以是public 多态 方法或对象具有多种形态&#xff0c;是面向对象的第三大特征&#xff0c;多态是建立在封装和继承基础之上的。 多态的具体体现…

【JavaEE】Servlet

文章目录 一、Servlet 是什么二、如何创建Servlet程序1、创建项目2、引入依赖3、创建目录4、编写代码5、打包程序6、部署程序7、验证程序 一、Servlet 是什么 二、如何创建Servlet程序 1、创建项目 2、引入依赖 Maven 项目创建完后&#xff0c;会自动生成一个 pom.xml 的文…

Spi Pwm Tim 对比分析

spi SPI时序图 (spi是主从机 所以主机需要从机数据 需要主极先喊从机 把从机喊答应了 才能开始读从机的数据&#xff09; cpol时钟极性 和cpha时钟相位分析 1.cpha为高&#xff0c;cpol为高&#xff0c;则偶数上升沿有效 2.cpha为高&#xff0c;cpol为低&#xff0c;则偶数…

山东军博会—2024年智能装备和通信技术展:见证类脑视觉芯片如何重塑未来

随着人工智能技术的飞速发展&#xff0c;类脑计算成为了科研领域的一个热点。最近&#xff0c;我国科学家成功研发出世界首款类脑互补视觉芯片&#xff0c;这一重大突破不仅标志着我国在人工智能硬件领域迈出了重要一步&#xff0c;也为未来的智能设备带来了无限可能。本文将从…

【轻触按键】终篇 -- 纯硬 VS 复合

1、选型 2、开关机电路–填坑1 3、开关机电路–填坑1.a 4、开关机电路–复合芯片解决方案 填坑2 总结 上述几篇&#xff0c;基本上都是比较靠谱的硬件方案&#xff1b; ①所有开关均关闭&#xff1b; X1灯亮&#xff1b;P-MOS 管Q1关断&#xff1b; 特别注意&#xff0c;…

代码界的奥斯卡:SpringBoot测试的艺术与科学

探索SpringBoot测试的神秘世界&#xff0c;揭秘如何成为代码质量的守护神&#xff01;从基础环境搭建到高级集成测试&#xff0c;本系列教程带你一步步构建坚不可摧的测试防线。深入JUnit 5的强大功能&#xff0c;学习如何用MockMvc和Testcontainers打造逼真的测试场景。准备好…

小型企业网络组网与配置仿真实验

实验要求如下: 我这里以学号46为例 一、IP 地址规划表 &#xff08;一&#xff09;主类网络 &#xff08;二&#xff09;子网划分 需要自己计算有效ip范围 在C类主网络192.168.46.0/24中&#xff0c;我们需要先了解这个网络的子网掩码为255.255.255.0&#xff0c;其二进制…

MOS管开关电路简单笔记

没错&#xff0c;这一篇还是备忘录&#xff0c;复杂的东西一律不讨论。主要讨论增强型的PMOS与NMOS。 PMOS 首先上场的是PMOS,它的导通条件&#xff1a;Vg-Vs<0且|Vg-Vs|>Vgsth&#xff0c;PMOS的电流流向是S->D,D端接负载&#xff0c;S端接受控电源。MOS管一般无法…

LeetCode:环形链表II

文章收录于LeetCode专栏 LeetCode地址 环形链表II 题目 给定一个链表&#xff0c;返回链表开始入环的第一个节点。如果链表无环&#xff0c;则返回null。   为了表示给定链表中的环&#xff0c;我们使用整数pos来表示链表尾连接到链表中的位置&#xff08;索引从0开始&#…

三十五、openlayers官网示例Dynamic Data——在地图上加载动态数据形成动画效果

官网demo地址&#xff1a; Dynamic Data 初始化地图 const tileLayer new TileLayer({source: new OSM(),});const map new Map({layers: [tileLayer],target: "map",view: new View({center: [0, 0],zoom: 2,}),}); 创建了三个样式 const imageStyle new Style(…