POI封裝一:導入 Import

已整理成完整項目,並進行了優化。看參考地址:java

https://gitee.com/andy_longjie/exceltools   或者 https://github.com/youmulongjie/exceltoolsgit

POI 導入篇

一、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包,加入項目中。github

二、項目目錄樹:

三、定義註解類:

(一):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>
 * 一、導入的類必須添加註解類ExcelImportConfig<br>
 * 二、該註解類用在類屬性上,獲取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>
 * 一、導入的類必須添加該註解類 <br>
 * 二、默認從第1行導入 <br>
 * 三、若是 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>
	 * 一、若是非空列數組爲null,則讀取每一行的數據做爲一條記錄<br>
	 * 二、若是非空列數組不爲null,例如爲[0],則若每行的第0列爲空,則不讀取該行記錄;反之讀取該行記錄<br>
	 * 三、若是非空列數組不爲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;
	}
}

 

已整理成完整項目,並進行了優化。看參考地址:apache

https://gitee.com/andy_longjie/exceltools   或者 https://github.com/youmulongjie/exceltools數組

相關文章
相關標籤/搜索