Java 读取 Excel 表格—— Easy Excel 基本使用

两种读对象的方式

  1. 确定表头:建立对象,和表头形成映射关系。
  2. 不确定表头:每一行数据映射为 Map<String, Object>,比如用户自己上传的表格。

两种读取模式

  1. 监听器:先创建监听器、在读取文件时绑定监听器。单独抽离处理逻辑,代码清晰易于维护;一条一条处理,适用于数据量大的场景。
  2. 同步读:无需创建监听器,一次性获取完整数据。方便简单,但是数据量大时会有等待时长,造成卡顿,也可能出现内存溢出。

Easy Excel 基本使用

Easy Excel官网

  1. 导入依赖

    复制代码
         <!-- easy Excel -->
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>easyexcel</artifactId>
             <version>3.1.0</version>
         </dependency>
  2. 需要读取的类对象:

java 复制代码
package com.heo.matchmatebackend.easyExcel;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * 用户表格信息
 */
@Data
public class TableUserInfo {
    /**
     * 用户编号
     */
    @ExcelProperty("用户编号") // 列名匹配(或者也可以用列数 index=0 的方式进行匹配第一列)
    private String userCode;

    /**
     * 用户昵称
     */
    @ExcelProperty("用户昵称")
    private String username;
}
  1. 读取监听器
java 复制代码
package com.heo.matchmatebackend.easyExcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;

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

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(TableUserInfo data, AnalysisContext context) {
        System.out.println(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("已解析完成");
    }

}
  1. 两种读取数据的方法
java 复制代码
package com.heo.matchmatebackend.easyExcel;

import com.alibaba.excel.EasyExcel;

import java.util.List;

/**
 *  导入Excel,读取数据
 */
public class ImportExcel {
    /**
     * 读取数据
     */
    public static void main(String[] args) {
        // 写法1:JDK8+ ,不用额外写一个DemoDataListener
        // since: 3.0.0-beta1
        // Excel数据文件放在自己电脑上,能够找到的路径
        String fileName = "C:\\Codefield\\MY_PROJECT\\match-mate-backend\\src\\main\\resources\\testExcel.xlsx";
//          readByListener(fileName);
        synchronousRead(fileName);
    }
    /**
     * 监听器读取
     * @param fileName
     */
    public static void readByListener(String fileName) {
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        // 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行
        EasyExcel.read(fileName, TableUserInfo.class, new TableListener()).sheet().doRead();
    }

    /**
     * 同步读
     * 同步的返回,不推荐使用,如果数据量大会把数据放到内存里面,且响应时间太久
     */
    public static void synchronousRead(String fileName) {
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<TableUserInfo> list = EasyExcel.read(fileName).head(TableUserInfo.class).sheet().doReadSync();
        for (TableUserInfo tableUserInfo : list) {
            System.out.println(tableUserInfo);
        }

    }
}
  1. 实操案例
java 复制代码
package com.heo.matchmatebackend.easyExcel;

import com.alibaba.excel.EasyExcel;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ImportUser {
    public static void main(String[] args) {
        //Excel数据文件放在自己电脑上,能够找到的路径
        String fileName = "C:\\Codefield\\MY_PROJECT\\match-mate-backend\\src\\main\\resources\\testExcel.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<TableUserInfo> userInfoList =
                EasyExcel.read(fileName).head(TableUserInfo.class).sheet().doReadSync();
        System.out.println("总数 = " + userInfoList.size());
        // 过滤username为空的信息,并分组为 map<列名,列数据的list>
        Map<String, List<TableUserInfo>> listMap =
                userInfoList.stream()
                        .filter(userInfo -> StringUtils.isNotEmpty(userInfo.getUsername()))
                        .collect(Collectors.groupingBy(TableUserInfo::getUsername));
        for (Map.Entry<String, List<TableUserInfo>> stringListEntry : listMap.entrySet()) {
            if (stringListEntry.getValue().size() > 1) {
                System.out.println("username = " + stringListEntry.getKey());
//                System.out.println("1");
            }
        }
        System.out.println("不重复昵称数 = " + listMap.keySet().size());
    }
}
相关推荐
努力学习的小廉13 小时前
【QT(七)】—— 常用控件(四)
开发语言·qt
Coder_Boy_13 小时前
基于SpringAI的在线考试系统-DDD(领域驱动设计)核心概念及落地架构全总结(含事件驱动协同逻辑)
java·人工智能·spring boot·微服务·架构·事件驱动·领域驱动
CoderCodingNo13 小时前
【GESP】C++六级考试大纲知识点梳理, (3) 哈夫曼编码与格雷码
开发语言·数据结构·c++
froginwe1114 小时前
C 标准库 - `<errno.h>`
开发语言
wtsolutions14 小时前
Understanding JSON Formats - What JSON to Excel Supports
json·excel
黎雁·泠崖14 小时前
Java&C语法对比:分支与循环结构核心全解析
java·c语言
鹿角片ljp14 小时前
Java IO流案例:使用缓冲流恢复《出师表》文章顺序
java·开发语言·windows
毕设源码-郭学长14 小时前
【开题答辩全过程】以 广告投放管理系统为例,包含答辩的问题和答案
java
纵有疾風起14 小时前
【Linux 系统开发】基础开发工具详解:自动化构建、版本控制与调试器开发实战
linux·服务器·开发语言·c++·经验分享·开源·bash
wtsolutions14 小时前
Advanced Features - Unlocking the Power of JSON to Excel Pro
linux·json·excel