问题: 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);