已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools
POI 导入篇
1、maven jar 包依赖:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<poi.version>3.12</poi.version>
<dict>exceltools</dict><!-- 项目名称 -->
</properties>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
不用maven的可以自行下载这两个jar包,加入项目中。
2、项目目录树:
3、定义注解类:
(一):ExcelImportCol.java :
/**
* @package :com.andy.demo.execltools.imports.annotation<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:44:28<br>
*/
package com.andy.demo.execltools.imports.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述:Excel 导入属性注解类 <br>
* <br>
* 1、导入的类必须添加注解类ExcelImportConfig<br>
* 2、该注解类用在类属性上,获取Excel所在列的记录<br>
*
* @package :com.andy.demo.execltools.imports.annotation<br>
* @file :ExcelImportCol.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:44:28<br>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface ExcelImportCol {
/**
*
* 描述:Excel 所在列 <br>
*
* @method :col<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:44:59 <br>
* @return Excel 所在列
*/
int col();
}
(二):ExcelImportConfig.java :
/**
* @package :com.andy.demo.execltools.imports.annotation<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:21:11<br>
*/
package com.andy.demo.execltools.imports.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述:Excel 导入注解类: <br>
* <br>
* 1、导入的类必须添加该注解类 <br>
* 2、默认从第1行导入 <br>
* 3、如果 notNullCols 方法中每一列都为空,则系统认为该条数据不正确,需去除 <br>
*
* @package :com.andy.demo.execltools.imports.annotation<br>
* @file :ExcelImportConfig.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:21:11<br>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ExcelImportConfig {
/**
*
* 描述:读取Excel数据记录的开始行,默认为1,即从第1行开始 <br>
*
* @method :startLine<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:21:48 <br>
* @return 有效数据记录的开始行
*/
int startLine() default 1;
/**
*
* 描述:读取Excel数据记录非空列索引数组,默认为null,即每一列都可以为空;列索引从0开始<br>
* <br>
* 1、如果非空列数组为null,则读取每一行的数据作为一条记录<br>
* 2、如果非空列数组不为null,例如为[0],则若每行的第0列为空,则不读取该行记录;反之读取该行记录<br>
* 3、如果非空列数组不为null,例如为[0,1],则若每行的第0列、第1列同时都为空,则不读取该行记录;反之读取该行记录<br>
*
* @method :notNullCols<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:28:57 <br>
* @return Excel数据记录非空列索引数组
*/
int[] notNullCols() default {};
}
3、导入工具类:
/**
* @package :com.andy.demo.execltools.imports<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:18:29<br>
*/
package com.andy.demo.execltools.imports;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
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.ss.usermodel.WorkbookFactory;
import com.andy.demo.execltools.imports.annotation.ExcelImportCol;
import com.andy.demo.execltools.imports.annotation.ExcelImportConfig;
/**
* 描述: Excel 导入工具类<br>
* <br>
* 方法一:excelImport(InputStream, Class) : 将 文件流 转化为 List对象集合,sheet索引默认为0;<br>
* 方法一:excelImport(InputStream, Class, int) : 将 文件流 转化为 List对象集合,可设置sheet索引位置<br>
*
* @package :com.andy.demo.execltools.imports<br>
* @file :ExcelToolsImport.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:18:29<br>
*/
public class ExcelToolsImport {
/**
*
* 描述:获取Excel的载体实体类集合,默认导入Excel的sheet索引值为0 <br>
*
* @method :excelImport<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午11:14:59 <br>
* @param fileInputStream
* :导入Excel生成的文件流
* @param cla
* :导入Excel的载体实体类
* @return
* @throws Exception
*/
public static <T> List<T> excelImport(InputStream fileInputStream,
Class<T> cla) throws Exception {
return excelImport(fileInputStream, cla, 0);
}
/**
*
* 描述:获取Excel的载体实体类集合 <br>
*
* @method :excelImport<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午11:08:17 <br>
* @param fileInputStream
* :导入Excel生成的文件流
* @param cla
* :导入Excel的载体实体类
* @param sheetIndex
* :导入Excel的sheet索引值
* @return
* @throws Exception
*/
public static <T> List<T> excelImport(InputStream fileInputStream,
Class<T> cla, int sheetIndex) throws Exception {
checkValidate(fileInputStream, cla);
Workbook workbook = WorkbookFactory.create(fileInputStream);
Sheet sheet = workbook.getSheetAt(sheetIndex);
// 获取最大行和开始行
int rows = sheet.getLastRowNum();
int startLine = getStartLine(cla);
List<T> list = new ArrayList<T>();
Row row = null;
T t = null;
for (int i = startLine; i <= rows; i++) {
row = sheet.getRow(i);
t = addLine2List(row, cla);
if (validateNotNull(t)) {
list.add(t);
}
}
return list;
}
/**
*
* 描述:读取行,转化为指定的对象 <br>
*
* @method :addLine2List<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午11:27:04 <br>
* @param row
* : Excel Row行对象
* @param cla
* :导入Excel的载体实体类
* @return
* @throws Exception
*/
private static <T> T addLine2List(Row row, Class<T> cla) throws Exception {
T t = cla.newInstance();
List<Field> list = getExcelImportColAnnoFields(cla);
for (Field field : list) {
setCell2Obj(field, row, t);
}
return t;
}
/**
*
* 描述:读取单元格,设置实体属性值 <br>
*
* @method :setCell2Obj<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午12:47:32 <br>
* @param field
* :实体对象中带有ExcelImportCol注解的属性
* @param row
* :Excel Row 行对象
* @param t
* :封装的实体对象
* @return
* @throws Exception
*/
private static <T> T setCell2Obj(Field field, Row row, T t)
throws Exception {
// 获取列索引、单元格
int col = field.getAnnotation(ExcelImportCol.class).col();
Cell cell = row.getCell(col);
if (null != cell) {
String typeName = field.getType().getSimpleName();
// 获取属性的写入方法
String propertyName = field.getName();
PropertyDescriptor pd = new PropertyDescriptor(propertyName,
t.getClass());
Method m = pd.getWriteMethod();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
// 字符串
String value = cell.getRichStringCellValue().getString();
m.invoke(t, value);
break;
case Cell.CELL_TYPE_NUMERIC:
// 数字 | 日期
if (DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
m.invoke(t, date);
} else {
double d = cell.getNumericCellValue();
if (BigDecimal.class.getSimpleName().equals(typeName)) {
BigDecimal bigDecimal = new BigDecimal(d);
m.invoke(t, bigDecimal);
}
if (Double.class.getSimpleName().equals(typeName)
|| "double".equals(typeName)) {
Double d1 = new Double(d);
m.invoke(t, d1);
}
if (Float.class.getSimpleName().equals(typeName)
|| "float".equals(typeName)) {
Float f = new Float(d);
m.invoke(t, f);
}
if (Integer.class.getSimpleName().equals(typeName)
|| "int".equals(typeName)) {
Integer i = new BigDecimal(d).intValue();
m.invoke(t, i);
}
if (Long.class.getSimpleName().equals(typeName)
|| "long".equals(typeName)) {
Long l = new BigDecimal(d).longValue();
m.invoke(t, l);
}
}
break;
case Cell.CELL_TYPE_BOOLEAN:
// boolean 类型
boolean b = cell.getBooleanCellValue();
m.invoke(t, b);
break;
default:
break;
}
}
return t;
}
/**
*
* 描述:获取开始行
*
* <br>
*
* @method :getStartLine<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:54:34 <br>
* @param cla
* :导入Excel的载体实体类
* @return 获取开始行
*/
private static <T> int getStartLine(Class<T> cla) {
return cla.getAnnotation(ExcelImportConfig.class).startLine();
}
/**
*
* 描述:获取Excel的载体实体类中添加ExcelImportCol注解的属性集合 <br>
*
* @method :getExcelImportColAnnoFields<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午10:59:24 <br>
* @param cla
* :导入Excel的载体实体类
* @return
* @throws Exception
*/
private static <T> List<Field> getExcelImportColAnnoFields(Class<T> cla)
throws Exception {
List<Field> fieldList = new ArrayList<Field>();
Field[] fields = cla.getDeclaredFields();
for (Field f : fields) {
if (f.isAnnotationPresent(ExcelImportCol.class)) {
fieldList.add(f);
}
}
return fieldList;
}
/**
*
* 描述:验证导入Excel的载体实体类是否合法
*
* <br>
*
* @method :checkValidate<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日上午11:01:59 <br>
* @param fileInputStream
* : 导入Excel生成的文件流
* @param cla
* :导入Excel的载体实体类
* @return 验证通过返回 true;验证失败返回 false
* @throws Exception
*/
private static <T> boolean checkValidate(InputStream fileInputStream,
Class<T> cla) throws Exception {
if (null == fileInputStream) {
throw new Exception("导入Excel生成的文件流为空!");
}
if (!cla.isAnnotationPresent(ExcelImportConfig.class)) {
throw new Exception("指定的实体类" + cla.getName()
+ " 缺少ExcelImportConfig注解!");
}
if (getExcelImportColAnnoFields(cla).size() == 0) {
throw new Exception("指定的实体类" + cla.getName()
+ " 属性缺少ExcelImportCol注解!");
}
return true;
}
/**
*
* 描述:判断实体对象是否为空(通过 notNullCols() 判断) <br>
*
* @method :validateNotNull<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午12:50:25 <br>
* @param t
* : 实体对象
* @return
* @throws Exception
*/
private static <T> boolean validateNotNull(T t) throws Exception {
boolean validate = false;
int[] notNullCols = t.getClass().getAnnotation(ExcelImportConfig.class)
.notNullCols();
if (null == notNullCols || notNullCols.length == 0) {
validate = true;
} else {
boolean[] b = new boolean[notNullCols.length];
List<Field> list = getExcelImportColAnnoFields(t.getClass());
PropertyDescriptor pd = null;
Method m = null;
Object fieldValue = null;
int col = 0;
for (int i = 0; i < notNullCols.length; i++) {
for (Field f : list) {
col = f.getAnnotation(ExcelImportCol.class).col();
// 判断 该列值是否为空
if (notNullCols[i] == col) {
pd = new PropertyDescriptor(f.getName(), t.getClass());
m = pd.getReadMethod();
fieldValue = m.invoke(t);
if (null == fieldValue) {
b[i] = false;
} else {
b[i] = true;
}
break;
}
}
}
for (int i = 0; i < b.length; i++) {
validate = validate || b[i];
}
}
return validate;
}
}
已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools