代碼實現
PropertyAnno.java
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD)//規定用於全局變量 @Retention(RetentionPolicy.RUNTIME)//定義為運行時注解 /** * excel讀取所用注解 * @author Administrator * */ public @interface PropertyAnno { String value() default ""; }
AnnoCreator.java
import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 注解解釋工具類 * @author Administrator * */ public class AnnoCreator { /** * 注解解釋方法 * @return Map<屬性名(String), 注解名(String)> */ public static Map<String, String> annoCreator(Class<?> clazz) { Map<String, String> map = Collections.synchronizedMap(new HashMap<>()); for (Field field : clazz.getDeclaredFields()) { //獲取屬性上所有注解 Annotation[] annotations = field.getAnnotations(); //判斷屬性上是否存在注解 if(annotations.length < 1) { continue; } //判斷屬性上是否存在需要注解 if(annotations[0] instanceof PropertyAnno) { map.put(field.getName(), ((PropertyAnno)annotations[0]).value()); } } return map; } }
ReadExcel
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; 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; public class ReadExcel<T> { /** * 錯誤信息 */ private String errorMsg; /** * 表格數據對象 */ private Class<T> clazz; /** * 改寫初始化方法,將對象傳入T */ @SuppressWarnings("unchecked") public ReadExcel() { @SuppressWarnings("rawtypes") Class clazz = getClass(); while (clazz != Object.class) { Type t = clazz.getGenericSuperclass(); if (t instanceof ParameterizedType) { Type[] args = ((ParameterizedType) t).getActualTypeArguments(); if (args[0] instanceof Class) { this.clazz = (Class<T>) args[0]; break; } } clazz = clazz.getSuperclass(); } } /** * 根據文件名讀取Excel文件 * * @param filePath 文件完整路徑 * @return Map<表名(sheet名,String), 表中的屬性(List<T>)> */ public Map<String, List<T>> read(String filePath) { Map<String, List<T>> map = null; InputStream is = null; try { // 驗證文件是否正確 if (!validateExcel(filePath)) { System.out.println(errorMsg); return null; } // 判斷文件的類型,是2003還是2007 boolean isExcel2003 = true; if (isExcel2007(filePath)) { isExcel2003 = false; } // 創建流進行讀取 File file = new File(filePath); is = new FileInputStream(file); // 根據版本選擇創建Workbook的方式 Workbook workbook = null; if (isExcel2003) { workbook = new HSSFWorkbook(is); } else { workbook = new XSSFWorkbook(is); } map = readExcel(workbook); } catch (Exception ex) { ex.printStackTrace(); } finally { if (is != null) { try { // 關閉連接 is.close(); } catch (IOException e) { is = null; e.printStackTrace(); } } } return map; } /** * 讀取Excel表格 */ @SuppressWarnings("deprecation") private Map<String, List<T>> readExcel(Workbook workbook) { Map<String, List<T>> map = Collections.synchronizedMap(new HashMap<>()); List<T> list = null; // 獲取表格數量 int numberOfSheets = workbook.getNumberOfSheets(); for (int sheetNum = 0; sheetNum < numberOfSheets; sheetNum++) { list = new ArrayList<>(); // 獲取注解 Map<String, String> creatorMap = AnnoCreator.annoCreator(clazz); // 獲取指定的Excel Sheet sheet = workbook.getSheetAt(sheetNum); // 獲取Excel的行數 int totalRows = sheet.getPhysicalNumberOfRows(); // Excel的列數 int totalCells = 0; if (totalRows >= 1 && sheet.getRow(0) != null) { // 獲取Excel的列數 totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } List<String> li = new ArrayList<>(); // 循環Excel的行 for (int r = 0; r < totalRows; r++) { // 獲取對象 T t = null; try { t = clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } Row row = sheet.getRow(r); if (row == null) { continue; } // 遍歷Excel的列 for (int c = 0; c < totalCells; c++) { Cell cell = row.getCell(c); String cellValue = ""; if (null != cell) { // 判斷數據的類型 switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 數字 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; } } //此處可修改為自己的表格樣式,例如打印第二行第二列的數據: /* if(r == 1 && c == 1){ System.out.println(cellValue); } */ if (r == 0) { // 存儲第一行數據(列名) li.add(cellValue); } else { // 存儲第一行后數據 fill(creatorMap, li.get(c), cellValue, t); } } if (r != 0) { list.add(t); } } map.put(sheet.getSheetName(), list); } return map; } /** * 判斷是否Excel格式是否為2003 */ private static boolean isExcel2003(String filePath) { return filePath.matches("^.+\\.(?i)(xls)$"); } /** * 判斷是否Excel格式是否為2007 */ private static boolean isExcel2007(String filePath) { return filePath.matches("^.+\\.(?i)(xlsx)$"); } /** * 驗證Excel文件 */ private boolean validateExcel(String filePath) { // 檢查文件名格式是否正確 if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) { System.out.println("文件名不是Excel格式"); return false; } // 檢查文件是否存在 File file = new File(filePath); if (file == null || !file.exists()) { System.out.println("文件不存在"); return false; } return true; } /** * 為對象進行賦值 * * @param map 注解map(注解=屬性名) * @param str 當前讀取到的列名 * @param obj 當前讀到的數據 * @param t 需要進行賦值的對象 */ private void fill(Map<String, String> map, String str, String obj, T t) { for (Entry<String, String> entry : map.entrySet()) { try { if (str.equals(entry.getValue())) { // 為對象進行賦值 Field f = clazz.getDeclaredField(entry.getKey().trim()); f.setAccessible(true); f.set(t, obj); return; } } catch (Exception e) { e.printStackTrace(); } } } }
BasicsEntity.java
/** * excel內容實體類(示例) * 注意:實體類屬性需定義為String類型 * @author Administrator * */ public class BasicsEntity { @PropertyAnno("列名")//被注解字段與excel中列名對應 private String name;//字段名 @PropertyAnno("類型") private String type;//字段類型 @PropertyAnno("長度") private String length;//字段長度 @PropertyAnno("小數點長度") private String decimal;//小數點長度 @PropertyAnno("默認值") private String defaults;//默認值 @PropertyAnno("備注") private String annotation;//備注 @PropertyAnno("是否為非空(Y或N)") private String isNull;//是否為非空(Y或N) @PropertyAnno("是否為主鍵(Y或N)") private String isPrincipal;//是否為主鍵(Y或N) @PropertyAnno("是否啟用主鍵自增(Y或N)") private String isProgressive;//是否啟用主鍵自增(Y或N) @Override public String toString() { return "BasicsEntity [name=" + name + ", type=" + type + ", length=" + length + ", decimal=" + decimal + ", defaults=" + defaults + ", annotation=" + annotation + ", isNull=" + isNull + ", isPrincipal=" + isPrincipal + ", isProgressive=" + isProgressive + "]"; } }
ReadTest.java
import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.myutils.entity.BasicsEntity; /** * 測試類 * @author Administrator */ public class ReadTest { public static void main(String[] args) { //調用方法時必須寫成以下格式,否則反射無法獲取到實體類 ReadExcel<BasicsEntity> util = new ReadExcel<BasicsEntity>(){}; //調用方法,返回實體類集合 Map<String, List<BasicsEntity>> map = util.read("D:數據庫文檔\\測試表格.xlsx"); for (Entry<String, List<BasicsEntity>> baMap : map.entrySet()) { System.out.println("表名:" + baMap.getKey().split("\\|")[0]); System.out.println("表備注:" + baMap.getKey().split("\\|")[1]); for (BasicsEntity basicsEntity : baMap.getValue()) { System.out.println(basicsEntity.toString()); } } } }
pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cn</groupId> <artifactId>myExcel</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.apache.directory.studio</groupId> <artifactId>org.apache.commons.codec</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.54</version> </dependency> </dependencies> </project>
測試使用表格: