本人在日常开发中发现很多地方需要对Excel表格进行读取导入的工作,在使用poi开源工具时个人的一些小心得分享给大家.
Maven依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
读取Excel数据的构造方法
ExcelUtil<TestInfo> excelUtil = new ExcelUtil<>(TestInfo.class);
List<TestInfo> testInfo= excelUtil.importExcelNew("构件清单",file.getInputStream());
TestInfo为和Excel表头对应的实体类(请根据实际开发自行调整)
public class TestInfo {
/**
@Excel注解必加
name 参数:是和Excel中的表头字段做映射
defaultValue 参数:建议设置空字符串,这样避免读取到Excel中空值的时候报错
*/
@Excel(name = "姓名",defaultValue = "")
private String name;
@Excel(name = "年龄",defaultValue = "")
private Integer age;
@Excel(name = "地址",defaultValue = "")
private String address;
getter and setter;
}
ExcelUtil 该工具类这里就不展示了,放在文章最后有附件大家可以下载.
importExcelNew方法
ExcelUtil 中的方法,根据传入的sheet名读取对应的Excel中的内容.
该方法可以跳过Excel中的空白行 并且Excel中表头字段的顺序无需按照实体类中的字段顺序排列
同时如果Excel中存在计算公式,会把最终计算的结果赋值到实体类对应的字段上.
public List<T> importExcelNew(String sheetName, InputStream is) throws Exception {
this.type = Type.IMPORT;
this.wb = WorkbookFactory.create(is);
List<T> list = new ArrayList<T>();
Sheet sheet = wb.getSheet(sheetName);
//如果找不到指定sheet名的excel表格 则默认取第一个sheet
if (sheet == null) {
sheet = wb.getSheetAt(0);
}
int rows = sheet.getLastRowNum();
if (rows > 0) {
// 默认序号
int serialNum = 0;
// 有数据时才处理 得到类的所有field.
Field[] allFields = clazz.getDeclaredFields();
// 定义一个map用于存放列的序号和field.
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
Row row2 = sheet.getRow(0);
serialNum = row2.getLastCellNum();
List<Integer> list1 = new ArrayList<>();
Row row1 = sheet.getRow(0);
for (int column = 0; column < serialNum; column++) {
Object val = this.getCellValue(row1, column);
String s = Convert.toStr(val);
for (Field field : allFields) {
String name = field.getAnnotation(Excel.class).name();
if (name.equals(s)){
field.setAccessible(true);
fieldsMap.put(column,field);
list1.add(column);
break;
}
}
}
for (int i = 1; i <= rows; i++) {
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
int cellNum = serialNum;
if (row != null){//判断excel中读取的那一行是否为空 为空就跳过
T entity = null;
for (Integer integer : list1) {
Object val = this.getCellValue(row, integer);
// 如果不存在实例则新建.
entity = (entity == null ? clazz.newInstance() : entity);
// 从map中得到对应列的field.
Field field = fieldsMap.get(integer);
// 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType();
if (String.class == fieldType) {
String s = Convert.toStr(val);
if (StringUtils.endsWith(s, ".0")) {
val = StringUtils.substringBefore(s, ".0");
} else {
val = Convert.toStr(val).trim();
}
} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
val = Convert.toInt(val);
} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
val = Convert.toLong(val);
} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
if (val.equals("")){
val = 0.0;
}else {
val = Convert.toDouble(val);
}
} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
val = Convert.toFloat(val);
} else if (BigDecimal.class == fieldType) {
val = Convert.toBigDecimal(val);
} else if (Date.class == fieldType) {
if (val instanceof String) {
if (((String) val).contains("年") && ((String) val).contains("月") && ((String) val).contains("日")){
val = DateUtils.parseDate(val);
}else {
val = null;
}
} else if (val instanceof Double) {
val = DateUtil.getJavaDate((Double) val);
}
}
if (StringUtils.isNotNull(fieldType)) {
Excel attr = field.getAnnotation(Excel.class);
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr())) {
propertyName = field.getName() + "." + attr.targetAttr();
} else if (StringUtils.isNotEmpty(attr.readConverterExp())) {
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
}
list.add(entity);
}
}
}
return list;
}
ReflectUtils工具类为反射工具类,这里不展示,可在文章结尾的附件下载
几个工具类的文件
链接:https://share.weiyun.com/5GnrCHE 密码:ke3k9a