使用了Hibernate的項目中須要導入多張表的數據,可是我又不想寫屢次取出Excle數據放到Bean裏的代碼,因而寫了個ExcleUtils來幫助我作這件事。java
技術上,首先確定是要藉助反射的,而後選擇了jxl來操做Excle。數組
須要的參數上,Excle文件不能少;好像沒有什麼方法可以在Excel隱藏地放入對應屬性名的信息(就是屬性名字不會在Excle中顯示出來,若是有方法可以作到,請給我留言,多謝!),因而我會須要按照Excle順序的屬性名稱數組;而後我須要在Sheet頁的序號以及數據從第幾行開始;對於Date類型,可能須要SimpleDateFormat對象來進行轉換,若是沒有就使用默認的。所以這個方法應該是這樣的(而且有一個重載版本):ui
public static <T> List<T> getDataList(File excelFile, int sheetindex, int start, String[] props, Class<T> clazz) throws Exception { return getDataList(excelFile, sheetindex, start, props, clazz, null); } public static <T> List<T> getDataList(File excelFile, int sheetindex, int start, String[] props, Class<T> clazz, SimpleDateFormat sdf) { //TODO }
原本想把代碼拆開說說本身的思路,想了想仍是整塊代碼貼上而後寫註釋把(只貼相關部分的),其實都蠻簡單的。excel
private static final Map<Class<?>, Class<?>> pwMap = new HashMap<Class<?>, Class<?>>(); static { pwMap.put(byte.class, Byte.class); pwMap.put(short.class, Short.class); pwMap.put(int.class, Integer.class); pwMap.put(long.class, Long.class); pwMap.put(float.class, Float.class); pwMap.put(double.class, Double.class); pwMap.put(boolean.class, Boolean.class); pwMap.put(char.class, Character.class); } private ExcelUtils() { } /** * <p> * 從Excel中獲取對象列 * </p> * * @param excelFile * 文件 * @param sheetindex * 第幾個sheet * @param props * 屬性名(按順序) (若是有非基本類型須要實現valueOf方法) * @param clazz * 類型 * @return * @throws Exception * String[], Class, SimpleDateFormat) */ public static <T> List<T> getDataList(File excelFile, int sheetindex, int startRow, int startCol, String[] props, Class<T> clazz) throws Exception { return getDataList(excelFile, sheetindex, startRow, startCol, props, clazz, null); } /** * * @param excelFile * Excel文件 * @param sheetindex * @param start * @param props * @param clazz * @param sdf * @return * @throws Exception */ public static <T> List<T> getDataList(File excelFile, int sheetindex, int startRow, int startCol, String[] props, Class<T> clazz, SimpleDateFormat sdf) throws Exception { Workbook excel = null; try { excel = Workbook.getWorkbook(excelFile); Sheet sheet = excel.getSheet(sheetindex); int n = sheet.getRows(); List<T> result = new ArrayList<T>(n); for (int i = startRow; i < n; i++) { Cell[] row = sheet.getRow(i); result.add(getRowData(props, row, clazz, sdf, startCol)); } return result; } catch (BiffException | IOException e) { throw new Exception("讀取Excel文件出錯!"); } finally { excel.close(); } } /** * <p> * 獲取其中一行的數據注入到對象中 * </p> * * @param props * @param row * @param clazz * @return * @throws Exception */ public static <T> T getRowData(String[] props, Cell[] row, Class<T> clazz, int startCol) throws Exception { return getRowData(props, row, clazz, null, startCol); } /** * * @param props * @param row * @param clazz * @param sdf * @return * @throws Exception */ public static <T> T getRowData(String[] props, Cell[] row, Class<T> clazz, SimpleDateFormat sdf, int startCol) throws Exception { // 屬性首字母大寫 for (int i = 0; i < props.length; i++) { if (props[i] == null) continue; StringBuilder sb = new StringBuilder(props[i]); sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); props[i] = sb.toString(); } // 實例化一個對象 T result = clazz.newInstance(); for (int i = 0; i < props.length; i++) { String propName = props[i]; if (propName == null) { continue; } Class<?> type = getPropType(clazz, propName); // 把getter的返回類型做爲參數類型獲取setter Method setter = clazz.getMethod("set" + propName, type); String contents = row[i + startCol].getContents(); if (contents != null) { Object val = string2Type(contents, type, sdf); // 執行setter setter.invoke(result, val); } } return result; } private static final SimpleDateFormat DEFALUT_SIMPLEDATEF = new SimpleDateFormat( "yyyy-MM-dd"); @SuppressWarnings("unchecked") private static <T> T string2Type(String val, Class<T> clazz, SimpleDateFormat sdf) throws Exception { Method valueOf = null; // 對Date和String特殊處理 if (String.class == clazz) { return (T) val; } if (Date.class == clazz) { return (T) (sdf != null ? sdf.parse(val) : DEFALUT_SIMPLEDATEF .parse(val)); } if (char.class == clazz || Character.class == clazz) { Character c = val.toCharArray().length > 0 ? val.toCharArray()[0] : (Character.class == clazz ? null : (char) 0); return (T) c; } // 對基本類型作處理 Class<?> finalclazz = clazz.isPrimitive() ? pwMap.get(clazz) : clazz; try { valueOf = finalclazz.getMethod("valueOf", String.class); } catch (NoSuchMethodException e) { throw new Exception("成員類型須要有T valueOf(String)靜態方法"); } return (T) valueOf.invoke(null, val); } private static Class<?> getPropType(Class<?> clazz, String propName) throws NoSuchMethodException, SecurityException { Method getter = clazz.getMethod("get" + propName); Class<?> type = getter.getReturnType(); return type; }