藉助jxl將Excel中的數據注入到Bean中

前言

使用了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;
    }
相關文章
相關標籤/搜索