|
|
package com.engine.organization.util.excel;
|
|
|
|
|
|
import com.engine.salary.util.excel.ExcelParseException;
|
|
|
import com.engine.salary.util.excel.ExcelProperty;
|
|
|
import com.engine.salary.util.excel.ExcelSupport;
|
|
|
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.salary.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;
|
|
|
}
|
|
|
}
|