<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包,加入项目中。
/** * @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(); }
/** * @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 {}; }
/** * @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; } }