記錄一下最近使用java操作excel的代碼。
- 導包。注意兩者版本需要一致
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
- 解析excel代碼
public class ExcelDemo {
public static void main(String[] args) {
// 獲取輸入流
InputStream in = getResourcesFileInputStream("Test.xlsx");
//InputStream in = getResourcesFileInputStream("Test.xls");
// 解析---1
// 解析Excel所有sheet,所有行,所有列
List<List<String[]>> allData = ExcelUtil.read(in);
// 解析---2
// 解析第一個sheet數據
ExcelUtil.readSheet(in, 0, sheet -> {
//解析第3行到最後一行,第2列到第9列的數據
List<String[]> source = ExcelUtil.readSheetPart(sheet, 2, sheet.getLastRowNum(), 1, 8);
});
// 解析---3
// 完全自定義解析
ExcelUtil.readByCustomize(in, wb -> {
// doSomeThing()...可參照ExcelUtil.readExcel()方法
});
in.close();
}
/**
* 加載Resources目錄下的文件
* @param fileName 文件名
* @return
*/
public static InputStream getResourcesFileInputStream(String fileName){
// Resources目錄的絕對路徑
// String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
return in;
}
}
注意事項:獲取的excel行數不正確解決方法
- Excel工具類
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* Excel工具類
*/
public class ExcelUtil {
private static Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
/**
* 對excel單個sheet進行處理的接口
*/
public interface SheetHandler {
/**
* 對sheet進行處理
* @param sheet
*/
void handle(Sheet sheet);
}
/**
* 對excel進行處理的接口
*/
public interface WorkBookHandler {
/**
* 對excel進行處理
* @param wb
* @return
*/
void handle(Workbook wb);
}
/**
* 讀取excel指定sheet數據<br>未關閉io
* @param in
*/
public static void readSheet(InputStream in, int sheetIdx, SheetHandler handler) throws IOException, InvalidFormatException {
// 創建工作簿
Workbook wb = createWorkBook(in);
// 接口回調處理
handler.handle(getSheetByIdx(wb, sheetIdx));
}
/**
* 讀取excel全部sheet全部行數據<br>未關閉io
* @param in
* @return List<List<String[]>> <br>List<String[]>表示第i個sheet<br> String[]表示sheet某行
*/
public static List<List<String[]>> read(InputStream in) throws IOException, InvalidFormatException {
// 創建工作簿
Workbook wb = createWorkBook(in);
// 默認讀取所有行,所有列
return readExcel(wb);
}
/**
* 讀取excel<br>自定義解析方式<br>未關閉io
* @param in
* @return
*/
public static void readByCustomize(InputStream in, WorkBookHandler handler) throws IOException, InvalidFormatException {
// 創建工作簿
Workbook wb = createWorkBook(in);
handler.handle(wb);
}
/**
* 讀取指定sheet的範圍行,範圍列
* @param sheet excel 某個sheet
* @param startRow 開始行下標
* @param endRow 結束行下標
* @param startCol 開始列下標
* @param endCol 結束列下標
* @return 指定範圍的數據。一個String[]是一行數據
*/
public static List<String[]> readSheetPart(Sheet sheet, int startRow, int endRow, int startCol, int endCol){
if(sheet == null){
logger.warn("excel sheet is not exist");
return null;
}
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
logger.info("sheet firstRow:"+firstRow);
logger.info("sheet lastRow:"+lastRow);
if(startRow < 0 || startRow > lastRow || startRow > endRow){
return null;
}
if(endRow > lastRow){
return null;
}
List<String[]> list = new ArrayList<>();
// 逐行解析
for (int i = startRow; i <= endRow ; i++) {
Row row = sheet.getRow(i);
// 過濾空行
if(row == null){
continue;
}
int firstCol = row.getFirstCellNum();
int lastCol = row.getLastCellNum();
logger.info("row("+i+") firstCol:"+firstCol);
logger.info("row("+i+") lastCol:"+lastCol);
if(startCol < 0 || startCol > lastCol || startCol > endCol){
return null;
}
if(endCol > lastCol){
return null;
}
int colIdx = 0;
int objIdx = 0;
String[] objs = new String[endCol-startCol+1];
// 逐列解析
for (Cell c : row) {
// 讀取指定列數據
if(colIdx >= startCol && colIdx <= endCol){
c.setCellType(Cell.CELL_TYPE_STRING);
boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
String data = "";
//判斷是否具有合併單元格
if(isMerge) {
data = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
}else {
data = c.getRichStringCellValue().toString();
}
objs[objIdx++]=data;
}
colIdx++;
}
list.add(objs);
}
if(list.size() == 0){
logger.warn("excel sheet data is space");
}
return list;
}
/**
* 讀取excel文件
* @param wb
* @return List<List<String[]>> <br>List<String[]>表示第i個sheet<br> String[]表示sheet某行
*/
public static List<List<String[]>> readExcel(Workbook wb) {
// 總sheet數
int sheetNum = wb.getNumberOfSheets();
logger.info("excel sheetNum is :"+sheetNum);
// 遍歷sheet
List<List<String[]>> list = new ArrayList<>();
for (int i = 0; i < sheetNum ; i++) {
Sheet sheet = wb.getSheetAt(i);
List<String[]> sheetData = readOneSheet(sheet);
list.addAll(Collections.singleton(sheetData));
}
return list;
}
/**
* 讀取單個sheet數據,封裝爲List<String[]><br>
* @warn 可能會有全是空串的數據
* @return List<String[]>,一個String[]是
*/
public static List<String[]> readOneSheet(Sheet sheet){
int startRow = sheet.getFirstRowNum();
int endRow = sheet.getLastRowNum();
logger.info("sheet startRow:"+startRow);
logger.info("sheet endRow:"+endRow);
List<String[]> list = new ArrayList<>();
// 遍歷行
for (int i = startRow; i <= endRow ; i++) {
Row row = sheet.getRow(i);
if(row == null){
continue;
}
// int startColIdx = row.getFirstCellNum();
int endColIdx = row.getLastCellNum();
String[] objs = new String[endColIdx+1];
int colIdx = 0;
// 遍歷列
for (Cell c : row) {
c.setCellType(Cell.CELL_TYPE_STRING);
String data = "";
boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
//判斷是否具有合併單元格
if(isMerge) {
data = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
}else {
data = c.getRichStringCellValue().toString();
}
objs[colIdx]=data;
colIdx++;
}
list.add(objs);
}
if(list.size() == 0){
logger.warn("excel sheet data is space");
}
return list;
}
/**
* 獲取合併單元格的值<br>
* 即獲取合併單元格第一個cell的值
* @param sheet
* @param row
* @param column
* @return
*/
public static String getMergedRegionValue(Sheet sheet ,int row , int column){
// 獲得一個 sheet 中合併單元格的數量
int sheetMergeCount = sheet.getNumMergedRegions();
// 遍歷合併單元格
for(int i = 0 ; i < sheetMergeCount ; i++){
// 得出具體的合併單元格
CellRangeAddress ca = sheet.getMergedRegion(i);
// 得到合併單元格的起始行, 結束行, 起始列, 結束列
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
// 獲取合併單元格第一個cell的值
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell) ;
}
}
}
return null ;
}
/**
* 判斷指定的單元格是否是合併單元格
* @param sheet
* @param row 行下標
* @param column 列下標
* @return
*/
public static boolean isMergedRegion(Sheet sheet,int row ,int column) {
// 得到一個sheet中有多少個合併單元格
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
// 得出具體的合併單元格
CellRangeAddress range = sheet.getMergedRegion(i);
// 得到合併單元格的起始行, 結束行, 起始列, 結束列
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
// 判斷該單元格是否在合併單元格範圍之內, 如果是, 則返回 true
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}
/**
* 判斷sheet頁中是否含有合併單元格
* @param sheet
* @return
*/
public static boolean hasMerged(Sheet sheet) {
return sheet.getNumMergedRegions() > 0 ? true : false;
}
/**
* 獲取單元格的值
* @param cell
* @return
*/
public static String getCellValue(Cell cell){
if(cell == null) return "";
switch (cell.getCellType()){
case Cell.CELL_TYPE_STRING:
return cell.getStringCellValue();
case Cell.CELL_TYPE_BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case Cell.CELL_TYPE_FORMULA:
return cell.getCellFormula() ;
case Cell.CELL_TYPE_NUMERIC:
return String.valueOf(cell.getNumericCellValue());
default:
return "";
}
}
/**
* 創建工作簿
* @param in
*/
private static Workbook createWorkBook(InputStream in) throws IOException, InvalidFormatException {
Workbook wb = WorkbookFactory.create(in);
return wb;
}
/**
* 獲取sheet
* @param wb
* @param sheetIdx
*/
public static Sheet getSheetByIdx(Workbook wb, int sheetIdx){
// 總sheet數
int sheetNum = wb.getNumberOfSheets();
// sheet不存在
if(sheetIdx < 0 || sheetIdx >= sheetNum){
return null;
}
// 獲取sheet
Sheet sheet = wb.getSheetAt(sheetIdx);
return sheet;
}
/*----------寫excel相關----------*/
/**
* 添加合併單元格
* @param sheet
* @param firstRow 開始行
* @param lastRow 結束行
* @param firstCol 開始列
* @param lastCol 結束列
*/
public static void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
}
}