当前位置: 首页 > news >正文

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

需求说明:如下图所示,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);
    }

 

 

 

 

相关文章:

  • nginx 丢失端口问题
  • centos 安装docker及docker-compose
  • 多个docker-compose文件共享一个网络
  • idea 远程调试springboot项目
  • spring-cloud-consul配置中心获取指定路径下的配置
  • 将red5项目部署到tomcat下,并且red5项目嵌入到J2EE项目中
  • mysql 本机登录错误提示及解决方法
  • 禅道程序员的10条原则
  • 完全删除MYSQL:windows 7下完全删除MYSQL,windows xp 下完全删除MYSQL
  • 小故事大人生 -----七个顶级心理寓言
  • windows 7下mysql5.5.18主从同步设置
  • Flex+Java项目,Myeclipse环境下“Target runtime Apache Tomcat v6.0 is not defined ” 错误解决方法
  • Slave_SQL_Running: No mysql同步故障解决方法
  • 通过基站信息(LAC,CID)调用google的json接口获取地理位置信息的Java代码
  • 笔记本电脑改装成WiFi热点
  • @jsonView过滤属性
  • Akka系列(七):Actor持久化之Akka persistence
  • Angular 响应式表单之下拉框
  • Asm.js的简单介绍
  • CentOS 7 防火墙操作
  • flutter的key在widget list的作用以及必要性
  • Js基础知识(四) - js运行原理与机制
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • php中curl和soap方式请求服务超时问题
  • Ruby 2.x 源代码分析:扩展 概述
  • sublime配置文件
  • 初识 webpack
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 今年的LC3大会没了?
  • 数据结构java版之冒泡排序及优化
  • 思考 CSS 架构
  • 微服务核心架构梳理
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ${factoryList }后面有空格不影响
  • (4)事件处理——(7)简单事件(Simple events)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (8)STL算法之替换
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (已解决)什么是vue导航守卫
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • .sdf和.msp文件读取
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @synthesize和@dynamic分别有什么作用?
  • @TableLogic注解说明,以及对增删改查的影响
  • [20170728]oracle保留字.txt
  • [Android]使用Android打包Unity工程
  • [BSGS算法]纯水斐波那契数列