版本1.4
新增通过输入流解析全部数据的方法。
工具类:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.LocaleUtil;
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;
/**
* excel文件上传解析工具类
*
* @author zql
* @version 1.4 on 2019-10-05
* 新增通过输入流解析全部数据的方法
*/
public class ExcelParseMapper {
/**
* 解析指定工作薄方法
*
* @param file excel文件对象
* @param type 用于横向读取或者纵向读取的判断,1为纵向,反之则为横向
* @param sheetNum 第几个工作薄,从1开始
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
public void parseSpecifiedSheet(File file,int type,int sheetNum,ParseSheetCell parseSheetCell){
if (file != null) {
if (file.getName().endsWith("xls")) {
parseExcel2003(file, type, sheetNum, parseSheetCell);
}
if (file.getName().endsWith("xlsx")) {
parseExcel2007(file, type, sheetNum, parseSheetCell);
}
}
}
/**
* 读取2003Excel
*
* @param file excel文件对象
* @param type 用于横向读取或者纵向读取的判断,1为纵向,反之则为横向
* @param sheetNum 第几个工作薄,从1开始
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseExcel2003(File file, int type, int sheetNum, ParseSheetCell parseSheetCell) {
try {
FileInputStream fis = new FileInputStream(file);
HSSFWorkbook wb = new HSSFWorkbook(fis);
fis.close();
// 因为sheet索引从1开始,所以要减1
int sheetIndex = sheetNum - 1;
/*
* 对sheet进行判断,防止越界
* 当sheet小于0时,取第一个sheet,当sheet大于所有sheet总数时,取最后一个
*/
sheetIndex = sheetIndex < 0 ? 0 : sheetIndex;
int getNumberOfSheets = wb.getNumberOfSheets();
sheetIndex = sheetIndex >= getNumberOfSheets ? getNumberOfSheets - 1 : sheetIndex;
HSSFSheet sheet = wb.getSheetAt(sheetIndex);
// 取得最后一行的行号
int rowNum = sheet.getLastRowNum() + 1;
// 当type等于1时为纵向
if (type == 1) {
parseLengthwaysExcel2003(sheet, rowNum, parseSheetCell);
} else {
parseTransverseExcel2003(sheet, rowNum, parseSheetCell);
}
wb.close();
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + " by parseExcel2003");
}
}
/**
* 读取2007Excel
*
* @param file excel文件对象
* @param type 用于横向读取或者纵向读取的判断
* @param sheetNum 第几个工作薄,从1开始
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseExcel2007(File file, int type, int sheetNum, ParseSheetCell parseSheetCell) {
try {
FileInputStream fis = new FileInputStream(file);
XSSFWorkbook wb = new XSSFWorkbook(fis);
fis.close();
// 因为sheet索引从1开始,所以要减1
int sheetIndex = sheetNum - 1;
/*
* 对sheet进行判断,防止越界
* 当sheet小于0时,取第一个sheet,当sheet大于所有sheet总数时,取最后一个
*/
sheetIndex = sheetIndex < 0 ? 0 : sheetIndex;
int getNumberOfSheets = wb.getNumberOfSheets();
sheetIndex = sheetIndex >= getNumberOfSheets ? getNumberOfSheets - 1 : sheetIndex;
XSSFSheet sheet = wb.getSheetAt(sheetIndex);
// 取得最后一行的行号
int rowNum = sheet.getLastRowNum() + 1;
// 当type等于1时为纵向
if (type == 1) {
parseLengthwaysExcel2007(sheet, rowNum, parseSheetCell);
} else {
parseTransverseExcel2007(sheet, rowNum, parseSheetCell);
}
wb.close();
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + " by parseExcel2007");
}
}
/**
* 横向解析2003excel
*
* @param sheet HSSFSheet对象
* @param rowNum 总行数
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseTransverseExcel2003(HSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
String sheetName = sheet.getSheetName();
HSSFRow rowTitle = sheet.getRow(0);
int cellTitleNum = rowTitle.getLastCellNum();
String[] title = new String[cellTitleNum];
// 保存标题
for (int i = 0; i < cellTitleNum; i++) {
HSSFCell cell = rowTitle.getCell(Short.parseShort(i + ""));
if (cell != null) {
// 把类型先设置为字符串类型
cell.setCellType(CellType.STRING);
title[i] = cell.getStringCellValue();
} else {
title[i] = "空标题" + i;
}
}
// 是否完成当前行的读取
boolean isComplete;
// 行循环开始
for (int i = 1; i < rowNum; i++) {
isComplete = false;
// 得到Excel工作表的行
HSSFRow row = sheet.getRow(i);
for (int j = 0; j < cellTitleNum; j++) {
// 得到Excel工作表指定行的单元格
HSSFCell cell = row.getCell(j);
if (j == (cellTitleNum - 1)) {
isComplete = true;
}
parseSheetCell.setCurCell(title[j], i, isComplete, sheetName, cell);
}
}
}
/**
* 纵向解析2003excel
*
* @param sheet HSSFSheet对象
* @param rowNum 总行数
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseLengthwaysExcel2003(HSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
String sheetName = sheet.getSheetName();
String title = null;
// 是否完成当前行的读取
boolean isComplete;
for (int i = 0; i < rowNum; i++) {
isComplete = false;
// 得到Excel工作表的行
HSSFRow row = sheet.getRow(i);
// 得到标题单元格
HSSFCell cell = row.getCell(0);
if (cell != null) {
// 把类型先设置为字符串类型
cell.setCellType(CellType.STRING);
title = cell.getStringCellValue();
} else {
title = "空标题" + i;
}
for (int j = 1, len = row.getLastCellNum(); j < len; j++) {
cell = row.getCell(j);
if (j == (len - 1)) {
isComplete = true;
}
parseSheetCell.setCurCell(title, i, isComplete, sheetName, cell);
}
}
}
/**
* 横向解析2007excel
*
* @param sheet XSSFSheet对象
* @param rowNum 总行数
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseTransverseExcel2007(XSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
String sheetName = sheet.getSheetName();
XSSFRow rowTitle = sheet.getRow(0);
int cellTitleNum = rowTitle.getLastCellNum();
String[] title = new String[cellTitleNum];
for (int i = 0; i < cellTitleNum; i++) {
XSSFCell cell = rowTitle.getCell(Short.parseShort(i + ""));
if (cell != null) {
// 把类型先设置为字符串类型
cell.setCellType(CellType.STRING);
title[i] = cell.getStringCellValue();
} else {
title[i] = "空标题" + i;
}
}
// 是否完成当前行的读取
boolean isComplete;
// 行循环开始
for (int i = 1; i < rowNum; i++) {
// 得到Excel工作表的行
XSSFRow row = sheet.getRow(i);
for (int j = 0; j < cellTitleNum; j++) {
isComplete = false;
// 得到Excel工作表指定行的单元格
XSSFCell cell = row.getCell(j);
if (j == (cellTitleNum - 1)) {
isComplete = true;
}
parseSheetCell.setCurCell(title[j], i, isComplete, sheetName, cell);
}
}
}
/**
* 纵向解析2007excel
*
* @param sheet XSSFSheet对象
* @param rowNum 总行数
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
private void parseLengthwaysExcel2007(XSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
String sheetName = sheet.getSheetName();
String title = null;
// 是否完成当前行的读取
boolean isComplete;
for (int i = 0; i < rowNum; i++) {
isComplete = false;
// 得到Excel工作表的行
XSSFRow row = sheet.getRow(i);
// 得到标题单元格
XSSFCell cell = row.getCell(0);
if (cell != null) {
// 把类型先设置为字符串类型
cell.setCellType(CellType.STRING);
title = cell.getStringCellValue();
} else {
title = "空标题" + i;
}
for (int j = 1, len = row.getLastCellNum(); j < len; j++) {
cell = row.getCell(j);
if (j == (len - 1)) {
isComplete = true;
}
parseSheetCell.setCurCell(title, i, isComplete, sheetName, cell);
}
}
}
/**
* 对单元格进行格式化
*
* @param cell
* @return
*/
public Object getFormartType(Cell cell) {
Object value;
if (cell == null) {
return "";
}
switch (cell.getCellType()) {
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
DateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd", LocaleUtil.getUserLocale());
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
value = sdf.format(cell.getDateCellValue());
} else if ("@".equals(cell.getCellStyle().getDataFormatString())) {
// 大数值读取时,会读到科学计数法形式,即后面带一个E,所以需要用new DecimalFormat("#")格式化
// #号表示前缀或后缀出现不必要的0时,将其忽略,因此,要想读到几位,就在点号后加几个#号,本例中,#.########将可读到1至8位小数
value = new DecimalFormat("#.########").format(cell.getNumericCellValue());
} else if ("0.00".equals(cell.getCellStyle().getDataFormatString())) {
value = new DecimalFormat("#.########").format(cell.getNumericCellValue());
} else if ("General".equals(cell.getCellStyle().getDataFormatString())) {
value = new DecimalFormat("#.########").format(cell.getNumericCellValue());
} else {
value = Double.toString(cell.getNumericCellValue());
}
break;
case STRING:
value = cell.getRichStringCellValue().toString();
break;
case FORMULA:
// try catch为了防止取到计算公式,而取到计算结果
try {
value = String.valueOf(cell.getNumericCellValue());
} catch (IllegalStateException e) {
value = String.valueOf(cell.getCellFormula());
}
break;
case BLANK:
value = "";
break;
case BOOLEAN:
value = cell.getBooleanCellValue() ? true : false;
break;
case ERROR:
value = ErrorEval.getText(cell.getErrorCellValue());
break;
default:
value = cell.toString();
}
return value;
}
/**
* 定义一个解析工作薄单元格内容的接口
*/
public interface ParseSheetCell {
/**
* @param title 当前单元格所在列的标题
* @param curRowNum 当前单元格所在的行数
* @param isComplete 是否完成当前行的读取
* @param sheetName 当前读取的工作薄名称
* @param cell 当前单元格对象
*/
void setCurCell(String title, int curRowNum, boolean isComplete, String sheetName, Cell cell);
}
/**
* 解析全部数据方法
*
* @param file excel文件对象
* @param parseAllSheet 解析全部sheet的接口
*/
public void parseALLData(File file, ParseAllSheet parseAllSheet) {
if (file != null) {
if (file.getName().endsWith("xls")) {
readALLSheet2003(file, parseAllSheet);
}
if (file.getName().endsWith("xlsx")) {
readALLSheet2007(file, parseAllSheet);
}
}
}
/**
* 读取2003Excel
*
* @param file excel文件对象
* @param parseAllSheet 解析全部sheet的接口
*/
private void readALLSheet2003(File file, ParseAllSheet parseAllSheet) {
try {
FileInputStream fis = new FileInputStream(file);
parseExcelInputStream2003(fis, parseAllSheet);
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + " by readALLSheet2003");
}
}
/**
* 读取2007Excel
*
* @param file excel文件对象
* @param parseAllSheet 解析全部sheet的接口
*/
private void readALLSheet2007(File file, ParseAllSheet parseAllSheet) {
try {
FileInputStream fis = new FileInputStream(file);
parseExcelInputStream2007(fis, parseAllSheet);
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + "by readALLSheet2007");
}
}
/**
* 解析当前sheet的方法,此方法配合解析全部数据方法使用
*
* @param type 用于横向读取或者纵向读取的判断,1为纵向,反之则为横向
* @param version 当前的excel版本
* @param sheet 当前的Sheet
* @param rowNum 总行数
* @param parseSheetCell 解析工作薄单元格内容的接口
*/
public void parseCurSheet(int type, int version, Sheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
if (version == 2003) {
HSSFSheet hs = (HSSFSheet) sheet;
// 当type等于1时为纵向
if (type == 1) {
parseLengthwaysExcel2003(hs, rowNum, parseSheetCell);
} else {
parseTransverseExcel2003(hs, rowNum, parseSheetCell);
}
}
if (version == 2007) {
XSSFSheet xs = (XSSFSheet) sheet;
// 当type等于1时为纵向
if (type == 1) {
parseLengthwaysExcel2007(xs, rowNum, parseSheetCell);
} else {
parseTransverseExcel2007(xs, rowNum, parseSheetCell);
}
}
}
/**
* 定义一个解析全部sheet的接口
*/
public interface ParseAllSheet {
/**
* @param version 当前的excel版本
* @param sheet 当前Sheet对象
* @param sheetName 当前工作薄名称
* @param rowNum 总行数
*/
void parseCurSheet(int version, Sheet sheet, String sheetName, int rowNum);
}
/**
* 解析全部数据方法
*
* @param in 字节输入流
* @param version excel版本
* @param parseAllSheet 解析全部sheet的接口
*/
public void parseALLData(InputStream in, int version, ParseAllSheet parseAllSheet) {
if (version == 2003) {
parseExcelInputStream2003(in, parseAllSheet);
}
if (version == 2007) {
parseExcelInputStream2007(in, parseAllSheet);
}
}
/**
* 解析2003Excel输入流
*
* @param in 字节输入流
* @param parseAllSheet 解析全部sheet的接口
*/
private void parseExcelInputStream2003(InputStream in, ParseAllSheet parseAllSheet) {
try {
HSSFWorkbook wb = new HSSFWorkbook(in);
in.close();
// 获取工作薄数
int getNumberOfSheets = wb.getNumberOfSheets();
HSSFSheet sheet = null;
int rowNum = 0;
String sheetName = null;
for (int i = 0; i < getNumberOfSheets; i++) {
// 得到工作薄内容
sheet = wb.getSheetAt(i);
// 得到工作薄名
sheetName = sheet.getSheetName();
// 取得最后一行的行号
rowNum = sheet.getLastRowNum() + 1;
parseAllSheet.parseCurSheet(2003, sheet, sheetName, rowNum);
}
wb.close();
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + " by parseExcelInputStream2003");
}
}
/**
* 解析2007Excel输入流
*
* @param in 字节输入流
* @param parseAllSheet 解析全部sheet的接口
*/
private void parseExcelInputStream2007(InputStream in, ParseAllSheet parseAllSheet) {
try {
XSSFWorkbook wb = new XSSFWorkbook(in);
in.close();
// 获取工作薄数
int getNumberOfSheets = wb.getNumberOfSheets();
XSSFSheet sheet = null;
int rowNum = 0;
String sheetName = null;
for (int i = 0; i < getNumberOfSheets; i++) {
// 得到工作薄内容
sheet = wb.getSheetAt(i);
// 得到工作薄名
sheetName = sheet.getSheetName();
// 取得最后一行的行号
rowNum = sheet.getLastRowNum() + 1;
parseAllSheet.parseCurSheet(2007, sheet, sheetName, rowNum);
}
wb.close();
} catch (Exception e) {
System.err.println("The error message:" + e.getMessage() + " by parseExcelInputStream2007");
}
}
}
普通项目需要引入的包
poi-4.0.1.jar
poi-ooxml-4.0.1.jar
poi-ooxml-schemas-4.0.1.jar
commons-codec-1.11.jar
commons-collections4-4.3.jar
commons-math3-3.6.1.jar
xmlbeans-3.0.2.jar
commons-compress-1.18.jar
curvesapi-1.06.jar
maven项目依赖
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>