史上最全EasyExcel

发布时间:2024年01月19日

一、EasyExcel介绍

1、数据导入:减轻录入工作量

2、数据导出:统计信息归档

3、数据传输:异构系统之间数据传输

二、EasyExcel特点

  • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
  • EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
  • EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

文档地址:https://alibaba-easyexcel.github.io/index.html

github地址:https://github.com/alibaba/easyexcel

三,具体的读写操作

1.准备工作

导入依赖

 <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>

创建与表格对应的实体类


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    @ExcelProperty(value = "学生id")
    private Integer id;
    @ExcelProperty(value = "学生姓名")
    private String name;

    @ExcelProperty(value = "学生年龄")
    private Integer age;
}

2.写操作


public class WriteExcel {
    public static void main(String[] args) {

        //准备文件路径
        String fileName="D:/destory/test/easyexcel.xls";
        //写出文件
        EasyExcel.write(fileName, Student.class).sheet("easyexcel")
                .doWrite(data());
    }


    private static List<Student> data(){
        ArrayList<Student> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Student student = new Student(i, "董德" + 1, 22 + i);
            list.add(student);
        }
        return  list;
    }
}

3.读操作

3.1改造实体类

给实体的每一个属性加上索引,对应xls表里面的具体列


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    @ExcelProperty(value = "学生id",index = 0)
    private Integer id;
    @ExcelProperty(value = "学生姓名",index = 1)
    private String name;

    @ExcelProperty(value = "学生年龄",index = 2)
    private Integer age;
}

3.2创建监听器


public class EasyExcelLinster extends AnalysisEventListener<Student> {

  List<Student> list=  new ArrayList<Student>();
    //一行一行的去读取里面的数据
    @Override
    public void invoke(Student student, AnalysisContext analysisContext) {
        System.out.println(student);
        list.add(student);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }


}

3.3读取


public class ReadExcel {
    public static void main(String[] args) {
        //准备文件路径
        String fileName="D:/destory/test/easyexcel.xls";
        EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead();
    }
}

四,实现导出/导入

文件的导入导出也就意味着是文件的下载和批量上传功能,

4.1导出具体实现

导出:需要将数据库里面的文件以附件的形式下载到本地电脑,需要参数为respoonse对象,返回值类型为void

4.1.1后端

controller相关操作,将逻辑交由service去做


    @ApiOperation("导出")
    @GetMapping("/exportData")
    public void exportData(HttpServletResponse response){
        dictService.exportData(response);
    }

service

 @Override
    public void exportData(HttpServletResponse response) {
        try {
            //设置相关参数
            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");
            //获取文件
            List<Dict> list = this.baseMapper.selectList(null);
            //转换文件
            ArrayList<DictEeVo> dictEeVos = new ArrayList<>();
            for (Dict dict : list) {
                DictEeVo dictEeVo = new DictEeVo();
                //转换
                BeanUtils.copyProperties(dict, dictEeVo);
                //添加
                dictEeVos.add(dictEeVo);
            }
            //写出
              EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictEeVos);
          } catch (Exception e) {
              e.printStackTrace();
        }
    }

4.1.2前端

window.open("http://localhost:8202/admin/cmn/dict/exportData")

里面写实际的url地址

前端的操作,非常简单,只需要我们添加单击按钮以及在事件里面操作即可

<div class="el-toolbar">
    <div class="el-toolbar-body" style="justify-content: flex-start;">
      <el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
    </div>
</div>
exportData() {
    window.open("http://localhost:8202/admin/cmn/dict/exportData")
},

4.2导入具体实现

导入:需要将本地文件插入到数据库,参数:multiparefile,返回值:"成功or失败"

4.2.1后端

使用excel进行导入需要监听器的配合,使用监听器对读取的文件进行操作

监听器:用来读取文件,并将数据插入数据库


@Component
public class DictHandler extends AnalysisEventListener<DictEeVo> {
    @Autowired
  private  DictMapper dictMapper;

    //一行一行的读取excel里面的内容
    @Override
    public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
        //转换对象
        Dict dict = new Dict();
        BeanUtils.copyProperties(dictEeVo,dict);
        //设置默认逻辑删除值
        dict.setIsDeleted(0);
        //写入数据库
        dictMapper.insert(dict);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

controller读取文件


    @ApiOperation("导入")
    @PostMapping("/importData")
    public R importData(MultipartFile file){
        //读取文件
        try {
            EasyExcel.read(file.getInputStream(), DictEeVo.class, dictHandler).sheet().doRead();
            return  R.ok().message("导入成功");
        } catch (IOException e) {
            e.printStackTrace();
            return  R.error().message("导入失败");
        }
    }

结合swanger测试发现文件可以成功导入到数据库,开始前端的开发

4.2.2前端

加入按钮以及上传的弹框

 <div class="app-container">
    <!-- 上传与下载的按钮 -->
    <div class="el-toolbar">
    <div class="el-toolbar-body" style="justify-content: flex-start;">
      <el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
        <el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
    </div>
<!-- 上传文件的弹框 -->
<el-dialog title="导入" :visible.sync="dialogImportVisible" width="480px">
    <el-form label-position="right" label-width="170px">
        <el-form-item label="文件">
            <el-upload
                       :multiple="false"
                       :on-success="onUploadSuccess"
                       :action="base_url"
                       class="upload-demo">
                <el-button size="small" type="primary">点击上传</el-button>
                <div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
            </el-upload>
        </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
        <el-button @click="dialogImportVisible = false">取消</el-button>
    </div>
</el-dialog>

点击上传按钮事件以及上传成功事件

//导入文件
    importData(){
      this.dialogImportVisible=true
    },
    onUploadSuccess(response, file, fileList){
    //debugger
    if(response.success){
      //成功
      this.$message.success(response.message);
      //弹框消失
      this.dialogImportVisible=false
      //刷新列表
      this.getAllDict(1)
    }
文章来源:https://blog.csdn.net/weixin_45766875/article/details/135704302
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。