zoukankan      html  css  js  c++  java
  • easyExcel用于导入导出

    1、添加依赖:

            <!-- 现在已经更新到1.1.2-beta5 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>1.1.1</version>
            </dependency>    

    导入:

    2、添加监听:

    package com.aikucun.goods.biz.easyexcel;
    
    import com.aikucun.goods.dao.model.vo.SkuModel;
    import com.aikucun.goods.dao.model.vo.SkuUploadFailModel;
    import com.aikucun.sc.common.utils.BeanUtils;
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.google.common.collect.Lists;
    import org.apache.commons.lang3.StringUtils;
    
    import java.util.List;
    
    public class SkuUploadListener extends AnalysisEventListener {
    
        private List<SkuUploadFailModel> uploadFailList = Lists.newArrayList();
    
        private List<SkuModel> skuModelList = Lists.newArrayList();
    
        private int totalSize = 0;
    
        /**
         * 每解析一行,执行一次该方法
         */
        @Override
        public void invoke(Object object, AnalysisContext context) {
            totalSize++;
            SkuModel skuModel = (SkuModel) object;
            if (!checkData(skuModel)) {
                return;
            }
            skuModelList.add(skuModel);
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
    
        }
    
        private boolean checkData(SkuModel skuModel) {
    
            // 失败原因
            String failMessage = "";
            // itemCode
            String itemCode = skuModel.getItemCode();
    
            if (null == skuModel) {
                failMessage = "数据为空";
            }
            // 验证sku
            if (StringUtils.isEmpty(itemCode)) {
                failMessage = "itemCode为空!";
            } else {
                if (skuModelList.contains(itemCode)) {
                    failMessage = failMessage + "itemCode重复!";
                }
            }
            //品牌名称
            if (StringUtils.isEmpty(skuModel.getBrandName())) {
                failMessage = failMessage + "品牌名称为空!";
            }
            //条码必填
            if (StringUtils.isEmpty(skuModel.getBarCode())) {
                failMessage = failMessage + "条码为空!";
            }
    
            if (StringUtils.isNotEmpty(failMessage)) {
                SkuUploadFailModel failModel = new SkuUploadFailModel();
                //数量校验???
                BeanUtils.convert(skuModel, failModel);
                failModel.setFailMessage(failMessage);
    
                uploadFailList.add(failModel);
                return false;
            }
            return true;
    
        }
    
        public List<SkuUploadFailModel> getUploadFailList(){
            return uploadFailList;
        }
    
        public List<SkuModel> getSkuModelList(){
            return skuModelList;
        }
    
        public int getTotalSize() {
            return totalSize;
        }
    }
    View Code

    3、导入商品controller:

        @PostMapping("/import-sku-list-async")
        @ApiOperation("批量导入商品(异步)")
        public Result importSkuListAsync(@RequestBody MultipartFile file) {
            return skuService.importSkuListAsync(file);
        }
    View Code

    4、ServiceImpl

    @Override
        public Result importSkuListAsync(MultipartFile file) {
    
            //1.参数校验
            if (file == null || file.isEmpty()) {
                throw new GoodsException("导入文件为空");
            }
            // 判断文件格式
            String filename = file.getOriginalFilename();
            String suffixName = filename.substring(filename.indexOf("."));
            if (!".xlsx".equalsIgnoreCase(suffixName) && !".xls".equalsIgnoreCase(suffixName)) {
                throw new GoodsException("文件格式要求:.xlsx/.xls");
            }
            dealDataAsync(file, suffixName);
            return Result.success();
        }
    
     /**
         * 异步处理excel数据校验、落库、上传文件服务器等
         *
         * @param file
         */
        @Async
        public void dealDataAsync(MultipartFile file, String suffixName) {
    
            InputStream inputStream = null;
            try {
                inputStream = file.getInputStream();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //1.注册任务
            String dataFlag = System.currentTimeMillis() + "";
            // 任务注册
            Long id = reg("{"service":"goods-web"}", getUserName(), dataFlag, getRealName(), DataFileTaskTypeEnum.IMPORT.getType());
            if (id == null) {
                log.error("【导入商品】 uploadSkuFile 数据版本号:" + dataFlag + ", 注册导入任务失败");
                return;
            }
            //2.excel数据校验
            SkuUploadListener listener = new SkuUploadListener();
            dealExcel(listener, suffixName, id, dataFlag, inputStream);
    
            //3.把错误数据分装集合中,正确数据封装集合中
            // 验证失败的数据
            List<SkuUploadFailModel> uploadFailList = listener.getUploadFailList();
            // 验证通过的数据
            List<SkuModel> skuModeList = listener.getSkuModelList();
            // 总数量
            int totalSize = listener.getTotalSize();
            //4.把成功集合插入数据库,错误数据上传文件服务器
            try {
                for (SkuModel skuModel : skuModeList) {
                    Sku sku = new Sku();
                    BeanUtils.copyProperties(skuModel, sku);
                    saveOrUpdateSku(sku);
                }
            }catch (Exception e){
                log.error("【导入商品】 数据版本号:{},保存采购单报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
                finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", totalSize, 0, "保存到数据库报错", dataFlag);
                return;
            }
            //5.完成任务(上传失败数据到文件服务器)
            // 导入状态
            int status = DataFileTaskStatusEnum.SUCCESS.getType();
            String fileUrl = "";
            // 导入失败的数据,生成异常文件
            if (!CollectionUtils.isEmpty(uploadFailList)) {
                if (CollectionUtils.isEmpty(skuModeList)) {
                    status = DataFileTaskStatusEnum.FAIL.getType();
                } else {
                    status = DataFileTaskStatusEnum.PART_SUCCESS.getType();
                }
                fileUrl = createErrFile(uploadFailList, dataFlag);
            }
            finish(id, status, fileUrl, totalSize, skuModeList.size(), "导入结束", dataFlag);
        }
    
    
    private void dealExcel(SkuUploadListener listener, String suffixName, Long id, String dataFlag, InputStream file) {
            ExcelTypeEnum excelTypeEnum;
            if (ExcelTypeEnum.XLSX.getValue().equalsIgnoreCase(suffixName)) {
                excelTypeEnum = ExcelTypeEnum.XLSX;
            } else if (ExcelTypeEnum.XLS.getValue().equalsIgnoreCase(suffixName)) {
                excelTypeEnum = ExcelTypeEnum.XLS;
            } else {
                log.error("【导入采购单】 uploadPurchaseFile 数据版本号:" + dataFlag + ",上传文件格式不是 " + ExcelTypeEnum.XLSX.getValue() + "/" + ExcelTypeEnum.XLS.getValue());
                finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "文件格式不正确", dataFlag);
                return;
            }
            // 解析文件
            try {
                ExcelReader excelReader = new ExcelReader(file, excelTypeEnum, null, listener);
                excelReader.read(new Sheet(1, 1, SkuModel.class));
            } catch (Exception e) {
                log.error("【导入采购单】 uploadPurchaseFile 数据版本号:{},解析文件报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
                finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "解析文件报错", dataFlag);
                return;
            }
        }
    
    /**
         * 导入商品,异常文件生成
         *
         * @param modelList
         * @param dataFlag
         */
        private String createErrFile(List<SkuUploadFailModel> modelList, String dataFlag) {
            // 生成文件类型
            ByteArrayOutputStream out = null;
            String fileUrl = "";
            try {
                out = new ByteArrayOutputStream();
                ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
                if (modelList.size() > FILE_SIZE) {
                    List<List<SkuUploadFailModel>> splitList = Lists.partition(modelList, FILE_SIZE);
                    for (int i = 0; i < splitList.size(); i++) {
                        //写一个sheet,
                        Sheet sheet = new Sheet(i + 1, 0, SkuUploadFailModel.class);
                        writer.write(splitList.get(i), sheet);
                    }
                } else {
                    //写一个sheet,
                    Sheet sheet = new Sheet(1, 0, SkuUploadFailModel.class);
                    writer.write(modelList, sheet);
                }
                writer.finish();
                CloudStorageService oss = oSSFactory.build();
                String path = oss.getDefaultPath("/导入商品异常反馈.xlsx");
                fileUrl = oss.upload((out).toByteArray(), path);
                log.info("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",生成文件url:" + fileUrl);
            } catch (Exception e) {
                log.error("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return fileUrl;
        }
    
    
    private Long reg(String param, String userName, String dataFlag, String realName, Integer type) {
    
            DataFileTaskDTO dataFileTaskDTO = new DataFileTaskDTO();
            dataFileTaskDTO.setParams(param);
            dataFileTaskDTO.setDataType(SystemModuleEnum.DOWNLOAD_GOODS.getType());
            dataFileTaskDTO.setType(type);
            dataFileTaskDTO.setRemark(SystemModuleEnum.DOWNLOAD_GOODS.getTypeName() + ",数据版本号:" + dataFlag);
            dataFileTaskDTO.setSource(SystemModuleEnum.DOWNLOAD_GOODS.getSystem());
            dataFileTaskDTO.setCreateUser(realName);
            dataFileTaskDTO.setCreateUserJobNumber(userName);
    
            log.info("【导入商品】推送到磐石注册任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(dataFileTaskDTO));
            Result ret = remote.reg(dataFileTaskDTO);
            log.info("【导入商品】推送到磐石注册任务返回结果,ret:{}", JSONObject.toJSONString(ret));
            if (!CheckUtils.isNull(ret) && ret.isSuccess() && ret.getData() != null) {
                return Long.parseLong( ret.getData().toString());
            }
            return null;
        }
    
        private Long finish(Long id, Integer taskStatus, String fileUrl, Integer total, Integer successTotal, String remark, String dataFlag) {
    
            DataFileTaskDTO taskDTO = new DataFileTaskDTO();
            taskDTO.setId(id);
            taskDTO.setTaskStatus(taskStatus);
            taskDTO.setFileUrl(fileUrl);
            taskDTO.setTotal(total == null ? 0 : total);
            taskDTO.setSuccessTotal(successTotal == null ? 0 : successTotal);
            taskDTO.setRemark(remark + ",数据版本号:" + dataFlag);
    
            log.info("【导入商品】推送到磐石完成任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(taskDTO));
            Result ret = remote.finsh(taskDTO);
            log.info("【导入商品】推送到磐石完成任务返回结果,ret:{}", JSONObject.toJSONString(ret));
            if (!CheckUtils.isNull(ret) && ret.isSuccess()) {
                return (Long) ret.getData();
            }
            return null;
        }
    
    
     /**
         * 获取用户名
         *
         * @return
         */
        private String getUserName() {
            // 获取当前用户
            String userName = "";
            LoginUserVo loginUserVo = UserVoThreadLocal.get();
            if (Objects.nonNull(loginUserVo)) {
                userName = loginUserVo.getUserName();
            }
            return userName;
        }
    
        /**
         * 获取真实姓名
         *
         * @return
         */
        private String getRealName() {
            // 获取当前用户
            String realName = "";
            LoginUserVo loginUserVo = UserVoThreadLocal.get();
            if (Objects.nonNull(loginUserVo)) {
                realName = loginUserVo.getRealName();
            }
            return realName;
        }
    View Code

    导出:

    1、导出controller

    /**
         * 导出维护记录
         * @param vo
         */
        @PostMapping("/download")
        @ApiOperation(value = "采购单下载")
        public Result<String> exportRecord(@RequestBody PurchaseOrderHeadVO vo) {
            purchaseManageService.exportRecord(vo);
            return Result.success("导出成功");
        }
    View Code

    2、serviceImpl

    @Async
        public void createRecordFile(PurchaseOrderHeadVO vo, String currentUserName, String realName,Long id,String dataFlag) {
            log.info("【导出采购单】 createRecordFile 开始,参数:{},用户:{},开始时间:{} ,数据版本号:{}", JSON.toJSONString(vo), currentUserName, System.currentTimeMillis(), dataFlag);
            // 任务注册
            if (id == null) {
                return;
            }
            // 生成文件类型
            ByteArrayOutputStream out = null;
            Map<String, Object> map = getStringObjectMap(vo);
            // 根据条件查询
            List<PurchaseOrderModel> list = purchaseOrderExtendMapper.listForEceport(map);
            if (CollectionUtils.isEmpty(list)) {
                log.info("【导出采购单】 createRecordFile 未查询到需要导出的数据,数据版本号:" + dataFlag);
                finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "查询数据为空", dataFlag);
                return;
            }
            try {
                // 批量生成文件,每个文件数据,最多 6万
                List<PurchaseDownloadModel> modelList = new ArrayList<>();
                for (PurchaseOrderModel entity : list) {
                    PurchaseDownloadModel model = new PurchaseDownloadModel();
                    BeanUtils.copyProperties(entity, model);
                    // 采购模型
                    model.setPurchaseMode(PurchaseModeDictEnum.getNameByCode(model.getPurchaseMode()));
                    // 采购类型
                    model.setPurchaseType(PurchaseTypeDictEnum.getNameByCode(model.getPurchaseType()));
                    // 采购状态
                    model.setStatus(PurchaseStatusEnum.getNameByCode(model.getStatus()));
                    // 业务线
                    model.setBusinessLine(PurchaseBusinessDictEnum.getNameByCode(model.getBusinessLine()));
                    modelList.add(model);
                }
                out = new ByteArrayOutputStream();
                ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
                if (modelList.size() > FILE_SIZE) {
                    List<List<PurchaseDownloadModel>> splitList = Lists.partition(modelList, FILE_SIZE);
                    for (int i = 0; i < splitList.size(); i++) {
                        //写一个sheet,
                        Sheet sheet = new Sheet(i + 1, 0, PurchaseDownloadModel.class);
                        writer.write(splitList.get(i), sheet);
                    }
                } else {
                    //写一个sheet,
                    Sheet sheet = new Sheet(1, 0, PurchaseDownloadModel.class);
                    writer.write(modelList, sheet);
                }
                writer.finish();
                CloudStorageService oss = oSSFactory.build();
                String path = oss.getDefaultPath("/采购单导出.xlsx");
                String url = oss.upload((out).toByteArray(), path);
                finish(id, DataFileTaskStatusEnum.SUCCESS.getType(), url, list.size(), list.size(), "导出成功", dataFlag);
                log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",生成文件url:" + url);
            } catch (Exception e) {
                log.error("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
                // 发生异常,删除文件
                finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", list.size(), 0, "导出报错,数版本号:" + dataFlag, dataFlag);
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",结束,时间:" + System.currentTimeMillis());
        }
    View Code

    另外建议参考:https://github.com/HowieYuan/easyexcel-encapsulation

  • 相关阅读:
    cocos2dx3.0戳青蛙游戏(打地鼠)
    深入理解Tomcat系列之五:Context容器和Wrapper容器
    linux下拷贝隐藏文件
    8.8.1 运行计划
    UVALive
    堆排序实现
    C语言中的signal函数
    uboot和内核分区的改动
    Android缩放动画
    .Net 自定义应用程序配置
  • 原文地址:https://www.cnblogs.com/wzk-0000/p/11208199.html
Copyright © 2011-2022 走看看