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. 最小栈问题:题目描述:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

    MinStack minStack = new MinStack();minStack.push(-2);minStack.push(0);minStack.push(-3);minStack.get ...

  2. 微信小程序超出后...

    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;

  3. 去掉有定位的left值

    left: initial;   一开始就是初始(默认值)的意思,就可以解决定位的left啦

  4. LeetCode刷题知识点总结——二叉树

    二叉树 一.二叉树理论基础 1.满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树.通俗话理解:从底层开始到顶部的所有节点都全部填满的二叉树.深 ...

  5. PyQt5 基础知识(六):展示控件

    目录 3. 展示控件 3.1 QLabel 3.1.1 描述 3.1.2 功能作用 3.1.2.1 基本功能 3.1.2.2 文本交互 3.1.2.3 内容操作 3.1.2.3.1 文本字符串 3.1 ...

  6. 如何写好一份晋升PPT(附PPT模板)

    又到了每年晋升述职的时间,在过去的5.6年里,我以评委身份参与了大量的晋升述职(主要是前端,也包括客户端和测试),也辅导了许多(100+)组内外的同学,指导他们书写和完善PPT.过程中我发现大家有许多 ...

  7. Lumia一键刷稳定版 Win10 arm 及其报错处理

    前言 之前我发了一篇Lumia1520 刷Win10 arm双系统的文章,不过后来发现那个方法对小白来说太不友好,且系统也不稳定,所以我找到了更好的方法 刷机 我们可以利用刷机迷进行刷机,支持一键刷机 ...

  8. Java语言学习day03--6月30日

    今日内容介绍 1.变量 2.运算符 ###01变量概述     * A: 什么是变量?         * a: 变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用 ...

  9. python基础练习题(题目 字母识词)

    day22 --------------------------------------------------------------- 实例031:字母识词 题目 请输入星期几的第一个字母来判断一 ...

  10. 微博python爬虫weiboSpider注意事项

    首先我看的weiboSpider爬虫项目教程出自https://github.com/dataabc/weiboSpider 1.这爬取的是手机端的,所以我把网址https://weibo.com的. ...