使用Easyexcel对Excel进行读写操作

1.概述

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址:GitHub - alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具

通过java代码完成对Excel的读写操作,所谓的读写理解为上传和下载

官网:关于Easyexcel | Easy Excel (alibaba.com) 

2. easyexcel写操作

所谓的写操作就是把java中的类对象写入到excel表格中。

使用Easyexcel对Excel进行读写操作_第1张图片

 实现步骤:

1.引入相关依赖

     
          com.alibaba
          easyexcel
          3.0.5
      

2.封装响应的对象

package com.wzh.excel;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

使用Easyexcel对Excel进行读写操作_第2张图片

3.通过easyexcel完成写操作

package com.wzh.excel;

import com.alibaba.excel.EasyExcel;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ProjectName: computer
 * @Package: com.wzh.excel
 * @ClassName: TestWriterDemo
 * @Author: 王振华
 * @Description:
 * @Date: 2022/10/24 20:37
 * @Version: 1.0
 */
public class TestWriterDemo {
    public static void main(String[] args) {
        //fileName:表示excel文件所在路径以及名称
        String fileName = "D:\\java_idea_2020\\dev\\自己代码\\computer\\easyexcel.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可

        //模拟要写入excel的数据
        List list = new ArrayList<>();
        list.add(new DemoData("aaa",new Date(),3.1,"aaaaaa"));
        list.add(new DemoData("bbb",new Date(),3.1,"bbbbbb"));

        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(list);
    }
}

3.easyexcel写操作--web模式

写Excel | Easy Excel (alibaba.com)

package com.wzh.controller;

import com.alibaba.excel.EasyExcel;
import com.wzh.excel.DemoData;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Controller
public class ExcelController {
    /**
     * 文件下载(失败了会返回一个有部分数据的Excel)
     * 

* 1. 创建excel对应的实体对象 参照{@link DownloadData} *

* 2. 设置返回的 参数 *

* 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大 */ @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman 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"); //模拟要写入excel的数据 List list = new ArrayList<>(); list.add(new DemoData("aaa",new Date(),3.1,"aaaaaa")); list.add(new DemoData("bbb",new Date(),3.1,"bbbbbb")); EasyExcel.write(response.getOutputStream(), DemoData.class).sheet("模板").doWrite(list); } }

 这个是我之前的一个工具类:

package com.wzh.utils;

import com.alibaba.excel.EasyExcel;

import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: computer
 * @packageName: com.wzh.utils
 * @author: xmhz45
 * @create: 2022/7/6 19:31
 */
public class ExcelUtil {

    public void print(String filename, List objects, HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            //防止中文乱码
            //String fileName = URLEncoder.encode("测试","utf-8");
            response.setHeader("Content-Disposition","attachment;filename=UTF-8''"+fileName+".xlsx");
            ServletOutputStream outputStream = response.getOutputStream();
            //工作簿对象
            ExcelWriterBuilder writerWork = EasyExcel.write(outputStream,objects.get(0).getClass());
            //工作表对象
            ExcelWriterSheetBuilder sheet = writerWork.sheet(filename);
            sheet.doWrite(objects);
            outputStream.flush();
            outputStream.close();

        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map map = new HashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            e.printStackTrace();

        }
    }

}

4.easyexcel完成读操作

读Excel | Easy Excel (alibaba.com)

使用Easyexcel对Excel进行读写操作_第3张图片

 1.需要一个监听器

package com.wzh.excel;

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 lombok.extern.slf4j.Slf4j;



import java.util.List;

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用   excel数据 07版没有限制
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        //如果excel数据够100条执行if语句  不够的话执行doAfterAllAnalysed方法
        if (cachedDataList.size() >= BATCH_COUNT) {
            System.out.println("100条保存");
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context   最后需要执行的代码
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        System.out.println("不足100条最后调用");
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

2.dao层  之后只需要操作这个  存入数据库即可

package com.wzh.excel;

import java.util.List;

/**
 * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
 **/
@Component
public class DemoDAO {
    public void save(List list) {
        // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    }
}

3.测试

package com.wzh.excel;

import com.alibaba.excel.EasyExcel;

import java.io.File;


public class TestReadDemo {
    public static void main(String[] args) {
        //要读的文件路劲及文件名
        String fileName = "D:\\java_idea_2020\\dev\\自己代码\\computer\\easyexcel.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet
        //DemoData.class:实体类
        //new DemoDataListener() 监听器
        EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
    }
}

使用Easyexcel对Excel进行读写操作_第4张图片

5.easyexcel读操作--web 

ssm框架:

1.依赖--文件上传的依赖

    
    
      commons-fileupload
      commons-fileupload
      1.4
    

2.文件上传解析器


    
    
        
        
    
    /**
     * 文件上传
     * 

* 1. 创建excel对应的实体对象 参照{@link UploadData} *

* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link UploadDataListener} *

* 3. 直接读即可 */ @PostMapping("upload") @ResponseBody public String upload(MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead(); return "success"; }

package com.wzh.controller;

import com.alibaba.excel.EasyExcel;
import com.wzh.excel.DemoDAO;
import com.wzh.excel.DemoData;
import com.wzh.excel.DemoDataListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Controller
public class ExcelController {
    /**
     * 文件下载(失败了会返回一个有部分数据的Excel)
     * 

* 1. 创建excel对应的实体对象 参照{@link DownloadData} *

* 2. 设置返回的 参数 *

* 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大 */ @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman 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"); //模拟要写入excel的数据 List list = new ArrayList<>(); list.add(new DemoData("aaa",new Date(),3.1,"aaaaaa")); list.add(new DemoData("bbb",new Date(),3.1,"bbbbbb")); EasyExcel.write(response.getOutputStream(), DemoData.class).sheet("模板").doWrite(list); } @Autowired private DemoDAO demoDAO; /** * 文件上传 *

* 1. 创建excel对应的实体对象 参照{@link UploadData} *

* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link UploadDataListener} *

* 3. 直接读即可 */ @PostMapping("upload") @ResponseBody public String upload(MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener(demoDAO)).sheet().doRead(); return "success"; } }

测试用postman传参文件:

使用Easyexcel对Excel进行读写操作_第5张图片

 测试的时候会出现一个问题DemoDao没有注入成功,那是因为没有被包扫描到。

springboot:

一个普通类如何被spring所管理,spring boot整合EasyExcel_calf小小牛的博客-CSDN博客

前端需要注意的是  要设置类型  blob

//导出
            printC(){

                if(this.multipleSelection.length!=0){
                    var that = this;
                    axios.post("/outlibrarytransfer/printC?filename=平调入库", this.multipleSelection
                        ,{responseType: 'blob'}).then(function (res){
                        var blob = new Blob([res.data])
                        var downloadElement = document.createElement('a');
                        var href = window.URL.createObjectURL(blob); //创建下载的链接
                        downloadElement.href = href;
                        downloadElement.download = '平调入库.xlsx'; //下载后文件名
                        document.body.appendChild(downloadElement);
                        downloadElement.click(); //点击下载
                        document.body.removeChild(downloadElement); //下载完成移除元素
                        window.URL.revokeObjectURL(href); //释放掉blob对象
                        console.log(res);
                        that.initTable();

                    });
                }else{
                    this.$message.error("请选择要到导出的数据!");
                }
            },

2.poi导出excel

(8条消息) postman 导出excel_天狼1222的博客-CSDN博客_postman 导出excel

(8条消息) poi excel操作汇总_天狼1222的博客-CSDN博客

你可能感兴趣的:(SSM,1024程序员节,excel,java)