easyExcel读数据后在写入另一个excel

本文介绍了一种使用Java程序批量处理Excel文件的方法,通过读取Excel中的订单ID,从数据库查询相关信息,并将数据填充回Excel文件的相应位置。文章详细展示了如何利用EasyExcel进行高效的数据读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求说明:如下图所示,excel中有4个sheet,每个sheet的数据格式都一样,有5列,第一列为订单id,现在要根据订单id到数据库中查询出其他几列的信息并补充到excel中。

代码如下:首先为service中的主方法

 public void userMessage() {
//        String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
        ApplicationHome h = new ApplicationHome(getClass());
        File jarF = h.getSource();
        String path = jarF.getParentFile().toString();
        log.info("excel service jar2 path is:"+path+"==============================");
        //获取附件1的excel
        String adjunctOnePath = path+ File.separator+"1.xlsx";
        String adjunctOneWritePath = path+ File.separator+"1_complete.xlsx";
        File srcFile = new File(adjunctOnePath);
        File destFile = new File(adjunctOneWritePath);
        FileUtils.copyFile(srcFile,destFile);

        ExcelReader excelReader = EasyExcel.read(adjunctOnePath)
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(true)
                .build();
        // 新建一个ExcelWriterBuilder实例
        ExcelWriter excelWriter = EasyExcel
                .write(new FileOutputStream(destFile))
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(true).build();

        processSheet(0,excelReader,excelWriter,this::completeSheet1Data);
        processSheet(1,excelReader,excelWriter,this::completeSheet2Data);
        processSheet(2,excelReader,excelWriter,this::completeSheet2Data);
        processSheet(3,excelReader,excelWriter,this::completeSheet4Data);



       excelReader.finish();
       excelWriter.finish();
    }

上面首先我获取到了jar包的所在目录,因为我把excel和jar包放到了同一目录,其中1.xlsx是原始文件,1_complete.xlsx是要写入数据的文件,我这里直接复制了一份原文件。

然后我分别创建了ExcelReader 和ExcelWriter俩个对象,用于读和写excel。后面就是处理4个sheet的代码,我调用了4次方法,下面看下主要逻辑processSheet的代码:

private void processSheet(int sheetNo,ExcelReader excelReader, ExcelWriter excelWriter, Consumer<Map<Integer, String>> consumer) {
        Map<Integer, String> head = new HashMap<>();
        List<List<String>> data = new LinkedList<>();
        // 构建输出的sheet
        WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo,"模板-"+sheetNo).build();

        final int[] num = {0};
        ReadSheet readSheet = EasyExcel.readSheet(sheetNo).registerReadListener(new AnalysisEventListener<Map<Integer, String>>() {

            @Override
            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                head.putAll(headMap);
                List<List<String>> header = head.values().stream().map(Collections::singletonList).collect(Collectors.toList());
                writeSheet.setHead(header);
            }

            @Override
            public void invoke(Map<Integer, String> row, AnalysisContext analysisContext) {
                num[0]++;
                //补充数据
                consumer.accept(row);
                data.add( row.values().stream().collect(Collectors.toList()));
                if(num[0]%50==0){
                    log.info("================read num is {}==============",num[0]);
                    excelWriter.write(data,writeSheet);
                    data.clear();
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                // 这里可以打印日志告知所有行读取完毕
                System.out.println("读取完毕");
                excelWriter.write(data,writeSheet);
            }
        }).build();
        writeSheet.setSheetName(readSheet.getSheetName());
        excelReader.read(readSheet);
    }

可以看到有4个参数,分别是sheet的序号(从0开始),还有上面提到的ExcelReader 和ExcelWriter俩个对象,最后是一个Consumer对象主要用来根据orderid查询其他列的数据,这个consumer跟我的业务有关,不是重点。上面可以看到构造readSheet 对象的时候注册了一个AnalysisEventListener,这个对象内部有三个方法:

invokeHeadMap方法会读取到excel的标题行,我这里读取到之后直接设置到了writeSheet里。

invoke方法会没每一行数据都会触发一次,我这里对每一行数据调用了上面提到的Consumer进行了处理(主要是到数据库里查询其他的数据),将处理后的数据放到一个list里保存,同时每50条会写一次,防止内存数据过多。

doAfterAllAnalysed方法 读取完之后会触发,我这里接着把剩余的数据写入到writesheet。

下面是Consumer对象对应的方法,如下:主要是查询数据。

 private void completeSheet2Data(Map<Integer, String> row) {
        String outerId = row.get(0);
        Condition condition = new Condition(BaixinCreditApply.class);
        condition.createCriteria().andEqualTo("outerOrderId",outerId);
        BaixinCreditApply   baixinCreditApply = baixinCreditApplyMapper.selectOneByExample(condition);
        if(Objects.isNull(baixinCreditApply)){
            log.info("======根据outer id {} 未查询到数据========",outerId);
            return ;
        }
        Long uid = baixinCreditApply.getUid();


        //查询身份证号
        String idCard = "-";
        String idStartDate = "-";
        String idEndDate = "-";
        condition = new Condition(OcrIdCard.class);
        condition.createCriteria().andEqualTo("uid",uid);
        OcrIdCard ocrIdCard = ocrIdCardMapper.selectOneByExample(condition);
        if(Objects.nonNull(ocrIdCard)){
            String idNumberAes = ocrIdCard.getIdNumberAes();
            idCard = BasicInfoEncryptUtil.decrypt(idNumberAes);
            String validDate = ocrIdCard.getValidDate();
            if(StringUtils.isNotBlank(validDate)&&validDate.indexOf("-")>=0){
                idStartDate = validDate.split("-")[0];
                idEndDate = validDate.split("-")[1];
            }

        }

        row.put(1,String.valueOf(uid));
        row.put(2,idStartDate);
        row.put(3,idEndDate);
        row.put(4,idCard);
    }

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值