1、引入easyexcel依赖

!-- 阿里开源easyexcel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.0-beta2</version></dependency>

2、ExcelMergeUtil工具类

package com.sdy.resdir.biz.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.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.math.BigDecimal;
import java.util.List;import static org.apache.poi.ss.usermodel.CellType.NUMERIC;public class ExcelMergeUtil implements CellWriteHandler {private int[] mergeColumnIndex;private int mergeRowIndex;public ExcelMergeUtil() {}public ExcelMergeUtil(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 relativeRowIndex, Boolean isHead) {}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {//当前行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();// 将当前单元格数据与上一个单元格数据比较Boolean dataBool = preData.equals(curData);//此处需要注意:因为我是按照工程名称确定是否需要合并的,所以获取每一行第二列数据和上一行第一列数据进行比较,如果相等合并,getCell里面的值,是工程名称所在列的下标BigDecimal d1 = new BigDecimal(cell.getRow().getCell(0).getNumericCellValue());BigDecimal d2 = new BigDecimal(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getNumericCellValue());Boolean bool = d1.compareTo(d2) == 0 ? true:false;// 原始的// Boolean bool =  cell.getRow().getCell(1).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(1).getStringCellValue());if (dataBool && bool) {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);}}}
}

3、导出的excel标题

package com.sdy.resdir.biz.vo;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.metadata.BaseRowModel;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.sdy.common.utils.DateUtil;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;import java.util.Date;/*** Excel模板文件类** @author hyh*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class ResItemExcelVo extends BaseRowModel {/*** 序号*/@ExcelProperty(value = {"资源基本信息", "序号"},index = 0)private Integer resNo;/*** 资源名称*/@ColumnWidth(20)// @ExcelProperty(value = "资源名称",index = 1)@ExcelProperty(value = {"资源基本信息", "资源名称"}, index = 1)private String resName;/*** 资源类型*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "资源类型"} ,index = 2)private String resType;/*** 资源提供部门*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "资源提供部门"},index = 3)private String resSourceDept;/*** 资源权限*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "资源权限"},index = 4)private String resPower;/*** 资源层级(1.省级 2.市级 3.区级)*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "资源层级"},index = 5)private String resLevel;/*** 归集情况(1.已上线 2.未上线)*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "归集情况"},index = 6)private String collectionSituation;/*** 是否导入省里(0-否,1-是)*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "是否导入省里"},index = 7)private String isImport;/*** 回流标记(0-否,1-是)*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "是否回流"}, index = 8)private String backFlow;/*** 单位名称*/@ColumnWidth(20)@ExcelProperty(value = {"资源基本信息", "单位名称"}, index = 9)private String companyName;/*** 数据项*/@ColumnWidth(10)@ExcelProperty(value = {"编目信息","数据项"}, index = 10)private String chineseName;/*** 英文名称*/@ColumnWidth(20)@ExcelProperty(value = {"编目信息","英文名称"}, index = 11)private String englishName;/*** 字段类型*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","字段类型"}, index = 12)private String fieldType;/*** 字段长度*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","字段长度"}, index = 13)private String fieldLength;/*** 字段精度*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","字段精度"}, index = 14)private String fieldAccuracy;/*** 是否主键*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","是否主键"}, index = 15)private String keywords;/*** 是否字典项(0-否,1-是)*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","是否字典项"}, index = 16)private String isDictionary;/*** 字段描述*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","字段描述"}, index = 17)private String fieldDesc;/*** 是否为空(0-否,1-是)*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","是否为空"}, index = 18)private String isEmpty;/*** 默认值*/@ColumnWidth(15)@ExcelProperty(value = {"编目信息","默认值"}, index = 19)private String defaultValue;/*** 共享属性*/@ColumnWidth(18)@ExcelProperty(value = {"编目信息","共享属性"}, index = 20)private String shareAttribute;/*** 共享条件*/@ColumnWidth(18)@ExcelProperty(value = {"编目信息","共享条件"}, index = 21)private String shareCondition;/*** 开放属性*/@ColumnWidth(18)@ExcelProperty(value = {"编目信息","开放属性"}, index = 22)private String openAttribute;}

4、控制层调用

public void downLoadResItem(HttpServletResponse response, String resName, Integer isOnline, Integer resType, Integer resLevel, Integer resPower, Integer resPowerDept, Integer realmId) throws IOException {if (StringUtil.isNotBlank(resName)) {resName = URLDecoder.decode(resName, "UTF-8");}List<RdResourceDirExcelDTO> rdResourceDirList = rdResourceDirService.getList(resName, isOnline, resType, resLevel, resPower, resPowerDept, realmId);response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("资源列表下载", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");ServletOutputStream output = response.getOutputStream();ExcelWriter writer = new ExcelWriter(output, ExcelTypeEnum.XLS, true);Sheet sheet = new Sheet(1, 0, ResItemExcelVo.class);// sheet.setSheetName("第一页");List<ResItemExcelVo> voList = setResItemData(rdResourceDirList);// writer.write(voList, sheet);//需要合并的列int[] mergeColumeIndex = {0,1,2,3,4,5,6,7,8,9};// 从第二行后开始合并int mergeRowIndex = 2;EasyExcel.write(response.getOutputStream(), ResItemExcelVo.class).sheet("第一页")// .registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex)).registerWriteHandler(new ExcelMergeUtil(mergeRowIndex, mergeColumeIndex)).doWrite(voList);writer.finish();output.flush();}

导出的效果excel ,我是通过序号相同合并

导出的数据类似

序号 日志名称 日志时间 字段名 字段描述 字段值
1 根据ID查询详情 2021-01-13 total 总数 25
1 根据ID查询详情 2021-01-13 total 总数 25
1 根据ID查询详情 2021-01-13 total 总数 25
2 获取日志列表 2021-01-12 logName 日志名称 查询
2 获取日志列表 2021-01-12 logTime 日志时间 2021-10-01 14:25:14
2 获取日志列表 2021-01-12 logUser 查询人姓名 王杰
3 查询用户信息 2021-01-11 userName 用户名 tqf_123
3 查询用户信息 2021-01-11 age 年龄 25
3 查询用户信息 2021-01-11 sex 性别(0-男,1-女,2-未知) 0

easyexcel导出excel文件合并相同单元格数据相关推荐

  1. ExcelJs导出Excel文件并设置单元格样式

    下载exceljs并引入 数据源格式:二维数组,null值是后面要合并单元格的,占个位置. //创建对象 var wb = new ExcelJS.Workbook(); //创建一个名称为Sheet ...

  2. POI导出Excel文件时,单元格内文字竖排、横排默认不展示,必须点击一下问题解决

    //创建单元格样式设置CellStyle cs_vertical = wb.createCellStyle();//设置字体Font textFont = wb.createFont();textFo ...

  3. 批量提取多个Excel文件内指定单元格的数据(文件名和数据)

    批量提取多个Excel文件内指定单元格的数据(文件名和数据) 例如收集了excel表格统一格式的个人简历,从中抽取个人基本信息,生成数据表. 将源数据excel文件放在同一个文件夹下. 新建一个sho ...

  4. swagger easyExcel导出Excel文件打不开,文件损坏

    alibaba/easyexcel文件导出 swagger easyExcel导出Excel文件打不开,文件损坏 文件下载打不开,将文件输出到本地发现可以打开,而且swagger下载的文件大小比本地文 ...

  5. Java 使用EasyExcel导出excel文件

    Java 使用EasyExcel导出excel文件 一.引入pom依赖 二.导出实体 三. 生成excelController 四.效果 一.引入pom依赖 <dependency>< ...

  6. thinkphp导出到excel,合并拆分单元格!

    导出到excel合并拆解单元格操作(奇怪操作) 接到需求做一个奇怪的产品表格,时间紧任务重,开始演示,目的以下样式 目标确定开始操作! 首先数据格式为图中,我们需要先分析出这应该是一条数据但是需要合并 ...

  7. excel导出java不完整_有关Java POI导出excel表格中,单元格合并之后显示不全的解决方法。...

    我在table变换excel之后发现合并的单元格不能显示全部边框,在网上找了半天解决方案,终于解决了.具体解决代码如下; /** * 设置合并单元格的边框样式 * * @param sheet 当前表 ...

  8. Java poi插件导出Excel文件合并多sheet页

    文章目录 一.java导出excel格式文件 二.excel文件多sheet页合并 前言:2020年第一篇文章,就写这两天工作中遇到的这个小需求吧,导出多excel,每个excel有多个sheet页, ...

  9. poi导出Excel时设置某个单元格颜色

    需求: 查询数据库表数据然后到另一个表找错误的对应字段(就是找到需要填充的单元格所在行的列),对这个单元格进行设置背景色,然后导出数据. 具体的工具类如下 import cn.afterturn.ea ...

最新文章

  1. 《精通自动化测试框架设计》—第2章 2.3节测试数据交互基本方法
  2. python写web难受-pythonweb为什么不火-问答-阿里云开发者社区-阿里云
  3. CNN(Convolutional Neural Networks)算法
  4. VMware 当中出现:无法将 Ethernet0 连接到虚拟网络VMnet8的问题
  5. 用计算机乘九位数怎么用,用计算器计算
  6. Python中的计数(词频)
  7. 转字符串_【转】什么是字符串?字符串是用来做什么的?
  8. java将明文变为密文,使用java编程实现明文和密文之间的互转
  9. 机器学习这10年我们能在各自的领域做点什么?
  10. mysql 5.6.21 winx64_mysql-advanced-5.6.21-winx64部署及使用
  11. 【杂叙】北京住房公积金提取
  12. 电视android已停止运行是什么意思,智能电视提示应用停止运行,三种方法亲测有效!...
  13. 计算机网络安全第一课
  14. 似然函数,极大似然估计(一文搞定,能用嘴说的不堆公式)
  15. HTML CSS杂记
  16. 在线拍卖系统、竞拍源码中降价拍(荷兰式拍卖)的逻辑和实现
  17. Java 下载多个文件至内存并压缩文件包返回,无需保存至本地打包压缩
  18. poi-tl循环表格列和行
  19. 老照片怎么修复清晰?掌握这个技巧,一键智能修复
  20. gym 自定义游戏环境

热门文章

  1. 当前佛教界的乱相之一就是以凡滥圣、惑乱人心
  2. 【山东seo】-淄博孔祥永seo技术分享博客
  3. 菜刀、冰蝎、蚁剑、哥斯拉
  4. 排序算法的时间与空间复杂度分析
  5. JavaScript的深浅拷贝
  6. 旧电脑利用:windows网页版魔镜【不需树莓派】
  7. 买天猫网店转让商标需要注意的
  8. 搬砖:网络数据包解析
  9. R语言中的“<-” 、 “=” 、“->”
  10. mysql中sql语句日期比较,mysql sql语句中 日期函数的使用