阿里巴巴EasyExcel使用(3)-導入


導入的話比較簡單了,參照官方文檔,有好幾個Demo。

我這里主要考慮幾個情況: ①數據量較大,分批讀取 ②數據格式需要校驗,因為導入的數據有可能存在格式問題,但是需要給前端提醒一下哪里出錯了.

一、Excel數據

這里在數字格式的地方用字符串導入,引起出錯~

 

 

 

二、API 調用

這里參考官方文檔,修改的地方在DemoExceptionListener監聽類里面

  /**
     * 數據轉換等異常處理
     *
     * <p>
     * 1. 創建excel對應的實體對象 參照{@link ExceptionDemoData}
     * <p>
     * 2. 由於默認異步讀取excel,所以需要創建excel一行一行的回調監聽器,參照{@link DemoExceptionListener}
     * <p>
     * 3. 直接讀即可
     */
    @Test
    public void exceptionRead() {
        String fileName = "I:\\temp\\readDemo1.xlsx";
        // 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet
        EasyExcel.read(fileName, ExceptionDemoData.class, new DemoExceptionListener()).sheet().doRead();
    }

 

/**
 * 基礎數據類.這里的排序和excel里面的排序一致
 *
 **/
@Data
public class ExceptionDemoData {
    
    private String string;
    private Date date;
    private Double doubleData;

}

 

三、DemoExceptionListener監聽類

主要內部定義一個存儲異常信息的StringBuffer,用於收集異常,並在讀取完Excel之后可以用於校驗是否轉換數據出錯~

/**
 * 讀取轉換異常
 *  
 */
public class DemoExceptionListener extends AnalysisEventListener<ExceptionDemoData> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoExceptionListener.class);
    /**
     * 每隔5條存儲數據庫,實際使用中可以3000條,然后清理list ,方便內存回收
     */
    private static final int BATCH_COUNT = 5;
    List<ExceptionDemoData> list = new ArrayList<ExceptionDemoData>();

    //定義接收異常
    private StringBuffer  errorMsg;


    /**
     * 在轉換異常 獲取其他異常下會調用本接口。拋出異常則停止讀取。如果這里不拋出異常則 繼續讀取下一行。
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        LOGGER.error("解析失敗,但是繼續解析下一行:{}", exception.getMessage());
        // 如果是某一個單元格的轉換異常 能獲取到具體行號
        // 如果要獲取頭的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            LOGGER.error("第{}行,第{}列解析異常,數據為:{}", excelDataConvertException.getRowIndex(),
                excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
          String msg="第"+excelDataConvertException.getRowIndex()+"行,第"+excelDataConvertException.getColumnIndex()+"列解析異常,數據為:"+
        excelDataConvertException.getCellData(); if(errorMsg==null){ errorMsg=new StringBuffer(); } //拼接報錯信息
errorMsg.append(msg).append(System.lineSeparator()); } } /** * 這里會一行行的返回頭 * * @param headMap * @param context */ @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { LOGGER.info("解析到一條頭數據:{}", JSON.toJSONString(headMap)); } @Override public void invoke(ExceptionDemoData data, AnalysisContext context) { LOGGER.info("解析到一條數據:{}", JSON.toJSONString(data)); if (list.size() >= BATCH_COUNT) { //操作數據之前統一判斷異常信息,可以直接拋異常 if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析數據異常!!信息:"+errorMsg.toString()); LOGGER.error("解析數據異常!!信息:" + errorMsg.toString()); } saveData(); list.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { ////操作數據之前統一判斷異常信息 /*if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析數據異常!!信息:"+errorMsg.toString()); LOGGER.error("解析數據異常!!信息:" + errorMsg.toString()); }else{ LOGGER.info("所有數據解析完成!"); //解析完成無錯誤保存數據 saveData(); }*/ } /** * 加上存儲數據庫 */ private void saveData() { LOGGER.info("{}條數據,開始存儲數據庫!", list.size()); LOGGER.info("存儲數據庫成功!"); } }

 結果:

 

 我這里每次讀5行數據,如果調成讀10條,這兩個異常會合並到一起。

四、總結

這里不知道有沒有線程安全和變量未回收問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM