Spring boot poi 导入(根据表头名导入,合并单元格导入)
添加依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
代码实现
导入注解类 ExcelImportAnnotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelImportAnnotation {
String titleName() default "";
boolean required() default false;
String format() default "yyyy-MM-dd";
String judge_items() default "";
String judge_values() default "";
String judge_defaultValue() default "";
boolean isRow() default false;
}
导入映射类
@Data
public class ImportDto {
@ApiModelProperty(value = "Excel行号")
@ExcelImportAnnotation(isRow = true)
private Integer row;
@ApiModelProperty(value = "班级")
@ExcelImportAnnotation(titleName = "班级",required = true)
private String grade;
@ApiModelProperty(value = "学生姓名")
@ExcelImportAnnotation(titleName = "学生姓名",required = true)
private Date studentName;
@ApiModelProperty(value = "语文分数")
@ExcelImportAnnotation(titleName = "语文分数",required = true)
private BigDecimal chineseScore;
@ApiModelProperty(value = "数学分数")
@ExcelImportAnnotation(titleName = "数学分数",required = true)
private BigDecimal mathScore;
@ApiModelProperty(value = "英语分数")
@ExcelImportAnnotation(titleName = "英语分数",required = true)
private BigDecimal englishScore;
}
导入异常处理类
public class ImportException extends RuntimeException{
public ImportException(String msg) {
super(msg);
}
}
导入工具类
public class ExcelUtil {
public static final String XLS = "xls";
public static final String XLS_X = "xlsx";
public static <T> List<T> importExcelSheet1(MultipartFile file, Class<T> clazz) throws Exception {
Workbook workbook = getWorkBook(file);
List<T> list = new ArrayList<T>();
checkFile(file);
if (workbook != null) {
Sheet sheet = workbook.getSheetAt(0);
Map<String,Integer> titleMap=getExcelSheetTitle(sheet);
Map<Integer,Field> fieldMap= getFieldMap(clazz,titleMap);
Map<String,Cell> combineCellMap=getCombineCell(sheet);
int firstLine = sheet.getRow(0).getPhysicalNumberOfCells();
int firstRowNum = sheet.getFirstRowNum()+1;
int lastRowNum = sheet.getLastRowNum();
for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++) {
Row row = sheet.getRow(rowNum);
if (row == null) {
continue;
}
Object obj = clazz.newInstance();
for (int cellNum = 0; cellNum < firstLine; cellNum++) {
Field field=fieldMap.get(cellNum);
if(field==null){
continue;
}
Cell cell = row.getCell(cellNum);
if(!combineCellMap.isEmpty()&&combineCellMap.containsKey(rowNum+"#"+cellNum)){
cell=combineCellMap.get(rowNum+"#"+cellNum);
}
Field mfield=fieldMap.get(-1);
if(mfield!=null){
if (!mfield.isAccessible()) {
mfield.setAccessible(true);
}
if(mfield.get(obj)==null&&cell!=null){
mfield.set(obj,cell.getRowIndex());
}
}
if(cell!=null){
Object value=getCellValue(cell);
createBean(field, obj, value,rowNum);
}
}
if (rowNum == 0) {
continue;
}
if(checkObjFieldIsNotNull(obj)) {
checkRequired(obj,rowNum);
list.add((T) obj);
}else{
return list;
}
}
}
return list;
}
private static void checkRequired(Object obj,int rowNum ) throws IllegalAccessException {
Field[] fields = obj.getClass().getDeclaredFields();
if (fields == null || fields.length == 0) {
return;
}
StringJoiner joiner=new StringJoiner(",");
for (Field field : fields) {
if(!field.isAccessible()){
field.setAccessible(true);
}
ExcelImportAnnotation annotation=field.getAnnotation(ExcelImportAnnotation.class);
Object obj2=field.get(obj);
if(annotation!=null && annotation.required() && obj2==null){
joiner.add(annotation.titleName());
}else if(obj2!=null&&annotation!=null&& StringUtils.isNotBlank(annotation.judge_items())){
List<String> items=Arrays.asList(annotation.judge_items().split(","));
List<String> values=Arrays.asList(annotation.judge_values().split(","));
int index=items.indexOf(obj2.toString());
if(index>-1&&values.size()>index){
field.set(obj,values.get(index));
}
}
}
if(joiner.length()>0){
rowNum++;
throw new ImportException("第"+rowNum+"行【"+joiner+"】不能为空");
}
}
private static Map<String, Integer> getExcelSheetTitle(Sheet sheet) {
Map<String, Integer> titleMap=new HashMap<>();
Row row = sheet.getRow(0);
int allLine = row.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < allLine; cellNum++) {
Cell cell = row.getCell(cellNum);
if(cell!=null&&StringUtils.isNotBlank(cell.getStringCellValue())){
titleMap.put(cell.getStringCellValue(),cellNum);
}
}
return titleMap;
}
private static Workbook getWorkBook(MultipartFile file) {
String fileName = file.getOriginalFilename();
Workbook workbook = null;
InputStream is = null;
try {
is = file.getInputStream();
if (fileName.endsWith(XLS)) {
workbook = new HSSFWorkbook(is);
} else if (fileName.endsWith(XLS_X)) {
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
throw new ImportException("excel 转换 HSSFWorkbook 异常!");
}
return workbook;
}
private static void checkFile(MultipartFile file) {
if (null == file) {
throw new ImportException("文件不存在");
}
String fileName = file.getOriginalFilename();
if (!fileName.endsWith(XLS) && !fileName.endsWith(XLS_X)) {
throw new ImportException( fileName + "不是excel文件");
}
}
private static Map<Integer,Field> getFieldMap(Class clazz,Map<String,Integer> titleMap) {
Map<Integer,Field> fieldMap=new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) {
return fieldMap;
}
Class<ExcelImportAnnotation> cls=ExcelImportAnnotation.class;
for (Field field : fields) {
if(field.isAnnotationPresent(cls)){
if (StringUtils.isNotBlank(field.getAnnotation(cls).titleName())) {
String key=field.getAnnotation(cls).titleName();
if(titleMap.get(key)!=null){
fieldMap.put(titleMap.get(key),field);
}
}else if(field.getAnnotation(cls).isRow()){
fieldMap.put(-1,field);
}
}
}
return fieldMap;
}
private static <T> void createBean(Field field, T newInstance, Object value,int rowNum) {
if(field==null){
return;
}
if (!field.isAccessible()) {
field.setAccessible(true);
}
try {
if (value == null|| StringUtils.isBlank(String.valueOf(value))) {
field.set(newInstance, null);
} else if (Long.class.equals(field.getType())) {
field.set(newInstance, Long.valueOf(String.valueOf(value)));
} else if (String.class.equals(field.getType())) {
field.set(newInstance, String.valueOf(value));
} else if (Integer.class.equals(field.getType())) {
field.set(newInstance, Integer.valueOf(String.valueOf(value)));
} else if (Date.class.equals(field.getType())) {
SimpleDateFormat sdf = new SimpleDateFormat(field.getAnnotation(ExcelImportAnnotation.class).format());
if (value instanceof Date) {
field.set(newInstance, sdf.parse(sdf.format(value)));
} else {
field.set(newInstance, sdf.parse(value.toString()));
}
} else if (Boolean.class.equals(field.getType())) {
field.set(newInstance, (Boolean) value);
} else if (Double.class.equals(field.getType())) {
field.set(newInstance, Double.valueOf(String.valueOf(value)));
} else if (Float.class.equals(field.getType())) {
field.set(newInstance, Float.valueOf(String.valueOf(value)));
} else if (BigDecimal.class.equals(field.getType())) {
field.set(newInstance, new BigDecimal(String.valueOf(value)));
} else {
field.set(newInstance, value);
}
} catch (Exception e) {
rowNum++;
throw new ImportException("【excel导入】excel实体转换异常!第"+rowNum+"行字段【"
+ field.getAnnotation(ExcelImportAnnotation.class).titleName() + "】,值(" + value + ")");
}
}
private static Object getCellValue(Cell cell) {
if (cell == null) {
return null;
}
Object cellValue;
switch (cell.getCellTypeEnum()) {
case NUMERIC:
if (DateUtil.isValidExcelDate(cell.getNumericCellValue())) {
CellStyle style = cell.getCellStyle();
if (style == null) {
return false;
}
int formatIndex = style.getDataFormat();
String formatString = style.getDataFormatString();
boolean isDate = DateUtil.isADateFormat(formatIndex, formatString);
if (isDate) { Date date = cell.getDateCellValue();
return date;
}
}
if ((long) cell.getNumericCellValue() != cell.getNumericCellValue()) {
cellValue = new BigDecimal(String.valueOf(cell.getNumericCellValue()));
} else {
cellValue = (long)cell.getNumericCellValue();
}
break;
case STRING:
cellValue = String.valueOf(cell.getStringCellValue());
break;
case BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case FORMULA:
cellValue = String.valueOf(cell.getCellFormula());
break;
case BLANK:
cellValue = null;
break;
case ERROR:
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
private static boolean checkObjFieldIsNotNull(Object obj){
try {
Class<ExcelImportAnnotation> cls=ExcelImportAnnotation.class;
for (Field f : obj.getClass().getDeclaredFields()) {
if(f.isAnnotationPresent(cls)&&f.getAnnotation(cls).isRow()){
continue;
}
f.setAccessible(true);
if (f.get(obj) != null) {
return true;
}
}
}catch (IllegalAccessException e){
}
return false;
}
public static Map<String,Cell> getCombineCell(Sheet sheet)
{
Map<String,Cell> map = new HashMap<>();
int sheetmergerCount = sheet.getNumMergedRegions();
for(int i = 0; i<sheetmergerCount;i++)
{
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
for(int r=firstRow;r<=lastRow;r++){
for(int c=firstColumn;c<=lastColumn;c++){
map.put(r+"#"+c,sheet.getRow(firstRow).getCell(firstColumn));
}
}
}
return map;
}
Controller
@RestController
@RequestMapping("/excel")
public class ExcelCtrl {
@PostMapping("/excelImport")
public List<ImportDto> excelImport(@RequestParam("file") MultipartFile file) throws Exception {
List<ImportDto> importDtos= ExcelUtil.importExcelSheet1(file,ImportDto.class);
return importDtos;
}
}
excel内容