讀取Excel文件的兩種寫法
阿新 • • 發佈:2021-08-07
需用讀取Excel文件,所以瞭解了一下大概做法,並整理如下:
1.使用jxl,建立單元格物件,讀取文件內容,優點是程式碼簡單,按行讀取,缺點是在智慧處理03版本的EXCEL檔案,如下 :
匯入依賴:
1 <!-- https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl --> 2 <dependency> 3 <groupId>net.sourceforge.jexcelapi</groupId> 4 <artifactId>jxl</artifactId> 5 <version>2.6.12</version> 6 </dependency>
接下來是程式碼實現,邏輯比較簡單就不多說了
import jxl.Cell; import jxl.Sheet; import jxl.Workbook; public class simple { public static void main(String[] args) { try { File file = new File("XXX.xls" +""); //建立檔案物件 Workbook wb = Workbook.getWorkbook(file); // 從檔案流中獲取Excel工作區物件(WorkBook) Sheet sheet = wb.getSheet(0); // 從工作區中取得頁(Sheet) for (int i = 0; i < sheet.getRows(); i++) { // 迴圈列印Excel表中的內容 for (int j = 0; j < sheet.getColumns(); j++) { Cell cell = sheet.getCell(j, i); System.out.printf(cell.getContents()+" "); } System.out.println(); } } catch (Exception e) { e.printStackTrace(); } } }
2.使用阿里巴巴的fastExcel,程式碼稍微複雜一點,功能多,能處理03和07版本的
我的目錄結構如下:
匯入依賴
<!--EasyExcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.0-beta2</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.1</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--fastJson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.72</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency>
根據EXCEL文件表頭資訊編輯實體類,即pojo中的TableInfo
import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @Data public class TableInfo { @ExcelIgnore @ExcelProperty("序號") private Integer num; //欄位 資料型別 欄位標題 欄位說明 欄位來源 @ExcelProperty("欄位") private String fieldName; @ExcelProperty("資料型別") private String dataType; @ExcelProperty("欄位標題") private String comment1; @ExcelProperty("欄位說明") private String comment2; @ExcelIgnore @ExcelProperty("欄位來源") private String url; }
dao層用於處理資料庫,如果不需要儲存到資料庫可以不寫具體實現:
1 import ExcelRead.pojo.TableInfo; 2 import java.util.List; 3 4 public class TableDao { 5 public void save(List<TableInfo> list) { 6 // 如果是mybatis,儘量別直接呼叫多次insert,自己寫一個mapper裡面新增一個方法batchInsert,所有資料一次性插入 7 } 8 }
具體實現程式碼:
1 import ExcelRead.dao.TableDao; 2 import ExcelRead.pojo.TableInfo; 3 import com.alibaba.excel.context.AnalysisContext; 4 import com.alibaba.excel.event.AnalysisEventListener; 5 import com.alibaba.fastjson.JSON; 6 import org.slf4j.Logger; 7 import org.slf4j.LoggerFactory; 8 import java.util.ArrayList; 9 import java.util.List; 10 11 public class TableDataListener extends AnalysisEventListener<TableInfo> { 12 private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(TableDataListener.class); 13 /** 14 * 每隔5條儲存資料庫,實際使用中可以3000條,然後清理list ,方便記憶體回收 15 */ 16 private static final int BATCH_COUNT = 200; 17 List<TableInfo> list = new ArrayList<TableInfo>(); 18 /** 19 * 假設這個是一個DAO,當然有業務邏輯這個也可以是一個service。當然如果不用儲存這個物件沒用。 20 */ 21 private TableDao tableDao; 22 public TableDataListener() { 23 // 這裡是demo,所以隨便new一個。實際使用如果到了spring,請使用下面的有參建構函式 24 tableDao = new TableDao(); 25 } 26 /** 27 * 如果使用了spring,請使用這個構造方法。每次建立Listener的時候需要把spring管理的類傳進來 28 * 29 * @param tableDao 30 */ 31 public TableDataListener(TableDao tableDao) { 32 this.tableDao = tableDao; 33 } 34 /** 35 * 這個每一條資料解析都會來呼叫 36 * 37 * @param data 38 * one row value. Is is same as {@link AnalysisContext#readRowHolder()} 39 * @param context 40 */ 41 @Override 42 public void invoke(TableInfo data, AnalysisContext context) { 43 System.out.println(JSON.toJSONString(data)); 44 list.add(data); 45 // 達到BATCH_COUNT了,需要去儲存一次資料庫,防止資料幾萬條資料在記憶體,容易OOM 46 if (list.size() >= BATCH_COUNT) { 47 saveData(); 48 // 儲存完成清理 list 49 list.clear(); 50 } 51 } 52 /** 53 * 所有資料解析完成了 都會來呼叫 54 * 55 * @param context 56 */ 57 @Override 58 public void doAfterAllAnalysed(AnalysisContext context) { 59 // 這裡也要儲存資料,確保最後遺留的資料也儲存到資料庫 60 saveData(); 61 LOGGER.info("所有資料解析完成!"); 62 } 63 /** 64 * 加上儲存資料庫 65 */ 66 private void saveData() { 67 // System.out.println("{}條資料,開始儲存資料庫!"+ list.size()); 68 tableDao.save(list); 69 LOGGER.info("儲存資料庫成功!"); 70 } 71 }
到這裡基本就結束了,最後來個測試檔案
1 import ExcelRead.listener.TableDataListener; 2 import ExcelRead.pojo.TableInfo; 3 import com.alibaba.excel.EasyExcel; 4 import org.junit.Test; 5 6 public class readTest { 7 @Test 8 public void simpleRead() { 9 // 有個很重要的點 DemoDataListener 不能被spring管理,要每次讀取excel都要new,然後裡面用到spring可以構造方法傳進去 10 String fileName ="XXX.xlsx"; 11 12 // 這裡 需要指定讀用哪個class去讀,然後讀取第一個sheet 檔案流會自動關閉 13 EasyExcel.read(fileName, TableInfo.class, new TableDataListener()).sheet().doRead(); 14 } 15 }