@@ -9,9 +9,11 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil ;
import cn.hutool.core.util.StrUtil ;
import cn.hutool.poi.excel.cell.CellEditor ;
import cn.hutool.poi.excel.cell.CellHandler ;
import cn.hutool.poi.excel.cell.CellUtil ;
import org.apache.poi.hssf.usermodel.HSSFWorkbook ;
import org.apache.poi.ss.extractor.ExcelExtractor ;
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 ;
@@ -34,19 +36,26 @@ import java.util.Map;
*/
public class ExcelReader extends ExcelBase < ExcelReader > {
/** 是否忽略空行 */
/**
* 是否忽略空行
*/
private boolean ignoreEmptyRow = true ;
/** 单元格值处理接口 */
/**
* 单元格值处理接口
*/
private CellEditor cellEditor ;
/** 标题别名 */
/**
* 标题别名
*/
private Map < String , String > headerAlias = new HashMap < > ( ) ;
// ------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造
*
* @param excelFilePath Excel文件路径, 绝对路径或相对于ClassPath路径
* @param sheetIndex sheet序号, 0表示第一个sheet
* @param sheetIndex sheet序号, 0表示第一个sheet
*/
public ExcelReader ( String excelFilePath , int sheetIndex ) {
this ( FileUtil . file ( excelFilePath ) , sheetIndex ) ;
@@ -55,7 +64,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param bookFile Excel文件
* @param bookFile Excel文件
* @param sheetIndex sheet序号, 0表示第一个sheet
*/
public ExcelReader ( File bookFile , int sheetIndex ) {
@@ -65,7 +74,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param bookFile Excel文件
* @param bookFile Excel文件
* @param sheetName sheet名, 第一个默认是sheet1
*/
public ExcelReader ( File bookFile , String sheetName ) {
@@ -75,8 +84,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param bookStream Excel文件的流
* @param sheetIndex sheet序号, 0表示第一个sheet
* @param bookStream Excel文件的流
* @param sheetIndex sheet序号, 0表示第一个sheet
* @param closeAfterRead 读取结束是否关闭流
*/
public ExcelReader ( InputStream bookStream , int sheetIndex , boolean closeAfterRead ) {
@@ -86,8 +95,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param bookStream Excel文件的流
* @param sheetName sheet名, 第一个默认是sheet1
* @param bookStream Excel文件的流
* @param sheetName sheet名, 第一个默认是sheet1
* @param closeAfterRead 读取结束是否关闭流
*/
public ExcelReader ( InputStream bookStream , String sheetName , boolean closeAfterRead ) {
@@ -97,7 +106,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param book {@link Workbook} 表示一个Excel文件
* @param book {@link Workbook} 表示一个Excel文件
* @param sheetIndex sheet序号, 0表示第一个sheet
*/
public ExcelReader ( Workbook book , int sheetIndex ) {
@@ -107,7 +116,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 构造
*
* @param book {@link Workbook} 表示一个Excel文件
* @param book {@link Workbook} 表示一个Excel文件
* @param sheetName sheet名, 第一个默认是sheet1
*/
public ExcelReader ( Workbook book , String sheetName ) {
@@ -125,6 +134,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
// ------------------------------------------------------------------------------------------------------- Constructor end
// ------------------------------------------------------------------------------------------------------- Getters and Setters start
/**
* 是否忽略空行
*
@@ -181,7 +191,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* 增加标题别名
*
* @param header 标题
* @param alias 别名
* @param alias 别名
* @return this
*/
public ExcelReader addHeaderAlias ( String header , String alias ) {
@@ -225,10 +235,10 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* 读取工作簿中指定的Sheet
*
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 结束行( 包含, 从0开始计数)
* @param endRowIndex 结束行( 包含, 从0开始计数)
* @return 行的集合, 一行使用List表示
*/
@SuppressWarnings ( { " rawtypes " , " unchecked " } )
@SuppressWarnings ( { " rawtypes " , " unchecked " } )
public List < List < Object > > read ( int startRowIndex , int endRowIndex ) {
checkNotClosed ( ) ;
List < List < Object > > resultList = new ArrayList < > ( ) ;
@@ -255,6 +265,45 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
return resultList ;
}
/**
* 读取工作簿中指定的Sheet, 此方法为类流处理方式, 当读到指定单元格时, 会调用CellEditor接口<br>
* 用户通过实现此接口,可以更加灵活的处理每个单元格的数据。
*
* @param cellHandler 单元格处理器,用于处理读到的单元格及其数据
* @since 5.3.8
*/
public void read ( CellHandler cellHandler ) {
read ( 0 , Integer . MAX_VALUE , cellHandler ) ;
}
/**
* 读取工作簿中指定的Sheet, 此方法为类流处理方式, 当读到指定单元格时, 会调用CellEditor接口<br>
* 用户通过实现此接口,可以更加灵活的处理每个单元格的数据。
*
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 结束行( 包含, 从0开始计数)
* @param cellHandler 单元格处理器,用于处理读到的单元格及其数据
* @since 5.3.8
*/
public void read ( int startRowIndex , int endRowIndex , CellHandler cellHandler ) {
checkNotClosed ( ) ;
startRowIndex = Math . max ( startRowIndex , this . sheet . getFirstRowNum ( ) ) ; // 读取起始行(包含)
endRowIndex = Math . min ( endRowIndex , this . sheet . getLastRowNum ( ) ) ; // 读取结束行(包含)
Row row ;
short columnSize ;
for ( int y = startRowIndex ; y < = endRowIndex ; y + + ) {
row = this . sheet . getRow ( y ) ;
columnSize = row . getLastCellNum ( ) ;
Cell cell ;
for ( short x = 0 ; x < columnSize ; x + + ) {
cell = row . getCell ( x ) ;
cellHandler . handle ( cell , CellUtil . getCellValue ( cell ) ) ;
}
}
}
/**
* 读取Excel为Map的列表, 读取所有行, 默认第一行做为标题, 数据从第二行开始<br>
* Map表示一行, 标题为key, 单元格内容为value
@@ -270,8 +319,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* Map表示一行, 标题为key, 单元格内容为value
*
* @param headerRowIndex 标题所在行,如果标题行在读取的内容行中间,这行做为数据将忽略
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 读取结束行( 包含, 从0开始计数)
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 读取结束行( 包含, 从0开始计数)
* @return Map的列表
*/
public List < Map < String , Object > > read ( int headerRowIndex , int startRowIndex , int endRowIndex ) {
@@ -307,7 +356,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 读取Excel为Bean的列表, 读取所有行, 默认第一行做为标题, 数据从第二行开始
*
* @param <T> Bean类型
* @param <T> Bean类型
* @param beanType 每行对应Bean的类型
* @return Map的列表
*/
@@ -318,10 +367,10 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 读取Excel为Bean的列表
*
* @param <T> Bean类型
* @param <T> Bean类型
* @param headerRowIndex 标题所在行, 如果标题行在读取的内容行中间, 这行做为数据将忽略, , 从0开始计数
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param beanType 每行对应Bean的类型
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param beanType 每行对应Bean的类型
* @return Map的列表
* @since 4.0.1
*/
@@ -332,11 +381,11 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
/**
* 读取Excel为Bean的列表
*
* @param <T> Bean类型
* @param <T> Bean类型
* @param headerRowIndex 标题所在行, 如果标题行在读取的内容行中间, 这行做为数据将忽略, , 从0开始计数
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 读取结束行( 包含, 从0开始计数)
* @param beanType 每行对应Bean的类型
* @param startRowIndex 起始行( 包含, 从0开始计数)
* @param endRowIndex 读取结束行( 包含, 从0开始计数)
* @param beanType 每行对应Bean的类型
* @return Map的列表
*/
@SuppressWarnings ( " unchecked " )
@@ -420,6 +469,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
}
// ------------------------------------------------------------------------------------------------------- Private methods start
/**
* 读取一行
*
@@ -443,7 +493,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
return result ;
}
for ( int i = 0 ; i < size ; i + + ) {
for ( int i = 0 ; i < size ; i + + ) {
result . add ( aliasHeader ( headerList . get ( i ) , i ) ) ;
}
return result ;
@@ -453,12 +503,12 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* 转换标题别名, 如果没有别名则使用原标题, 当标题为空时, 列号对应的字母便是header
*
* @param headerObj 原标题
* @param index 标题所在列号, 当标题为空时, 列号对应的字母便是header
* @param index 标题所在列号, 当标题为空时, 列号对应的字母便是header
* @return 转换别名列表
* @since 4.3.2
*/
private String aliasHeader ( Object headerObj , int index ) {
if ( null = = headerObj ) {
if ( null = = headerObj ) {
return ExcelUtil . indexToColName ( index ) ;
}