1. 程式人生 > 其它 >把Excel解析成List

把Excel解析成List

技術標籤:javaexcel

0x01 作用

把有固定格式的Excel解析成List,方便操作

0x02 使用到的包 (Maven)

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>RELEASE</version>
        </dependency>

0x03 程式碼

public class ExcelAnalysisUtils<T> {

    /**
     * Date包名
     */
    private final String TYPE_DATE = "java.util.Date";
    /**
     * Double包名
     */
    private final String TYPE_DOUBLE = "java.lang.Double";
    /**
     * Integer包名
     */
    private final String TYPE_INTEGER = "java.lang.Integer";
    /**
     * String包名
     */
    private final String TYPE_STRING = "java.lang.String";

    /**
     * Excel匯出為實體
     *
     * @param is          is流
     * @param fileName    檔名稱
     * @param clazz       class
     * @param columnNames 列名list
     * @param startRow    起始行(索引從0開始)
     * @return
     * @throws Exception
     */
    public List<T> excelToEntity(InputStream is, String fileName, Class<T> clazz, List columnNames, int startRow) throws Exception {
        Workbook wb = null;
        Sheet sheet = null;
        Row row = null;
        List<T> list = null;
        wb = readExcel(is, fileName);
        if (wb != null) {
            //用來存放表中資料
            list = new ArrayList<T>();
            //獲取第一個sheet
            sheet = wb.getSheetAt(0);
            //獲取最大行數
            int rownum = sheet.getPhysicalNumberOfRows();
            for (int i = startRow; i < rownum; i++) {
                row = sheet.getRow(i);
                if (row != null) {
                    list.add((T) getFieldValueByName(columnNames, row, clazz));
                }
            }
        }
        return list;
    }


    /**
     * @param colnames 欄位名
     * @param row      錶行
     * @param clazz    class
     * @return 欄位值
     * @MethodName : getFieldValueByName
     * @Description : 根據欄位名獲取欄位值
     */
    private T getFieldValueByName(List<String> colnames, Row row, Class<T> clazz) throws Exception {
        T t = clazz.newInstance();
        //獲取全部欄位
        Field[] fields = clazz.getDeclaredFields();

        //遍歷欄位
        for (Field field : fields) {
            //判斷欄位是否存在colnames中
            if (colnames.contains(field.getName())) {

                //開啟強制賦值
                field.setAccessible(true);

                //獲取值
                Object val = getCellFormatValue(row.getCell(colnames.indexOf(field.getName())));

                //判斷欄位對應型別,然後轉換賦值
                switch (field.getType().getName()) {
                    case TYPE_DATE:
                        //getCellFormatValue(row.getCell(colnames.indexOf(field.getName()))).toString()
                        field.set(t, StringUtils.isEmpty(val) ? null : VeDateUtils.strToDateLong(val.toString()));
                        break;
                    case TYPE_DOUBLE:
                        //getCellFormatValue(row.getCell(colnames.indexOf(field.getName()))).toString()
                        field.set(t, StringUtils.isEmpty(val) ? null : Double.valueOf(val.toString()));
                        break;
                    case TYPE_INTEGER:
                        if (val instanceof Double) {
                            field.set(t, StringUtils.isEmpty(val) ? null : ((Double) val).intValue());
                        } else {
                            field.set(t, StringUtils.isEmpty(val) ? null : Integer.valueOf(val.toString()));
                        }
                        break;
                    default:
                        //去除小數
                        if (val instanceof Double) {
                            field.set(t, String.valueOf(((Double) val).intValue()));
                        } else {
                            field.set(t, val);
                        }
                }
            }
        }

        return t;
    }


    //讀取excel
    private Workbook readExcel(InputStream is, String fileName) throws Exception {
        if (fileName == null) {
            return null;
        }
        String extString = fileName.substring(fileName.lastIndexOf("."));
        try {
            if (".xls".equals(extString)) {
                return new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                return new XSSFWorkbook(is);
            } else {
                return null;
            }

        } catch (FileNotFoundException e) {
            throw new Exception("檔案未找到");
        } catch (IOException e) {
            throw new Exception("IO錯誤");
        }
    }

    private Object getCellFormatValue(Cell cell) {
        Object cellValue = null;
        if (cell != null) {
            //判斷cell型別
            switch (cell.getCellType()) {
                case NUMERIC: {
                    cellValue = cell.getNumericCellValue();
                    break;
                }
                case FORMULA: {
                    //判斷cell是否為日期格式
                    if (DateUtil.isCellDateFormatted(cell)) {
                        //轉換為日期格式YYYY-mm-dd
                        cellValue = cell.getDateCellValue();
                    } else {
                        //數字
                        cellValue = cell.getNumericCellValue();
                    }
                    break;
                }
                case STRING: {
                    cellValue = cell.getStringCellValue();
                    break;
                }
                default:
            }
        }
        return cellValue;
    }
}

0x04 使用方法

new ExcelAnalysisUtils<類>().excelToEntity(檔案流,帶格式的檔名稱,類class,Excel類對應列的欄位list,從x行開始解析內容);

  • 檔案流 --> 需要解析的檔案流
  • 帶格式的檔名稱 ---> xxx.xls or xxx.xlsx
  • 類class --> 需要解析成的類的class
  • Excel類對應列的欄位list --> 要與Excel列對應,如 Excel列順序為 名稱、年齡,則list.get(0)="name",list.get(1)="age"
  • 從x行開始解析內容 --> 要從第幾行開始解析Excel,索引從0開始,即Excel中第一行行標是1,則填0,以此類推