实现Excel文件的统一读取功能(包含xls、xlsx、csv格式)

笔者之前使用esayexcel的时候碰到了一个问题,就是easyexcel无法读取csv文件,所以迫不得已之下自己手写了一个统一读取的工具类,在这里分享一下,当然还有许多的不足之处,希望各位看官老爷们不吝指点


一、功能与局限

功能:
1、该工具类可以自动识别表格标题(默认每列的第一行为标题);
2、该工具累可以将读出的表格数据自动转化为实体类集合(表格标题必须要与实体类的属性名一致);

局限:
csv格式的文件只能读取第一页sheet中的表格,xls、xlsx文件是读取的选中sheet页的表格(也就是打开文件开到的那一页);

二、具体实现代码

1、需要的依赖

<!--读取xlsx、xls文件的包-->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.17</version>
</dependency>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.17</version>
</dependency>

<!--读取csv文件的包-->
<dependency>
	<groupId>net.sf.opencsv</groupId>
	<artifactId>opencsv</artifactId>
	<version>2.3</version>
</dependency>

<!--实体类转换需要的包-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.68.noneautotype</version>
</dependency>

2、实现代码

工具类:

package com.muyichen.demo.util;

import au.com.bytecode.opencsv.CSVReader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.muyichen.demo.vo.WorkBookTitleVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ExcelUtil<T> {
    
    

    public static final String CSV_SUFFIX = ".csv";
    public static final String XLS_SUFFIX = ".xls";
    public static final String XLSX_SUFFIX = ".xlsx";


    /**
     * 转换特定类型的集合
     * @param file
     * @param requestId
     * @param t
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> excelRead(MultipartFile file, String requestId, T t) {
    
    
        List<JSONObject> jsonObjects = transExcelForMultipartFile(file, requestId);
        String objs = JSON.toJSONString(jsonObjects);
        return (List<T>) JSONObject.parseArray(objs, t.getClass());
    }

    /**
     * 转换特定类型的集合
     * @param file
     * @param requestId
     * @param c
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> excelReadForFile(File file, String requestId, Class<?> c) {
    
    
        List<JSONObject> jsonObjects = transExcelForFile(file, requestId);
        String objs = JSON.toJSONString(jsonObjects);
        return (List<T>) JSONObject.parseArray(objs, c);
    }

    /**
     * 读取上传Excel文件
     * @param file
     * @param requestId
     * @return
     */
    private static List<JSONObject> transExcelForMultipartFile(MultipartFile file, String requestId) {
    
    
        List<JSONObject> resultList = null;
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件后缀名,截取.后面的类容
        assert fileName != null;
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        try (InputStream inputStream = file.getInputStream()) {
    
    
            resultList = transExcel(requestId, inputStream, suffix);
        } catch (IOException e) {
    
    
            log.error("【黑名单导入】导入文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
            e.printStackTrace();
        }
        return resultList;
    }

    /**
     * 读取Excel文件
     * @param file
     * @param requestId
     * @return
     */
    private static List<JSONObject> transExcelForFile(File file, String requestId) {
    
    
        List<JSONObject> resultList = null;
        // 获取文件名
        String fileName = file.getName();
        // 获取文件后缀名,截取.后面的类容
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        try (InputStream inputStream = new FileInputStream(file)) {
    
    
            resultList = transExcel(requestId, inputStream, suffix);
        } catch (IOException e) {
    
    
            log.error("【黑名单导入】导入文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
        }
        return resultList;
    }

    /**
     * 根据文件后缀名区分读取Excel表格方法
     * @param requestId
     * @param inputStream
     * @param suffix
     * @return
     */
    private static List<JSONObject> transExcel(String requestId, InputStream inputStream, String suffix) {
    
    
        List<JSONObject> resultList = null;
        if (XLS_SUFFIX.equals(suffix)) {
    
    
            // .xls文件
            resultList = readXlsFile(requestId, inputStream);
        } else if (XLSX_SUFFIX.equals(suffix)) {
    
    
            // .xlsx文件
            resultList = readXlsxFile(requestId, inputStream);
        } else if (CSV_SUFFIX.equals(suffix)) {
    
    
            // .csv文件
            resultList = readCsvFile(requestId, inputStream);
        } else {
    
    
            // 不支持格式,抛出异常
        }
        return resultList;
    }

    /**
     * 读取xls文件
     * @param requestId
     * @param in
     * @return
     */
    private static List<JSONObject> readXlsFile(String requestId, InputStream in) {
    
    
        List<JSONObject> resultList = new ArrayList<>();
        HSSFWorkbook hssfWorkbook;
        try {
    
    
            hssfWorkbook = new HSSFWorkbook(in);
            // 获取Excel中所有的sheet
            // int sheetNum = hssfWorkbook.getNumberOfSheets();
            // 获取导入之前Excel文档中的选中页
            int activeSheetIndex = hssfWorkbook.getActiveSheetIndex();
            // 获取选中页中的表格数据
            HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(activeSheetIndex);
            //获取该页有多少行数据
            int rowNum = hssfSheet.getLastRowNum();
            //处理列名数据、自动转化表格标题名为列名
            List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForXls(hssfSheet);
            for(int i = 1; i <= rowNum; i++) {
    
    
                // 获取第i行数据
                HSSFRow hssfRow = hssfSheet.getRow(i);
                JSONObject obj = new JSONObject();
                workBookTitleVOS.forEach(vo -> {
    
    
                    // 将所有字段都默认以字符串的格式读取
                    hssfRow.getCell(vo.getCellIndex()).setCellType(CellType.STRING);
                    obj.put(vo.getColumnName(), hssfRow.getCell(vo.getCellIndex()).toString());
                });
                resultList.add(obj);
            }
        } catch (IOException e) {
    
    
            log.error("Xls文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
        }
        return resultList;
    }

    /**
     * 读取xlsx文件
     * @param requestId
     * @param in
     * @return
     */
    private static List<JSONObject> readXlsxFile(String requestId, InputStream in) {
    
    
        List<JSONObject> resultList = new ArrayList<>();
        XSSFWorkbook xssfWorkbook = null;
        try {
    
    
            //将InputStream转XLSX对象(即表格对象)
            xssfWorkbook = new XSSFWorkbook(in);
            // 获取导入之前Excel文档中的选中页
            int activeSheetIndex = xssfWorkbook.getActiveSheetIndex();
            // 获取选中页中的表格数据
            XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(activeSheetIndex);
            //获取该页有多少行数据
            int rowNum = xssfSheet.getLastRowNum();
            //处理列名数据、自动转化表格标题名为列名
            List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForXlsx(xssfSheet);
            //遍历列表中的每一行数据,并将之封装为JSONObject对象
            for(int i = 1; i <= rowNum; i++) {
    
    
                // 获取第i行数据
                XSSFRow xssfRow = xssfSheet.getRow(i);
                JSONObject obj = new JSONObject();
                workBookTitleVOS.forEach(vo -> {
    
    
                    // 将所有字段都默认以字符串的格式读取
                    xssfRow.getCell(vo.getCellIndex()).setCellType(CellType.STRING);
                    obj.put(vo.getColumnName(), xssfRow.getCell(vo.getCellIndex()).toString());
                });
                resultList.add(obj);
            }
        } catch (IOException e) {
    
    
            log.error("Xlsx文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
        }
        return resultList;
    }

    /**
     * 读取csv文件
     * @param requestId
     * @param in
     * @return
     */
    private static List<JSONObject> readCsvFile(String requestId, InputStream in) {
    
    
        List<JSONObject> resultList = new ArrayList<>();
        InputStreamReader reader = new InputStreamReader(in);
        CSVReader csvReader = new CSVReader(reader);
        List<String[]> list = null;
        try {
    
    
            //将InputStream转XLSX对象(即表格对象)
            list = csvReader.readAll();
            //处理列名数据、自动转化表格标题名为列名
            List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForCsv(list);
            //遍历列表中的每一行数据,并将之封装为JSONObject对象
            for(int i = 1; i < list.size(); i++) {
    
    
                // 获取第i行数据
                String[] csvRow = list.get(i);
                JSONObject obj = new JSONObject();
                workBookTitleVOS.forEach(vo -> {
    
    
                    obj.put(vo.getColumnName(), csvRow[vo.getCellIndex()]);
                });
                resultList.add(obj);
            }
        } catch (IOException e) {
    
    
            log.error("Xlsx文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
        }
        return resultList;
    }

    /**
     * 分析xls文件选中页表格标题栏
     * @return
     */
    private static List<WorkBookTitleVO> analysisWorkBookForXls(HSSFSheet hssfSheet) {
    
    
        // 获取该页有多少列数据
        int cellNum = hssfSheet.getRow(0).getPhysicalNumberOfCells();
        // 遍历取出每一列的第一行数据作为标题存入集合中
        List<WorkBookTitleVO> titleList = new ArrayList<>();
        for(int i = 0; i < cellNum; i++) {
    
    
            // 取出第一行数据
            HSSFRow hssfRow = hssfSheet.getRow(0);
            // 存入表格title实体类中
            WorkBookTitleVO vo = new WorkBookTitleVO();
            vo.setCellIndex(i);
            vo.setColumnName(hssfRow.getCell(i).toString());
            titleList.add(vo);
        }
        return titleList;
    }

    /**
     * 分析xlsx文件选中页表格标题栏
     * @return
     */
    private static List<WorkBookTitleVO> analysisWorkBookForXlsx(XSSFSheet xssfSheet) {
    
    
        // 获取该页有多少列数据
        int cellNum = xssfSheet.getRow(0).getPhysicalNumberOfCells();
        // 遍历取出每一列的第一行数据作为标题存入集合中
        List<WorkBookTitleVO> titleList = new ArrayList<>();
        for(int i = 0; i < cellNum; i++) {
    
    
            // 取出第一行数据
            XSSFRow xssfRow = xssfSheet.getRow(0);
            // 存入表格title实体类中
            WorkBookTitleVO vo = new WorkBookTitleVO();
            vo.setCellIndex(i);
            vo.setColumnName(xssfRow.getCell(i).toString());
            titleList.add(vo);
        }
        return titleList;
    }

    /**
     * 分析csv文件选中页表格标题栏
     * @return
     */
    private static List<WorkBookTitleVO> analysisWorkBookForCsv(List<String[]> list) {
    
    
        // 获取该页有多少列数据
        int cellNum = list.get(0).length;
        // 遍历取出每一列的第一行数据作为标题存入集合中
        List<WorkBookTitleVO> titleList = new ArrayList<>();
        for(int i = 0; i < cellNum; i++) {
    
    
            // 取出第一行数据
            String[] row = list.get(0);
            // 存入表格title实体类中
            WorkBookTitleVO vo = new WorkBookTitleVO();
            vo.setCellIndex(i);
            vo.setColumnName(row[i]);
            titleList.add(vo);
        }
        return titleList;
    }

}

表格标题实体类(转化表格标题使用)

package com.muyichen.demo.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 表格实体类
 * @author muyichen
 * @version 1.0
 */
@Data
public class WorkBookTitleVO implements Serializable {
    
    

    /**
     * sheet页数
     */
    private Integer sheetPage;

    /**
     * 列名
     */
    private String columnName;

    /**
     * 列名所对应的表格列数
     */
    private Integer cellIndex;

}

3、使用方式和结果

测试模版类

package com.muyichen.demo.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 测试模版类
 * @author muyichen
 * @version 1.0
 */
@Data
public class model implements Serializable {
    
    
    
    private Long id;
    
    private String name;
    
    private String video;
    
    private String upImage;
    
    private String downImage;
    
}

测试表格
在这里插入图片描述

测试方法

public static void main(String[] args) {
    
    
    File file = new File("/Users/muyichen/Documents/model.xlsx");
    ExcelUtil<Model> excelUtil = new ExcelUtil<>();
    List<Model> models = excelUtil.excelReadForFile(file, Model.class);
    System.out.println("==============");
}

测试结果
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42697271/article/details/117389200