package com.engine.organization.util.excel ;
import org.apache.commons.lang3.StringUtils ;
import org.apache.commons.lang3.Validate ;
import org.apache.commons.lang3.exception.ContextedRuntimeException ;
import org.apache.poi.ss.usermodel.Sheet ;
import org.springframework.web.multipart.MultipartFile ;
import java.io.InputStream ;
import java.lang.reflect.Field ;
import java.math.BigDecimal ;
import java.util.* ;
import static com.engine.organization.util.excel.ExcelSupport.EXCEL_TYPE_XLSX ;
/ * *
* Excel 解 析 工 具 类
* * /
public class ExcelParseHelper {
//待校验的行号
private static final int PARSE_EXCEL_ROW_VALID_CELL_INDEX = 0 ;
//字符开始下标
private static final int CHARACTER_FIRST_INDEX = 0 ;
/ * *
* 将 Excel 解 析 为 JavaBean 对 象
*
* @param file excel 文 件
* @param clazz 解 析 bean 的 类
* @param sheetIndex excel 中 第 几 个 sheet , 从 0 开 始
* @param rowIndex 从 第 几 行 开 始 解 析 , 第 一 行 是 0
* @param standardCellNum 模 板 验 证 , 该 sheet 应 有 多 少 列
* @return
* /
public static < T > List < T > parse2Map ( MultipartFile file , Class < T > clazz , int sheetIndex , int rowIndex , int standardCellNum ) {
List < List < String > > result = parse2Map ( file , sheetIndex , rowIndex , standardCellNum ) ;
List < T > list = new ArrayList < T > ( ) ;
for ( List < String > rowDatas : result ) {
T t = setField ( clazz , rowDatas ) ;
list . add ( t ) ;
}
return list ;
}
/ * *
* 将 Excel 解 析 为 JavaBean 对 象
*
* @param file excel 文 件
* @param clazz 解 析 bean 的 类
* @param sheetIndex excel 中 第 几 个 sheet , 从 0 开 始
* @param rowIndex 从 第 几 行 开 始 解 析 , 第 一 行 是 0
* @param standardCellNum 模 板 验 证 , 该 sheet 应 有 多 少 列
* @param fileName 文 件 名
* @return
* /
public static < T > List < T > parse2Map ( InputStream file , Class < T > clazz , int sheetIndex , int rowIndex , int standardCellNum , String fileName ) {
List < List < String > > result = parse2Map ( file , sheetIndex , rowIndex , standardCellNum , fileName ) ;
List < T > list = new ArrayList < T > ( ) ;
for ( List < String > rowDatas : result ) {
T t = setField ( clazz , rowDatas ) ;
list . add ( t ) ;
}
return list ;
}
/ * *
* < strong > 获 取 excel 数 据 。 < / strong >
*
* @param file 文 件
* @param sheetIndex 解 析 第 几 个 sheet
* @param rowIndex 从 第 几 行 开 始 解 析 , 第 一 行 为 0 , 依 次 类 推
* @return 二 维 数 据 集 合
* /
private static List < List < String > > parse2Map ( MultipartFile file , int sheetIndex , int rowIndex , int standardCellNum ) {
Sheet sheet = ExcelSupport . parseFile ( file , sheetIndex ) ;
int rowCount = sheet . getPhysicalNumberOfRows ( ) ; // 总行数
int cellCount = sheet . getRow ( PARSE_EXCEL_ROW_VALID_CELL_INDEX ) . getPhysicalNumberOfCells ( ) ; // 总列数
Validate . isTrue ( standardCellNum = = cellCount , "Error in excel template! Page %s sheet should have %s column data, existing in %s column , please check the template!" , sheetIndex , standardCellNum , cellCount ) ;
List < List < String > > result = new ArrayList < List < String > > ( ) ;
for ( ; rowIndex < rowCount ; rowIndex + + ) {
List < String > cellResult = new ArrayList < String > ( ) ;
for ( int j = 0 ; j < cellCount ; j + + ) {
cellResult . add ( ExcelSupport . getCellValue ( sheet , rowIndex , j ) ) ;
}
result . add ( cellResult ) ;
}
return result ;
}
/ * *
* < strong > 获 取 excel 数 据 。 < / strong >
*
* @param file 文 件
* @param sheetIndex 解 析 第 几 个 sheet
* @param rowIndex 从 第 几 行 开 始 解 析 , 第 一 行 为 0 , 依 次 类 推
* @return 二 维 数 据 集 合
* /
private static List < List < String > > parse2Map ( InputStream file , int sheetIndex , int rowIndex , int standardCellNum , String fileName ) {
Sheet sheet = ExcelSupport . parseFile ( file , sheetIndex , fileName ) ;
int rowCount = sheet . getPhysicalNumberOfRows ( ) ; // 总行数
int cellCount = sheet . getRow ( PARSE_EXCEL_ROW_VALID_CELL_INDEX ) . getPhysicalNumberOfCells ( ) ; // 总列数
Validate . isTrue ( standardCellNum = = cellCount , "Error in excel template! Page %s sheet should have %s column data, existing in %s column , please check the template!" , sheetIndex , standardCellNum , cellCount ) ;
List < List < String > > result = new ArrayList < List < String > > ( ) ;
for ( ; rowIndex < rowCount ; rowIndex + + ) {
List < String > cellResult = new ArrayList < String > ( ) ;
for ( int j = 0 ; j < cellCount ; j + + ) {
cellResult . add ( ExcelSupport . getCellValue ( sheet , rowIndex , j ) ) ;
}
result . add ( cellResult ) ;
}
return result ;
}
/ * *
* 将 sheet 数 据 转 为 map
*
* @param file
* @param sheetIndex sheet 下 标
* @param rowIndex 从 哪 行 开 始 解 析
* @return
* /
public static List < Map < String , Object > > parse2Map ( InputStream file , int sheetIndex , int rowIndex ) {
Sheet sheet = ExcelSupport . parseFile ( file , sheetIndex , EXCEL_TYPE_XLSX ) ;
int rowCount = sheet . getPhysicalNumberOfRows ( ) ; // 总行数
int cellCount = sheet . getRow ( PARSE_EXCEL_ROW_VALID_CELL_INDEX ) . getPhysicalNumberOfCells ( ) ; // 总列数
List < String > sheetHeader = ExcelSupport . getSheetHeader ( sheet , PARSE_EXCEL_ROW_VALID_CELL_INDEX ) ;
List < Map < String , Object > > result = new ArrayList < > ( ) ;
for ( ; rowIndex < rowCount ; rowIndex + + ) {
Map < String , Object > cellResult = new HashMap < > ( ) ;
for ( int j = 0 ; j < cellCount ; j + + ) {
String key = sheetHeader . get ( j ) ;
cellResult . put ( key , ExcelSupport . getCellValue ( sheet , rowIndex , j ) ) ;
}
result . add ( cellResult ) ;
}
return result ;
}
/ * *
* 将 sheet 数 据 转 为 map
*
* @param rowIndex 从 哪 行 开 始 解 析
* @return
* /
public static List < Map < String , Object > > parse2Map ( Sheet sheet , int rowIndex ) {
int rowCount = sheet . getPhysicalNumberOfRows ( ) ; // 总行数
int cellCount = sheet . getRow ( PARSE_EXCEL_ROW_VALID_CELL_INDEX ) . getPhysicalNumberOfCells ( ) ; // 总列数
List < String > sheetHeader = ExcelSupport . getSheetHeader ( sheet , PARSE_EXCEL_ROW_VALID_CELL_INDEX ) ;
List < Map < String , Object > > result = new ArrayList < > ( ) ;
for ( ; rowIndex < rowCount ; rowIndex + + ) {
Map < String , Object > cellResult = new HashMap < > ( ) ;
for ( int j = 0 ; j < cellCount ; j + + ) {
String key = sheetHeader . get ( j ) ;
cellResult . put ( key , ExcelSupport . getCellValue ( sheet , rowIndex , j ) ) ;
}
result . add ( cellResult ) ;
}
return result ;
}
/ * *
* 将 sheet 数 据 转 为 List
*
* @param rowIndex 从 哪 行 开 始 解 析
* @return
* /
public static List < List < String > > parse2List ( Sheet sheet , int rowIndex ) {
int rowCount = sheet . getPhysicalNumberOfRows ( ) ; // 总行数
int cellCount = sheet . getRow ( PARSE_EXCEL_ROW_VALID_CELL_INDEX ) . getPhysicalNumberOfCells ( ) ; // 总列数
List < List < String > > result = new ArrayList < List < String > > ( ) ;
for ( ; rowIndex < rowCount ; rowIndex + + ) {
List < String > cellResult = new ArrayList < String > ( ) ;
for ( int j = 0 ; j < cellCount ; j + + ) {
cellResult . add ( ExcelSupport . getCellValue ( sheet , rowIndex , j ) ) ;
}
result . add ( cellResult ) ;
}
return result ;
}
/ * *
* 为 对 象 的 每 一 个 属 性 赋 值
*
* @param clazz
* @param rowDatas
* @param < T >
* @return
* /
private static < T > T setField ( Class < T > clazz , List < String > rowDatas ) {
try {
T obj = clazz . newInstance ( ) ;
Field [ ] fields = clazz . getDeclaredFields ( ) ;
for ( Field field : fields ) {
ExcelProperty excelProperty = field . getAnnotation ( ExcelProperty . class ) ;
if ( excelProperty = = null ) {
continue ;
}
int index = excelProperty . index ( ) ;
Object value = getFieldValue ( field , rowDatas . get ( index ) , excelProperty ) ;
field . setAccessible ( true ) ;
field . set ( obj , value ) ;
}
return obj ;
} catch ( Exception e ) {
throw new ExcelParseException ( e . getMessage ( ) , e ) ;
}
}
/ * *
* < strong > 获 取 javaBean 属 性 值 < / strong >
*
* @param field javaBean 的 对 象 属 性
* @param value excel 中 对 应 的 值
* @param excelProperty javaBean 中 解 析 excel 注 解 , 包 含 日 期 格 式 、 错 误 提 示 信 息
* @return
* /
@SuppressWarnings ( "rawtypes" )
private static Object getFieldValue ( Field field , String value , ExcelProperty excelProperty ) {
if ( StringUtils . isEmpty ( value ) ) {
return null ;
}
Object val = null ;
try {
Class typeClass = field . getType ( ) ;
if ( typeClass = = Integer . class ) {
val = Integer . valueOf ( value ) ;
} else if ( typeClass = = Long . class ) {
val = Long . valueOf ( value ) ;
} else if ( typeClass = = Float . class ) {
val = Float . valueOf ( value ) ;
} else if ( typeClass = = Double . class ) {
val = Double . valueOf ( value ) ;
} else if ( typeClass = = Date . class ) {
val = ExcelSupport . getDate ( value , excelProperty . format ( ) ) ;
} else if ( typeClass = = Short . class ) {
val = Short . valueOf ( value ) ;
} else if ( typeClass = = Character . class ) {
val = value . charAt ( CHARACTER_FIRST_INDEX ) ;
} else if ( typeClass = = BigDecimal . class ) {
val = new BigDecimal ( value ) ;
} else {
val = value ;
}
} catch ( Exception e ) {
throw new ContextedRuntimeException ( excelProperty . msg ( ) , e ) ;
}
return val ;
}
}