Apache POI教程
欢迎使用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文件