Apache POI教程

时间:2020-02-23 14:29:41  来源:igfitidea点击:

欢迎使用Apache POI教程。
有时我们需要从Microsoft Excel文件中读取数据,或者我们需要以Excel格式生成报告,主要用于商业或者财务目的。
Java不提供使用excel文件的内置支持,因此我们需要为此工作寻找开源API。
当我开始寻找excel的Java 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的一些重要点是:

  • Apache POI包含适用于Excel ’97(-2007)文件格式(即XLS)的HSSF实现。

  • Apache POI XSSF实现应用于Excel 2007 OOXML(.xlsx)文件格式。

  • Apache POI HSSF和XSSF API提供了读取,写入或者修改excel电子表格的机制。

  • Apache POI还提供了SXSSF API,它是XSSF的扩展,可以与非常大的excel工作表一起使用。
    SXSSF API需要较少的内存,适用于处理非常大的电子表格并且堆内存有限。

  • 有两种模型可供选择-事件模型和用户模型。
    事件模型需要较少的内存,因为excel文件是在令牌中读取并需要对其进行处理的。
    用户模型更加面向对象并且易于使用,我们将在示例中使用它。

  • 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文件

假设我们有一个Excel文件" Sample.xlsx",其中包含两张纸,数据如下图所示。
我们想读取excel文件并创建国家列表。
Sheet1还有一些其他数据,在解析时我们将忽略它们。

我们国家的Java bean代码是:

Country.java

package com.theitroad.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;
	}
	
}

用于将excel文件读取到国家/地区列表的Apache POI示例程序如下所示。

ReadExcelFileToList.java

package com.theitroad.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<Country> readExcelData(String fileName) {
		List<Country> countriesList = new ArrayList<Country>();
		
		try {
			//Create the input stream from the xlsx/xls file
			FileInputStream fis = new FileInputStream(fileName);
			
			//Create Workbook instance for xlsx/xls file input stream
			Workbook workbook = null;
			if(fileName.toLowerCase().endsWith("xlsx")){
				workbook = new XSSFWorkbook(fis);
			}else if(fileName.toLowerCase().endsWith("xls")){
				workbook = new HSSFWorkbook(fis);
			}
			
			//Get the number of sheets in the xlsx file
			int numberOfSheets = workbook.getNumberOfSheets();
			
			//loop through each of the sheets
			for(int i=0; i < numberOfSheets; i++){
				
				//Get the nth sheet from the workbook
				Sheet sheet = workbook.getSheetAt(i);
				
				//every sheet has rows, iterate over them
				Iterator<Row> rowIterator = sheet.iterator();
				while (rowIterator.hasNext()) 
		        {
					String name = "";
					String shortCode = "";
					
					//Get the row object
					Row row = rowIterator.next();
					
					//Every row has columns, get the column iterator and iterate over them
					Iterator<Cell> cellIterator = row.cellIterator();
		             
		            while (cellIterator.hasNext()) 
		            {
		            	//Get the Cell object
		            	Cell cell = cellIterator.next();
		            	
		            	//check the cell type and process accordingly
		            	switch(cell.getCellType()){
		            	case Cell.CELL_TYPE_STRING:
		            		if(shortCode.equalsIgnoreCase("")){
		            			shortCode = cell.getStringCellValue().trim();
		            		}else if(name.equalsIgnoreCase("")){
		            			//2nd column
		            			name = cell.getStringCellValue().trim();
		            		}else{
		            			//random data, leave it
		            			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
			
			//close file input stream
			fis.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return countriesList;
	}

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

}

该程序非常易于理解,包含以下步骤:

  • 根据文件类型创建Workbook实例。
    xlsx格式的" XSSFWorkbook"和xls格式的" HSSFWorkbook"。
    请注意,我们可以使用工厂模式创建包装类,以基于文件名获取工作簿实例。

  • 使用工作簿getNumberOfSheets()获取工作表数量,然后使用for循环来解析每个工作表。
    使用getSheetAt(int i)方法获取Sheet实例。

  • 获取"行"迭代器,然后获取"单元"迭代器以获取Cell对象。
    Apache POI在这里使用迭代器模式。

  • 使用开关箱读取单元格的类型并对其进行相应处理。

现在,当我们在Apache POI示例程序之上运行时,它将在控制台上产生以下输出。

Random data::1.0
Random data::2.0
Random data::3.0
Random data::4.0
Country List
[San Franceco::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.theitroad.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<Country> 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<Country> 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());
		}
		
		//lets write the excel data to file now
		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<Country> list = ReadExcelFileToList.readExcelData("Sample.xlsx");
		WriteListToExcelFile.writeCountryListToFile("Countries.xls", list);
	}
}

当我执行以上apache POI示例程序时,生成的excel文件如下图所示。

Apache POI示例–阅读Excel公式

有时我们需要使用公式处理复杂的excel文件,让我们看一个简单的apache POI示例,以读取具有其值的单元格的公式。

ReadExcelFormula.java

package com.theitroad.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);
		
		//assuming xlsx file
		Workbook workbook = new XSSFWorkbook(fis);
		Sheet sheet = workbook.getSheetAt(0);
		Iterator<Row> rowIterator = sheet.iterator();
		while (rowIterator.hasNext()) 
      {
			Row row = rowIterator.next();
			Iterator<Cell> 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.theitroad.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);
		//set formula cell
		row.createCell(3).setCellFormula("A1*B1*C1");
		
		//lets write to file
		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文件