Apache POI 教程

歡迎來到 Apache POI 教程。有時我們需要從 Microsoft Excel 文件中讀取數據,或者我們需要生成 Excel 格式的報告,主要是用於商業或財務目的。Java 不提供內置支持來處理 Excel 文件,所以我們需要尋找開源 API 來完成這項任務。當我開始尋找 Java 用於 Excel 的 API 時,大多數人都推薦 JExcel 或 Apache POI。經過進一步研究,我發現 Apache POI 是最佳選擇,主要有以下幾個原因。還有一些其他與高級功能相關的原因,但我們不需要進行太多細節。

  • Apache 基金會的支持。
  • JExcel 不支持 xlsx 格式,而 POI 支持 xls 和 xlsx 格式。
  • Apache POI 提供基於流的處理,適用於大型文件且需要較少的內存。

Apache POI

Apache POI 提供了卓越的支持,用於處理 Microsoft Excel 文檔。Apache POI 能夠處理電子表格的 XLS 和 XLSX 格式。有關 Apache POI API 的一些重要點如下:

  1. Apache POI 包含了 Excel ’97(-2007) 文件格式即 XLS 的 HSSF 實現。
  2. 應該使用 Apache POI XSSF 實現來處理 Excel 2007 OOXML (.xlsx) 文件格式。
  3. Apache POI HSSF 和 XSSF API 提供了讀取、寫入或修改 Excel 電子表格的機制。
  4. Apache POI 也提供了 SXSSF API,它是 XSSF 的擴展,用於處理非常大的 Excel 表格。SXSSF API 需要較少的內存,在處理非常大的電子表格且堆內存有限時很適用。
  5. 有兩種模型可供選擇 – 事件模型和用戶模型。事件模型需要較少的內存,因為 Excel 文件是以標記形式讀取並需要處理它們。用戶模型更加面向對象且易於使用,我們將在我們的示例中使用它。
  6. Apache POI 還提供了出色的支持,可以處理額外的 Excel 功能,如處理公式、通過填充顏色和邊框、字體、頁首和頁腳、數據驗證、圖像、超鏈接等。

Apache POI Maven 依賴項

如果您正在使用 Maven,請添加以下 Apache POI 依賴項。

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.10-FINAL</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.10-FINAL</version>
</dependency>

目前的 Apache POI 版本為 3.10-FINAL。如果您正在使用獨立的 Java 應用程序,請將下圖中的 jar 文件包含在內。

Apache POI 示例 – 讀取 Excel 文件

假設我們有一個名為“Sample.xlsx”的Excel文件,其中包含兩個工作表,並具有如下圖所示的數據。我們希望讀取Excel文件並創建一個國家列表。Sheet1有一些額外的數據,我們在解析時將忽略它。 我們的Country Java Bean代碼如下:Country.java

package com.journaldev.excel.read;

public class Country {

	private String name;
	private String shortCode;
	
	public Country(String n, String c){
		this.name=n;
		this.shortCode=c;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getShortCode() {
		return shortCode;
	}
	public void setShortCode(String shortCode) {
		this.shortCode = shortCode;
	}
	
	@Override
	public String toString(){
		return name + "::" + shortCode;
	}
	
}

Apache POI讀取Excel文件到國家列表的示例程序如下:ReadExcelFileToList.java

package com.journaldev.excel.read;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ReadExcelFileToList {

	public static List readExcelData(String fileName) {
		List countriesList = new ArrayList();
		
		try {
			//從xlsx/xls文件創建輸入流
			FileInputStream fis = new FileInputStream(fileName);
			
			//為xlsx/xls文件的輸入流創建Workbook實例
			Workbook workbook = null;
			if(fileName.toLowerCase().endsWith("xlsx")){
				workbook = new XSSFWorkbook(fis);
			}else if(fileName.toLowerCase().endsWith("xls")){
				workbook = new HSSFWorkbook(fis);
			}
			
			//獲取xlsx文件中的工作表數量
			int numberOfSheets = workbook.getNumberOfSheets();
			
			//遍歷每個工作表
			for(int i=0; i < numberOfSheets; i++){
				
				//從工作簿中獲取第n個工作表
				Sheet sheet = workbook.getSheetAt(i);
				
				//每個工作表都有行,遍歷它們
				Iterator rowIterator = sheet.iterator();
				while (rowIterator.hasNext()) 
		        {
					String name = "";
					String shortCode = "";
					
					//獲取行對象
					Row row = rowIterator.next();
					
					//每行都有列,獲取列迭代器並遍歷它們
					Iterator cellIterator = row.cellIterator();
		             
		            while (cellIterator.hasNext()) 
		            {
		            	//獲取單元格對象
		            	Cell cell = cellIterator.next();
		            	
		            	//檢查單元格類型並相應處理
		            	switch(cell.getCellType()){
		            	case Cell.CELL_TYPE_STRING:
		            		if(shortCode.equalsIgnoreCase("")){
		            			shortCode = cell.getStringCellValue().trim();
		            		}else if(name.equalsIgnoreCase("")){
		            			//第2列
		            			name = cell.getStringCellValue().trim();
		            		}else{
		            			//隨機數據,忽略它
		            			System.out.println("Random data::"+cell.getStringCellValue());
		            		}
		            		break;
		            	case Cell.CELL_TYPE_NUMERIC:
		            		System.out.println("Random data::"+cell.getNumericCellValue());
		            	}
		            } //end of cell iterator
		            Country c = new Country(name, shortCode);
		            countriesList.add(c);
		        } //end of rows iterator
				
				
			} //end of sheets for loop
			
			//關閉文件輸入流
			fis.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return countriesList;
	}

	public static void main(String args[]){
		List list = readExcelData("Sample.xlsx");
		System.out.println("Country List\n"+list);
	}

}

該程序非常容易理解,包含以下步驟:

  1. 根據文件類型創建Workbook實例。xlsx格式使用XSSFWorkbook,xls格式使用HSSFWorkbook。請注意,我們可以使用工廠模式創建包裝類,根據文件名獲取工作簿實例。
  2. 使用workbook的getNumberOfSheets()方法獲取工作表數量,然後使用for循環解析每個工作表。使用getSheetAt(int i)方法獲取Sheet實例。
  3. 獲取Row迭代器,然後獲取Cell迭代器以獲取Cell對象。Apache POI在這裡使用迭代器模式
  4. 使用switch-case來讀取Cell的類型並相應地處理它。

現在,當我們運行上述Apache POI示例程序時,它在控制台上產生以下輸出。

Random data::1.0
Random data::2.0
Random data::3.0
Random data::4.0
Country List
[India::IND, Afghanistan::AFG, United States of America::USA, Anguilla::AIA, 
Denmark ::DNK, Dominican Republic ::DOM, Algeria ::DZA, Ecuador ::ECU]

Apache POI示例 – 寫Excel文件

寫入 Apache POI 中的 Excel 檔案與讀取類似,唯一不同的是我們首先要建立工作簿。然後設置工作表、行和儲存格的值,並使用 FileOutputStream 將其寫入檔案。讓我們寫一個簡單的 Apache POI 範例,我們將使用上述方法中的國家列表將其保存到另一個單一工作表的檔案中。`WriteListToExcelFile.java`

package com.journaldev.excel.read;

import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class WriteListToExcelFile {

	public static void writeCountryListToFile(String fileName, List countryList) throws Exception{
		Workbook workbook = null;
		
		if(fileName.endsWith("xlsx")){
			workbook = new XSSFWorkbook();
		}else if(fileName.endsWith("xls")){
			workbook = new HSSFWorkbook();
		}else{
			throw new Exception("invalid file name, should be xls or xlsx");
		}
		
		Sheet sheet = workbook.createSheet("Countries");
		
		Iterator iterator = countryList.iterator();
		
		int rowIndex = 0;
		while(iterator.hasNext()){
			Country country = iterator.next();
			Row row = sheet.createRow(rowIndex++);
			Cell cell0 = row.createCell(0);
			cell0.setCellValue(country.getName());
			Cell cell1 = row.createCell(1);
			cell1.setCellValue(country.getShortCode());
		}
		
		//現在將 Excel 數據寫入檔案
		FileOutputStream fos = new FileOutputStream(fileName);
		workbook.write(fos);
		fos.close();
		System.out.println(fileName + " written successfully");
	}
	
	public static void main(String args[]) throws Exception{
		List list = ReadExcelFileToList.readExcelData("Sample.xlsx");
		WriteListToExcelFile.writeCountryListToFile("Countries.xls", list);
	}
}

當我執行上述 Apache POI 範例程式時,生成的 Excel 檔案如下圖所示。

Apache POI 範例 – 讀取 Excel 公式

有時我們需要處理帶有公式的複雜 Excel 檔案,讓我們看一個簡單的 Apache POI 範例來讀取具有其值的儲存格的公式。`ReadExcelFormula.java`

package com.journaldev.excel.read;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ReadExcelFormula {

	public static void readExcelFormula(String fileName) throws IOException{
		
		FileInputStream fis = new FileInputStream(fileName);
		
		//假設是 xlsx 檔
		Workbook workbook = new XSSFWorkbook(fis);
		Sheet sheet = workbook.getSheetAt(0);
		Iterator rowIterator = sheet.iterator();
		while (rowIterator.hasNext()) 
        {
			Row row = rowIterator.next();
			Iterator cellIterator = row.cellIterator();
            
            while (cellIterator.hasNext()) 
            {
            	Cell cell = cellIterator.next();
            	switch(cell.getCellType()){
            	case Cell.CELL_TYPE_NUMERIC:
            		System.out.println(cell.getNumericCellValue());
            		break;
            	case Cell.CELL_TYPE_FORMULA:
            		System.out.println("Cell Formula="+cell.getCellFormula());
            		System.out.println("Cell Formula Result Type="+cell.getCachedFormulaResultType());
            		if(cell.getCachedFormulaResultType() == Cell.CELL_TYPE_NUMERIC){
            			System.out.println("Formula Value="+cell.getNumericCellValue());
            		}
            	}
            }
        }
	}
	
	public static void main(String args[]) throws IOException {
		readExcelFormula("FormulaMultiply.xlsx");
	}
}

當我們執行上述 Apache POI 範例程式時,我們得到以下輸出。

1.0
2.0
3.0
4.0
Cell Formula=A1*A2*A3*A4
Cell Formula Result Type=0
Formula Value=24.0

Apache POI 示例 – Excel 写入公式

有时,我们需要进行一些计算,然后写入单元格值。我们可以使用 Excel 公式来进行这些计算,这样做会更准确,因为如果计算中使用的单元格值发生变化,数值也会随之改变。让我们来看一个使用 Apache POI API 编写带有公式的 Excel 文件的简单示例。WriteExcelWithFormula.java

package com.journaldev.excel.read;

import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class WriteExcelWithFormula {

	public static void writeExcelWithFormula(String fileName) throws IOException{
		Workbook workbook = new XSSFWorkbook();
		Sheet sheet = workbook.createSheet("Numbers");
		Row row = sheet.createRow(0);
		row.createCell(0).setCellValue(10);
		row.createCell(1).setCellValue(20);
		row.createCell(2).setCellValue(30);
		// 设置公式单元格
		row.createCell(3).setCellFormula("A1*B1*C1");
		
		// 写入文件
		FileOutputStream fos = new FileOutputStream(fileName);
		workbook.write(fos);
		fos.close();
		System.out.println(fileName + " written successfully");
	}
	
	public static void main(String[] args) throws IOException {
		writeExcelWithFormula("Formulas.xlsx");
	}
}

上述 Apache POI API 示例程序生成的 Excel 文件如下图所示。关于使用 Excel 文件的 Apache POI 教程就介绍到这里,可以查阅 Apache POI 类的方法以了解更多功能。参考资料: Apache POI 开发者指南

Source:
https://www.digitalocean.com/community/tutorials/apache-poi-tutorial