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

利用POI和反射实现Excel自动识别实体类导入

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前言:

    刚开始导入Excel的时候,每次有新的Excel文件需要导入的时候就需要重新再新写一个对应的工具来导入excel。所以,鄙人痛定思痛,觉得有必要写一个可以万能导入的Excel工具。

上代码:

private final static String xls = "xls";
private final static String xlsx = "xlsx";

public static Map<String, Object> readExcelPOIT(Object obj) throws Exception
    {
//        FileInputStream fis = (FileInputStream) file.getInputStream();
        Map<String,Object> jsonObject = new HashMap<>();

        String msg = null;
        List<String> msgList = new ArrayList<>();
        //创建输入流
        FileInputStream fis = new FileInputStream(new File("g:\\data\\test.xlsx"));
        //通过构造函数传参
        Workbook workbook = getWorkBookT(new File("g:\\data\\test.xlsx"));
//        Workbook workbook = getWorkBook(file);
        int sheets = workbook.getNumberOfSheets();
        if (sheets<1){
            msg="内容为空";
            msgList.add(msg);
            jsonObject.put("msg",msgList);
            return jsonObject;
        }
        //获取工作标名称
//        for (int i=0;i<sheets;i++){
//            System.out.println(workbook.getSheetName(i));
//
//        }
        //获取工作表 第一张工作表
        Sheet sheet = workbook.getSheetAt(0);
        //获取行,行号作为参数传递给getRow方法,第一行从0开始计算
        //获取第一行
        int firstRowNum = sheet.getFirstRowNum()+2;

        //获取第一行的第一个值进行判断是否为我需要的值
        Row row1 = sheet.getRow(firstRowNum);
        Row row2 = sheet.getRow(firstRowNum-1);

        Class cl = obj.getClass();
        Field[] fs  = cl.getDeclaredFields();
        StringBuilder stringBuilder = new StringBuilder();
        for (Field f : fs ){
            if (stringBuilder.length()==0){
                stringBuilder.append(f.getName());
            }else {
                stringBuilder.append(",");
                stringBuilder.append(f.getName());
            }
        }
        String containsIn = stringBuilder.toString();
        if (row1==null){
            msg="内容为空";
            msgList.add(msg);
            jsonObject.put("msg",msgList);
            return jsonObject;
        }


//        判断 所需字段是否存在
        int cellNum = -1;
        short rowNum = row2.getLastCellNum();
        for (int i=0;i<rowNum;i++){
            Cell cell1 = row2.getCell(i);
            cell1.setCellType(CellType.STRING);
            if (cell1!=null){
                String cellValue = cell1.getStringCellValue();

                if (!containsIn.contains(cellValue)){
                    cellNum=i;
                    break;
                }
            }
        }
        if (cellNum!=-1){
            msg="不存在需要的字段";
            msgList.add(msg);
            jsonObject.put("msg",msgList);
            return jsonObject;
        }


        //最后 一列
//        short lastCellNum = row.getLastCellNum();

        //最后一行
        Integer sheetLastRowNum = sheet.getLastRowNum();
        List<Object> list = new ArrayList<>();
        if (sheetLastRowNum<1){
            msg="数据行不存在";
            msgList.add(msg);
        }
        for (int i=firstRowNum+1;i<sheetLastRowNum+1;i++){
            //获取第i行
            Row row = sheet.getRow(i);
            //获取该列
            Cell cell1 = null;
            if (row!=null){
                Object object = obj.getClass().newInstance();
                BeanUtils.copyProperties(obj,object);
                for (int j=0;j<rowNum;j++){
                    cell1 = row.getCell(j);
//                    String cellValue = row1.getCell(j).getStringCellValue();
                    String cellValue = row2.getCell(j).getStringCellValue();
                    if (cell1==null){
                        msg="第"+i+"行第"+(j+1)+"列值为空";
                        msgList.add(msg);
                        break;
                    }
                    if (cell1!=null){
                        cell1.setCellType(CellType.STRING);
                        if (containsIn.contains(cellValue)){
                            String value = cell1.getStringCellValue();
                            Class cal = CustomerPoolAddRequest.class;
                            Field field = cal.getDeclaredField(cellValue);
                            field.setAccessible(true);
                            field.set(object,value);
                        }

                    }
                }
                Object o =AnnotationUtils.validate(object).get("result");
                if (Boolean.TRUE.equals(o)){

                    list.add(object);
                }
            }
        }
        logger.warn("msgList={}",msgList);
        jsonObject.put("list",list);
        jsonObject.put("msg",msgList);
        workbook.close();
        fis.close();
        return jsonObject;
    }


 public static Workbook getWorkBookT(File file) {
        //获得文件名
//        String fileName = file.getOriginalFilename();
        String fileName = file.getName();
        //创建Workbook工作薄对象,表示整个excel
        Workbook workbook = null;
        try {
            //获取excel文件的io流
//            InputStream is = file.getInputStream();
            FileInputStream is = new FileInputStream(file);
            //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
            if(fileName.endsWith(xls)){
                //2003
                workbook = new HSSFWorkbook(is);
            }else if(fileName.endsWith(xlsx)){
                //2007
                workbook = new XSSFWorkbook(is);
            }
        } catch (IOException e) {
            logger.info(e.getMessage());
        }
        return workbook;
    }
Excel导入规则:

|注释:前三行不被读取|第二行内容字段与接收实体类字段相同|--| |:--------|--------:|:--:| |name|phone|address| |姓名|手机号|地址| |张三|11011011000|杭州| 本次demo中,前三行是被忽略的。第二行的字段与接受的实体类相对应。

如上:只需实体类中用name,phone,address就能接收到姓名为张三 手机号为 11011011000 地址为杭州

ps:

这里我们只对第一张Excel表进行了处理,需要对所有表进行处理的可自行修改

转载于:https://my.oschina.net/u/3022975/blog/2120235

相关文章:

  • 随谈10年的技术生涯和技术成长(转)
  • 以太坊开发环境
  • 8.Kafka offset机制
  • Webview独立进程并通过AIDL实现数据通信
  • axios执行原理了解一下!
  • MySQL语句执行分析(二)
  • 大数据争论:批处理与流处理的C位之战
  • 汉诺(hanio)塔问题
  • docker 系列 - Docker CheatSheet | Docker 配置与实践清单 (转载)
  • CentOS下rpm指令和yum指令详解
  • 微软产品大升级:Surface Pro 6、Studio 2、Laptop 2 重磅来袭
  • mysql8.0 Authentication plugin 'caching_sha2_password' cannot be loaded
  • PostgreSQL 函数式索引使用注意 - 暨非immutable函数不适合索引的原因
  • 零基础兴趣或者转行学习Python,我们应该如何入门呢?
  • bartender 9.4 错误消息6670 无法链接到数据库的解决办法
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • Date型的使用
  • egg(89)--egg之redis的发布和订阅
  • Fastjson的基本使用方法大全
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Javascripit类型转换比较那点事儿,双等号(==)
  • java第三方包学习之lombok
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Linux gpio口使用方法
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Mac转Windows的拯救指南
  • 基于web的全景—— Pannellum小试
  • 讲清楚之javascript作用域
  • 今年的LC3大会没了?
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 微信小程序开发问题汇总
  • 为视图添加丝滑的水波纹
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • !$boo在php中什么意思,php前戏
  • #、%和$符号在OGNL表达式中经常出现
  • #FPGA(基础知识)
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (二开)Flink 修改源码拓展 SQL 语法
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)linux 命令大全
  • (转)菜鸟学数据库(三)——存储过程
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .“空心村”成因分析及解决对策122344
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .NET简谈设计模式之(单件模式)
  • @Autowired @Resource @Qualifier的区别
  • @ConfigurationProperties注解对数据的自动封装
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [4.9福建四校联考]
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [AutoSar]BSW_Memory_Stack_003 NVM与APP的显式和隐式同步
  • [C语言]一维数组二维数组的大小
  • [HackMyVM]靶场Crossbow