阿里Excel工具的简单使用

记一次阿里Excel工具easyexcel的导入简单使用

maven的配置

<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>easyexcel</artifactId>
			<version>1.1.2-beat1</version>
</dependency>

ExcelData类继承BaseRowModel类

public class XlsMonitorData extends BaseRowModel{
    @ExcelProperty(value = "采样日期",index = 1)
    private String time;
}

导入功能的使用

直接使用EasyExcel读取数据,注意的是这里的invoke和doAfterAllAnalysed需要重写,因为是观察者模式,这两个函数再取数据时候会被调用,

ZnfkHsjcMapper znfkHsjcMapper = SpringContextHolder.getBean(ZnfkHsjcMapper.class);
        Integer BATCH_COUNT = 1000;
        List<ZnfkHsjc> znfkHsjcList = new ArrayList<>();
        try {
            EasyExcelFactory.read(multipartFile.getInputStream(),
                    new AnalysisEventListener<Map<Integer,String>>() {
                        //一行一行的读取数据,每到1000个存一次数据,把list集合清空
                        @Override
                        public void invoke(Map<Integer,String> row, AnalysisContext analysisContext) {
                            if(znfkHsjcList.size() >= BATCH_COUNT) {
                                /**
                                 *  保存到数据库
                                 * @date 2022/5/30 16:21
                                 */
                                saveData(znfkHsjcMapper,znfkHsjcList);
                                znfkHsjcList.clear();
                            }

                            if(row != null && row.size() > 0) {
                                ZnfkHsjc znfkHsjc = toZnfkHsjc(row);
                                znfkHsjcList.add(znfkHsjc);
                            }
                        }
						
			//最后读取完的逻辑,因为我们没每1000行存一次list,所以最后这里一定会剩余几行,所以这里可以把剩余的数据存到数据库,然后在清除
                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            /**
                             *  保存到数据库
                             * @date 2022/5/30 16:21
                             */
                            saveData(znfkHsjcMapper,znfkHsjcList);
                            znfkHsjcList.clear();
                        }
                    }
            ).sheet(0).headRowNumber(1).doRead();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("导入数据错误,error = {} \n",e.getMessage(),e);
        }

上传文件的代码,这里使用多线程,先返回给用户结果,保存数据的逻辑操作,在后台慢慢处理。主要逻辑是,把MultipartFile的InputStream取出传入ExcelReader构造函数内,excelReader.read()函数执行会调用观察者的invoke函数。

    public ResponseStatus importHsjcExcel(MultipartFile multipartFile) {
        executor.execute(new ZnfkHsjcThread(multipartFile));
        return ResponseUtil.createResponseStatus(ResponseEnum.OK,("导入成功"));
    }

导出功能

实体类注解

@Data
@Builder
@HeadRowHeight(value = 20)//设置表头行高
@ColumnWidth(value = 15)//设置表头行宽
public class UserExcel {

    @ColumnWidth(value = 15)//单独设置表头行宽
     @ExcelProperty(value = "患者姓名", index = 0)//”0“表示excel中的第一列
    private String Name;
   
    }

创建Excel导出工具类

package com.lyt.business.app.data.v1.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import lombok.extern.log4j.Log4j2;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

@Log4j2
public class ExcelUtil {

    /**
     * web中的读excel
     * 简单读,读到的异常数据会返回;如果需要扩展,请重写EasyExcelReadEventListener监听器中的方法
     * @param inputStream 需要读取的文件流
     * @param list 接收读出的数据
     * @param t 根据注解@ExcelProperty(index = ?)中的index值依次对应赋值
     * @return java.lang.String 返回读取过程中的异常数据及其位置
     */
    public static <T extends Object> String readExcel(InputStream inputStream, Class<T> t,List<T> list){
        StringBuffer errorMsg = new StringBuffer();
        List<T> finalList = list;
        EasyExcel.read(inputStream,t, new EasyExcelReadEventListener(){
            @Override
            public void invoke(Object data, AnalysisContext context) {
                finalList.add((T) data);
            }
            @Override
            public void onException(Exception e, AnalysisContext analysisContext){
                log.error("解析失败,但是继续解析下一行:{}", e.getMessage());
                // 如果是某一个单元格的转换异常 能获取到具体行号
                // 如果要获取头的信息 配合invokeHeadMap使用
                if (e instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)e;
                    log.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex()+1,
                            excelDataConvertException.getColumnIndex()+1, excelDataConvertException.getCellData().getStringValue());
                    String msg = "第"+(excelDataConvertException.getRowIndex()+1)+"行,第"+(excelDataConvertException.getColumnIndex()+1)+"列解析异常,数据为:"
                            +excelDataConvertException.getCellData().getStringValue()+"<br/>";
                    errorMsg.append(msg);
                }
            }
        }).sheet().headRowNumber(2).doRead();
        return errorMsg.toString();
    }

    /**
     * web中的读excel
     * 扩展读,自己重写EasyExcelReadEventListener监听器中的方法
     * @param inputStream 需要读取的文件流
     * @param list 接收读出的数据
     * @param t 根据注解@ExcelProperty(index = ?)中的index值依次对应赋值
     * @param listener 自定义的监听器
     * @return java.lang.String 返回读取过程中的异常数据及其位置
     */
    public static <T extends Object> String readExcel(InputStream inputStream, Class<T> t,List<T> list,EasyExcelReadEventListener listener){
        if (listener == null){
            return readExcel(inputStream,t,list);
        }
        //自行处理数据
        EasyExcel.read(inputStream,t,listener).sheet().headRowNumber(2).doRead();
        return null;
    }

    /**
     * web中的写Excel
     * @param list 要写入的数据
     * @param t Class 读的模板,列标题写成注解@ExcelProperty(value = "")中的value值
     * @param fileName 文件名称
     * @param response HttpServletResponse
     */
    public static <T extends Object> void writeExcel(HttpServletResponse response,List<T> list, Class<T> t, String fileName) throws Exception {
        // 这里注意 使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), t).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("sheet").doWrite(list);
    }
}


serviceImpl层

public ResponseStatus keyPersonYjsOutput(Param param, HttpServletResponse response) {
        List<UserExcel> list = mapper.queryList(param);
        try {
            ExcelUtil.writeExcel(response,list,UserExcel.class,"excel导出");
        } catch (Exception e) {
            log.error("导出出现错误{}",e);
        }
        return ResponseStatus.createOk();
    }

参考链接:

https://blog.csdn.net/qq_41910048/article/details/108934354
https://blog.csdn.net/weixin_44774355/article/details/118967819
posted @ 2022-05-30 19:26  Cloverlove  阅读(1615)  评论(0编辑  收藏  举报