实例详解在java poi导入Excel通用工具类

这篇文章主要给大家介绍了关于在java poi导入Excel通用工具类的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

前言

本文主要给大家介绍了关于java poi导入Excel通用工具类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

问题引入和分析

提示:如果不想看罗嗦的文章,可以直接到最后点击源码下载运行即可

最近在做一个导入Excel的功能,在做之前在百度上面查找“java通用导入Excel工具类”,没有查到,大多数都是java通用导出Excel。后来仔细想想,导出可以利用java的反射,做成通用的,放进相应的实体成员变量中,导入为什么不可以呢?也是可以的,不过在做之前我们要解决如下两个问题:

1.表格中的列数和顺序要和实体类中的成员变量个数和顺序一致。

2.表格中的列的类型要和成员变量的类型一致。

第一个问题:

列数一致可以做到,但是我们最后都是要插入数据库的。那么id是必不可少的,或者良好的习惯可能还有创建时间,创建人等信息。

所以我想到了两个办法:

1.封装一个Vo,只将需要的字段封装进去,并且字段顺序和表格列的顺序一致,再将vo与实体类po转化(用PropertyUtil.copy方法);

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.jarcommons-lang-2.6.jarcommons-logging-1.1.jardom4j-1.6.1.jarlog4j-1.2.13.jarpoi-3.8-20120326.jarpoi-excelant-3.8-20120326.jarpoi-ooxml-3.8-20120326.jarpoi-ooxml-schemas-3.8-20120326.jarpoi-scratchpad-3.8-20120326.jarstax-api-1.0.1.jarxmlbeans-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, T t, 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, fields, f, cellValue);       // 赋值       PropertyUtils.setProperty(newInstance, fieldName, 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("excelfile\\student.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, idnum=233314199009062304, sex=男, grade=81], StudentBaseInfo [id=null, no=2012240003, name=张三3, idnum=233314199009062304, sex=男, grade=82], StudentBaseInfo [id=null, no=2012240004, name=张三4, idnum=233314199009062304, sex=男, grade=83], StudentBaseInfo [id=null, no=2012240005, name=张三5, idnum=233314199009062304, sex=男, grade=84], StudentBaseInfo [id=null, no=2012240006, name=张三6, idnum=233314199009062304, sex=男, grade=85], StudentBaseInfo [id=null, no=2012240007, name=张三7, idnum=233314199009062304, sex=男, grade=86], StudentBaseInfo [id=null, no=2012240008, name=张三8, idnum=233314199009062304, sex=男, grade=87], StudentBaseInfo [id=null, no=2012240009, name=张三9, idnum=233314199009062304, sex=男, grade=88], StudentBaseInfo [id=null, no=2012240010, name=张三10, idnum=233314199009062304, sex=男, grade=89]]

以上就是实例详解在java poi导入Excel通用工具类的详细内容,更多请关注其它相关文章!

穷则思变,差则思勤!没有比人更高的山没有比脚更长的路。

实例详解在java poi导入Excel通用工具类

相关文章:

你感兴趣的文章:

标签云: