用 Apache POI 读取 XLSX 数据
Posted 兔大沛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 Apache POI 读取 XLSX 数据相关的知识,希望对你有一定的参考价值。
最近因为项目的原因,需要从一些 Microsoft Office Excel 文件读取数据并加载到数据库。
Google了一下方法,发现其实可以用的 Java 第三方库很多,最著名的是 Apache 的 POI 开源项目,其官网地址是 https://poi.apache.org
从首页的简介中我发现这个项目功能非常强大,不仅能处理 Excel,它还可以处理 Word、PowerPoint、Outlook、Visio,基本上囊括了 MS Office 的全部常用组件。目前 POI 更新到了 3.16 版本,可以从这个页面下载 https://poi.apache.org/download.html#POI-3.16
和所有的 Apache 开源项目一样,POI 下载页面同时提供源码和编译好的库文件下载,有时间的朋友建议下源码看看,写得非常好(编译用 ant 就行)。下载好库文件后(或者下载源文件自己编译好后),以 External Jars 的形式导入 Eclipse 项目中,就可以开始编程了。
读取 Excel 其实很简单,步骤如下:
1. 使用一个 java.io.FileInputStream 对象打开要访问的 Excel 文件获取一个输入流
2. 用这个文件流创建一个 org.apache.poi.xssf.usermodel.XSSFWorkbook 类的实例
3. 使用 XSSFWorkbook 类的 getSheetAt(int index) 方法读取指定的 sheet,其返回一个 org.apache.poi.xssf.usermodel.XSSFSheet 类的实例
4. 使用 XSSFSheet 类的 getRow(int index) 方法读取指定的 row(这里可以进行一个循环,详情请参阅下面的代码),其返回一个 org.apache.poi.xssf.usermodel.XSSFRow 类的实例
5. 使用 XSSFRow 类的 getCell(int index) 方法读取指定的 cell(同上,可以循环读取,参阅代码),其返回一个 org.apache.poi.xssf.usermodel.XSSFCell 类的实例
6. 根据返回的 Cell 的不同类型,分别处理:字符型数字型直接输出,日期型可以指定一个格式输出,表达式则需要使用 org.apache.poi.ss.usermodel.FormulaEvaluator 类的 evaluate(Cell arg0) 方法先得到表达式的值,然后再进行第二次类型判断后才能输出。
PS:因为目标数据的特性,我只需要把数据输出到标准输出即可。
完整程序如下:
package com.peisu.xlsx;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class XLSXLoader {
//Define the variables
private static InputStream inputStream;
private static XSSFWorkbook xssfWorkbook;
private static FormulaEvaluator formulaEvaluator;
private static int maxCellCount = 0;
//args[0]: the path to the xlsx file
//args[1]: the sheet number to process, start from 0
//args[2]: the date format output to standard output, for example, yyyy-MM-dd
//args[3]: start from which line to read, if there is a header, start from line 1
public static void main(String[] args) {
try {
//Open the input stream from the file, initialize the workbook
inputStream = new FileInputStream(args[0]);
xssfWorkbook = new XSSFWorkbook(inputStream);
formulaEvaluator = xssfWorkbook.getCreationHelper().createFormulaEvaluator();
//Open the sheet
XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(Integer.valueOf(args[1]));
if (xssfSheet != null){
//Get the first row of the sheet
XSSFRow firstXSSFRow = xssfSheet.getRow(0);
if (firstXSSFRow != null){
//Set the max cell count to be the last cell number of the first line
maxCellCount = firstXSSFRow.getLastCellNum();
//Loop to read the rows
for (int rowNum = Integer.valueOf(args[3]);rowNum <= xssfSheet.getLastRowNum();rowNum++) {
//Get the row
XSSFRow xssfRow = xssfSheet.getRow(rowNum);
if (xssfRow != null){
//Loop to read the cells
for (int cellNum = 0;cellNum < maxCellCount;cellNum++){
//Get the cell
XSSFCell xssfCell = xssfRow.getCell(cellNum);
if (xssfCell != null){
//Process the cell based on the cell type
switch (xssfCell.getCellTypeEnum()){
case STRING:
System.out.print(xssfCell.getStringCellValue());
break;
case NUMERIC:
//If the cell matches the date format, output the cell as a date
if (DateUtil.isCellDateFormatted(xssfCell)) {
SimpleDateFormat dateFormat = new SimpleDateFormat(args[2]);
System.out.print(dateFormat.format(xssfCell.getDateCellValue()));
}
else
System.out.print(xssfCell.getNumericCellValue());
break;
case BOOLEAN:
System.out.print(xssfCell.getBooleanCellValue());
break;
case FORMULA:
//For formula cell, evaluate the formula to get the result
CellValue cellValue = formulaEvaluator.evaluate(xssfCell);
//Process the formula cell based on the type of the result
switch(cellValue.getCellTypeEnum()){
case STRING:
System.out.print(xssfCell.getStringCellValue());
break;
case NUMERIC:
//If the result matches the date format, output the result as a date
if (DateUtil.isCellDateFormatted(xssfCell)) {
SimpleDateFormat dateFormat = new SimpleDateFormat(args[2]);
System.out.print(dateFormat.format(xssfCell.getDateCellValue()));
}
else
System.out.print(xssfCell.getNumericCellValue());
break;
case BOOLEAN:
System.out.print(xssfCell.getBooleanCellValue());
break;
default:
System.out.print(xssfCell.getRawValue());
}
break;
case ERROR:
//System.out.print(xssfCell.getErrorCellString());
System.out.print("");
break;
default:
System.out.print(xssfCell.getRawValue());
}
}
//Add a column delimiter between the output cells
if(cellNum < maxCellCount - 1)
System.out.print("\t");
}
}
//Add a row delimiter between the output rows
System.out.println("");
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
xssfWorkbook.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以上是关于用 Apache POI 读取 XLSX 数据的主要内容,如果未能解决你的问题,请参考以下文章
在使用 apache poi 从扩展名为 xlsx 的 Excel 文件中读取数据时,需要很长时间
通过 Apache POI 读取大型 Excel 文件 (xlsx) 时出错
JAVA编程中用Apache POI 怎么用SXSSFWorkbook对已存在的excel(.xlsx)操作进行写数据操作