Java實現讀取Excel文件功能(EasyExcel初使用)
前言
在我們項目的開發(fā)中啊,前端有時候會傳送 Excel 文件給后端(Java)去解析,那我們作為后端該如何實現對 Excel 文件的解析和數據讀取呢?說到這我就不得不推薦 EasyExcel 了!
EasyExcel 介紹
引用下官方對于 EasyExcel 介紹:EasyExcel是一個基于Java的、快速、簡潔、解決大文件內存溢出的Excel處理工具。他能讓你在不用考慮性能、內存的等因素的情況下,快速完成Excel的讀、寫等功能。
官方網址:EasyExcel官方文檔 - 基于Java的Excel處理工具 | Easy Excel
快速上手 EasyExcel
前置工作
先創(chuàng)建一個 Spring Boot 工程,并在 pom.xml 文件添加 EasyExcel 和 Lombok 依賴。
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency>
知道表頭
如果我們知道 Excel 數據的表頭,即每列數據的類型包括有多少列時就可以用此方法讀取 Excel 文件數據。
我們以下圖數據為例,對改 Excel 中的數據進行獲取和處理。
方法一:
首先我們創(chuàng)建一個名為 ExcelData 的 Java 對象,共有兩個屬性,分別是 date(日期列數據)和 useNum(用戶列數據),每個屬性對應 Excel 每列某一行中的數據。那么很顯而易見,每一行的數據就是一個 ExcelData 對象,所有行的數據合起來就是一個泛型為 ExcelData 的 ExcelData 的集合。
@Data public class ExcelData implements Serializable { /** * 對應表格的日期列 */ private String date; /** * 對應表格的用戶數列 */ private Integer userNum; }
隨后編寫一個測試類,并在其中編寫測試方法。
EasyExcel 的 read 方法有很多中構造方法,其中 Class head 就是表頭類型,傳入它還要傳入 ReadListener 監(jiān)聽器,以便在去讀取每行數據時做些自定義操作。我們直接傳入它的實現類實例,因為 PageReadListener 支持逐頁讀取數據,通過讀取指定行數的數據保證占用更少的內存。
話不多說直接上代碼:
/** * 知道表頭,并形成映射關系 */ @Test public void doImportsForMapping() throws FileNotFoundException{ // 讀取 resource 目錄下的 Excel 文件(網站數據.xlsx) File file = ResourceUtils.getFile("classpath:網站數據.xlsx"); // 創(chuàng)建一個 list 存儲每行的數據,即 ExcelData 對象 List<ExcelData> list = new ArrayList<>(); // 直接使用 EasyExcel 的 read 方法,同時定義表頭的類型,以便將列中數據映射為 ExcelData 對象 EasyExcel.read(file, ExcelData.class, new PageReadListener<ExcelData>(dataList -> { // 并且每行數據,并將其 add 至 list 中 for (ExcelData excelData : dataList) { if (excelData != null) { list.add(excelData); } } })).excelType(ExcelTypeEnum.XLSX).sheet().doRead(); // 指定 Excel 的文件后綴,開始分析讀取 for (ExcelData excelData : list) { System.out.println(excelData.getDate() + "," + excelData.getUserNum()); } }
執(zhí)行結果:
方法二:
方法一是直接一次性讀取 Excel 中的數據,缺少要讀取的數據行數和一些自定義操作,所以我們在這里對上面的代碼增強一下。
在此方法中我們通過匿名內部類的方式實現 ReadListenser 接口,無需額外寫一個類去實現 ReadListener了。我們設置了一個臨時存儲的列表(大小為 2),當每次讀取的數據(執(zhí)行 invoke 方法)添加到臨時存儲表中。當其長度超過 2 時進行全部刪除,在刪除前我們可以將臨時存儲的列表存到數據庫中,或進行一些其他的自定義操作。
doAfterAllAnalysed 方法是分析并獲取所有的數據后會執(zhí)行的一個方法,我們可以在其中打上日志,表示 Excel 所有數據已存入數據庫中。
/** * 知道表頭,并形成映射關系 * @throws FileNotFoundException */ @Test public void doImportsForMappingByInnerClass() throws FileNotFoundException{ File file = ResourceUtils.getFile("classpath:網站數據.xlsx"); EasyExcel.read(file, ExcelData.class, new ReadListener<ExcelData>() { // 單次緩存的數據量 public static final int BATCH_COUNT = 2; // 臨時存儲的列表 private List<ExcelData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); @Override public void invoke(ExcelData excelData, AnalysisContext analysisContext) { cachedDataList.add(excelData); getData(excelData); if (cachedDataList.size() >= BATCH_COUNT) { cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { System.out.println("存儲數據庫成功"); } private void getData(ExcelData excelData) { System.out.println(excelData.getDate() + "," + excelData.getUserNum()); } }).excelType(ExcelTypeEnum.XLSX).sheet().doRead(); }
執(zhí)行結果:
不知道表頭
方法三:
上面的兩種方法都是我們知道表頭,包括列的類型和列數量的情況下對 Excel 文件進行數據獲取的。那我們不知道表頭信息,又該如何操作呢?
我們依賴利用 EasyExcel 的 read 方法,和前面的步驟大差不差,只不過這次參數少了,如果你還要獲取表頭即表格的第一行數據,還可通過 headRowNumber 方法指定首行編號為 0。
此時返回的是一個 List<Map<Integer, String>> 集合,其中 Map 的 鍵對應表格的列編號(從 0 開始),值就是對應某一行某一列的值,List 的索引代表某一行的數據。調用 Map 對象的 values() 方法即可直接獲取某一行數據的集合,List<Map<Integer, String>> 就是所有行數據的集合。我們這說可能不太直觀,我把它打印出來給你們看就很簡單明了了。
[{0=日期, 1=用戶數}, {0=1號, 1=10}, {0=2號, 1=20}, {0=3號, 1=30}, {0=4號, 1=70}, {0=5號, 1=20}, {0=6號, 1=29}, {0=7號, 1=24}, {0=8號, 1=31}, {0=9號, 1=40}, {0=10號, 1=38}, {0=11號, 1=43}]
代碼如下:
@Test public void doImport() throws FileNotFoundException { List<Map<Integer, String>> list = null; File file = ResourceUtils.getFile("classpath:網站數據.xlsx"); try { list = EasyExcel.read(file) .excelType(ExcelTypeEnum.XLSX) .sheet() .headRowNumber(0) .doReadSync(); } catch (Exception e) { throw new RuntimeException("讀取 Excel 文件失敗"); } StringBuilder stringBuilder = new StringBuilder(); for (int i=0;i<list.size();i++) { // 轉為 LinkedHashMap 主要是為了保證讀取的數據和表格順序一致 LinkedHashMap<Integer, String> linkedHashMap = (LinkedHashMap) list.get(i); List<String> dataList = linkedHashMap.values().stream() .filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); stringBuilder.append(StringUtils.join(dataList, ",")).append("\n"); } System.out.println(stringBuilder.toString()); }
執(zhí)行結果:
總結
如果知道表頭并且數據量較小,就用方法一,如果數據量較大或者想添加一些自定操作就用方法二。如果不知道表頭并且想要讀取表頭的信息就用方法三。
到此這篇關于Java實現讀取Excel文件功能的文章就介紹到這了,更多相關Java讀取Excel文件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
spring boot+mybatis 多數據源切換(實例講解)
下面小編就為大家?guī)硪黄猻pring boot+mybatis 多數據源切換(實例講解)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-095分鐘快速搭建SpringBoot3?+?MyBatis-Plus工程/項目的實現示例
本文主要介紹了使用IntelliJ?IDEA創(chuàng)建Spring?Boot工程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-01-01詳解SpringBoot如何創(chuàng)建自定義Starter
Spring Boot的自動配置機制為開發(fā)人員提供了一種輕松集成和配置各種功能的便捷方式,本文將深入探討在Spring Boot中如何創(chuàng)建自定義Starter,為構建模塊化且易維護的應用提供有力的支持,需要的朋友可以參考下2024-02-02