excel匯入通用程式碼
阿新 • • 發佈:2018-12-06
匯入模板的樣式:
1:自定義註解
/** * 用於註解需要插入的物件 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Excel { } /** * 用於註解物件的屬性 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Column { /** * 單元格對應的列號,必須指明,不能重複 * *@return */ public int column() default -1; /** * 對應的名字、描述 * * @return */ public String description() default "no description"; /** * 單元格內容是否可為空 * true:可以為空,false:不能為空 * @return */ public boolean nullable() default true; }
2:使用註解
@Data @Excelpublic class CreateReservoirDto { @Column(column = 0,nullable = false,description = "測站名字") private String name; @Column(column = 1,nullable = false,description = "測站編碼") private String number; @Column(column = 2,nullable = false,description = "東經") private String lng; @Column(column= 3,nullable = false,description = "北緯") private String lat; @Column(column = 4,description = "地區") private String address; @Column(column = 5,description = "壩頂高程") private Double damTop; @Column(column = 6,description = "堰頂高程") private Double weirTop; @Column(column = 7,description = "汛限水位") private Double floodWaterLevel; @Column(column = 8,description = "校核洪水位") private Double checkFloodWaterLevel; @Column(column = 9,description = "設計洪水位") private Double designFloodWaterLevel; @Column(column = 10,description = "正常蓄水位") private Double normalStoreWater; @Column(column = 11,description = "死水位") private Double deadWaterLevel; @Column(column = 12,description = "總庫容") private Double totalStorage; @Column(column = 13,description = "興利庫容") private Double utilizableCapacity; @Column(column = 14,description = "死庫容") private Double deadStorage; @Column(column = 15,description = "建立時間") private Long createdTime; }
3:匯入轉轉物件的工具類
import com.irrigation.icl.exception.ContextRuntimeException; import com.irrigation.synthetic.annotation.Column; import com.irrigation.synthetic.annotation.Excel; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @Slf4j public class ExcelUtils { /** * 將excel資料轉換為javaBean * * @param file excel檔案 * @param startRow 匯入內容的開始行號(排除表頭) * @param clazz 要轉換的物件 * @param <T> * @return */ public static <T> List<T> getDataFromExcel(MultipartFile file, int startRow, Class<T> clazz) { List<T> list = new ArrayList<>(); InputStream is = null; try { //建立工作簿 is = file.getInputStream(); String excelFileName = file.getOriginalFilename(); Workbook workbook = createWorkbook(is, excelFileName); //建立工作表sheet Sheet sheet = getSheet(workbook, 0); //獲取sheet中資料的行數 int rows = sheet.getPhysicalNumberOfRows(); //獲取表頭單元格個數 int cells = sheet.getRow(0).getPhysicalNumberOfCells(); //判斷是否使用excel註解 if (!clazz.isAnnotationPresent(Excel.class)) { log.error(clazz + "沒有使用@Excel註解"); return null; } //利用反射,給JavaBean的屬性進行賦值 Field[] fields = clazz.getDeclaredFields(); Map<Integer, Field> fieldMap = new HashMap<>(); if (null != fields && fields.length > 0) { for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); int number = column.column(); if (number < 0) { log.error(field.getName() + "沒有使用@column註解"); return null; } else { fieldMap.put(number, field); } } } } //包裝物件 for (int i = startRow; i < rows; i++) { Row row = sheet.getRow(i); int index = 0; T instance = clazz.newInstance(); while (index < cells) { Field field = fieldMap.get(index); if (null != field) { //獲得單元格 Cell cell = row.getCell(index); Column column = field.getAnnotation(Column.class); Object value = null; if (Integer.class.equals(field.getType()) || Double.class.equals(field.getType())) { if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){ cell.setCellType(CellType.NUMERIC); value =cell.getNumericCellValue(); } } else if (String.class.equals(field.getType())) { if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){ cell.setCellType(CellType.STRING); value = cell.getStringCellValue(); } } else if (Date.class.equals(field.getType())) { if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){ cell.setCellType(CellType.STRING); value = cell.getDateCellValue(); } } else if (Boolean.class.equals(field.getType())) { if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){ cell.setCellType(CellType.BOOLEAN); value = cell.getBooleanCellValue(); } } else { log.error("單元格型別錯誤"); return null; } //不能為空 if (!column.nullable()) { if (StringUtils.isEmpty(value)) { throw new ContextRuntimeException("第" + i+1 + "行第" + index+1 + "列不能為空"); } } //設定屬性值 if(!StringUtils.isEmpty(value)){ String fieldName = field.getName(); String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); //獲得set方法的名字 Method setMethod = clazz.getMethod(methodName, new Class[]{field.getType()}); setMethod.invoke(instance, new Object[]{value}); } } index++; } list.add(instance); } } catch (ContextRuntimeException e) { throw e; } catch (Exception e) { log.error(e.getMessage()); } finally { try { if (null != is) { is.close();//關閉流 } } catch (Exception e2) { log.error(e2.getMessage()); } } return list; } /** * 建立工作簿 * * @param is * @param excelFileName * @return * @throws IOException */ private static Workbook createWorkbook(InputStream is, String excelFileName) throws IOException { if (null != excelFileName) { if (excelFileName.endsWith(".xls")) { return new HSSFWorkbook(is); } else if (excelFileName.endsWith(".xlsx")) { return new XSSFWorkbook(is); } } return null; } /** * 建立工作表 * * @param workbook * @param sheetIndex * @return */ private static Sheet getSheet(Workbook workbook, int sheetIndex) { return workbook.getSheetAt(0); } }
4:controller層
@ApiOperation(value = "匯入excel", notes = "匯入excel") @ApiImplicitParam(name = "irriAreaId", value = "灌區id", paramType = "query", dataType = "int", required = true) @PostMapping("/import") public RestResult<String> importReservoir(@RequestParam("file") MultipartFile file, @RequestParam("irriAreaId") Integer irriAreaId) { try { reservoirService.importReservoir(file, irriAreaId); return RestResultGeneratorUtil.getSuccessResult(); } catch (ContextRuntimeException e) { throw e; } catch (Exception e) { throw new ContextRuntimeException(ErrorEnum.IMPORT_DATA_ERROR.getMessage()); } }
5:service層
@Override public void importReservoir(MultipartFile file, Integer irriAreaId) { //excel表中每一列對應資料欄位的屬性 List<CreateReservoirDto> createReservoirDtoList = ExcelUtils.getDataFromExcel(file,1, CreateReservoirDto.class); if (!CollectionUtils.isEmpty(createReservoirDtoList)) { createReservoirDtoList = createReservoirDtoList.parallelStream().map(r -> { r.setIrriAreaId(irriAreaId); r.setCreatedTime(System.currentTimeMillis()); return r; }).collect(Collectors.toList()); //批量寫入資料庫 reservoirMapper.batchInsert(createReservoirDtoList); } }