Springboot 整合 easyexcel导入导出excel

1. 引入核心依赖

<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 是必须的

1. 根据实体类导出

@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 来看看效果
在这里插入图片描述

是不是特别轻松简单

2. 读取数据

读取数据是一行一行读取的,所以需要创建一个读取一行数据后的监听器

这个监听器需要继承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

有时候我们用传统的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我模板锁放的位置:
在这里插入图片描述
模板:
在这里插入图片描述

直接调用这个接口测试
在这里插入图片描述

更多教程

更多教程请参考官网
github

源码下载

https://github.com/weihubeats/springcloud-shopping-parent.git

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页