版本1.1
新增了縱向解析。示例圖如下:
工具類:
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.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;
import java.io.File;
import java.io.FileInputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Objects;
/**
* excel檔案上傳解析工具類
* @author zql
* @createTime 2021-01-16 02:33:40
* @version 1.1
* <pre>新增縱向解析</pre>
*
*/
public class ExcelParseMapper {
/**
* 2003版字尾
*/
private String suffix2003 = ".xls";
/**
* 2007版字尾
*/
private String suffix2007 = ".xlsx";
/**
* 解析方法
*
* @param file excel檔案對象
* @param type 用于橫向讀取或者縱向讀取的判斷
* @param parseSheetCell 解析工作薄單元格内容的接口
*/
public void parseFirstSheet(File file, Integer type, ParseSheetCell parseSheetCell) {
if (Objects.isNull(file)) {
return;
}
if (file.getName().endsWith(suffix2003)) {
parseExcel2003(file, type, parseSheetCell);
}
if (file.getName().endsWith(suffix2007)) {
parseExcel2007(file, type, parseSheetCell);
}
}
/**
* 讀取2003Excel
*
* @param file excel檔案對象
* @param type 用于橫向讀取或者縱向讀取的判斷
* @param parseSheetCell 解析工作薄單元格内容的接口
*/
private void parseExcel2003(File file, Integer type, ParseSheetCell parseSheetCell) {
try {
FileInputStream fis = new FileInputStream(file);
HSSFWorkbook wb = new HSSFWorkbook(fis);
fis.close();
HSSFSheet sheet = wb.getSheetAt(0);
// 取得最後一行的行号
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.out.println("The error message:" + e.getMessage());
}
}
/**
* 讀取2007Excel
*
* @param file excel檔案對象
* @param type 用于橫向讀取或者縱向讀取的判斷
* @param parseSheetCell 解析工作薄單元格内容的接口
*/
private void parseExcel2007(File file, Integer type, ParseSheetCell parseSheetCell) {
try {
FileInputStream fis = new FileInputStream(file);
XSSFWorkbook wb = new XSSFWorkbook(fis);
fis.close();
XSSFSheet sheet = wb.getSheetAt(0);
// 取得最後一行的行号
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.out.println("The error message:" + e.getMessage());
}
}
/**
* 橫向解析excel
*
* @param sheet
* @param rowNum
* @param parseSheetCell
*/
private void parseTransverseExcel2003(HSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
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(String.valueOf(i)));
if (Objects.nonNull(cell)) {
// 把類型先設定為字元串類型
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, cell);
}
}
}
/**
* 縱向解析excel
*
* @param sheet
* @param rowNum
* @param parseSheetCell
*/
private void parseLengthwaysExcel2003(HSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
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 (Objects.nonNull(cell)) {
// 把類型先設定為字元串類型
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, cell);
}
}
}
/**
* 橫向解析excel
*
* @param sheet
* @param rowNum
* @param parseSheetCell
*/
private void parseTransverseExcel2007(XSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
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(String.valueOf(i)));
if (Objects.nonNull(cell)) {
// 把類型先設定為字元串類型
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, cell);
}
}
}
/**
* 縱向解析excel
*
* @param sheet
* @param rowNum
* @param parseSheetCell
*/
private void parseLengthwaysExcel2007(XSSFSheet sheet, int rowNum, ParseSheetCell parseSheetCell) {
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 (Objects.nonNull(cell)) {
// 把類型先設定為字元串類型
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, cell);
}
}
}
/**
* 對單元格進行格式化
*
* @param cell
* @return
*/
public Object getFormartType(Cell cell) {
if (Objects.isNull(cell)) {
return "";
}
Object value;
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 cell 目前單元格對象
*/
void setCurCell(String title, int curRowNum, boolean isComplete, Cell cell);
}
}
測試類:
import org.apache.poi.ss.usermodel.Cell;
import org.junit.Test;
import java.io.File;
/**
*
* @author zql
* @version 1.1
* @createTime 2020-12-06 16:08:30
*/
public class ExcelParseMapperTest {
private ExcelParseMapper epm = new ExcelParseMapper();
@Test
public void parse2003() {
File file = new File("E:\\excel\\測試資料.xls");
File file2 = new File("E:\\excel\\測試資料2.xls");
epm.parseFirstSheet(file, 0, new ExcelParseMapper.ParseSheetCell(){
@Override
public void setCurCell(String title, int curRowNum, boolean isComplete, Cell cell) {
// 如果不使用工具類的getFormartType方法,就自行調用cell的方法,例如,cell.getStringCellValue()
System.out.println(title + "--" + curRowNum + "--" + epm.getFormartType(cell) + "--" + isComplete);
}
});
epm.parseFirstSheet(file2, 1, new ExcelParseMapper.ParseSheetCell(){
@Override
public void setCurCell(String title, int curRowNum, boolean isComplete, Cell cell) {
// 如果不使用工具類的getFormartType方法,就自行調用cell的方法,例如,cell.getStringCellValue()
System.out.println(title + "--" + curRowNum + "--" + epm.getFormartType(cell) + "--" + isComplete);
}
});
}
@Test
public void parse2007() {
File file = new File("E:\\excel\\測試資料.xlsx");
File file2 = new File("E:\\excel\\測試資料2.xlsx");
epm.parseFirstSheet(file, 0, new ExcelParseMapper.ParseSheetCell(){
@Override
public void setCurCell(String title, int curRowNum, boolean isComplete, Cell cell) {
//如果不使用工具類的getFormartType方法,就自行調用cell的方法,例如,cell.getStringCellValue()
System.out.println(title + "--" + curRowNum + "--" + epm.getFormartType(cell) + "--" + isComplete);
}
});
epm.parseFirstSheet(file2, 1, new ExcelParseMapper.ParseSheetCell(){
@Override
public void setCurCell(String title, int curRowNum, boolean isComplete, Cell cell) {
//如果不使用工具類的getFormartType方法,就自行調用cell的方法,例如,cell.getStringCellValue()
System.out.println(title + "--" + curRowNum + "--" + epm.getFormartType(cell) + "--" + isComplete);
}
});
}
}
普通項目需要引入的包
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>