pom版本

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

1.自定义合并单元格

在某些业务场景中可能会有合并单元格的需求,下面具体来说明如何实现

1.1 不合并单元格

先来看下不合并单元格的代码写法,简单复习下

public static void writeExcel() {
// 写excel的路径,当前项目路径下
String fileName = getPath();
// 构建ExcelWriter
ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build(); // 构建sheet
WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class).build();
// 写sheet
excelWriter.write(data1(), writeSheet);
excelWriter.finish();
} private static String getPath() {
return System.getProperty("user.dir") + "/" + System.currentTimeMillis() + ".xlsx";
} private static List<DemoData> data1() {
List<DemoData> list = Lists.newArrayList();
for (int i = 0; i < 3; i++) {
DemoData data = new DemoData();
data.setString("字符串" + 1);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
for (int i = 0; i < 3; i++) {
DemoData data = new DemoData();
data.setString("字符串" + 2);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
for (int i = 0; i < 4; i++) {
DemoData data = new DemoData();
data.setString("字符串" + 3);
data.setDate(new Date());
data.setDoubleData(0.57);
list.add(data);
}
return list;
} public static void main(String[] args) {
writeExcel();
}

打开输出的excel文件后如下,可以看到单元格没有合并。现在打算将第一列字符串标题相同的合并

1.2 合并单元格

// 自定义合并策略 该类继承了AbstractMergeStrategy抽象合并策略,需要重写merge()方法
public static class CustomMergeStrategy extends AbstractMergeStrategy { /**
* 分组,每几行合并一次
*/
private List<Integer> exportFieldGroupCountList; /**
* 目标合并列index
*/
private Integer targetColumnIndex; // 需要开始合并单元格的首行index
private Integer rowIndex; // exportDataList为待合并目标列的值
public CustomMergeStrategy(List<String> exportDataList, Integer targetColumnIndex) {
this.exportFieldGroupCountList = getGroupCountList(exportDataList);
this.targetColumnIndex = targetColumnIndex;
} @Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { if (null == rowIndex) {
rowIndex = cell.getRowIndex();
}
// 仅从首行以及目标列的单元格开始合并,忽略其他
if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == targetColumnIndex) {
mergeGroupColumn(sheet);
}
} private void mergeGroupColumn(Sheet sheet) {
int rowCount = rowIndex;
for (Integer count : exportFieldGroupCountList) {
if(count == 1) {
rowCount += count;
continue ;
}
// 合并单元格
CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1, targetColumnIndex, targetColumnIndex);
sheet.addMergedRegionUnsafe(cellRangeAddress);
rowCount += count;
}
} // 该方法将目标列根据值是否相同连续可合并,存储可合并的行数
private List<Integer> getGroupCountList(List<String> exportDataList){
if (CollectionUtils.isEmpty(exportDataList)) {
return new ArrayList<>();
} List<Integer> groupCountList = new ArrayList<>();
int count = 1; for (int i = 1; i < exportDataList.size(); i++) {
if (exportDataList.get(i).equals(exportDataList.get(i - 1))) {
count++;
} else {
groupCountList.add(count);
count = 1;
}
}
// 处理完最后一条后
groupCountList.add(count);
return groupCountList;
}
} // 修改WriteSheet的代码如下
public static void writeExcel() {
String fileName = getPath();
ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build(); List<DemoData> demoDataList = data1();
// 写sheet的时候注册相应的自定义合并单元格策略
WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
.build();
excelWriter.write(demoDataList, writeSheet);
excelWriter.finish();
}

打开输出的excel文件后如下,可以看到第一列有相同值的单元格已经合并了,成功实现

同理若要合并第三列的数据,则可以在注册一个sheet写处理器,代码如下

  public static void writeExcel() {
String fileName = getPath();
ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build(); List<DemoData> demoDataList = data1();
WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
.build();
excelWriter.write(demoDataList, writeSheet);
excelWriter.finish();
}

excel打开如下:

1.3 写多个sheet

  public static void writeExcel() {
String fileName = getPath();
ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build(); List<DemoData> demoDataList = data1();
WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
.build();
excelWriter.write(demoDataList, writeSheet); WriteSheet writeSheet1 = EasyExcel.writerSheet("模板2").head(DemoData.class).build();
excelWriter.write(data1(), writeSheet1);
excelWriter.finish();
}

输出excel可以看到已经有两个sheet了

1.4 WriteTable

若业务需求要求在同一个sheet中写多个表,就需要用到WriteTable了。只定义一个WriteSheet,有几个表就定义几个WriteTable

  public static void writeExcel01() {
String fileName = getPath();
ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build(); List<DemoData> demoDataList = data1();
// 需要表头设置为true,WriteTable一些属性会继承自WriteSheet
WriteTable writeTable = EasyExcel.writerTable(1).head(DemoData.class).needHead(Boolean.TRUE)
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
.registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
.build();
excelWriter.write(demoDataList, writeSheet, writeTable); WriteTable writeTable1 = EasyExcel.writerTable(2).head(DemoData.class).needHead(Boolean.TRUE).build();
excelWriter.write(data1(), writeSheet, writeTable1);
excelWriter.finish();
}

打开excel表格如下

结语

如有错误或者优化点欢迎指出,本文参考自EasyExcel文档

EasyExcel-合并单元格的更多相关文章

  1. C# 获取Excel中的合并单元格

    C# 获取Excel中的合并单元格 我们在制作表格时,有时经常需要合并及取消合并一些单元格.在取消合并单元格时需要逐个查找及取消,比较麻烦.这里分享一个简单的方法来识别Excel中的合并单元格,识别这 ...

  2. jquery操作表格 合并单元格

    jquery操作table,合并单元格,合并相同的行 合并的方法 $("#tableid").mergeCell({ cols:[X,X] ///参数为要合并的列}) /** * ...

  3. NPOI操作EXCEL(五)——含合并单元格复杂表头的EXCEL解析

    我们在第三篇文章中谈到了那些非常反人类的excel模板,博主为了养家糊口,也玩命做出了相应的解析方法... 我们先来看看第一类复杂表头: ...... 博主称这类excel模板为略复杂表头模板(蓝色部 ...

  4. poi获取合并单元格内的第一行第一列的值

    当读取如图所示的excel时,显示为第1行 第1列 的内容是:合并单元格 其它在合并单元格区域内的单元格不显示 示例代码如下: import java.io.FileInputStream; impo ...

  5. Repeater多列分别合并单元格

    GridView.Repeater合并单元格可以参考http://www.cnblogs.com/zhmore/archive/2009/04/22/1440979.html,但是原文例子是合并一列的 ...

  6. Aspose.Cells 首次使用,用到模版填充数据,合并单元格,换行

    Aspose.Cells 首次使用,用到模版填充数据,合并单元格,换行 模版格式,图格式是最简单的格式,但实际效果不是这种,实际效果图如图2 图2 ,注意看红色部分,一对一是正常的,但是有一对多的订单 ...

  7. easyui datagrid 合并单元格

    整理以前做的东西,这个合并单元格的问题再新浪博客也写过了..... 下面这段代码是列表数据 //载入排放系数管理报表数据 function LoadEmissionReportData() { //获 ...

  8. GRIDVIEW多行多列合并单元格(合并列)

    GitHub项目地址:https://github.com/mingceng/merge-gridviewcell 去年的时候,我写了两篇文章:  GridView多行多列合并单元格(完整代码和例子) ...

  9. C#导出Excel,并且设置Excel单元格格式,合并单元格.

    注:要添加COM组件 Microsoft Excel 11.0 Object Library  引用. 具体代码如下: using System; using System.Collections.G ...

  10. 带复杂表头合并单元格的HtmlTable转换成DataTable并导出Excel

    步骤: 一.前台JS取HtmlTable数据,根据设定的分隔符把数据拼接起来 <!--导出Excel--> <script type="text/javascript&qu ...

随机推荐

  1. parseFloat的取值

    <script type="text/javascript"> document.write(parseFloat("10")) document. ...

  2. vue引入echarts

    效果图: 1.安装Echarts :     npm install echarts -S 或者使用国内的淘宝镜像: 安装: npm install -g cnpm --registry=https: ...

  3. css换算rem单位

    地址:https://www.freetechs.cn/tool/rem2px.html

  4. SpringBoot其他框架-JPA-Hibernate-Swagger

    SpringBoot其他框架 通过了解其他的SpringBoot框架,我们就可以在我们自己的Web服务器上实现更多更高级的功能. 邮件发送:Mail 我们在注册很多的网站时,都会遇到邮件或是手机号验证 ...

  5. uTools .SRT 转 .VTT 格式转换自动化小工具

    不想用网上的转换工具,要有网,先上传,再下载,可能还要看广告.有些工具也不是很方便.打算配合uTools的自动化助手插件搞一个一键格式转换.

  6. MySql创建分区

    一.Mysql分区类型 1.RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区. 2.HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列 ...

  7. Spring的3级缓存和循环引用的理解

    此处是我自己的一个理解,防止以后忘记,如若那个地方理解不对,欢迎指出. 一.背景 在我们写代码的过程中一般会使用 @Autowired 来注入另外的一个对象,但有些时候发生了 循环依赖,但是我们的代码 ...

  8. Django学习——静态文件配置、request对象方法、pycharm如何链接数据库、Django如何指定数据库、Django orm操作

    静态文件配置 # 1.静态文件 网站所使用的已经提前写好的文件 css文件 js文件 img文件 第三方文件 我们在存储静态文件资源的时候一般默认都是放在static文件夹下 # 2.Django静态 ...

  9. Linux-流程控制语法-函数-属组

    1.流程控制 1.1 条件选择 1.1.1选择执行if语句 格式: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ] ... ...

  10. apparmor 源码分析

    这里不对apparmor做介绍,记录一下源码分析过程. 初始化 static int __init apparmor_init(void) -> security_add_hooks(appar ...