一、将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 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐