Apache POI 教程
欢迎来到Apache POI教程。有时候我们需要从Microsoft Excel文件中读取数据,或者需要生成Excel格式的报表,主要用于商业或金融目的。Java本身不提供与Excel文件的工作支持,所以我们需要寻找开源API来完成这个任务。当我开始寻找Java处理Excel的API时,大部分人推荐JExcel或Apache POI。经过进一步的研究,我发现Apache POI是首选的主要原因。还有一些高级特性相关的其他原因,但我们不需要去深入详细讨论。
- Backing of Apache foundation.
- JExcel doesn’t support xlsx format whereas POI supports both xls and xlsx formats.
- Apache POI provides stream-based processing, that is suitable for large files and requires less memory.
Apache POI 是一个用于读写 Microsoft Office 格式文件的 Java 库。
Apache POI在处理Microsoft Excel文档方面提供了出色的支持。Apache POI能够处理电子表格的XLS和XLSX格式。有关Apache POI API的一些重要要点是:
-
- Apache POI包含对Excel ’97(-2007)文件格式(即XLS)的HSSF实现。
-
- 对于Excel 2007 OOXML(.xlsx)文件格式,应使用Apache POI XSSF实现。
-
- Apache POI HSSF和XSSF API提供了读取、写入或修改电子表格的机制。
-
- 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应用程序,请包含下方图片中的Jars。
Apache POI 示例 – 读取 Excel 文件
假设我们有一个名为“Sample.xlsx”的Excel文件,其中包含两个工作表,并且具有以下图片中的数据。我们想要读取这个Excel文件,并创建一个国家列表。尽管在解析过程中Sheet1有一些额外的数据,但我们会忽略它。我们的国家Java Bean代码是:Country.java
package com.Olivia.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.Olivia.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。注意我們可以使用工廠模式創建一個包裝器類,根據文件名來獲取Workbook實例。
-
- 使用workbook的getNumberOfSheets()方法獲取表格的數量,然後使用for循環解析每個表格。使用getSheetAt(int i)方法獲取Sheet實例。
-
- 獲取Row迭代器,然後獲取Cell迭代器以獲取Cell對象。Apache POI在這裡使用了迭代器模式。
- 使用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.Olivia.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.Olivia.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.Olivia.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文件如下图所示。这就是关于使用Excel文件的Apache POI教程的全部内容,请查看Apache POI类中的方法以了解更多功能。参考文献:Apache POI开发者指南。