<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
只有easyexcel 是必须的
@Data
public class Student {
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("成绩")
private BigDecimal score;
}
ExcelProperty代表导出列表头
来看看 Controller
// 模拟从数据库查询出来的数据
private List<Student> data() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
Student student = new Student();
list.add(student);
student.setName("张三" + i);
student.setAge(18 + i);
student.setScore(new BigDecimal(i + ""));
}
return list;
}
// 导出
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
// Student.class 是按导出类 data()应为数据库查询数据,这里只是模拟
EasyExcel.write(response.getOutputStream(), Student.class).sheet("模板").doWrite(data());
}
这里导出就写完了,我们直接调用 http://localhost:8081/download 来看看效果
是不是特别轻松简单
读取数据是一行一行读取的,所以需要创建一个读取一行数据后的监听器
这个监听器需要继承AnalysisEventListener类,大致代码如下
StudentListener
package com.zou.springbooteasyexcel.com.Listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.zou.springbooteasyexcel.com.Dao.StudentDao;
import com.zou.springbooteasyexcel.com.model.Student;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* @author WH
* @version 1.0
* @date 2020/4/18 20:56
* @Description TODO
*/
public class StudentListener extends AnalysisEventListener<Student> {
private static final Logger LOGGER =
LoggerFactory.getLogger(com.zou.springbooteasyexcel.com.Listener.StudentListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<Student> list = new ArrayList<Student>();
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
private StudentDao studentDao;
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param studentDao
*/
public StudentListener(StudentDao studentDao) {
this.studentDao = studentDao;
}
/**
* 这个每一条数据解析都会来调用
*
* @param student
* one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param analysisContext
*/
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
System.out.println("invoke方法被调用");
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(student));
list.add(student);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("doAfterAllAnalysed方法 被调用");
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
studentDao.save(list);
LOGGER.info("存储数据库成功!");
}
}
controller层
/**
* 读取 excel
* @return
*/
@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
//写法一
// sheet里面可以传参 根据sheet下标读取或者根据名字读取 不传默认读取第一个
EasyExcel.read(file.getInputStream(), Student.class, new StudentListener(studentDao)).sheet().doRead();.
// 写法2:
/*ExcelReader excelReader = EasyExcel.read(file.getInputStream(), Student.class, new StudentListener(studentDao)).build();
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();*/
return "success";
}
读取excel是如何匹配的,这里我们传入的还是原来的 Student.class
会根据@ExcelProperty 名字去匹配,如果名字重复,会导致只有一个字段读取到数据
也可以通过index 去匹配类似这样
/**
* 强制读取第三个 不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 2)
实现效果大致是这样
有时候我们用传统的excel导出一些报表按一些特定的格式,拼接表头是最恶心的地方,这里我们可以通过配置模板导出
这里我们以填充集合为例
假定要填充 list结合 ,集合Student属性有两个 name ,age
我们先选择一个模板excel放入项目中
然后将数据填充到这个模板中导出,这里以常用的填充list集合为例
固定格式中name 和number需要替换为你自己实体类的属性
测试案例
@GetMapping("template")
public String downloadDataByExcelTemplate(HttpServletResponse response) throws Exception {
// 获取模板路径
/** public static String getPath() { return TestFileUtil.class.getResource("/").getPath(); }**/
String templateFileName =
TestFileUtil.getPath() + "excel" + File.separator + "list.xlsx";
System.out.println("templateFileName" +templateFileName);
response.setContentType("application/vnd.ms-excel");
String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
System.out.println("fileName" + fileName);
EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet().doFill(data());
return "success";
}
w我模板锁放的位置:
模板:
直接调用这个接口测试
https://github.com/weihubeats/springcloud-shopping-parent.git
原网址: 访问
创建于: 2021-08-10 10:48:13
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论