Java反射 Poi框架的导入功能

问题: bug记录       -> 希望大佬们指导下

1. 目前是单元格顺序跟属性的顺序必须一致   比如 单元格是  姓名  年龄         我的Bean属性也必须是一致的

2. 单元格数据类型错误, 基本数据类型  时间类型可能会报错
3. 反射级联对象时候判断了大量数据类型 , 目的是区分级联对象和数据类型对象

public @interface Excel {

    /**
     * 属性名称
     * @return
     */
    String attrName() default "";
}

2. 

public class ExcelImport implements Cloneable {

    /**
     * sheet页
     */
    private Sheet sheet;
    /**
     * 工作本
     */
    private Workbook workbook;
    /**
     * 过滤标题的行数
     */
    private final int headerNum = 0;

    /**
     * 存储数据的容器
     */
    private List<Object> objectList = Lists.newArrayList();

    /**
     * 日志记录
     */
    private Logger logger = LoggerFactory.getLogger(ExcelImport.class);

    /**
     * @param fileUrl          文件路径
     * @param sheetIndexOrName 工作表编号或工作表名称
     * @param importObject     那个类需要导入
     */
    public ExcelImport(@Required(message = "文件名称") String fileUrl, @Required(message = "sheet的名称") Object sheetIndexOrName, @Required(message = "需要导入的类") Object importObject) {


        try {
            InputStream inputStream = new FileInputStream(new File(fileUrl));
            if (fileUrl.toLowerCase().endsWith(ExcelEam.EXCEL_XCIX) || fileUrl.toLowerCase().endsWith(ExcelEam.EXCEL_XLS)) {
                workbook = new XSSFWorkbook(inputStream);
            } else {
                throw new OldExcelFormatException("\u4e0d\u5141\u8bb8\u7684\u683c\u5f0f");
            }
            setSheet(sheetIndexOrName, importObject);
        } catch (Exception ex) {
            logger.error("导入工具类出现异常--->异常原因:" + ex.getMessage());
        }

    }

    /**
     * 获取数据
     * @return
     */
    public List<Object> getObjectList() {
        return objectList;
    }


    /**
     * 设置当前工作表 和标题行数
     *
     * @param sheetIndexOrName 工作表编号或工作表名称
     */
    private void setSheet(Object sheetIndexOrName, Object obj) throws Exception {
        if (sheetIndexOrName instanceof Integer || sheetIndexOrName instanceof Long) {
            sheet = workbook.getSheetAt(ObjectUtils.toInteger(sheetIndexOrName));
        } else {
            sheet = workbook.getSheet(ObjectUtils.toString(sheetIndexOrName));
        }
        if (sheet == null) {
            throw new OldExcelFormatException("\u6ca1\u6709\u627e\u5230\u5339\u914d\u7684\u5de5\u4f5c\u8868\u7f16\u53f7\u6216\u5de5\u4f5c\u8868\u540d\u79f0");
        }
        importExcel(obj);


    }


    /**
     * 导入的类
     *
     * @param importObject
     * @return
     * @throws Exception
     */
    private void importExcel(Object importObject) throws Exception {
        //遍历excel的数据行
        for (Row row : sheet) {
            //如果当前行小于等于过滤的行号就跳过本次循环
            if (row.getRowNum() <= headerNum) {
                continue;
            } else {
                //获取单元格数
                int cellCount = row.getPhysicalNumberOfCells();
                for (int index = 0; index <= cellCount; index++) {
                    //如果当前行单元格==当前行最后一个单元格 就代表一个对象绑定成功
                    if (index == cellCount) {
                        objectList.add(importObject);
                        //TODO  创建一个对象重复使用    每行记录一个Object
                        importObject = importObject.getClass().newInstance();
                        continue;
                    } else {
                        //设置单元格类型 string
//                        Object val = getCellType(row, index);
                        //将单元格类型设置为STRING
                        row.getCell(index).setCellType(CellType.STRING);
                        //解析单元格的内容
                        String val = row.getCell(index).getStringCellValue();
                        //反射设置解析的内容
                        setProperty(importObject, val, index);
                    }

                }
            }

        }

        return;
    }


    /**
     * 注入解析的内容
     *
     * @param t
     * @param objectVal
     * @param index
     * @return
     * @throws NotFoundException
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    private void setProperty(Object t, Object objectVal, int index) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException {
        Class<?> classObj = t.getClass();
        Field[] fields = classObj.getDeclaredFields();
        for (int i = index; i < fields.length; i++) {
            //判断是否有加注解
            Excel excel = fields[i].getAnnotation(Excel.class);
            //如果没加注解跳过本次循环  开始加载下一个属性
            if (excel == null) {
                continue;
            } else {
                //获取属性类型
                Type propertyType = fields[i].getGenericType();
                //获取属性名称
                String propertyName = fields[i].getName();
                //转换属性名称 找到setter getter
                String[] propertyFields = formatProperty(propertyName);
                //判断属性类型  反射调用方法
                //TODO String的话不需要级联
                if ("".equals(objectVal) || null == objectVal) {
                    Method setter = classObj.getMethod(propertyFields[0], new Class[]{fields[i].getType()});
                    setter.invoke(t, objectVal);
                } else {
                    //过滤部分数据类型 TODO 这些数据类型也不需要级联
                    if (objectVal.getClass() != Date.class && objectVal.getClass() != Integer.class && objectVal.getClass() != Boolean.class) {
                        //获得一个级联对象
                        Object object = ((Class) propertyType).newInstance();
                        //过滤掉Stirng的Object TODO 如果是String类型说明是简单的属性 不需要级联
                        if ("".equals(object)) {
                            //反射调用属性setter
                            Method setter = classObj.getMethod(propertyFields[0], new Class[]{fields[i].getType()});
                            setter.invoke(t, objectVal);
                        } else {
                            //获取级联属性
                            Class<?> propertyClass = object.getClass();
                            Field[] propertyField = propertyClass.getDeclaredFields();
                            for (Field field : propertyField) {
                                //判断级联属性是否加了注解
                                Excel propertyAnon = field.getDeclaredAnnotation(Excel.class);
                                //如果没加就跳出当前循环
                                if (propertyAnon == null) {
                                    continue;
                                } else {
                                    //获取级联属性的构造参数 实例化无参构造
                                    Constructor constructor = propertyClass.getConstructor();
                                    //调用级联对象的构造函数
                                    Object caracas = constructor.newInstance();
                                    //获取属性名称
                                    String propertyProperty = field.getName();
                                    //转换属性名称 找到setter getter
                                    String[] propertyMethod = formatProperty(propertyProperty);
                                    //执行级联属性的setter  将某级联数据放在级联对象里
                                    Method setter = propertyClass.getMethod(propertyMethod[0], new Class[]{field.getType()});
                                    setter.invoke(caracas, objectVal);
                                    //将级联属性跟对象绑定
                                    Method classMethod = classObj.getMethod(propertyFields[0], caracas.getClass());
                                    classMethod.invoke(t, caracas);
                                }
                            }
                        }
                    }
                    else {
                        Method setter = classObj.getMethod(propertyFields[0], new Class[]{fields[i].getType()});
                        setter.invoke(t, objectVal);
                    }

                }
                return;
            }

        }

    }

    /**
     * 获取单元格内容
     *
     * @param row       哪行
     * @param cellIndex 那个单元格
     */
    private Object getCellType(Row row, int cellIndex) {
        switch (row.getCell(cellIndex).getCellTypeEnum()) {
            case STRING:
                return "".equals(row.getCell(cellIndex).getStringCellValue().trim()) ? "无内容" : row.getCell(cellIndex).getStringCellValue().trim();
            case BOOLEAN:
                return row.getCell(cellIndex).getBooleanCellValue();
            case ERROR:
                return row.getCell(cellIndex).getErrorCellValue();
            case NUMERIC:
                //日期格式
                if (DateUtil.isCellDateFormatted(row.getCell(cellIndex))) {
                    return row.getCell(cellIndex).getDateCellValue();
                } else {
                    return Integer.valueOf((int) row.getCell(cellIndex).getNumericCellValue());
                }
            case BLANK:
                return null;
            default:
                return "没有合适的数据类型";
        }


    }

    /**
     * 将属性首字母大写 转换setter getter
     * [0]setter [1]getter
     *
     * @return
     * @p0aram property
     */
    private String[] formatProperty(String property) {
        return new String[]{"set" + property.substring(0, 1).toUpperCase() + property.substring(1), "get" + property.substring(0, 1).toUpperCase() + property.substring(1)};
    }


}

使用方式 

ExcelImport excelImport = new ExcelImport("C:/Users/13227/Desktop/records.xlsx", "Sheet1", new HealthRecord());
List<Object> objectList = excelImport.getObjectList();
System.out.println(objectList);
上一篇:spring应用之Spring的依赖注入的方式四)


下一篇:Python_getter和setter方法