实现效果
遇到一个项目,里面要求把一些数据合并,研究了一天整的我头大,现在把这个方法公布出来,我也是抄的别人的实现
先看一下要操作的表格
这里分为读写两个操作,读是要将合并单元格的数据读出来,写是将相同的数据合并。
来看一下合并之后的样子
你觉得不好看可以自己调整一下表间距
ok 了家人们,上代码
依赖
<!-- easy excel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.4</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.6</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.22</version>
</dependency>
<!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
代码实现
package com.example.demo.excel.input;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.metadata.CellExtra;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/**
* 导入工具类
*
* @param <T>
*/
@Slf4j
public class ImportExcelHelper<T> {
/**
* 返回解析后的List
*
* @return java.util.List<T> 解析后的List
* @param: fileName 文件名
* @param: clazz Excel对应属性名
* @param: sheetNo 要解析的sheet
* @param: headRowNumber 正文起始行
*/
public List<T> getList(InputStream file, Class<T> clazz, Integer sheetNo, Integer headRowNumber) {
//开启监听器
ImportExcelListener<T> listener = new ImportExcelListener<>(headRowNumber);
//多线程倒计时计数器
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
//读取额外的可合并的数据 第 0 个 sheet 第 1 行开始
EasyExcel.read(file, clazz, listener).extraRead(CellExtraTypeEnum.MERGE).sheet(sheetNo).headRowNumber(headRowNumber).doRead();
} catch (Exception e) {
log.error(e.getMessage());
}
//开始倒计时减1
latch.countDown();
}).start();
try {
//阻塞程序等待完成
latch.await();
} catch (InterruptedException ignored) {
}
List<CellExtra> extraMergeInfoList = listener.getExtraMergeInfoList();
//没有合并单元格情况,直接返回即可
if (isEmpty(extraMergeInfoList)) {
return listener.getData();
}
CountDownLatch computerLatch = new CountDownLatch(1);
AtomicReference<List<T>> data = new AtomicReference<>();
new Thread(() -> {
//存在有合并单元格时,自动获取值,并校对
data.set(explainMergeData(listener.getData(), extraMergeInfoList, headRowNumber));
computerLatch.countDown();
}).start();
try {
computerLatch.await();
} catch (InterruptedException ignored) {
}
return data.get();
}
/**
* 处理合并单元格
*
* @param data 解析数据
* @param extraMergeInfoList 合并单元格信息
* @param headRowNumber 起始行
* @return 填充好的解析数据
*/
private List<T> explainMergeData(List<T> data, List<CellExtra> extraMergeInfoList, Integer headRowNumber) {
//循环所有合并单元格信息
extraMergeInfoList.forEach(cellExtra -> {
//获取第一行
int firstRowIndex = cellExtra.getFirstRowIndex() - headRowNumber;
//获取最后一行
int lastRowIndex = cellExtra.getLastRowIndex() - headRowNumber;
//获取第一列
int firstColumnIndex = cellExtra.getFirstColumnIndex();
//获取最后一列
int lastColumnIndex = cellExtra.getLastColumnIndex();
//获取初始值
Object initValue = getInitValueFromList(firstRowIndex, firstColumnIndex, data);
//设置值
for (int i = firstRowIndex; i <= lastRowIndex; i++