easyexcel导入简单封装

文章目录

1 场景

本文主要对EasyExcel的功能进行简单封装,实现我们在读取excel中的简单操作。
实现以下功能,能满足大多数情况下的Excel文件读取(03版本、07版本+大数据量导入):

(1)获取列索引对应表头(第一行为表头),获取表头主要用于判断
(2)以字符串的形式获取单元格内容,形式为(列号,单元格内容

2 版本

EasyExcel:2.2.7

3 maven依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.7</version>
</dependency>

4 代码

4.1 数据处理器接口

读取每xxx条(默认1000条)数据,调用一次数据处理接口

package com.sa.example.easyexcel.util;

import java.util.List;
import java.util.Map;

/**
 * 数据处理器
 */
public interface BaseProcessor {
    
    /**
     * 回调方法
     * @param list
     */
    void invoke(List<Map<Integer,String>> list);
}

4.2 工具类

(1)工具类方法说明如下:

  • 读取excel表头
// 读取前多少条的表头(第一行数据),封装到List<String>中返回
public static List<String> getExcelHead(InputStream inputStream, Integer headSize);
// 获取所有有内容的表头数据
public static List<String> getExcelHead(InputStream inputStream);
  • 读取excel数据
// 读取1000条数据后,调用一次数据处理器BaseProcessor
public static long readData(InputStream inputStream, BaseProcessor baseProcessor);
// 读取指定条数据batchSize,调用一次数据处理器BaseProcessor
public static long readData(InputStream inputStream, BaseProcessor baseProcessor, final Integer batchSize);

(2)完整工具类代码如下:

package com.sa.example.easyexcel.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Excel工具类
 */
public class ExcelUtil {
    
    /**
     * 行号索引
     */
    public static final Integer ROW_NUMBER_INDEX = -1;
    
    private ExcelUtil() {
        
    }
    
    /**
     * 读取Excel表头
     * @param inputStream 输入流
     * @param headSize    excel表头个数(指定返回的个数)
     * @return
     */
    public static List<String> getExcelHead(InputStream inputStream, Integer headSize) {
        List<String> excelHeadList = getExcelHead(inputStream);
        if (headSize != null && headSize > 0 && CollectionUtils.isNotEmpty(excelHeadList) && excelHeadList.size() >= headSize) {
            return excelHeadList.subList(0, headSize);
        }
        
        return excelHeadList;
    }
    
    
    /**
     * 读取Excel表头
     * @param inputStream 输入流
     * @return excel表头
     */
    public static List<String> getExcelHead(InputStream inputStream) {
        // 表头名称列表
        final List<String> headList = new ArrayList<>();
        
        //继续执行标志
        final AtomicBoolean execFlag = new AtomicBoolean(true);
        
        EasyExcel.read(inputStream, new AnalysisEventListener<Map<Integer, String>>() {
            
            @Override
            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                if (MapUtils.isNotEmpty(headMap)) {
                    for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                        headList.add(entry.getValue());
                    }
                }
                // 终止读取
                execFlag.set(false);
            }
            
            @Override
            public void invoke(Map<Integer, String> data, AnalysisContext context) {
                // Do nothing
            }
            
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // Do nothing
            }
            
            @Override
            public boolean hasNext(AnalysisContext context) {
                return execFlag.get();
            }
        }).sheet().doRead();
        return headList;
    }
    
    /**
     * 读取数据 (默认1000)
     * @param inputStream 文件流
     * @param baseProcessor 自定义处理器
     * @return 读取数据总数量
     */
    public static long readData(InputStream inputStream, BaseProcessor baseProcessor) {
        return readData(inputStream, baseProcessor, 1000);
    }
    
    
    /**
     * 读取数据
     * @param inputStream   文件流
     * @param baseProcessor 处理器
     * @param batchSize     单批次处理数量
     * @return 读取数据总数量
     */
    public static long readData(InputStream inputStream, BaseProcessor baseProcessor, final Integer batchSize) {
        
        // 数据行数
        final AtomicLong dataCount = new AtomicLong(0L);
        
        EasyExcel.read(inputStream, new AnalysisEventListener<Map<Integer, String>>() {
            
            /**
             * 缓存集合
             */
            private List<Map<Integer, String>> list = new ArrayList<>(batchSize);
            
            /**
             * 当前行号
             */
            private Integer lineNumber = 1;
            
            @Override
            public void invoke(Map<Integer, String> data, AnalysisContext context) {
                lineNumber++;
                // 记录总行数
                dataCount.addAndGet(1);
                if (list.size() >= batchSize) {
                    // 批量执行任务
                    if (baseProcessor != null) {
                        baseProcessor.invoke(list);
                    }
                    // 清除缓存
                    list.clear();
                } else {
                    // 记录行号
                    data.put(ROW_NUMBER_INDEX, String.valueOf(lineNumber));
                    // 写入缓存表
                    list.add(data);
                }
            }
            
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                if (baseProcessor != null) {
                    baseProcessor.invoke(list);
                }
            }
        }).sheet().doRead();
        return dataCount.get();
    }
    
}

5 使用

使用到的excel文件《电话区域表.xlsx》如下:

easyexcel导入简单封装

5.1 测试代码

这里设定,每读取6条记录,执行一次数据处理。

// 声明要读取的文件
File file = new File("D:\\电话区域表.xlsx");

// ==========【一、读取表头】==========
final List<String> headList = new ArrayList<>();
try (InputStream inputStream = new FileInputStream(file)) {
    headList.addAll(ExcelUtil.getExcelHead(inputStream));
    System.out.println("获取表头:" + headList + "\n");
} catch (Exception e) {
    e.printStackTrace();
}

// ==========【二、读取文件内容】==========
try (InputStream inputStream = new FileInputStream(file)) {
    long readDataCount = ExcelUtil.readData(inputStream, list -> {
        System.out.println("----------开始调用数据处理----------");
        // 持久化存储
        List<Map<String, Object>> dbDataMapList = new ArrayList<>();
        int headSize = headList.size();
        for (Map<Integer, String> dataMap : list) {
            Map<String, Object> dbDataMap = new HashMap<>(headSize + 1);
            // 行号
            dbDataMap.put("行号", Integer.valueOf(dataMap.get(ExcelUtil.ROW_NUMBER_INDEX)));
            // 导入数据
            for (int i = 0; i < headSize; i++) {
                dbDataMap.put(headList.get(i), dataMap.get(i));
            }
            System.out.println("获取数据:" + dbDataMap);
        }
    }, 6);
    System.out.println("\n----------读取数据总数量:" + readDataCount + "----------");
} catch (Exception e) {
    e.printStackTrace();
}

5.2 输出内容

获取表头:[前缀号段, 手机所在省份, 手机所在城市, 服务商]

----------开始调用数据处理----------
获取数据:{前缀号段=1300000, 手机所在城市=济南, 行号=2, 手机所在省份=山东, 服务商=中国联通}
获取数据:{前缀号段=1300001, 手机所在城市=常州, 行号=3, 手机所在省份=江苏, 服务商=中国联通}
获取数据:{前缀号段=1300002, 手机所在城市=巢湖, 行号=4, 手机所在省份=安徽, 服务商=中国联通}
获取数据:{前缀号段=1300003, 手机所在城市=宜宾, 行号=5, 手机所在省份=四川, 服务商=中国联通}
获取数据:{前缀号段=1300004, 手机所在城市=自贡, 行号=6, 手机所在省份=四川, 服务商=中国联通}
获取数据:{前缀号段=1300005, 手机所在城市=西安, 行号=7, 手机所在省份=陕西, 服务商=中国联通}
----------开始调用数据处理----------
获取数据:{前缀号段=1300007, 手机所在城市=西安, 行号=9, 手机所在省份=陕西, 服务商=中国联通}
获取数据:{前缀号段=1300008, 手机所在城市=武汉, 行号=10, 手机所在省份=湖北, 服务商=中国联通}
获取数据:{前缀号段=1300009, 手机所在城市=西安, 行号=11, 手机所在省份=陕西, 服务商=中国联通}

----------读取数据总数量:10----------
上一篇:EasyExcel导出list到excel表格


下一篇:CLSID与ProgID转换