📚目录
- 📚简介:
- ✨代码的构建:
- 💭Web端接口Excel操作
- 🚀下载接口
- 🚀导入读取数据接口
- 🏡本地Excel文件操作
- ⚡导出数据
- 🌈导入读取数据
📚简介:
使用阿里巴巴开源组件Easy Excel对Excel的读取和写入。如需更详细查看官方文档,当前案例主要对Web端的数据导出,和Excel文件上传到服务端进行数据解析的Demo.其中主要的是工具类的用法。
工具类的主要用法:
- web端接口导出
- web接口导入
- 本地文件读取
- 本地文件导出
✨代码的构建:
Maven坐标
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--easyexcel导出-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<artifactId>poi-ooxml-schemas</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!--这个库提供了操作 Microsoft Office 格式文件的核心功能,包括读取和写入 Excel、Word、PowerPoint 等文件格式的能力。-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<!--这个库提供了对 OOXML 格式文件的读写能力,因此在处理 .xlsx 格式的 Excel 文件时需要导入这个库。-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
项目结构:
EasyExcelUtils 工具代码我放到文章的末尾,其他工具类如果需要的话可以去Gitee上拉代码自行查看 项目Demo
解析类的Excel注解解释
@Data
public class UserInfo {
/**
* 姓名
*/
@ExcelProperty(value = "姓名",index = 0)
private String name;
/**
* 性别
*/
@ExcelProperty(value ="性别",index = 1)
private String sex;
/**
* 年龄
*/
@ExcelProperty(value ="年龄",index = 2)
private Integer age;
/**
* 忽略这个字段 ExcelIgnore添加后导出和导入都会过滤这个字段
*/
//@ExcelIgnore()
@ExcelProperty(value ="手机",index = 3)
private String phone;
}
- ExcelProperty index 指定写到第几列,默认根据成员变量排序(使用了index那读取的时候Excel中的文件必须和这个index对应,Excel默认第一个字段就是index=0)。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头
- ExcelIgnore 添加后导出和导入都会过滤这个字段
- DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat
- NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat
ExcelProperty的属性介绍
💭Web端接口Excel操作
本次使用的是ApiPost工具模拟接口请求
🚀下载接口
代码
@GetMapping("userInfo/excelExport")
public ResultData userInfoExcelExport() {
List<UserInfo> userInfoList = getUserInfoList();
EasyExcelUtils.download("用户列表", userInfoList);
return ResultData.success();
}
public List<UserInfo> getUserInfoList() {
List<UserInfo> userInfoList = new ArrayList<>();
List<String> sexStrList = Arrays.asList("男", "女");
Random sexRandom = new Random();
for (int i = 0; i < 10; i++) {
UserInfo userInfo = new UserInfo();
String sexStr = sexStrList.get(sexRandom.nextInt(sexStrList.size()));
userInfo.setSex(sexStr);
String name = UserBuildUtils.buildName(sexStr);
userInfo.setName(name);
userInfo.setAge(RandomUtils.nextInt(18, 35));
userInfo.setPhone(UserBuildUtils.generatePhoneNumber());
userInfoList.add(userInfo);
}
return userInfoList;
}
效果
下载文件中打开
🚀导入读取数据接口
代码
@PostMapping("userInfo/excelImport")
public ResultData userInfoExcelImport(@RequestParam("file") MultipartFile file) throws IOException {
//解析导入的excel文件成对象
List<UserInfo> userInfoList = EasyExcelUtils.readExcel(UserInfo.class, file.getInputStream());
//处理对象
System.out.println(userInfoList);
return ResultData.success();
}
效果
本地文件用户列表1713077847559.xlsx
文件中一共有100条用户数据,接下来使用工具请求导入接口完成Excel文件数的读取
请求接口:
🏡本地Excel文件操作
⚡导出数据
代码
/**
* Excel的导出
*/
@Test
void ExcelExport() {
String outFile = System.getProperty("user.dir") + File.separatorChar + "file";
List<UserInfo> userInfoList = new ArrayList<>();
List<String> sexStrList = Arrays.asList("男","女");
Random sexRandom = new Random();
for (int i = 0; i < 100; i++) {
UserInfo userInfo = new UserInfo();
String sexStr = sexStrList.get(sexRandom.nextInt(sexStrList.size()));
userInfo.setSex(sexStr);
String name = UserBuildUtils.buildName(sexStr);
userInfo.setName(name);
userInfo.setAge(RandomUtils.nextInt(18, 35));
userInfo.setPhone(UserBuildUtils.generatePhoneNumber());
userInfoList.add(userInfo);
}
String outFileName = "用户列表" + System.currentTimeMillis() + ".xlsx";
EasyExcelUtils.write(outFile, outFileName, UserInfo.class, userInfoList, "用户列表");
}
效果:会在当前工程中的file文件夹中创建导出的Excel文件
🌈导入读取数据
代码
/**
* Excel导入
*/
@Test
void ExcelImport() {
//Excel文件路径
String filePath = System.getProperty("user.dir") + File.separatorChar + "file" + File.separatorChar
+ "readFile" + File.separatorChar + "用户列表1713077847559.xlsx";
List<UserInfo> userInfoList = EasyExcelUtils.readExcel(UserInfo.class, filePath);
System.out.println(userInfoList);
}
效果: 指定需要读取的文件路径
EasyExcelUtils 工具类:
/**
* @Author itmei
* @Date 2024/4/13 20:49
* @description:
* @Title: EasyExcelUtils
* @Package com.itmei.exceldemo.utils
*/
public class EasyExcelUtils {
/**
* 写文件
*
* @param outFileName 写的路径
* @param clazz 用于获取类中的Excel注解
* @param list 数据
*/
public static void write(String outFileName, Class<?> clazz, List<?> list) {
// 新版本会自动关闭流,不需要自己操作
EasyExcel.write(outFileName, clazz).sheet().doWrite(list);
}
/**
* 写文件
*
* @param outFileName 文件名称
* @param clazz 用于获取类中的Excel注解
* @param list 数据
* @param sheetName 工作簿名称
*/
public static void write(String outFileName, Class<?> clazz, List<?> list, String sheetName) {
// 新版本会自动关闭流,不需要自己操作
EasyExcel.write(outFileName, clazz).sheet(sheetName).doWrite(list);
}
/**
* 写文件
*
* @param outFile 保存的文件位置(必须存在否则报错)
* @param outFileName 文件名称
* @param clazz 用于获取类中的Excel注解
* @param list 数据
* @param sheetName 工作簿名称
*/
public static void write(String outFile, String outFileName, Class<?> clazz, List<?> list, String sheetName) {
// 新版本会自动关闭流,不需要自己操作
ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outFile + File.separatorChar + outFileName, clazz);
excelWriterBuilder.sheet(sheetName).doWrite(list);
}
/**
* 写文件
*
* @param outputStream 输出流
* @param list 数据
* @param sheetName 工作簿名称
*/
public static void write(OutputStream outputStream, List<?> list, String sheetName) {
Class<?> clazz = list.get(0).getClass();
// sheetName为sheet的名字,默认写第一个sheet
EasyExcel.write(outputStream, clazz).sheet(sheetName).doWrite(list);
}
/**
* 文件下载,用于前端下载Excel
*
* @param sheetName 工作簿名称
* @param list 数据
* @throws IOException
*/
public static void download(String sheetName, List<?> list) {
HttpServletResponse response = HttpServletUtil.getResponse();
try {
Class<?> clazz = list.get(0).getClass();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode(sheetName + "_" + DateUtils.format(new Date()), "UTF-8").replaceAll("\\+", "%20") + ".xlsx";
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
EasyExcel.write(response.getOutputStream(), clazz)
.autoCloseStream(false)
.sheet(sheetName)
.doWrite(list);
} catch (Exception e) {
handleException(response, e);
}
}
private static void handleException(HttpServletResponse response, Exception e) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, Object> map = MapUtils.newHashMap();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
try {
response.getWriter().println(mapToJsonString(map));
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* 将 Map 对象转换成 JSON 格式的字符串
*
* @param map
* @return
*/
public static String mapToJsonString(Map<String, Object> map) {
StringBuilder json = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (!first) {
json.append(",");
}
json.append("\"").append(entry.getKey()).append("\":");
Object value = entry.getValue();
if (value instanceof String) {
json.append("\"").append(value).append("\"");
} else {
json.append(value);
}
first = false;
}
json.append("}");
return json.toString();
}
/**
* 读取Excel文件并且返回集合对象
*
* @param classT
* @param filePath
* @param <T>
* @return
*/
public static <T> List<T> readExcel(Class<T> classT, String filePath) {
List<T> readAllList = new ArrayList<>();
EasyExcel.read(filePath, classT, new ReadListener<T>() {
@Override
public void invoke(T data, AnalysisContext context) {
//这个每一条数据解析都会来调用
readAllList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
//全部读取完成后会调用
}
}).sheet().doRead();
return readAllList;
}
public static <T> List<T> readExcel(Class<T> classT, InputStream inputStream) {
List<T> readAllList = new ArrayList<>();
try {
EasyExcel.read(inputStream, classT, new ReadListener<T>() {
@Override
public void invoke(T data, AnalysisContext context) {
// 这个每一条数据解析都会来调用
readAllList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 全部读取完成后会调用
try {
inputStream.close(); // 关闭输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}).sheet().doRead();
} catch (Exception e) {
e.printStackTrace();
// 处理异常情况,比如日志记录或者抛出自定义异常
}
return readAllList;
}
}