超簡潔!利用easyExcel導出,讀入Excel

来源:https://www.cnblogs.com/ljy-1471914707/archive/2020/07/02/13226392.html
-Advertisement-
Play Games

x 深夜,在東莞,7天酒店,打開電腦,訪問國內最大的同性交友網站。 日常開發中,導出導入場景非常多,尤其是對於後臺管理更是一個列表一個導出,如果從導出的業務中抽離出復用代碼,專註於邏輯開發,對於開發者而言非常重要。前有使用POI,但作者還是更喜EasyExcel的簡潔高效不拖沓,所以特意寫篇文章記錄 ...


     
x
       
    深夜,在東莞,7天酒店,打開電腦,訪問國內最大的同性交友網站。
   

日常開發中,導出導入場景非常多,尤其是對於後臺管理更是一個列表一個導出,如果從導出的業務中抽離出復用代碼,專註於邏輯開發,對於開發者而言非常重要。前有使用POI,但作者還是更喜EasyExcel的簡潔高效不拖沓,所以特意寫篇文章記錄下。

準備工作

準備工作是看文檔瞭解EasyExcel嗎?不,我們直接上手吧!我發現最近的業務裡面,最簡單的例子已經應付下來了!所以準備工作自然只需導入EasyExcel的jar包,這裡我們由於是springboot項目,所以直接使用maven。直接上最新的版本了!pom.xml給它加上:

     
xxxxxxxxxx
       
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.5</version>
</dependency>
   

導出

準備工作已經完成,導出開始,首先需要一個Bean類,導出的欄位和Excel文件的欄位一樣即可。@Data是用了lombok,@ExcelProperty則包含了Excel首行的名稱和欄位所在位置,從0開始,不能重覆。

      x        
@Data
public class ExportVo {
  
  @ExcelProperty(value = "名稱", index = 0)
  private String name;
  @ExcelProperty(value = "時間", index = 1)
  private Date time;
  
  @NumberFormat("#.##%")
  @ExcelProperty(value = "完成率", index = 2)
  private Float rate;
  
}
   

接下來是邏輯實現:

     
xxxxxxxxxx
       
  @PostMapping("/export")
  public void export(@RequestBody ExportDto dto, HttpServletResponse response)
          throws IOException {
    String fileName = "統計表";
    ExcelUtil.download(response, fileName, ExportVo.class,
            getExportVoList());
  }
  private List getExportVoList() {
    //  這裡主要是獲取List<ExportVo>內容,不提供實現了,需要說下註意點。
      1、導出列表應該有時間之類的限制(例如最近一個月),避免導出Excel過大,過大Excel一般採用分sheet導出(尤其xls文件,有65535條數限制)、分文件打包導出,上傳文件伺服器非同步導出,不可突破的最大導出(限死5w條)。
      2、一來考慮資料庫查詢和記憶體壓力,二來分頁插件可能存在最大頁數限制,所以較多條數時必須做分頁查詢,再組合List對象。
      3、一般從資料庫直接查出數據不滿足導出欄位需要,有必要時需要做欄位轉換。
  }
   

導出的處理類:

     
xxxxxxxxxx
       
public class ExcelUtil {
  public static void download(HttpServletResponse response, String fileName,
                              Class cls, List dataList)
          throws IOException {
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    String fname = URLEncoder.encode(fileName, "utf-8");
    response.setHeader("Content-disposition",
            "attachment;filename=" + fname + ExcelTypeEnum.XLSX.getValue());
    LongestMatchColumnWidthStyleStrategy longestMatchColumnWidthStyleStrategy =
            new LongestMatchColumnWidthStyleStrategy();
    EasyExcel.write(response.getOutputStream(), cls)
            .sheet("sheet1")
            .registerWriteHandler(longestMatchColumnWidthStyleStrategy)
            .doWrite(dataList);
    response.flushBuffer();
  }
   

啟動程式,使用postman試下,直接點Send的話會返回一堆亂碼,選擇Send and Download則可導出Excel,不過文件名是URL編碼過的,這個文件名編碼問題在瀏覽器則不會存在。

image-20200702002721411

導入

導入是為了減少人工錄入大量數據的煩惱,挺好的。

     
xxxxxxxxxx
       
  @Autowired
  private ImportService importService;
  @PostMapping("/import")
  public void import(
          @RequestParam(value = "file") MultipartFile file,
          @Min(1) @RequestParam("type") int type
  ) throws IOException {
    ImportQueryDto dto = new ImportQueryDto();
    dto.setType(type);
    // ImportDto是導入對應類,UploadDataListener是處理類,邏輯處理服務需要以參數形式傳入
    EasyExcel.read(file.getInputStream(), ImportDto.class,
            new UploadDataListener(importService)).sheet().doRead();
  }
   

導入Excel對應類,ExcelProperty對應導入欄位的首部。

     
xxxxxxxxxx
       
@Data
public class ImportDto {
  @ExcelProperty("名稱")
  private String name;
  @ExcelProperty("數量")
  private Integer num;
}
   

導入處理:

     
xxxxxxxxxx
       
public class UploadDataListener
        extends AnalysisEventListener<ImportDto> {
  //  一次導入多少便入庫,避免大量入庫
  private static final int BATCH_COUNT = 50;
  //  存放導入列表
  List<ImportDto> list = new ArrayList<>();
  private ImportService importService;
  public UploadDataListener(ImportService importService) {
    this.importService = importService;
  }
  @Override
  public void invoke(ImportDto importDto, AnalysisContext analysisContext) {
    list.add(importDto);
    if (list.size() >= BATCH_COUNT) {
      saveData();
      list.clear();
    }
  }
  @Override
  public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    saveData();
  }
  private void saveData() {
    List<ImportModel> importModelList = new ArrayList<>();
    for (ImportDto dto : list) {
      ImportModel model = new ImportModel();
      model.setName(dto.getName());
      model.setNum(dto.getNum())
      importModelList.add(model);
    }
    importService.saveBatch(importModelList);
  }
}
   

實際上,導入文件的內容是需要校驗的,數據格式校驗等,需要詢問產品是否忽略錯誤的數據,只導入正常的數據,然後怎麼友好提示錯誤的內容,通過返回一個包含錯誤信息Excel或提示框,更進一步的提示,則是提示到哪一個格子有問題。

睡覺。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 以下麵試題來自騰訊、阿裡、網易、餓了麽、美團、拼多多、百度等等大廠綜合起來常考的題目。 如何寫一個漂亮的簡歷 簡歷不是一份記流水賬的東西,而是讓用人方瞭解你的亮點的。平時有在做一些修改簡歷的收費服務,也算看過蠻多簡歷了。很多簡歷都有如下特征 喜歡說自己的特長、優點,用人方真的不關註你的性格是否陽光等 ...
  • 從webpack打包結構中我們知道,vue中有一個存放外部資源的文件夾static,它裡面的文件是不會被打包編譯的,所以我們就可以利用外部引入js的方式將我們的想要的數據在index.html中以js文件的方式引入,然後就可以全局使用。 具體的方法如下: 1.在項目中找到static文件夾,在裡面創 ...
  • 單例模式 線程安全的Singleton 會破壞Singleton的情況 線程級Singleton 單例模式是幾個創建型模式中最獨立的一個,它的主要目標不是根據客戶程式調用生成一個新的實例,而是控制某個類型的實例數量只有一個。 GOF對單例的描述為: Ensure a class only has o ...
  • 創建型模式 簡單工廠模式 工廠方法模式 IOC與工廠方法模式的結合 泛型工廠 委托工廠 創建型模式 創建型模式可以隔離客戶程式對需要實例化類型的依賴關係,這類模式一般通過將實例化具體對象的職責委托給第三方對象的方式,使得客戶程式或者外部系統在獲得所需的具體類型實例的同時,而不必對其發生直接的引用。 ...
  • 譯者前言:相信凡是用過 zip() 內置函數的人,都會贊同它很有用,但是,它的最大問題是可能會產生出非預期的結果。PEP-618 提出給它增加一個參數,可以有效地解決大家的痛點。 這是 Python 3.10 版本正式採納的第一個 PEP,「Python貓」一直有跟進社區最新動態的習慣,所以翻譯了出 ...
  • 上次講了微服務的前世今生(五):CAP 原則與 BASE 理論,這次我們再說微服務架構的前世今生(六):微服務架構帶來的問題。 一、客戶端如何訪問服務? 傳統的開發方式,所有的服務都是本地的,客戶端可以直接調用,現在按功能拆分成獨立的服務,客戶端如何訪問? 後臺有 N 個服務,前臺就需要管理 N 個 ...
  • 我認為,代碼優化的最重要的作用應該是:避免未知的錯誤。在代碼上線運行的過程中,往往會出現很多我們意想不到的錯誤,因為線上環境和開發環境是非常不同的,錯誤定位到最後往往是一個非常小的原因。 ...
  • 【SpringCloud】Gateway 配置全局過濾器獲取請求參數和響應值 實現Ordered介面getOrder()方法,數值越小越靠前執行,記得這一點就OK了。 獲取請求參數RequestBody @Component @Slf4j @AllArgsConstructor public cla ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...