在java poi导入Excel通用工具类示例详解
前言 本文主要给大家介绍了关于java poi导入Excel通用工具类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 问题引入和分析 提示:如果不想看罗嗦的文章,可以直接到最后点击源码下载运行即可 最近在做一个导入Excel的功能,在做之前在百度上面查找“java通用导入Excel工具类”,没有查到,大多数都是java通用导出Excel。后来仔细想想,导出可以利用java的反射,做成通用的,放进相应的实体成员变量中,导入为什么不可以呢?也是可以的,不过在做之前我们要解决如下两个问题: 1.表格中的列数和顺序要和实体类中的成员变量个数和顺序一致。 2.表格中的列的类型要和成员变量的类型一致。 第一个问题: 列数一致可以做到,但是我们最后都是要插入数据库的。那么id是必不可少的,或者良好的习惯可能还有创建时间,创建人等信息。 所以我想到了两个办法: 1.封装一个Vo,只将需要的字段封装进去,并且字段顺序和表格列的顺序一致,再将vo与实体类po转化(用 2.在需要的成员变量上注入自定义注解,并且加入注解的这些字段顺序和表格列的顺序一致,利用反射得到这些字段。 第二个问题: 获取表格数据的时候,我们要判断类型,并取得相应值,全部转化为String类型,当我们给实体类赋值的时候,利用反射获取需要的成员变量的类型,并赋值。 需求 假设我们需求的excel如下: 我们可以看做两部分: 第一部分: 第二行到第11行,为一个列表数据,共有字段5个,分别为:学号,姓名,身份证号码,性别,分数 第二部分: 第12行第五列,第12行第六列,共有字段2个,分别为:总计,平均 项目 需要导入的jar包 1.poi的相关jar包,主要用来处理excel 2.beanutils 利用反射为成员变量赋值 3.commons-lang String判断非空的方法,可以不用自己判断 如若maven项目导入下面的jar包 <!-- poi操作excel --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.8</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.8</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.8</version> </dependency> <!-- beanutils --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.8.3</version> </dependency> <!-- commons-lang--> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> 非maven项目导入下面的jar(下面例子当中用到的jar,有些没用到,可自行处理) commons-beanutils-1.8.3.jar commons-lang-2.6.jar commons-logging-1.1.jar dom4j-1.6.1.jar log4j-1.2.13.jar poi-3.8-20120326.jar poi-excelant-3.8-20120326.jar poi-ooxml-3.8-20120326.jar poi-ooxml-schemas-3.8-20120326.jar poi-scratchpad-3.8-20120326.jar stax-api-1.0.1.jar xmlbeans-2.3.0.jar 项目结构 工具类 package com.dao.chu.excel; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang.StringUtils; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * * excel读取工具类 * * @author daochuwenziyao * @see [相关类/方法] * @since [产品/模块版本] */ public class ImportExeclUtil { private static int totalRows = 0;// 总行数 private static int totalCells = 0;// 总列数 private static String errorInfo;// 错误信息 /** 无参构造方法 */ public ImportExeclUtil() { } public static int getTotalRows() { return totalRows; } public static int getTotalCells() { return totalCells; } public static String getErrorInfo() { return errorInfo; } /** * * 根据流读取Excel文件 * * * @param inputStream * @param isExcel2003 * @return * @see [类、类#方法、类#成员] */ public List<List<String>> read(InputStream inputStream,boolean isExcel2003) throws IOException { List<List<String>> dataLst = null; /** 根据版本选择创建Workbook的方式 */ Workbook wb = null; if (isExcel2003) { wb = new HSSFWorkbook(inputStream); } else { wb = new XSSFWorkbook(inputStream); } dataLst = readDate(wb); return dataLst; } /** * * 读取数据 * * @param wb * @return * @see [类、类#方法、类#成员] */ private List<List<String>> readDate(Workbook wb) { List<List<String>> dataLst = new ArrayList<List<String>>(); /** 得到第一个shell */ Sheet sheet = wb.getSheetAt(0); /** 得到Excel的行数 */ totalRows = sheet.getPhysicalNumberOfRows(); /** 得到Excel的列数 */ if (totalRows >= 1 && sheet.getRow(0) != null) { totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } /** 循环Excel的行 */ for (int r = 0; r < totalRows; r++) { Row row = sheet.getRow(r); if (row == null) { continue; } List<String> rowLst = new ArrayList<String>(); /** 循环Excel的列 */ for (int c = 0; c < getTotalCells(); c++) { Cell cell = row.getCell(c); String cellValue = ""; if (null != cell) { // 以下是判断数据的类型 switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 数字 cellValue = cell.getNumericCellValue() + ""; break; case HSSFCell.CELL_TYPE_STRING: // 字符串 cellValue = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean cellValue = cell.getBooleanCellValue() + ""; break; case HSSFCell.CELL_TYPE_FORMULA: // 公式 cellValue = cell.getCellFormula() + ""; break; case HSSFCell.CELL_TYPE_BLANK: // 空值 cellValue = ""; break; case HSSFCell.CELL_TYPE_ERROR: // 故障 cellValue = "非法字符"; break; default: cellValue = "未知类型"; break; } } rowLst.add(cellValue); } /** 保存第r行的第c列 */ dataLst.add(rowLst); } return dataLst; } /** * * 按指定坐标读取实体数据 * <按顺序放入带有注解的实体成员变量中> * * @param wb 工作簿 * @param t 实体 * @param in 输入流 * @param integers 指定需要解析的坐标 * @return T 相应实体 * @throws IOException * @throws Exception * @see [类、类#方法、类#成员] */ @SuppressWarnings("unused") public static <T> T readDateT(Workbook wb,T t,InputStream in,Integer[]... integers) throws IOException,Exception { // 获取该工作表中的第一个工作表 Sheet sheet = wb.getSheetAt(0); // 成员变量的值 Object entityMemberValue = ""; // 所有成员变量 Field[] fields = t.getClass().getDeclaredFields(); // 列开始下标 int startCell = 0; /** 循环出需要的成员 */ for (int f = 0; f < fields.length; f++) { fields[f].setAccessible(true); String fieldName = fields[f].getName(); boolean fieldHasAnno = fields[f].isAnnotationPresent(IsNeeded.class); // 有注解 if (fieldHasAnno) { IsNeeded annotation = fields[f].getAnnotation(IsNeeded.class); boolean isNeeded = annotation.isNeeded(); // Excel需要赋值的列 if (isNeeded) { // 获取行和列 int x = integers[startCell][0] - 1; int y = integers[startCell][1] - 1; Row row = sheet.getRow(x); Cell cell = row.getCell(y); if (row == null) { continue; } // Excel中解析的值 String cellValue = getCellValue(cell); // 需要赋给成员变量的值 entityMemberValue = getEntityMemberValue(entityMemberValue,fields,f,cellValue); // 赋值 PropertyUtils.setProperty(t,fieldName,entityMemberValue); // 列的下标加1 startCell++; } } } return t; } /** * * 读取列表数据 * <按顺序放入带有注解的实体成员变量中> * * @param wb 工作簿 * @param t 实体 * @param beginLine 开始行数 * @param totalcut 结束行数减去相应行数 * @return List<T> 实体列表 * @throws Exception * @see [类、类#方法、类#成员] */ @SuppressWarnings("unchecked") public static <T> List<T> readDateListT(Workbook wb,int beginLine,int totalcut) throws Exception { List<T> listt = new ArrayList<T>(); /** 得到第一个shell */ Sheet sheet = wb.getSheetAt(0); /** 得到Excel的行数 */ totalRows = sheet.getPhysicalNumberOfRows(); /** 得到Excel的列数 */ if (totalRows >= 1 && sheet.getRow(0) != null) { totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } /** 循环Excel的行 */ for (int r = beginLine - 1; r < totalRows - totalcut; r++) { Object newInstance = t.getClass().newInstance(); Row row = sheet.getRow(r); if (row == null) { continue; } // 成员变量的值 Object entityMemberValue = ""; // 所有成员变量 Field[] fields = t.getClass().getDeclaredFields(); // 列开始下标 int startCell = 0; for (int f = 0; f < fields.length; f++) { fields[f].setAccessible(true); String fieldName = fields[f].getName(); boolean fieldHasAnno = fields[f].isAnnotationPresent(IsNeeded.class); // 有注解 if (fieldHasAnno) { IsNeeded annotation = fields[f].getAnnotation(IsNeeded.class); boolean isNeeded = annotation.isNeeded(); // Excel需要赋值的列 if (isNeeded) { Cell cell = row.getCell(startCell); String cellValue = getCellValue(cell); entityMemberValue = getEntityMemberValue(entityMemberValue,cellValue); // 赋值 PropertyUtils.setProperty(newInstance,entityMemberValue); // 列的下标加1 startCell++; } } } listt.add((T)newInstance); } return listt; } /** * * 根据Excel表格中的数据判断类型得到值 * * @param cell * @return * @see [类、类#方法、类#成员] */ private static String getCellValue(Cell cell) { String cellValue = ""; if (null != cell) { // 以下是判断数据的类型 switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 数字 if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) { Date theDate = cell.getDateCellValue(); SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd"); cellValue = dff.format(theDate); } else { DecimalFormat df = new DecimalFormat("0"); cellValue = df.format(cell.getNumericCellValue()); } break; case HSSFCell.CELL_TYPE_STRING: // 字符串 cellValue = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean cellValue = cell.getBooleanCellValue() + ""; break; case HSSFCell.CELL_TYPE_FORMULA: // 公式 cellValue = cell.getCellFormula() + ""; break; case HSSFCell.CELL_TYPE_BLANK: // 空值 cellValue = ""; break; case HSSFCell.CELL_TYPE_ERROR: // 故障 cellValue = "非法字符"; break; default: cellValue = "未知类型"; break; } } return cellValue; } /** * * 根据实体成员变量的类型得到成员变量的值 * * @param realValue * @param fields * @param f * @param cellValue * @return * @see [类、类#方法、类#成员] */ private static Object getEntityMemberValue(Object realValue,Field[] fields,int f,String cellValue) { String type = fields[f].getType().getName(); switch (type) { case "char": case "java.lang.Character": case "java.lang.String": realValue = cellValue; break; case "java.util.Date": realValue = StringUtils.isBlank(cellValue) ? null : DateUtil.strToDate(cellValue,DateUtil.YYYY_MM_DD); break; case "java.lang.Integer": realValue = StringUtils.isBlank(cellValue) ? null : Integer.valueOf(cellValue); break; case "int": case "float": case "double": case "java.lang.Double": case "java.lang.Float": case "java.lang.Long": case "java.lang.Short": case "java.math.BigDecimal": realValue = StringUtils.isBlank(cellValue) ? null : new BigDecimal(cellValue); break; default: break; } return realValue; } /** * * 根据路径或文件名选择Excel版本 * * * @param filePathOrName * @param in * @return * @throws IOException * @see [类、类#方法、类#成员] */ public static Workbook chooseWorkbook(String filePathOrName,InputStream in) throws IOException { /** 根据版本选择创建Workbook的方式 */ Workbook wb = null; boolean isExcel2003 = ExcelVersionUtil.isExcel2003(filePathOrName); if (isExcel2003) { wb = new HSSFWorkbook(in); } else { wb = new XSSFWorkbook(in); } return wb; } static class ExcelVersionUtil { /** * * 是否是2003的excel,返回true是2003 * * * @param filePath * @return * @see [类、类#方法、类#成员] */ public static boolean isExcel2003(String filePath) { return filePath.matches("^.+.(?i)(xls)$"); } /** * * 是否是2007的excel,返回true是2007 * * * @param filePath * @return * @see [类、类#方法、类#成员] */ public static boolean isExcel2007(String filePath) { return filePath.matches("^.+.(?i)(xlsx)$"); } } public static class DateUtil { // ======================日期格式化常量=====================// public static final String YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss"; public static final String YYYY_MM_DD = "yyyy-MM-dd"; public static final String YYYY_MM = "yyyy-MM"; public static final String YYYY = "yyyy"; public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; public static final String YYYYMMDD = "yyyyMMdd"; public static final String YYYYMM = "yyyyMM"; public static final String YYYYMMDDHHMMSS_1 = "yyyy/MM/dd HH:mm:ss"; public static final String YYYY_MM_DD_1 = "yyyy/MM/dd"; public static final String YYYY_MM_1 = "yyyy/MM"; /** * * 自定义取值,Date类型转为String类型 * * @param date 日期 * @param pattern 格式化常量 * @return * @see [类、类#方法、类#成员] */ public static String dateToStr(Date date,String pattern) { SimpleDateFormat format = null; if (null == date) return null; format = new SimpleDateFormat(pattern,Locale.getDefault()); return format.format(date); } /** * 将字符串转换成Date类型的时间 * <hr> * * @param s 日期类型的字符串<br> * datePattern :YYYY_MM_DD<br> * @return java.util.Date */ public static Date strToDate(String s,String pattern) { if (s == null) { return null; } Date date = null; SimpleDateFormat sdf = new SimpleDateFormat(pattern); try { date = sdf.parse(s); } catch (ParseException e) { e.printStackTrace(); } return date; } } } 自定义注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * 是否需要从解析excel赋值 * @author daochuwenziyao * @see [相关类/方法] * @since [产品/模块版本] */ @Retention(value = RetentionPolicy.RUNTIME) @Target(value = {ElementType.FIELD}) public @interface IsNeeded { /** * 是否需要从解析excel赋值 * @return * true:需要 false:不需要 * @see [类、类#方法、类#成员] */ boolean isNeeded() default true; } 学生基本信息 import java.math.BigDecimal; /** * * 学生基本信息 * @author daochuwenziyao * @see [相关类/方法] * @since [产品/模块版本] */ public class StudentBaseInfo { private Integer id; @IsNeeded private String no; @IsNeeded private String name; @IsNeeded private String idnum; @IsNeeded private String sex; @IsNeeded private BigDecimal grade; @Override public String toString() { return "StudentBaseInfo [id=" + id + ",no=" + no + ",name=" + name + ",idnum=" + idnum + ",sex=" + sex + ",grade=" + grade + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getIdnum() { return idnum; } public void setIdnum(String idnum) { this.idnum = idnum; } public BigDecimal getGrade() { return grade; } public void setGrade(BigDecimal grade) { this.grade = grade; } } 学生统计信息 /** * * 学生统计信息 * @author daochuwenziyao * @see [相关类/方法] * @since [产品/模块版本] */ public class StudentStatistics { private Integer id; @IsNeeded private BigDecimal totalGrade; @IsNeeded private BigDecimal avgGrade; @Override public String toString() { return "StudentStatistics [id=" + id + ",totalGrade=" + totalGrade + ",avgGrade=" + avgGrade + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public BigDecimal getTotalGrade() { return totalGrade; } public void setTotalGrade(BigDecimal totalGrade) { this.totalGrade = totalGrade; } public BigDecimal getAvgGrade() { return avgGrade; } public void setAvgGrade(BigDecimal avgGrade) { this.avgGrade = avgGrade; } } 测试类 package com.dao.chu.excel; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.poi.ss.usermodel.Workbook; public class TestImportExcel { public static void main(String[] args) throws IOException,Exception { String fileName="student.xlsx"; InputStream in = new FileInputStream(new File("excelfilestudent.xlsx")); Workbook wb = ImportExeclUtil.chooseWorkbook(fileName,in); StudentStatistics studentStatistics = new StudentStatistics(); //读取一个对象的信息 StudentStatistics readDateT = ImportExeclUtil.readDateT(wb,studentStatistics,in,new Integer[] {12,5},new Integer[] {13,5}); System.out.println(readDateT); //读取对象列表的信息 StudentBaseInfo studentBaseInfo = new StudentBaseInfo(); //第二行开始,到倒数第三行结束(总数减去两行) List<StudentBaseInfo> readDateListT = ImportExeclUtil.readDateListT(wb,studentBaseInfo,2,2); System.out.println(readDateListT); } } 输出结果 StudentStatistics [id=null,totalGrade=845,avgGrade=84] [StudentBaseInfo [id=null,no=2012240001,name=张三1,idnum=233314199009062304,sex=男,grade=80],StudentBaseInfo [id=null,no=2012240002,name=张三2,grade=81],no=2012240003,name=张三3,grade=82],no=2012240004,name=张三4,grade=83],no=2012240005,name=张三5,grade=84],no=2012240006,name=张三6,grade=85],no=2012240007,name=张三7,grade=86],no=2012240008,name=张三8,grade=87],no=2012240009,name=张三9,grade=88],no=2012240010,name=张三10,grade=89]] 源码下载 源码分享给大家,上面提到的都在这里,由于很多的数据类型没有试验到,可能会有些类型有问题,所以希望大家如果遇到问题回复我,我会将其完善。 源码下载:http://xiazai.aspzz.cn/201709/yuanma/ImportExcelUtil(aspzz.cn).rar 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |