文章目录
目录
前言
一、EasyExcel是什么?
二、使用步骤
1.引入库
2.导入
2.1创建对应excel表格的实体类
2.2后端接收请求入口
2.3业务处理
2.4监听器处理数据
3.导出
3.1创建导出格式生成对应的excel表格的实体类,这个可以看2.1
3.2后端接收请求入口
3.3业务处理
4.合并工具类
总结
前言
该文章主要是介绍如何快速实现导入与导出功能
一、EasyExcel是什么?
引用官方的说明:EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
二、使用步骤
1.引入库
pom.xml引入jar依赖包:
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
2.导入
2.1创建对应excel表格的实体类
@ExcelProperty该注解的value是对应excle表格的列名称,index对应的是excel列的下标文章来源:https://www.toymoban.com/news/detail-769888.html
@Data
public class ImportModel {
/**
* 树根
*/
@ExcelProperty(value = "名称", index = 0)
private String ;
/**
* 树根标题
*/
@ExcelProperty(value = "编码", index = 1)
private String code;
}
2.2后端接收请求入口
/**
* 导入
*/
@ApiOperation("导入")
@PostMapping("/importTree")
public R importTree(@RequestParam("file") MultipartFile file) {
/** 根据自己的业务自行选择在哪处理 */
/** 直接在controllerr处理 */
// EasyExcel.read(file.getInputStream(), BigTreeImportCommand.class, new ExcelListener(urbanFacilityManageService)).sheet().doRead();
/** 在service实现类处理 */
Boolean flag = treeService.importTree(file, tenantId);
return R.ok("导入成功");
}
2.3业务处理
@Override
public Boolean importTree(MultipartFile file) {
try {
/** 处理数据的监听器,有参构造,根据自己的业务决定 */
TreeExcelListener excelListener = new TreeExcelListener(importService,tenantId);
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
//EasyExcel.read(文件流,对应的Model实体类,监听器).sheet(那张sheet表,可以使用下标或者使用sheet名字).head(表头对应的实体类).headRowNumber(表头占几行).registerReadListener(处理数据的监听器类).doRead()
EasyExcel.read(file.getInputStream(), ImportModel.class, excelListener).sheet(0).head(ImportModel.class).headRowNumber(1).doRead();
return true;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
2.4监听器处理数据
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ieds.back.interfaces.sys.web.command.BigTreeImportModel;
/**
* @Author: ChenFB
* @CreateTime: 2023-04-23 17:18
* @Description: 导入监听器
*/
public class ImportListener extends AnalysisEventListener<BigTreeImportModel> {
private ImportService importService;
private String tenantId;
/** 有参构造,建议将serverjie接口以参数的方式参进来,方便数据入库处理,这个参数自行界定 */
public ImportListener(ImportService importService, String tenantId) {
this.importService = importService;
this.tenantId = tenantId;
}
/** 读取每一行数据都会进入该方法,数据处理与校验可以在该方法进行处理 */
@Override
public void invoke(BigTreeImportModel data, AnalysisContext context) {
}
/** 所有数据读取完毕后,最终会执行这个方法,所以建议数据处理完后,批量在该方法进行入库处理 */
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
}
3.导出
3.1创建导出格式生成对应的excel表格的实体类,这个可以看2.1
3.2后端接收请求入口
/**
* 导出
*/
@ApiOperation("导出")
@GetMapping("/exportTree")
public void exportTree(HttpServletResponse response, @RequestParam("tenantId") String tenantId) {
treeService.exportTree(response,tenantId);
}
3.3业务处理
@Override
public void exportTree(HttpServletResponse response, String tenantId) {
ExcelWriter writer = null;
try {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //设置响应内容类型
response.setCharacterEncoding("utf-8");//编码
// 设置文件名, ps:把字符串中所有的'+'替换成'%20',在URL中%20代表空格
String fileName = URLEncoder.encode("文件名,根据业务决定", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");//设置响应头
response.setHeader("fileName", fileName + ".xlsx");//设置响应头
/** 导出的数据集合 */
List<ExportModel> modelList = new ArrayList<>();
/** registerWriteHandler(合并行数,那些列需要合并) */
writer = EasyExcel.write(response.getOutputStream(), BigTreeImportModel.class).registerWriteHandler(new MergeStrategy(modelList.size(), 0, 1, 2, 7, 8, 10, 11)).build();//获取写出流
WriteSheet sheet = EasyExcel.writerSheet("sheet名称,自行决定").build();//创建表格,设置表格页名称
writer.write(modelList, sheet);//读出
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (null != writer) {
writer.finish();//关闭流
}
}
}
4.合并工具类
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.commons.collections.map.HashedMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.*;
/**
* @Author: ChenFB
* @CreateTime: 2023-04-20 10:56
* @Description: Excel单元格合并工具类
*/
public class MergeStrategy extends AbstractMergeStrategy {
// 合并的列编号,从0开始,指定的index或自己按字段顺序数
private Set<Integer> mergeCellIndex = new HashSet<>();
// 数据集大小,用于区别结束行位置
private Integer maxRow = 0;
// 禁止无参声明
private MergeStrategy() {
}
public MergeStrategy(Integer maxRow, int... mergeCellIndex) {
Arrays.stream(mergeCellIndex).forEach(item -> {
this.mergeCellIndex.add(item);
});
this.maxRow = maxRow;
}
// 记录上一次合并的信息
private Map<Integer, MergeRange> lastRow = new HashedMap();
// 每行每列都会进入,绝对不要在这写循环
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
int currentCellIndex = cell.getColumnIndex();
// 判断该行是否需要合并
if (mergeCellIndex.contains(currentCellIndex)) {
String currentCellValue = cell.getStringCellValue();
int currentRowIndex = cell.getRowIndex();
if (!lastRow.containsKey(currentCellIndex)) {
// 记录首行起始位置
lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
return;
}
//有上行这列的值了,拿来对比.
MergeRange mergeRange = lastRow.get(currentCellIndex);
if (!(mergeRange.lastValue != null && mergeRange.lastValue.equals(currentCellValue))) {
// 结束的位置触发下合并.
// 同行同列不能合并,会抛异常
if (mergeRange.startRow != mergeRange.endRow || mergeRange.startCell != mergeRange.endCell) {
sheet.addMergedRegionUnsafe(new CellRangeAddress(mergeRange.startRow, mergeRange.endRow, mergeRange.startCell, mergeRange.endCell));
}
// 更新当前列起始位置
lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
}
// 合并行 + 1
mergeRange.endRow += 1;
// 结束的位置触发下最后一次没完成的合并
if (relativeRowIndex.equals(maxRow - 1)) {
MergeRange lastMergeRange = lastRow.get(currentCellIndex);
// 同行同列不能合并,会抛异常
if (lastMergeRange.startRow != lastMergeRange.endRow || lastMergeRange.startCell != lastMergeRange.endCell) {
sheet.addMergedRegionUnsafe(new CellRangeAddress(lastMergeRange.startRow-1, lastMergeRange.endRow, lastMergeRange.startCell, lastMergeRange.endCell));
}
}
}
}
}
class MergeRange {
public int startRow;
public int endRow;
public int startCell;
public int endCell;
public String lastValue;
public MergeRange(String lastValue, int startRow, int endRow, int startCell, int endCell) {
this.startRow = startRow;
this.endRow = endRow;
this.startCell = startCell;
this.endCell = endCell;
this.lastValue = lastValue;
}
}
总结
以上就是使用EasyExcel时限导入与导出功能的实现步骤,鄙人才疏学浅,本文章仅供参考,有不对之处,还望各位大佬提醒与指教.文章来源地址https://www.toymoban.com/news/detail-769888.html
到了这里,关于教您如何三分钟搞定EasyExcel导入与导出功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!