1. 程式人生 > 其它 >讀取Excel文件的兩種寫法

讀取Excel文件的兩種寫法

需用讀取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 }