JAVA读取Excel文件

工具类

 

/**
     * 同步无模型读取(默认读取sheet0,从第2行开始读)
     *
     * @param filePath 文件路径
     * @return List<Map < Integer, String>>
     */
    public static List<Map<Integer, String>> syncRead(String filePath) {
        return EasyExcelFactory.read(filePath).sheet().doReadSync();
    }

    /**
     * 同步无模型读取(默认表头占一行,从第2行开始读)
     *
     * @param filePath 文件路径
     * @param sheetNo  sheet页号,从0开始
     * @return List<Map < Integer, String>>
     */
    public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).doReadSync();
    }

    /**
     * 同步无模型读取(指定sheet和表头占的行数)
     *
     * @param inputStream 输入流
     * @param sheetNo     sheet页号,从0开始
     * @param headRowNum  表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<Map < colNum, cellValue>>
     */
    public static List<Map<Integer, String>> syncRead(InputStream inputStream, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }

    /**
     * 同步无模型读取(指定sheet和表头占的行数)
     *
     * @param file       文件
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<Map < colNum, cellValue>>
     */
    public static List<Map<Integer, String>> syncRead(File file, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }

    /**
     * 同步无模型读取(指定sheet和表头占的行数)
     *
     * @param filePath   文件路径
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<Map < colNum, cellValue>>
     */
    public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
    }

    /**
     * 同步按模型读取(默认读取sheet0,从第2行开始读)
     *
     * @param filePath 文件路径
     * @param clazz    模型的类类型(excel数据会按该类型转换成对象)
     * @return List<T>
     */
    public static List<T> syncReadModel(String filePath, Class<?> clazz) {
        return EasyExcelFactory.read(filePath).sheet().head(clazz).doReadSync();
    }

    /**
     * 同步按模型读取(默认表头占一行,从第2行开始读)
     *
     * @param filePath 文件路径
     * @param clazz    模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo  sheet页号,从0开始
     * @return List<T>
     */
    public static List<T> syncReadModel(String filePath, Class<?> clazz, Integer sheetNo) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读取(指定sheet和表头占的行数)
     *
     * @param inputStream 输入流
     * @param clazz       模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo     sheet页号,从0开始
     * @param headRowNum  表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<T>
     */
    public static List<T> syncReadModel(InputStream inputStream, Class<?> clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读取(指定sheet和表头占的行数)
     *
     * @param file       文件
     * @param clazz      模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<T>
     */
    public static List<T> syncReadModel(File file, Class<?> clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }

    /**
     * 同步按模型读取(指定sheet和表头占的行数)
     *
     * @param filePath   文件路径
     * @param clazz      模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo    sheet页号,从0开始
     * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
     * @return List<T>
     */
    public static List<T> syncReadModel(String filePath, Class<?> clazz, Integer sheetNo, Integer headRowNum) {
        return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
    }


    /**
     * 异步按模型读取(默认表头占一行,从第2行开始读)
     */

    /**
     * 异步按模型读取
     *
     * @param file          文件
     * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
     * @param clazz         模型的类类型(excel数据会按该类型转换成对象)
     * @param sheetNo       sheet页号,从0开始
     * @param headRowNum    表头占的行数,从0开始(如果要连表头一起读出来则传0)
     */
    public static void asyncReadModel(File file, AnalysisEventListener<T> excelListener, Class<?> clazz, Integer sheetNo, Integer headRowNum) {
        EasyExcelFactory.read(file, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
    }

    /**
     * 异步按模型读取 文件路径
     */

    /**
     * 异步按模型读取 输入流
     *
     */

    /**
     * 无模板写文件 文件路径
     */


    /**
     * 无模板写文件 指定sheet名称
     */

    /**
     * 根据excel模板文件写入文件
     */

    /**
     * 根据excel模板文件写入文件
     *
     */

    /**
     * 按模板写文件
     */

    /**
     * 按模板写文件
     *
     */

    /**
     * 按模板写文件(包含某些字段)
     */

    /**
     * 按模板写文件(排除某些字段)
     */

    /**
     * 多个sheet页的数据链式写入
     */


    /**
     * 多个sheet页的数据链式写入(失败了会返回一个有部分数据的Excel)
     */

    /**
     * 同步按模型读,设置监听(指定sheet和表头占的行数)
     */
View Code

 监听器

public class ExcelListener<T> extends AnalysisEventListener<T> {

    // 保存读取的对象
    private final List<T> rows = new ArrayList<>();
    // 日志输出
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private String sheetName = "";
    // 获取对应类
    private Class headClazz;
    // 此map用来存储错误信息
    private final List<String> errorMessage = new ArrayList<>();

    public ExcelListener(Class headClazz) {
        this.headClazz = headClazz;
    }

    /**
     * @param headClazz
     * @Description 通过class获取类字段信息
     */
    public Map<Integer, String> getIndexNameMap(Class headClazz) throws NoSuchFieldException {
        Map<Integer, String> result = new HashMap<>();
        Field field;
        Field[] fields = headClazz.getDeclaredFields();     //获取类中所有的属性
        for (int i = 0; i < fields.length; i++) {
            field = headClazz.getDeclaredField(fields[i].getName());
//            logger.info(String.valueOf(field));
            field.setAccessible(true);
            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);//获取根据注解的方式获取ExcelProperty修饰的字段
            if (excelProperty != null) {
                int index = excelProperty.index();         //索引值
                String[] values = excelProperty.value();   //字段值
                StringBuilder value = new StringBuilder();
                for (String v : values) {
                    value.append(v);
                }
                result.put(index, value.toString());
            }
        }
        return result;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        logger.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
        Map<Integer, String> head = new HashMap<>();
        try {
            head = getIndexNameMap(headClazz);   //通过class获取到使用@ExcelProperty注解配置的字段
            logger.info(String.valueOf(head));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        Set<Integer> keySet = head.keySet();  //解析到的excel表头和实体配置的进行比对
        for (Integer key : keySet) {
            if (StringUtils.isEmpty(headMap.get(key))) {
                errorMessage.add("您上传的文件第" + (key + 1) + "列表头为空,请安照模板检查后重新上传");
            }
            if (!headMap.get(key).equals(head.get(key))) {
                errorMessage.add("您上传的文件第" + (key + 1) + "列表头与模板表头不一致,请检查后重新上传");
            }
        }
    }


    @Override
    public void invoke(T t, AnalysisContext analysisContext) {
        rows.add(t);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 当前sheet的名称 编码获取类似
        sheetName = analysisContext.readSheetHolder().getSheetName();
        logger.info(sheetName);
        logger.info("read {} rows", rows.size());
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
        logger.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
            errorMessage.add("第" + excelDataConvertException.getRowIndex() + "行,第" + (excelDataConvertException.getColumnIndex() + 1) + "列数据类型解析异常,数据为:" + excelDataConvertException.getCellData());
            logger.error("第{}行,第{}列数据类型解析异常,数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex() + 1, excelDataConvertException.getCellData());
        }
    }



    public List<T> getRows() {
        return rows;
    }

    public Class getHeadClazz() {
        return headClazz;
    }

    public List<String> getErrorMessage() {
        return errorMessage;
    }

    public String getSheetName() {
        return sheetName;
    }
}
View Code

 

 

 

具体使用

public void upload(@RequestParam("file") MultipartFile file) throws Exception {
        File newFile = FileUtil.multipartFileToFile(file);

        //创建监听器
        ExcelListener listener = new ExcelListener(BoxAndUnitDTO.class);
        //调用EasyExcelUtils
        EasyExcelUtils.asyncReadModel(newFile, listener, BoxAndUnitDTO.class, 0, 1);

        //获取解决出的错误信息
        List<String> errorMessage = listener.getErrorMessage();
        System.out.println("errorMessage = " + errorMessage);

        //获取监听器读到的数据
        List<String> rows = listener.getRows();
        for (Object o : rows) {
            System.out.println(o.toString());
        }
        FileUtil.deleteTempFile(newFile);
}
View Code

 

posted @ 2023-02-27 09:33  歳月  阅读(47)  评论(0)    收藏  举报