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

网友投稿 399 2023-04-06


在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包

org.apache.poi

poi-ooxml

3.8

org.apache.poi

poi

3.8

org.apache.poi

poi-ooxml-schemas

3.8

commons-beanutils

commons-beanutils

1.8.3

commons-lang

commons-lang

2.6

非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> read(InputStream inputStream, boolean isExcel2003)

throws IOException

{

List> 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> readDate(Workbook wb)

{

List> dataLst = new ArrayList>();

/** 得到第一个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 rowLst = new ArrayList();

/** 循环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 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 实体列表

* @throws Exception

* @see [类、类#方法、类#成员]

*/

@SuppressWarnings("unchecked")

public static List readDateListT(Workbook wb, T t, int beginLine, int totalcut)

throws Exception

{

List listt = new ArrayList();

/** 得到第一个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类型的时间

*

*

* @param s 日期类型的字符串

* datePattern :YYYY_MM_DD

* @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 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]]

源码下载

源码分享给大家,上面提到的都在这里,由于很多的数据类型没有试验到,可能会有些类型有问题,所以希望大家如果遇到问题回复我,我会将其完善。

源码下载:http://xiazai.jb51.net/201709/yuanma/ImportExcelUtil(jb51.net).rar

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:利用java生成二维码工具类示例代码
下一篇:详解 maven的pom.xml用&lt;exclusion&gt;解决版本问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~