EasyExcel专题(一) Excel 读取、写入、上传和下载
easyexcel
快速、简洁、解决大文件内存溢出的java处理Excel工具
项目地址:https://gitcode.com/gh_mirrors/ea/easyexcel
免费下载资源
·
一、将10万条数据从Excel读取出来
读取支持多标题,我们只需要指定最后一行的标题的行号即可,例如上述excel标题的行号为1,因此需要设置headRowNumber为1。
定义User 类,使用User类映射excel单条记录, 使用ExcelProperty注解标注excel里的字段名称。
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class User {
@ExcelProperty("id")
private String id;
@ExcelProperty("用户名")
private String userName;
@ExcelProperty("地址")
private String address;
}
FileUtil:
public class FileUtil {
public static String getResourcePath() {
return FileUtil.class.getResource("/").getPath();
}
}
执行读取,指定read方法的三个重要参数: file对象, 映射的pojo对象,读取监听器。
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.read.listener.PageReadListener;
import lombok.Data;
import lombok.ToString;
import org.junit.Test;
import java.io.File;
public class ExcelReadWriteTest{
@Test
public void readData() {
File file = new File(FileUtil.getResourcePath() + "demo.xlsx");
if (file.exists()) {
long start = System.currentTimeMillis();
EasyExcel.read(file, User.class, new PageReadListener<User>(dataList -> {
for (User user : dataList) {
System.out.println(user);
}
})).headRowNumber(1).sheet().doRead();
System.out.println("总耗时:" + (System.currentTimeMillis() - start) / 1000 + " s");
}
}
}
检查第一条数据是否正确:
总耗时1S:
二、将10万条数据写入到Excel
先看下写入的效果,单标题和多标题的区别。
1. 单标题
2. 多标题
完整代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ExcelReadWriteTest {
@Test
public void readData() {
File file = new File(FileUtil.getResourcePath() + "demo.xlsx");
if (file.exists()) {
long start = System.currentTimeMillis();
EasyExcel.read(file, User.class, new PageReadListener<User>(dataList -> {
for (User user : dataList) {
System.out.println(user);
}
})).headRowNumber(1).sheet().doRead();
System.out.println("总耗时:" + (System.currentTimeMillis() - start) / 1000 + " s");
}
}
@Test
public void WriteData() throws IOException {
File file = new File(FileUtil.getResourcePath() + "test01.xlsx");
if (!file.exists()) {
file.createNewFile();
}
EasyExcel.write(file, User.class).head(head()).sheet("用户表").doWrite(() -> data());
}
@Test
public void WriteData0() throws IOException {
File file = new File(FileUtil.getResourcePath() + "test02.xlsx");
if (!file.exists()) {
file.createNewFile();
}
EasyExcel.write(file, User.class).head(manyHead()).sheet("用户表").doWrite(() -> data());
}
//单行标题
private List<List<String>> head() {
List<List<String>> head = new ArrayList<>();
head.add(Arrays.asList("id"));
head.add(Arrays.asList("用户名"));
head.add(Arrays.asList("地址"));
return head;
}
// 多行标题
private List<List<String>> manyHead() {
List<List<String>> head = new ArrayList<>();
head.add(Arrays.asList("用户", "id"));
head.add(Arrays.asList("用户", "用户名"));
head.add(Arrays.asList("用户", "地址"));
return head;
}
private List<User> data() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
User user = new User();
user.setId(i + "");
user.setUserName("zhangsan" + i);
user.setAddress("shanghai" + i);
userList.add(user);
}
return userList;
}
}
三、上传和下载excel
可以新建一个SpringBoot工程,使用接口测试上传和下载功能。
1. 上传10万条数据
写要给upLoad接口,同时指定下excel里的标题所在行号。
@PostMapping("/upLoad")
public String uploadExcel(MultipartFile file, Integer headRowNumber) throws IOException {
//指定headRowNumber
EasyExcel.read(file.getInputStream(), User.class, new UploadListener(userService)).headRowNumber(headRowNumber).sheet().doRead();
return "success";
}
指定一个上传监听器,用于文件的回调处理。
package com.example;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UploadListener implements ReadListener<User> {
private static Logger logger = LoggerFactory.getLogger(UploadListener.class);
private UserService userService;
private List<User> cacheLists = new ArrayList<>(100);
public UploadListener(UserService userService) {
this.userService = userService;
}
@Override
public void invoke(User data, AnalysisContext context) {
logger.info("解析到一条数据: {}", JSON.toJSONString(data));
cacheLists.add(data);
if (cacheLists.size() > 100) {
saveData();
cacheLists = ListUtils.newArrayListWithExpectedSize(100);
}
}
private void saveData() {
logger.info("存储数据" + cacheLists.size() + "条!");
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (CollectionUtils.isNotEmpty(cacheLists)) {
saveData();
logger.info("所有数据解析完成!");
}
}
}
用postman测试
查看第一条数据id为0, 说明上传正确。
2. 下载10万条数据
指定sheet名称,同时将URL用UTF-8编码,防止文件名导出出现乱码的情况。
@PostMapping("/downLoad")
public String downloadExcel(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
// 如果指定了ExcelProperty,那么可以不用不用指定head,到处的excel仍然含有标题,如果想要多标题,那么就需要指定
EasyExcel.write(response.getOutputStream(), User.class).sheet("用户表").doWrite(data());
return "success";
}
用postman测试
保存到本地,可以打开说明下载正确!
代码地址: https://gitee.com/bingbing-123456/easyexcel_practice
如果链接打不开,可私信找我。
GitHub 加速计划 / ea / easyexcel
31.64 K
7.47 K
下载
快速、简洁、解决大文件内存溢出的java处理Excel工具
最近提交(Master分支:3 个月前 )
c42183df
Bugfix 3 个月前
efa7dff6 * 重新加回 `commons-io`
3 个月前
更多推荐
已为社区贡献3条内容
所有评论(0)