使用函数作为参数 传递数据,封装阿里 easyexcel 导出,导入大数据量 excel

  1. 注意 数据是 从函数里面拿到,很多语言都支持 函数作为参数,java8 之后也支持
  2. 函数作为参数 有些不好理解,但是 很多写法 就是比较灵活了 如Scala 代码就十分优雅,鼓励用
 /**
     * 大数量导出
     * @param fileName 生成文件地址
     * @param head 表头
     * @param pageSize 页大小
     * @param pages 总页数
     * @param function 获取数据函数
     * @return
     */
    public String exportBigData(String fileName, Class head, int pageSize, int pages, Function<Integer,List<?>> function) {
        // 每个 sheet 数据量大小 固定最大1百万
        int sheet = 1000000;
        int sheetNum = sheet / pageSize;
        int sheetIndex = 1;
        com.alibaba.excel.ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(fileName, head).build();
            WriteSheet writeSheet = null;
            for (int i = 1; i <= pages; i++) {
                writeSheet = EasyExcel.writerSheet(sheetIndex, "Sheet"+sheetIndex).build();
                // 分页去数据库查询数据
                List list = function.apply(i);
                excelWriter.write(list, writeSheet);
                if(i % sheetNum == 0){
                    sheetIndex++;
                }
            }
        } finally {
            // 关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
        return fileName;
    }
调用

1.导出过 5000w 数据 但是很耗时,数据量大了 可能出现重复数据,因为导出的时候数据可能发生变化
2.分页数据量大,多线程分页加载提高效率 可能会出现内存溢出

 @Test
    public void testExport() throws Exception {
        long  start = System.currentTimeMillis();
        String fileName = "F:\\"+ "repeatedWritetest" + System.currentTimeMillis() + ".xlsx";
        int pageSize = 20000;
        PageHelper.startPage(1,pageSize);
        List<Map> maps = testUserMapper.listData();
        PageInfo pageInfo = new PageInfo<Map>(maps);
        int pages = pageInfo.getPages();
        // 调用
        exportBigData(fileName,DemoData01.class,pageSize, pages,(i)->{
            PageHelper.startPage(i,pageSize,false);
            List<Map> data = testUserMapper.listData();
            return getDemoData01List(maps);
        });

        long  end = System.currentTimeMillis();
        System.out.println("耗时:"+(end-start)/1000 +"秒");
    }

导入封装

/**
     * easy-excel 导入
     * @param inputStream
     * @param clazz
     */
    public static <T> void importEasyExcel(InputStream inputStream, Class clazz, Consumer consumer){
        EasyExcel.read(inputStream, clazz, new ReadListener<T>() {
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 250;
            /**
             *临时存储
             */
            private List<T> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

            @Override
            public void invoke(T data, AnalysisContext context) {
                cachedDataList.add(data);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    consumer.accept(cachedDataList);
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                if(CollectionUtil.isNotEmpty(cachedDataList)){
                    consumer.accept(cachedDataList);
                }
            }
        }).sheet().doRead();;
    }

使用

 @PostMapping("/import")
    public Rest importCard(@NotNull(message = "文件为空") MultipartFile file,
                           @NotNull(message = "规格id 不能为空") Integer specsId) throws IOException {
        ExcelUtils.importEasyExcel(file.getInputStream(), AdminConversionCardExcelImportDTO.class,(data -> {
            List<AdminConversionCardExcelImportDTO> cardExcelImportDTOList = (List<AdminConversionCardExcelImportDTO>) data;
            // 处理数据
        }));
        return Rest.success();
    }
posted @ 2022-05-11 17:10  川流不息&  阅读(408)  评论(0编辑  收藏  举报