easyExcel用於導入導出

一、添加依賴:java

        <!-- 如今已經更新到1.1.2-beta5 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>1.1.1</version>
        </dependency>    

導入:git

二、添加監聽:github

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

三、導入商品controller:web

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

四、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

導出:apache

一、導出controller服務器

/**
     * 導出維護記錄
     * @param vo
     */
    @PostMapping("/download")
    @ApiOperation(value = "採購單下載")
    public Result<String> exportRecord(@RequestBody PurchaseOrderHeadVO vo) {
        purchaseManageService.exportRecord(vo);
        return Result.success("導出成功");
    }
View Code

二、serviceImplapp

@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異步

相關文章
相關標籤/搜索