EasyExcel實(shí)現(xiàn)導(dǎo)入+各種數(shù)據(jù)校驗(yàn)功能
實(shí)現(xiàn)的功能
1.導(dǎo)入非xls和xlsx格式的文件
2.導(dǎo)入空數(shù)據(jù)的excel文件
3.數(shù)據(jù)缺失
4.導(dǎo)入的excel文件中有重復(fù)的數(shù)據(jù)
5.導(dǎo)入的excel文件數(shù)據(jù)錯誤
6.導(dǎo)入的模板不是正確模板
前置條件: 1)傳的參數(shù)是 MultipartFile file
2)編寫一個(gè)接收excel文件的實(shí)體類,保證@ExcelProperty(“表頭1”)中的屬性和excel導(dǎo)入的一致
@Data @JsonIgnoreProperties(ignoreUnknown = true) public class ConfigVO { @ExcelProperty("表頭1") private String head1; @ExcelProperty("表頭2") private String head2; }
3)在Impl中使用EasyExcel讀數(shù)據(jù),就會執(zhí)行監(jiān)聽器
EasyExcel.read(multipartFile.getInputStream(), ConfigVO.class, new ConfigListener(this)).sheet().doRead();
4)自定義監(jiān)聽器
@Slf4j public class ConfigListener extends AnalysisEventListener<ConfigVO> { private static int count = 0; List<ConfigVO> list = new ArrayList<>(); // 此map用來存儲模板錯誤的提示,由于我的全局異常捕獲沒有處理在監(jiān)聽器內(nèi)拋出的異常信息, //所以就將數(shù)據(jù)挪到service層處理拋異常 Map<String, String> errMap = new HashMap<>(); @Autowired private IConfigService configcService; public ConfigListener(ConfigService configService) { this.configService = configService; } @Override public void invoke(ConfigVO configVO, AnalysisContext analysisContext) { count++; list.add(configVO); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { log.info("成功讀取" + count + "條數(shù)據(jù)"); //保存讀取到的數(shù)據(jù)到serviceImpl處理 configService.saveConfig(list, errMap); } @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { // 驗(yàn)證表頭 String head1 = "表頭1"; String head2 = "表頭2"; if (headMap.size() <= 0) { errMap.put("msg", "導(dǎo)入的模板不符合,請檢查后重新導(dǎo)入!"); } //value值才是表頭信息 if (!headMap.containsValue(head1) || !headMap.containsValue(head2)) { errMap.put("msg", "導(dǎo)入的模板不符合,請檢查后重新導(dǎo)入!"); } } }
5)serviceImpl層處理單個(gè)數(shù)據(jù)校驗(yàn)+存儲
public void saveConfig(List<ConfigVO> list, Map<String, String> errMap) { //批量存儲數(shù)據(jù)的list List<ConfigVO> customerlist = new ArrayList<>(); //提示錯誤的list List<Integer> errList = new ArrayList<>(); //用來去重的map Map<String, Integer> map = new HashMap<>(); //遍歷list進(jìn)行校驗(yàn) for (int i = 0; i < list.size(); i++) { //原因是因?yàn)槲蚁氆@取出錯的當(dāng)前行,但是excel表格是從1開始,一條數(shù)據(jù)就是2 Integer count = 2; count = count + i; ConfigVO configVO = list.get(i); //判有無空數(shù)據(jù) if (!ObjectUtils.isEmpty(configVO.getHead1()) && !ObjectUtils.isEmpty(configVO.getHead2())) { //判類型是否錯誤 if (("1").equals(configVO.getHead1()) || ("2").equals(configVO.getHead1())) { String customerName = configVO.getHead2(); //去前后空格 customerName = StrUtil.trim(customerName); //校驗(yàn)單個(gè)數(shù)據(jù)是否超出字?jǐn)?shù)限制 if (customerName.length() > 255) { errList.add(count); } //map去重的key String mapStr = configVO.getHead2() + ":" + configVO.getHead1(); //去除excel中重復(fù)數(shù)據(jù) if (map.containsKey(mapStr)) { //如果已經(jīng)有了,那說明有重復(fù)數(shù)據(jù),更新行數(shù)為最新的 map.put(mapStr, count); //放到錯誤提示的list,遍歷展示錯誤 errList.add(map.get(mapStr)); } else { //沒有重復(fù)也放到map中便于去重 map.put(mapStr, count); //放到需要存儲的list customerlist.add(configVO); } } else { errList.add(count); } } else { errList.add(count); } } //判斷是否是錯誤模板 if (!errMap.isEmpty()) { throw new CommonException(errMap.get("msg")); } //是否有導(dǎo)入錯誤的數(shù)據(jù) if (!errList.isEmpty()) { StringBuilder str = new StringBuilder(); str.append("第"); for (Integer err : errList) { str.append("" + err + "行,"); } str.append("導(dǎo)入失敗,請確認(rèn)信息是否有誤或數(shù)據(jù)是否有重復(fù)"); throw new CommonException(str.toString()); } else { //需要存到數(shù)據(jù)庫的數(shù)據(jù) //查數(shù)據(jù)庫查是否已經(jīng)存在 //存在就跳過,不存在就添加到list } //新增數(shù)據(jù)到數(shù)據(jù)庫 } } }
1.導(dǎo)入非xls和xlsx格式的文件
//獲取文件名+后綴 String filename = file.getOriginalFilename(); if (filename != null) { //獲取其后綴 String extension = filename.substring(filename.lastIndexOf(".") + 1); if (!(extension.equals("xls") || extension.equals("xlsx"))) { //此處為自定義異常捕獲,可使用其他方式 throw new CommonException("文件格式有誤,請檢查上傳文件格式!!"); } }
2.導(dǎo)入空數(shù)據(jù)的excel文件
//校驗(yàn)導(dǎo)入的是空模板 try { InputStream inputStream = file.getInputStream(); ExcelReader reader = ExcelUtil.getReader(inputStream, 0); int rowCount = reader.getRowCount(); if (rowCount <= 1) { throw new CommonException("導(dǎo)入的為空模板,請檢查后重新導(dǎo)入!!"); } }catch (IOException e) { log.error("文件獲取失敗:{}", e); throw new CommonException(e.getMessage()); }
3.導(dǎo)入的模板不是正確模板
判斷導(dǎo)入的excel是否是提供的表
使用EasyExcel實(shí)現(xiàn)
1)首先要自定義監(jiān)聽器,繼承AnalysisEventListener<轉(zhuǎn)換excel的對象>
2)實(shí)現(xiàn)他的三個(gè)方法
invoke 逐行解析excel,每一行都會執(zhí)行
doAfterAllAnalysed 解析完全部的excel,會調(diào)用該方法
invokeHeadMap 驗(yàn)證表頭的方法
3)在invokeHeadMap方法中編寫
@Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { // 驗(yàn)證表頭 String head1 = "表頭1"; String head2 = "表頭2"; if (headMap.size() <= 0) { errMap.put("msg", "導(dǎo)入的模板不符合,請檢查后重新導(dǎo)入!"); } //value值才是表頭信息 if (!headMap.containsValue(head1) || !headMap.containsValue(head2)) { errMap.put("msg", "導(dǎo)入的模板不符合,請檢查后重新導(dǎo)入!"); } }
headMap中存放的就是導(dǎo)入的excel全部的表頭信息,
只要判斷hashMap中是否包含我們的表頭就可以校驗(yàn)是否是我們提供的模板
到此這篇關(guān)于EasyExcel實(shí)現(xiàn)導(dǎo)入+各種數(shù)據(jù)校驗(yàn)的文章就介紹到這了,更多相關(guān)EasyExcel導(dǎo)入數(shù)據(jù)校驗(yàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot 使用Mongo的GridFs實(shí)現(xiàn)分布式文件存儲操作
這篇文章主要介紹了Spring Boot 使用Mongo的GridFs實(shí)現(xiàn)分布式文件存儲操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10Springboot配置文件內(nèi)容加密代碼實(shí)例
這篇文章主要介紹了Springboot配置文件內(nèi)容加密代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11簡單了解Java刪除字符replaceFirst原理及實(shí)例
這篇文章主要介紹了簡單了解Java刪除字符replaceFirst原理及實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05GraalVM和Spring Native嘗鮮一步步讓Springboot啟動飛起來66ms完成啟動
GraalVM是高性能的JDK,支持Java/Python/JavaScript等語言,它可以讓Java變成二進(jìn)制文件來執(zhí)行,讓程序在任何地方運(yùn)行更快,這篇文章主要介紹了GraalVM和Spring Native嘗鮮一步步讓Springboot啟動飛起來66ms完成啟動,需要的朋友可以參考下2023-02-02