阿里easyExcel使用—下(easyExcel2.0.0 版本)

在这里插入图片描述
源码地址:https://github.com/alibaba/easyexcel
升级版本 升级版本 升级版本
依赖

       <!--阿里easyExcel工具包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.0.2</version>
        </dependency>

对应工具类

/**
 * @author  yy
 * @version 2.0
 * @date 2019/7/30 16:27
 * @deprecated 版本升级为对应的2.0.0以上
 * 性能更加高效  导出数据更加稳定
 * 支持 64M内存1分钟内读取75M(46W行25列)
 **/
 @Component
public class ExcelUtil {
    /**
     * 导出 Excel :一个 sheet,带表头.
     *
     * @param response  HttpServletResponse
     * @param list      数据 list,每个元素为一个 BaseRowModel
     * @param fileName  导出的文件名
     * @param sheetName 导入文件的 sheet 名
     * @param model     映射实体类,Excel 模型
     * @throws Exception 异常
     */


    public  void writeExcel(HttpServletResponse response, List<? extends Object> data,
                                  String fileName, String sheetName, Class model) throws Exception {

        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //设置内容靠左对齐
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(getOutputStream(fileName, response), model)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(sheetName)
                .registerWriteHandler(horizontalCellStyleStrategy)
                //最大长度自适应 目前没有对应算法优化 建议注释掉不用 会出bug
//                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .doWrite(data);

    }


    /**
     * 导出文件时为Writer生成OutputStream.
     *
     * @param fileName 文件名
     * @param response response
     * @return ""
     */
    private  OutputStream getOutputStream(String fileName,
                                                HttpServletResponse response) throws Exception {
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e) {
            throw new Exception("导出excel表格失败!", e);
        }
    }
    
     /**
     * 简单的读
     * @param fileName
     * @param clazz
     * @return
     */
 public List<?> simpleRead(String fileName, Class clazz) {
        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, clazz, new DataListener()).sheet().doRead();
        return new DataListener().saveData();
    }
    
***由于本身listener类没有归spring管理 所以无法获取容器内部的bean实例*** 
 class DataListener extends AnalysisEventListener<User> {
 /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private  final int BATCH_COUNT = 10;
  private  List<User> list = new ArrayList<>();
    public List<User> getList() {
        return list;
    }
        /**
         * 这个每一条数据解析都会来调用
         *
         * @param data
         *            one row value. It is same as {@link AnalysisContext#readRowHolder()}
         * @param context
         */
        @Override
        public void invoke(User data, AnalysisContext context) {
            LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
            list.add(data);
            // 达到BATCH_COUNT了,就需要对list进行清空,防止数据几万条数据在内存,容易OOM
            if (list.size() >= BATCH_COUNT) {
                saveData();
                // 存储完成清理 list
                list.clear();
            }
        }

        /**
         * 所有数据解析完成了 都会来调用
         *
         * @param context
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            // 这里也要保存数据,确保最后遗留的数据也存储到数据库
//            saveData();
            LOGGER.info("所有数据解析完成!");
        }

        /**
         * 加上存储数据库
         */
        private List<?> saveData() {
            LOGGER.info("{}条数据,开始存储数据库!", list.size());
            return list;
        }
    }

实体映射Excelproperty 对应导出Excel表头

@Data
@ColumnWidth(22)
@ContentRowHeight(15) //由于新版本并没有对单元格设置默认值 
所以需要手动对单元格进行赋值
public class User extends BaseRowModel implements Serializable {
    /**
     * value: 单表头如下     如果多表头 则 @ExcelProperty(value = {"姓名1","姓名2","姓名3"}, index = 0)
     * index: 列的号, 0表示第一列
      * @ExcelIgnore   生成Excel忽略那个字段
     */
    /**
     * 姓名
     */

    @ExcelProperty(value = "姓名", index = 0)
    private String name;
    /**
     * 年龄
     */
    @ExcelProperty(value = "年龄", index = 1)
    private String age;
    /**
     * 性别
     */
    @ExcelProperty(value = "性别", index = 2)
    private String sex;
 
}

测试

   @Autowired
    private  ExcelUtil  excelUtil;
    public void testWright() {
        List<User> list = new HashList<>();
        for (int i = 0; i < 10000; i++) {
            User user = new User();
            user.setName(UUID.randomUUID().toString());
            user.setAge("10");
            user.setSex("男");
            list.add(user);
            }
            excelUtil.writeExcel(response, list, "test", "testsheet", user.getClass());
    }
 @Autowired
private  ExcelUtil  excelUtil;
public void testread(){
       User user = new User();
       List<User> list = excelUtil.simpleRead("报表路径",user.getClass());   
       //打印每一个读取的对象
        list.forEach(System.out::println);
    
    }

目前读取报表的监听器需要每次在读取报表时重新new 所以不可以给spring容器管理 只能使用构造方法自己实例化 导致了无法获取容器里面的bean实例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章