POI 讀寫excel表格
阿新 • • 發佈:2020-07-16
目錄
POI 讀寫excel表格
POI是Apache軟體基金會的,POI為“Poor Obfuscation Implementation”的首字母縮寫,意為“簡潔版的模糊實現”。
所以POI的主要功能是可以用Java操作Microsoft Office的相關檔案
1. 寫入
1.1 pom依賴
<!--2003(xls)--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <!--2007(xlsx)版本--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency>
所謂03版和07版最大的區別在於 03版表格最多支援65536行, 而07版則沒有上限
1.2 基本功能
結構
- HSSF - 提供讀寫Microsoft Excel格式文件的功能 (03版)
- XSSF - 提供讀寫Microsoft Excel OOXML格式文件的功能(07版)
- HWPF - 提供讀寫Microsoft Word格式文件的功能(word文件)
- HSLF - 提供讀寫Microsoft PowerPoint格式文件的功能(PPT幻燈片)
- HDGF - 提供讀寫Microsoft Visio格式文件的功能
1.3 Workbook介面的三個實現類
實現類 | 描述 |
---|---|
HSSFWorkbook() | 03版寫入 |
XSSFWorkbook() | 07版寫入 (把所有的資料儲存到記憶體 ,再寫入到檔案. 可能發生記憶體洩露) |
SXSSFWorkbook() | 寫入速度快, 佔用更少的記憶體. 中間會產生一個臨時檔案, 需要清理臨時檔案, 預設由100條記錄被儲存到記憶體中, 如果超出這個範圍,則被寫入到臨時檔案中,如果想自 定義記憶體中的數量 ,可以 new SXSSFWorkbook(數量) 來進行定義 |
1.4 寫入檔案演示 (03版)
// 生成檔案路徑定義
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testWrite03() throws Exception {
// 1. 建立一個工作簿
Workbook workbook = new HSSFWorkbook();
// 2. 建立一個工作表
Sheet sheet = workbook.createSheet("統計表");
// 3. 建立一個行 (第一行)
Row row1 = sheet.createRow(0);
// 建立單元格(1,1)
Cell cell11 = row1.createCell(0);
// 單元格(1,1)寫入內容
cell11.setCellValue("今日新增觀眾");
// 建立單元格(1,2)
Cell cell12 = row1.createCell(1);
// 單元格(1,2)寫入內容
cell12.setCellValue(666);
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("統計時間");
Cell cell22 = row2.createCell(1);
String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
// 生成一張表(IO流) 03 版本就是使用xls結尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "統計表03版.xls");
// 寫出檔案
workbook.write(fileOutputStream);
// 關閉流
fileOutputStream.close();
System.out.println("檔案生成完畢");
}
1.5 寫入檔案演示 (07版)
// 生成檔案路徑定義
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testWrite07() throws Exception {
// 1. 建立一個工作簿
Workbook workbook = new XSSFWorkbook();
// 2. 建立一個工作表
Sheet sheet = workbook.createSheet("統計表");
// 3. 建立一個行 (第一行)
Row row1 = sheet.createRow(0);
// 建立單元格(1,1)
Cell cell11 = row1.createCell(0);
// 單元格(1,1)寫入內容
cell11.setCellValue("今日新增觀眾");
// 建立單元格(1,2)
Cell cell12 = row1.createCell(1);
// 單元格(1,2)寫入內容
cell12.setCellValue(666);
// 第二行
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("統計時間");
Cell cell22 = row2.createCell(1);
String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(time);
// 生成一張表(IO流) 03 版本就是使用xls結尾
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "統計表07版.xlsx");
// 寫出檔案
workbook.write(fileOutputStream);
// 關閉流
fileOutputStream.close();
System.out.println("檔案生成完畢");
}
可見 若生成07版只需要把Workbook workbook = new HSSFWorkbook();
改為 Workbook workbook = new XSSFWorkbook();
並且生成的檔案字尾改為xlsx就可以了 ,這就是面向藉口程式設計的好處
1.6 (HSSF) 03版寫入大量資料
預設寫入65536行資料, 檢視所需要的時間
// 生成檔案路徑定義
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testWrite03BigData() throws Exception {
long begin = System.currentTimeMillis(); // 開始時間
// 建立一個簿
Workbook workbook = new HSSFWorkbook();
// 建立表
Sheet sheet = workbook.createSheet();
// 寫入資料
for (int rowNum = 0; rowNum < 65536; rowNum++) {
// 一共65536行
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
// 每列十條資料
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
// 輸出流
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "bigData03");
// 輸出
workbook.write(fileOutputStream);
// 關閉流
fileOutputStream.close();
long end = System.currentTimeMillis(); // 結束時間
// 時間結算
System.out.println((double)(end - begin)/1000 + " s");
}
執行結果: 總共耗時2.036秒
over
2.036 s
注意: 03版如果行數大於65536則丟擲異常
1.7 (XSSF) 07版寫入大量資料
// 生成檔案路徑定義
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testWrite07BigData() throws Exception {
// 時間
long begin = System.currentTimeMillis();
// 建立一個簿
Workbook workbook = new XSSFWorkbook();
// 建立表
Sheet sheet = workbook.createSheet();
// 寫入資料
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "bigData07.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
long end = System.currentTimeMillis();
System.out.println((double)(end - begin)/1000 + " s");
}
執行結果: 總共耗時8.015 秒
over
8.015 s
1.8 (SXSSF) 寫入大量資料
// 生成檔案路徑定義
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testWriteSXSSFBigData() throws Exception {
// 時間
long begin = System.currentTimeMillis();
// 建立一個簿
Workbook workbook = new SXSSFWorkbook();
// 建立表
Sheet sheet = workbook.createSheet();
// 寫入資料
for (int rowNum = 0; rowNum < 65536; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "bigDataSXSSF.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
// 清除臨時檔案
((SXSSFWorkbook) workbook).dispose();
long end = System.currentTimeMillis();
System.out.println((double)(end - begin)/1000 + " s");
}
結果: 2.192 秒
over
2.192 s
注意: 使用SXSSFWorkbook時需要清理臨時檔案
// 清除臨時檔案
((SXSSFWorkbook) workbook).dispose();
1.9 寫入大量資料結論
-
HSSF 寫入大量資料v
- 優點: 可以寫入快速寫入資料
- 缺點: 只能寫入65536行資料, 非常有限
-
XSSF 寫入大量資料
-
優點: 可以寫入任意條資料
-
缺點: 寫入速度慢的一批
-
-
SXSSF 寫入大量資料
- 優點: 快速而且佔用記憶體少
- 缺點: 仍然可能會消耗大量記憶體, 這些記憶體基於正在使用的功能,例如合併區域, 註釋仍然會儲存在記憶體中, 因此如果廣泛使用, 可能需要大量的記憶體
2. 讀取
2.1讀取檔案演示(03版)
// 路徑
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testRead03() throws Exception {
// 獲取檔案流
FileInputStream inputStream = new FileInputStream(PATH + "統計表03版.xls");
// 1. 建立一個工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
// 2. 獲取一個工作表, getSheetAt()方法是根據下標獲取
Sheet sheet = workbook.getSheetAt(0);
// 3. 得到行
Row row = sheet.getRow(0);
// 4. 得到單元格
Cell cell = row.getCell(0);
// 顯示(1,1)的內容, 獲取字串
System.out.println(cell.getStringCellValue());
// 關閉流
inputStream.close();
}
結果: (獲取到了上面寫入中的1.4中生成的檔案)
今日新增觀眾
2.2 讀取檔案演示(07版)
// 路徑
String PATH = "/home/zpk/DEV/idea/workspace/poi/";
@Test
public void testRead07() throws Exception {
// 獲取檔案流
FileInputStream inputStream = new FileInputStream(PATH + "統計表07版.xlsx");
// 1. 建立一個工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 2. 獲取一個工作表, getSheetAt()方法是根據下標獲取
Sheet sheet = workbook.getSheetAt(0);
// 3. 得到行
Row row = sheet.getRow(0);
// 4. 得到單元格
Cell cell = row.getCell(1);
// 顯示(1,1)的內容, 獲取數字型別
System.out.println(cell.getNumericCellValue());
// 關閉流
inputStream.close();
}
結果: (獲取到了上面寫入中的1.5中生成的文檔案)
666.0
2.3 獲取一行的資料(重點)
Row rows = sheet.getRow(0); // 獲取第一行
if (rows != null) {
int cellCount = rows.getPhysicalNumberOfCells(); // 計數,次行多少列存入cellCount中
for (int cellNum = 0; cellNum < cellCount; cellNum++){ // 遍歷列
Cell cell = rows.getCell(cellNum); // 獲取每一列
if (cell != null) {
int cellType = cell.getCellType(); // 每一列的資料型別(列舉)
String cellValue = cell.getStringCellValue(); // 獲取字串內容
System.out.print(cellValue + " | "); // 分割線
}
}
System.out.println() // 換行
}
2.4 獲取整張表的內容
(工具類), 只需要傳入輸入流即可
// 提取為工具類
public void read07Excel(FileInputStream inputStream) throws Exception {
// 1. 建立一個工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 2. 獲取一個工作表, getSheetAt()方法是根據下標獲取
Sheet sheet = workbook.getSheetAt(0);
Row rows = sheet.getRow(0); // 獲取第一行
if (rows != null) {
int cellCount = rows.getPhysicalNumberOfCells(); // 計數,次行多少列存入cellCount中
for (int cellNum = 0; cellNum < cellCount; cellNum++){ // 遍歷列
Cell cell = rows.getCell(cellNum); // 獲取每一列
if (cell != null) {
int cellType = cell.getCellType(); // 每一列的資料型別(列舉)
String cellValue = cell.getStringCellValue(); // 獲取字串內容
System.out.print(cellValue + " | "); // 分割線
}
}
System.out.println(); // 換行
}
int rowCount = sheet.getPhysicalNumberOfRows();
for (int rowNum = 1; rowNum < rowCount; rowNum++) {
Row rowData = sheet.getRow(rowNum);
if (rowData != null) {
// 讀取列
int cellCount = rows.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
System.out.println("[" + (rowNum + 1) + "-" + (cellNum + 1) + "]");
Cell cell = rowData.getCell(cellNum);
// 匹配列的資料型別
if (cell != null) {
int cellType = cell.getCellType();
String cellValue = "";
switch (cellType) {
case HSSFCell.CELL_TYPE_STRING : // 字串
System.out.print("[String]");
cellValue = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_BOOLEAN : // 布林型
System.out.print("[Boolean]");
cellValue = String.valueOf(cell.getStringCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK : // 空
System.out.print("[Blank]");
break;
case HSSFCell.CELL_TYPE_NUMERIC : // 數字(日期和普通數字
System.out.print("[Number]");
if (HSSFDateUtil.isCellDateFormatted(cell)) { // 日期
System.out.print("[日期]");
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM-dd");
} else { // 數字, 直接轉換為字串輸出
// 不是日期格式, 防止數字過長!
System.out.print("[轉為字串輸出]");
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cellValue = String.valueOf(cell.getStringCellValue());
cellValue = cell.toString();
}
break;
case HSSFCell.CELL_TYPE_ERROR : // 布林型
System.out.print("[資料型別錯誤]");
break;
}
System.out.println(cellValue);
}
}
}
}
// 關閉流
inputStream.close();
}