一、准备工作
1、导入依赖
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
2、定义上传下载工具类ExcelUtil
pojo类需要改成自己要上传下载的pojo类
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.haogu.config.ExcelDataListener;
import com.haogu.entity.User;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ExcelUtil {
public static void writeObjectsToExcel(List<User> objects, String filePath, Class<?> clazz) {
// 创建 Excel 写入器
ExcelWriterBuilder writerBuilder = EasyExcel.write(filePath, clazz);
// 写入数据到 Sheet1
WriteSheet sheet = EasyExcel.writerSheet("Sheet1").build();
writerBuilder.sheet().doWrite(objects);
// 完成写入操作
// writerBuilder.finish();
}
public static <T> List<T> readExcel(InputStream inputStream, Class<T> clazz) {
List<T> dataList = new ArrayList<>();
// 读取Excel文件
EasyExcel.read(inputStream, clazz, new ExcelDataListener()).sheet().doRead();
return dataList;
}
}
3、定义一个数据监听器用以文件上传
实体类需要改成自己要上传下载的对象类型
package com.haogu.config;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.haogu.entity.User;
import com.haogu.service.IUserService;
import com.haogu.service.impl.UserServiceImpl;
import java.util.ArrayList;
import java.util.List;
public class ExcelDataListener extends AnalysisEventListener<User> {
private List<User> dataList = new ArrayList<>();
@Override
public void invoke(User data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据解析完成后的处理逻辑,可以在这里对读取到的数据进行进一步处理
// 例如,存储到数据库或执行其他业务逻辑
handleData(dataList);
}
private void handleData(List<User> dataList) {
// 具体处理数据的逻辑
System.out.println("读取到的数据:");
for (User data : dataList) {
data.setId(null);
System.out.println(data);
}
IUserService userService = new UserServiceImpl();
// 这里调用的是service层批量添加的函数(mybatisPlus提供)
userService.saveBatch(dataList);
}
}
4、定义格式转换类TimestampStringConverter
该类用于Timestamp(java对象中的字段类型)与String(Excel文件中存储类型)两者间的转换,用于读取和写入
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.DateUtils;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Date;
public class TimestampStringConverter implements Converter<Timestamp> {
@Override
public Class<?> supportJavaTypeKey() {
return Timestamp.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
// 将excel文件中的对应数据(String)转换为Timestamp
@Override
public Timestamp convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return Timestamp.valueOf(cellData.getStringValue());
}
// 将Timestamp转换为excel文件中的对应数据(String)
@Override
public CellData convertToExcelData(Timestamp timestamp, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
CellData cellData = new CellData();
String cellValue = DateUtils.format(new Date(timestamp.getTime()), "yyyy-MM-dd HH:mm:ss");
cellData.setType(CellDataTypeEnum.STRING);
cellData.setStringValue(cellValue);
cellData.setData(cellValue);
return cellData;
}
}
5、实体类开启注解
使用 @ExcelProperty(converter = TimestampStringConverter.class)
代表该字段在读写excel文件时使用自定义转换器进行类型转换
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@ExcelProperty(converter = TimestampStringConverter.class)
private Timestamp createTime;
/**
* 修改时间
*/
@ExcelProperty(converter = TimestampStringConverter.class)
private Timestamp updateTime;
}
二、业务层代码
1、上传
1.1 controller层
直接编写上传文件的接口,因为没有多余逻辑判断,不需要编写service层代码
@PostMapping("/import")
public void uploadExcel(@RequestParam("file") MultipartFile file) {
try {
// User为用作数据载体的实体类类型
// 调用编写的ExcelUtil类的方法
ExcelUtil.read(file.getInputStream(), User.class);
} catch (IOException e) {
e.printStackTrace();
}
}
2、下载
2.1 controller层
直接在controller层编写下载接口
@PostMapping("/export")
public Result export(@RequestBody List<User> users, String path){
System.out.println(users);
try {
userService.exportToExcel(users, path);
return Result.success("导出成功" + path);
} catch (IOException e) {
e.printStackTrace();
return Result.failed("导出失败");
}
}
2.2 service层
public boolean exportToExcel(List<User> data, String filePath) throws IOException {
// 给出默认路径
if (filePath == null) {
filePath = "C:\\Users\\archer\\Desktop\\user.xlsx";
}
// 如果文件不存在则创建一个空文件
File file = new File(filePath);
if (!file.exists()){
file.createNewFile();
}
// 调用编写的ExcelUtil类的方法,将数据下载(写入)指定excel文件
ExcelUtil.writeObjectsToExcel(data, filePath, User.class);
return true;
}