java通过poi包导入Excel
Posted xiao-ovo-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java通过poi包导入Excel相关的知识,希望对你有一定的参考价值。
使用Apache POI包导入Excel时是需要根据行和列取到对应的值,因此取值时需要知道该列所对应的值应存放到对象的那个字段中去,表格出现变动就会变的比较麻烦,因此此处使用自定义注解的方式,在对象中标明该属性所对应的表头,从程序中遍历表头找到与之对应的单元格,方便数据的导入。
所需的jar包:(用了一下工具类,因此多导入了两个包)
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.2.1</version> </dependency>
自定义注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD ,ElementType.TYPE) public @interface ExcelIn /** * 导入sheet名称 * @return */ String sheetName() default ""; /** * 字段对应的表头名称 * @return */ String title() default "";
接收导入数据的实体:
@ExcelIn(sheetName = "用户信息") public class UserInfo private String id; @ExcelIn(title = "姓名") private String name; @ExcelIn(title = "年龄") private Integer age; @ExcelIn(title = "出生日期") private Date birthday;
导入Excel数据:
public class ExcelReader<T> private static BeanUtilsBean beanUtilsBean = new BeanUtilsBean(); static beanUtilsBean.getConvertUtils().register(new org.apache.commons.beanutils.converters.DateConverter(null), java.util.Date.class); /** * 表头名字和对应所在第几列的下标,用于根据title取到对应的值 */ private final Map<String,Integer> title_to_index = new HashMap<>(); /** * 所有带有ExcelIn注解的字段 */ private final List<Field> fields = new ArrayList<>(); /** * 统计表格的行和列数量用来遍历表格 */ private int firstCellNum = 0; private int lastCellNum = 0; private int firstRowNum = 0; private int lastRowNum = 0; private String sheetName ; private HSSFSheet sheet ; public List<T> read(InputStream in , Class clazz) throws Exception gatherAnnotationFields(clazz); configSheet(in); configHeader(); List rList= null; try rList = readContent(clazz); catch (IllegalAccessException e) throw new Exception(e); catch (InstantiationException e) throw new Exception(e); catch (InvocationTargetException e) throw new Exception(e); return rList ; private List readContent(Class clazz) throws IllegalAccessException, InstantiationException, InvocationTargetException Object o = null ; HSSFRow row = null ; List<Object> rsList = new ArrayList<>(); Object value = null ; for(int i = (firstRowNum+1);i<=lastRowNum;i++) o = clazz.newInstance(); row = sheet.getRow(i); HSSFCell cell = null ; for (Field field : fields) //根据注解中的title,取到表格中该列所对应的的值 Integer column=title_to_index.get(field.getAnnotation(ExcelIn.class).title()); if(column==null) continue; cell = row.getCell(column); value = getCellValue(cell) ; if(null != value && StringUtils.isNotBlank(value.toString())) beanUtilsBean.setProperty(o, field.getName(), value); rsList.add(o); return rsList ; private void configSheet(InputStream in) throws Exception //HSSFWorkbook:只能创建97-03版本的Excel,即:以xls结尾的Excel // 想要导入xlsx结尾的Excel,用XSSFWorkbook try(HSSFWorkbook wb = new HSSFWorkbook(in)) getSheetByName(wb); catch (FileNotFoundException e) throw new Exception(e); catch (IOException e) throw new Exception(e); /** * 根据sheet获取对应的行列值,和表头对应的列值映射 */ private void configHeader() this.firstRowNum = sheet.getFirstRowNum() ; this.lastRowNum = sheet.getLastRowNum() ; //第一行为表头,拿到表头对应的列值 HSSFRow row = sheet.getRow(firstRowNum); this.firstCellNum = row.getFirstCellNum(); this.lastCellNum = row.getLastCellNum(); for (int i = firstCellNum;i<lastCellNum;i++) title_to_index.put(row.getCell(i).getStringCellValue(),i); /** * 根据sheet名称获取sheet * @param workbook * @return * @throws Exception */ private void getSheetByName(HSSFWorkbook workbook) throws Exception int sheetNumber = workbook.getNumberOfSheets(); for (int i = 0; i < sheetNumber; i++) String name = workbook.getSheetName(i); if(StringUtils.equals(this.sheetName,name)) this.sheet = workbook.getSheetAt(i); return; throw new Exception("excel中未找到名称为"+this.sheetName+"的sheet"); /** * 根据自定义注解,获取所要导入表格的sheet名称和需要导入的字段名称 * @param clazz * @throws Exception */ private void gatherAnnotationFields(Class clazz) throws Exception if(!clazz.isAnnotationPresent(ExcelIn.class)) throw new Exception(clazz.getName()+"类上没有ExcelIn注解"); ExcelIn excelIn = (ExcelIn)clazz.getAnnotation(ExcelIn.class) ; this.sheetName = excelIn.sheetName(); // 得到所有定义字段 Field[] allFields = FieldUtils.getAllFields(clazz) ; // 得到所有field并存放到一个list中 for (Field field : allFields) if (field.isAnnotationPresent(ExcelIn.class)) fields.add(field); if( fields.isEmpty()) throw new Exception(clazz.getName()+"中没有ExcelIn注解字段"); private Object getCellValue(Cell cell) if (cell == null) return ""; Object obj = null; switch (cell.getCellTypeEnum()) case BOOLEAN: obj = cell.getBooleanCellValue(); break; case ERROR: obj = cell.getErrorCellValue(); break; case FORMULA: try obj = String.valueOf(cell.getStringCellValue()); catch (IllegalStateException e) obj = numericToBigDecimal(cell); break; case NUMERIC: obj = getNumericValue(cell); break; case STRING: String value = String.valueOf(cell.getStringCellValue()); value = value.replace(" ", ""); value = value.replace("\\n", ""); value = value.replace("\\t", ""); obj = value; break; default: break; return obj; private Object getNumericValue(Cell cell) // 处理日期格式、时间格式 if (HSSFDateUtil.isCellDateFormatted(cell)) return cell.getDateCellValue(); else if (cell.getCellStyle().getDataFormat() == 58) // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58) double value = cell.getNumericCellValue(); return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value); else return numericToBigDecimal(cell); private Object numericToBigDecimal(Cell cell) String valueOf = String.valueOf(cell.getNumericCellValue()); BigDecimal bd = new BigDecimal(valueOf); return bd;
测试导入结果:
@RunWith(SpringRunner.class) @SpringBootTest public class Test @org.junit.Test public void t() try File file = new File("d:/abc.xls"); ExcelReader<UserInfo> reader = new ExcelReader<>(); InputStream is = new FileInputStream(file); List<UserInfo> list = reader.read(is,UserInfo.class); if (CollectionUtils.isNotEmpty(list)) for (UserInfo u : list) System.out.println("姓名:" + u.getName() + " ,年龄:" + u.getAge() + " ,出身日期:" + u.getBirthday()); catch (Exception e) e.printStackTrace();
导入的Excel数据:(Excel的sheet名称为接收实体对象的sheetName)
结果展示:
以上是关于java通过poi包导入Excel的主要内容,如果未能解决你的问题,请参考以下文章