详细讲解Java使用EasyExcel函数来操作Excel表(附实战)

目录

  • 前言
  • [1. EasyExcel类](#1. EasyExcel类)
  • [2. 原理分析](#2. 原理分析)
  • [3. demo](#3. demo)
  • [4. 实战](#4. 实战)

前言

前阵时间好奇下载Excel,特意学习实战了该功能:详细讲解Java使用HSSFWorkbook函数导出Excel表(附实战)

现在发觉还有个EasyExcel也可专门用来读写Excel表

1. EasyExcel类

添加相应的依赖包

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.5</version>
</dependency>

EasyExcel 是一个基于 Java 的开源工具,用于简化 Excel 文件的读写操作。

具有易用性、高性能、低内存消耗的特点。

以下是 EasyExcel 的一些主要函数和用法:(本身有读和写的两种操作)

2. 原理分析

本身该函数通过继承EasyExcelFactory函数,主要在EasyExcelFactory函数中实现。

一、对于read函数主要通过流操作获取。

对于EasyExcel.read 方法中常用的一个read函数如下:

java 复制代码
EasyExcel.read(fileName, head, readListener).sheet().doRead();

大致三个参数如下:

  • fileName:Excel 文件的路径或输入流。
  • head:Excel 表头对应的实体类,定义了 Excel 表的结构。
  • readListener:数据读取的监听器,定义了数据读取的逻辑。

二、 Excel 表头的实体类:

在读取 Excel 文件时,需要定义一个实体类来映射 Excel 表头,每个字段对应一个表头列。这个实体类用于指定数据在 Java 对象中的存储结构。

java 复制代码
public class ExcelData {
    private String name;
    private Integer age;
    // 其他字段...

    // 省略 getter 和 setter 方法
}

三、数据读取监听器:

EasyExcel 提供了 AnalysisEventListener 类来处理 Excel 数据的读取。

需要继承该类,并实现 invoke 方法来处理每一行数据的读取逻辑,以及doAfterAllAnalysed 方法来处理所有数据解析完成后的逻辑。

java 复制代码
public class ExcelDataListener extends AnalysisEventListener<ExcelData> {

    @Override
    public void invoke(ExcelData data, AnalysisContext context) {
        // 处理每一行数据的逻辑
        System.out.println("Read data: " + data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完成后的逻辑
    }
}

四、Excel 写入:

EasyExcel 也提供了写入 Excel 文件的功能。

可以使用 EasyExcel.write 方法来配置写入参数,然后调用 sheet 方法指定写入的 sheet,最后调用 doWrite 方法执行写入操作。

java 复制代码
EasyExcel.write(fileName, head).sheet("Sheet1").doWrite(dataList);

大致的参数如下:

  • fileName:写入的 Excel 文件路径。
  • head:Excel 表头对应的实体类。
  • dataList:要写入的数据列表。dataList 应该是一个 List,其中的元素是实体类的对象

五、Excel 写入监听器:

写入 Excel 文件时进行一些额外的处理,可以使用写入监听器 WriteHandler

java 复制代码
public class ExcelWriteHandler implements WriteHandler {

    @Override
    public void sheet(int sheetNo, Sheet sheet) {
        // 对每个 sheet 进行处理的逻辑
    }

    @Override
    public void row(int rowNum, Row row) {
        // 对每一行进行处理的逻辑
    }

    @Override
    public void cell(int cellNum, Cell cell) {
        // 对每个单元格进行处理的逻辑
    }
}

在写入 Excel 文件时,通过 excelWriter.registerWriteHandler(new ExcelWriteHandler()) 注册写入监听器即可。

3. demo

假设创建的实体类如下:

java 复制代码
import lombok.Data;

@Data
@NoArgsConstructor
public class ExcelData {
	private String name;
	private Integer age;
	private String occupation;
	// 其他字段...

	// 省略 getter 和 setter 方法

	public ExcelData(String name, Integer age, String occupation) {
		this.name = name;
		this.age = age;
		this.occupation = occupation;
	}
}

写入Excel的函数:

java 复制代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;

import java.util.ArrayList;
import java.util.List;

public class test1 {

	public static void main(String[] args) {
		String fileName = "d:\\xxx\\测试.xlsx"; // 替换成实际的文件路径

		// 准备要写入的数据
		List<ExcelData> dataList = initData();

//		// 写入 Excel 文件
//		ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelData.class).build();
//		// 创建写入的 sheet
//		WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
//		// 写入数据
//		excelWriter.write(dataList, writeSheet);

		//与上面同理
		EasyExcel.write(fileName, ExcelData.class).sheet("模板").doWrite(dataList);

		System.out.println("Excel 写入完成!");
	}

	// 初始化要写入的数据
	private static List<ExcelData> initData() {
		List<ExcelData> dataList = new ArrayList<>();
		dataList.add(new ExcelData("John", 25, "Engineer"));
		dataList.add(new ExcelData("Alice", 30, "Manager"));
		dataList.add(new ExcelData("Bob", 28, "Developer"));
		// 添加更多数据...

		return dataList;
	}
}

最后截图如下:

读取函数的功能:

在这之前需要加一个监听器:

java 复制代码
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.Map;

public class ExcelListen extends AnalysisEventListener<ExcelData> {

	@Override
	public void invoke(ExcelData data, AnalysisContext context) {
		// 数据处理逻辑,可以将数据存储到数据库或进行其他操作
		System.out.println("Read data: " + data);
	}

	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		// 所有数据解析完成后的操作
	}
}

其读写的函数如下:

java 复制代码
import com.alibaba.excel.EasyExcel;

public class test1 {

	public static void main(String[] args) {
		String fileName = "d:\\xx\\测试.xlsx"; // 替换成实际的文件路径

		// 使用 EasyExcel 读取 Excel 文件
		EasyExcel.read(fileName, ExcelData.class, new ExcelListen()).sheet().doRead();
	}

}

截图如下:

4. 实战

对于实战中,多数是结合springboot以及数据库中,主要将其Excel中导入到界面中,同时也保存在数据库中!

关联数据库Entity的类如下:

java 复制代码
@Data
@TableName("xx")
@ApiModel(value = "Info对象", description = "Info对象")
public class Info{

	@ApiModelProperty(value = "设备编号")
	@ExcelProperty("设备编号")
	private String equipmentNo;
}

对应的监听类函数如下:(对于监听类的函数实际看个人数据库补充即可!以下只是给个模板)

java 复制代码
public class InfoDataListener extends AnalysisEventListener<Info> {

	/**
	 * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
	 */
	private static final int BATCH_COUNT = 5;

	List<Info> list = new ArrayList<Info>();

	private IInfoService infoService;

	private IInfoRunningDataService infoRunningDataService;

	//其他

	public InfoDataListener(IInfoService infoService) {
		this.infoService = infoService;
	}
	
	//弄构造函数
	public InfoDataListener(IInfoService infoService,
							//其他) {
		this.infoService = infoService;
		//其他
	}

	/**
	 * 这个每一条数据解析都会来调用
	 *
	 * @param info            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
	 * @param analysisContext
	 */
	@Override
	public void invoke(Info info, AnalysisContext analysisContext) {
		list.add(info);
		// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
		if (list.size() > BATCH_COUNT) {
			saveData();
			// 存储完成清理 list
			list.clear();
		}
	}

	/**
	 * 所有数据解析完成了 都会来调用
	 *
	 * @param analysisContext
	 */
	@Override
	public void doAfterAllAnalysed(AnalysisContext analysisContext) {
		// 这里也要保存数据,确保最后遗留的数据也存储到数据库
		saveData();
	}


	/**
	 * 除了保持自己本身,还要保存运行数据表,
	 * xxx
	 */
	public void saveData() {
		infoService.saveBatch(list);
		ArrayList<InfoRunningData> infoRunningDatas = new ArrayList<InfoRunningData>();
		// 其他数据一块
		list.stream().forEach(info ->{
			InfoRunningData infoRunningData = new InfoRunningData();
			infoRunningData.setInfoId(info.getId());
			infoRunningDatas.add(infoRunningData);

			//其他数据一并处理
		});


		infoRunningDataService.saveBatch(infoRunningDatas);
		//其他数据一并处理
	}
}

controller函数:

java 复制代码
@PostMapping("/importExcel")
@ResponseBody
public R upload(MultipartFile file) throws IOException {
	EasyExcel.read(file.getInputStream(), Info.class, new InfoDataListener(infoService,
		infoxxService,infoyyService	)).sheet().doRead();
//		EasyExcel.read(file.getInputStream(),Info.class,new InfoDataListener(infoService)).sheet().doRead();
	return R.success("导入成功");
}
相关推荐
北执南念5 分钟前
项目代码生成工具
java
中国lanwp11 分钟前
springboot logback 默认加载配置文件顺序
java·spring boot·logback
cherishSpring22 分钟前
在windows使用docker打包springboot项目镜像并上传到阿里云
spring boot·docker·容器
苹果酱056743 分钟前
【Azure Redis 缓存】在Azure Redis中,如何限制只允许Azure App Service访问?
java·vue.js·spring boot·mysql·课程设计
Java致死1 小时前
单例设计模式
java·单例模式·设计模式
胡子发芽1 小时前
请详细解释Java中的线程池(ThreadPoolExecutor)的工作原理,并说明如何自定义线程池的拒绝策略
java
沫夕残雪1 小时前
Tomcat的安装与配置
java·tomcat
胡子发芽1 小时前
请解释Java中的NIO(New I/O)与传统I/O的区别,并说明NIO中的关键组件及其作用
java
柚个朵朵2 小时前
IDEA中使用Git
java·git·spring
jerry6092 小时前
优先队列、堆笔记(算法第四版)
java·笔记·算法