关于EasyExcel 优化,实现格式自定义,数据字典自动转化。
生活随笔
收集整理的這篇文章主要介紹了
关于EasyExcel 优化,实现格式自定义,数据字典自动转化。
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
最終要達(dá)到的結(jié)果:
1.下載模板,添加模板說明sheet
2.導(dǎo)入數(shù)據(jù),對數(shù)據(jù)進(jìn)行校驗,對模板進(jìn)行檢驗,并將校驗結(jié)果展示給用戶。
3.導(dǎo)出數(shù)據(jù),可選導(dǎo)出字段
4.字典數(shù)據(jù)自動轉(zhuǎn)化,導(dǎo)入/導(dǎo)出
操作方式:添加一個注解即可。@ExcelVaild
下載模板優(yōu)化
優(yōu)化效果:如下(添加模板說明)實現(xiàn)方式:添加自定義注解@ExcelVaild
具體代碼:
注解:
@Documented @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelVaild {ExcelValidEnum value() default ExcelValidEnum.NULL;String dictType() default ""; //配置字典數(shù)據(jù) }枚舉
@AllArgsConstructor public enum ExcelValidEnum {NULL("", "可以為空"),//不校驗NOTNULL("\\S", "不為空"),BIRTHDAY("[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}", "生日"),BIRTHDAY_NOTNULL("[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}", "生日"),EMAIL("\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?", "郵件"),EMAIL_NOTNULL("\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?", "郵件"),IDCARD("[1-9]\\d{13,16}[a-zA-Z0-9]{1}", "身份證"),IDCARD_NOTNULL("[1-9]\\d{13,16}[a-zA-Z0-9]{1}", "身份證"),DIGIT("\\-?[1-9]\\d+", "整數(shù)"),DIGIT_NOTNULL("\\-?[1-9]\\d+", "整數(shù)"),DECIMAL("[-+]?[0-9]*\\.?[0-9]+", "浮點(diǎn)數(shù)"),DECIMAL_NOTNULL("[-+]?[0-9]*\\.?[0-9]+", "浮點(diǎn)數(shù)"),POSTCODE("[1-9]\\d{5}", "郵編"),POSTCODE_NOTNULL("[1-9]\\d{5}", "郵編"),CHINESE("[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}", "中文"),CHINESE_NOTNULL("[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}", "中文"),PHONE("^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$", "手機(jī)號碼"),PHONE_NOTNULL("^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$", "手機(jī)號碼"),CP("^[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng)A-Z]{1}[A-Z]{1}[A-Z0-9]{3,4}[A-Z0-9掛學(xué)警港澳]{1}$", "車牌號"),CP_NOTNULLL("^[京津滬渝冀豫云遼黑湘皖魯新蘇浙贛鄂桂甘晉蒙陜吉閩貴粵青藏川寧瓊使領(lǐng)A-Z]{1}[A-Z]{1}[A-Z0-9]{3,4}[A-Z0-9掛學(xué)警港澳]{1}$", "車牌號");private String regex;private String msg;/*** 正則校驗* @param enums* @param name* @param val* @return*/public static String regexCheck(ExcelValidEnum enums, String name, Object val) {String msgs = null;if (enums.name().equals(ExcelValidEnum.NULL.name())) {return msgs;}if (enums.name().equals(ExcelValidEnum.NOTNULL.name())) {boolean notEmpty = StringUtils.isNotEmpty(val);if (notEmpty) {return msgs;} else {msgs = ("【" + name + "】不符合" + enums.getMsg() + "的規(guī)則");return msgs;}}if (StringUtils.isNotEmpty(enums.regex)&& StringUtils.isNotEmpty(val)) {boolean flag = Pattern.matches(enums.getRegex(), String.valueOf(val));if (!flag) {msgs = ("【" + name + "】不符合" + enums.getMsg() + "的規(guī)則");return msgs;}}if (StringUtils.isNotEmpty(enums.regex)&& enums.name().endsWith("NOTNULL") ){if (StringUtils.isEmpty(val)){msgs = ("【" + name + "】不能為空");return msgs;}boolean flag = Pattern.matches(enums.getRegex(), String.valueOf(val));if (!flag) {msgs = ("【" + name + "】不符合" + enums.getMsg() + "的規(guī)則");return msgs;}}return msgs;}}vo類
public class DzdaQbztkBcDxsVO extends SysVO {private static final long serialVersionUID = 1L;/*** 姓名*/@ApiModelProperty(value = "姓名")//@NotBlank(message = "姓名 不能為空")@ExcelProperty(value = "姓名")private String xm;/*** 身份證號碼*/@ApiModelProperty(value = "身份證號碼")//@NotBlank(message = "身份證號碼 不能為空")@ExcelProperty("身份證號碼")@ExcelVaild(value =ExcelValidEnum.IDCARD_NOTNULL)private String sfzh;/*** 性別*/@ApiModelProperty(value = "性別")//@NotBlank(message = "性別 不能為空")@ExcelProperty("性別")@ExcelVaild(dictType = "gender")private String xb;/*** 民族*/@ApiModelProperty(value = "民族")//@NotBlank(message = "民族 不能為空")@ExcelProperty("民族")@ExcelVaild(dictType = "cqfk_common_mz")private String mz;/*** 學(xué)校*/@ApiModelProperty(value = "學(xué)校")//@NotBlank(message = "學(xué)校 不能為空")@ExcelProperty("學(xué)校")private String xx;/*** 專業(yè)名稱*/@ApiModelProperty(value = "專業(yè)名稱")//@NotBlank(message = "專業(yè)名稱 不能為空")@ExcelProperty("專業(yè)名稱")private String zymc;/*** 層次*/@ApiModelProperty(value = "層次")//@NotBlank(message = "層次 不能為空")@ExcelProperty("層次")@ExcelVaild(dictType = "dzda_ztk_cc")private String cc;/*** 政治面貌*/@ApiModelProperty(value = "政治面貌")//@NotBlank(message = "政治面貌 不能為空")@ExcelProperty("政治面貌")@ExcelVaild(dictType = "dzda_ztk_zzmm")private String zzmm;/*** 入學(xué)年份*/@ApiModelProperty(value = "入學(xué)年份")//@NotBlank(message = "入學(xué)年份 不能為空")@ExcelProperty("入學(xué)年份")private String rxnf;/*** 所屬區(qū)縣area_code*/@ApiModelProperty(value = "所屬區(qū)縣area_code")//@NotBlank(message = "所屬區(qū)縣area_code 不能為空")@ExcelProperty("所屬區(qū)縣area_code")private String ssqxAreacode;/*** 所屬區(qū)縣area_code*/@ApiModelProperty(value = "所屬區(qū)縣名")//@NotBlank(message = "所屬區(qū)縣area_code 不能為空")@ExcelProperty("所屬區(qū)縣名")private String ssqxmc;/*** 所屬派出所dept_id*/@ApiModelProperty(value = "所屬派出所dept_id")//@NotBlank(message = "所屬派出所dept_id 不能為空")@ExcelProperty("所屬派出所dept_id")private String sspcsId;/*** 所屬派出所dept_id*/@ApiModelProperty(value = "所屬派出所名稱")//@NotBlank(message = "所屬派出所dept_id 不能為空")@ExcelProperty("所屬派出所名稱")private String sspcsmc;/*** 是否在渝*/@ApiModelProperty(value = "是否在渝")//@NotBlank(message = "是否在渝 不能為空")@ExcelProperty("是否在渝")@ExcelVaild(dictType = "is_no")private String sfzy;/*** 是否有問題*/@ApiModelProperty(value = "是否有問題")//@NotBlank(message = "是否有問題 不能為空")@ExcelProperty("是否有問題")@ExcelVaild(dictType = "is_no")private String sfywt;controller
/*** 導(dǎo)出模板* @param response* @throws IOException*/@GetMapping("/export")public void downLoad( HttpServletResponse response) {ExportEasyExcelUtil.exportemplete(response,DzdaQbztkBcDxsVO.class);}ExportEasyExcelUtil
* @author ssp* @className ExportEasyExcelUtil* @description TODO excel導(dǎo)出工具類* @create 2022/8/11 16:18**/ public class ExportEasyExcelUtil {private static RemoteDicService getRemoteDicService(){return SpringContextHolder.getBean(RemoteDicService.class);}/*** 導(dǎo)出自定義列(導(dǎo)出數(shù)據(jù))* @param response* @param fileName 導(dǎo)出名稱* @param includeColumnFiledNames 導(dǎo)出字段屬性集合* @param objectClass 導(dǎo)出對象的class對象* @param datas 導(dǎo)出數(shù)據(jù)集合* 若調(diào)用此方法,瀏覽器可直接訪問接口即可下載文件*/public static void export(HttpServletResponse response, String fileName,List<String> includeColumnFiledNames, Class objectClass, List datas) {try {List list = converDict(objectClass, datas);response.addHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8") + ".xlsx");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");if (ListUtils.isEmpty(includeColumnFiledNames)){EasyExcel.write(response.getOutputStream(),objectClass).registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) // 簡單的列寬策略,列寬20.registerWriteHandler(new SimpleRowHeightStyleStrategy((short)25,(short)25)).sheet("Sheet1").doWrite(list);}else {EasyExcel.write(response.getOutputStream(),objectClass).includeColumnFiledNames(includeColumnFiledNames).sheet("Sheet1").doWrite(list);}} catch (IOException e) {e.printStackTrace();}}/*** 下載模板* @param response* @param objectClass*/public static void exportemplete(HttpServletResponse response,Class objectClass){ExcelWriter excelWriter = null;try {excelWriter = EasyExcel.write(response.getOutputStream()).build();response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");//可以防止中文亂碼,和easyexcel沒有關(guān)系String fileName = DateUtils.getYyyyMMdd();fileName = URLEncoder.encode(fileName,"utf-8");response.setHeader("Content-disposition","attachment;filename=" + fileName + ".xlsx");WriteSheet writeSheet = EasyExcel.writerSheet(0,"數(shù)據(jù)模板").head(objectClass).registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) // 簡單的列寬策略,列寬20.registerWriteHandler(new SimpleRowHeightStyleStrategy((short)25,(short)25)).build();excelWriter.write(new ArrayList(),writeSheet);//sheet2writeSheet = EasyExcel.writerSheet(1,"模板說明《必看》").head(ExcelVO.class).registerWriteHandler(new CellStyleStrategy()).registerWriteHandler(new SimpleColumnWidthStyleStrategy(25)) // 簡單的列寬策略,列寬20.registerWriteHandler(new SimpleRowHeightStyleStrategy((short)25,(short)25)).build();ArrayList arrayList = new ArrayList();Field[] fields = objectClass.getDeclaredFields();for (Field field : fields) {ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);if (null!=annotation){ExcelVO excelVO = new ExcelVO();excelVO.setZdsx(field.getName());String[] value = annotation.value();StringBuilder builder = new StringBuilder();for (String s : value) {builder.append(s);}excelVO.setZdmc(builder.toString());String typeName = field.getGenericType().getTypeName();String[] split = typeName.split("\\.");excelVO.setDateType(dataStringToChinese(split[split.length-1]));ExcelVaild vaild = field.getAnnotation(ExcelVaild.class);if (null!=vaild){if (StringUtils.isNotEmpty(vaild.dictType())){RemoteDicService remoteDicService = getRemoteDicService();excelVO.setIsDict("是");excelVO.setDictType(vaild.dictType());List<SysDictItem> data = remoteDicService.getDictByType(vaild.dictType(), SecurityConstants.FROM_IN).getData();if (ListUtils.isNotEmpty(data)){StringBuffer buffer = new StringBuffer();data.stream().forEach(e->{buffer.append(e.getLabel() + ";");});excelVO.setRemark(buffer.toString());}}if (vaild.value().name().endsWith("NOTNULL")){excelVO.setIsNotNull("是");}}arrayList.add(excelVO);}}excelWriter.write(arrayList, writeSheet);} catch (IOException e) {e.printStackTrace();}finally {excelWriter.finish();}}/*** 數(shù)據(jù)字段轉(zhuǎn)換* @param objectClass* @param datas* @return*/private static List converDict(Class objectClass, List datas){HashMap<String,Field> map = new HashMap();Field[] fields =objectClass.getDeclaredFields();Arrays.stream(fields).forEach(e->{ExcelVaild annotation = e.getAnnotation(ExcelVaild.class);if (null!=annotation){String s = annotation.dictType();if (StringUtils.isNotEmpty(s)){map.put(s, e);}}});datas.stream().forEach(e->{try {for (String key : map.keySet()) {Field field = map.get(key);field.setAccessible(true);String value = field.get(e).toString();if (StringUtils.isNotEmpty(value)){String labelByCache = DictUtil.getLabelByCache(key, value);map.get(key).set(e,labelByCache);}}}catch (Exception E){E.getMessage();}});return datas;}public static String dataStringToChinese(String data) {String s = data;switch (s) {case "String":s = "String(字符串)";break;case "Integer":s="Integer(數(shù)字)";break;case "Boolean":s="Boolean(判斷 true/false)";break;case "LocalDateTime":s = "LocalDateTime(日期 yyyy-MM-dd HH:mm:ss)";break;case "LocalDate":s = "LocalDate(日期 yyyy-MM-dd)";break;case "Date":s = "Date(日期 yyyy-MM-dd HH:mm:ss)";break;}return s;}} asheet2(模板說明:格式自定義攔截器)
public class CellStyleStrategy extends AbstractVerticalCellStyleStrategy {/*** 表頭樣式設(shè)置* @param head* @return*/@Overrideprotected WriteCellStyle headCellStyle(Head head) {WriteCellStyle headWriteCellStyle = new WriteCellStyle();headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 12);headWriteCellStyle.setWriteFont(headWriteFont);return headWriteCellStyle;}/*** 內(nèi)容樣式設(shè)置* @param head* @return*/@Overrideprotected WriteCellStyle contentCellStyle(Head head) {// 內(nèi)容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 字體策略WriteFont contentWriteFont = new WriteFont();// 字體大小contentWriteFont.setFontHeightInPoints((short) 12);contentWriteCellStyle.setWriteFont(contentWriteFont);contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//設(shè)置 自動換行contentWriteCellStyle.setWrapped(true);//設(shè)置 垂直居中contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);Integer columnIndex = head.getColumnIndex();if(2 == columnIndex || 4== columnIndex){WriteFont writeFont = contentWriteCellStyle.getWriteFont();writeFont.setColor(IndexedColors.RED1.getIndex());writeFont.setBold(true);return contentWriteCellStyle;}return contentWriteCellStyle;}}導(dǎo)入優(yōu)化
實現(xiàn)界面提示輸入錯誤項,字典自動轉(zhuǎn)化。
@PostMapping("/import")public R importFile(@RequestPart("file") MultipartFile file){try {EasyExcelListener listener = new EasyExcelListener(DzdaQbztkBcDxsVO.class);List<DzdaQbztkBcDxsVO> list = EasyExcel.read(file.getInputStream(), DzdaQbztkBcDxsVO.class, listener).headRowNumber(1).sheet().doReadSync();if (ListUtils.isNotEmpty(listener.getErrors())){return R.failed(listener.getErrors(),"導(dǎo)入excel校驗失敗");}return R.ok(dzdaQbztkBcDxsService.saveBatch(dzdaQbztkBcDxsUtil.convertVOList2Entiy(list)));} catch (IOException e) {e.printStackTrace();}return R.failed();}EasyExcelListener 監(jiān)聽器,實現(xiàn)模板校驗,數(shù)據(jù)校驗。
public class EasyExcelListener <T> extends AnalysisEventListener<T> {private static final Logger log = LoggerFactory.getLogger(DefaultAnalysisEventListener.class);private final List<Object> list = new ArrayList();private final List<ErrorMessage> errorMessageList = new ArrayList();private Long lineNum = 1L;@Setterprivate Class clazz;public EasyExcelListener(Class clazz) {this.clazz = clazz;}@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {/*count 記錄模板表頭有幾個,用以判斷用戶導(dǎo)入的表格是否和模板完全一致如果用戶導(dǎo)入表格較模板的表頭多,但其余符合模板,這樣不影響則不需要*/int count = 0;int i = -1;// 獲取數(shù)據(jù)實體的字段列表Field[] fields =clazz.getDeclaredFields();// 遍歷字段進(jìn)行判斷for (Field field : fields) {// 獲取當(dāng)前字段上的ExcelProperty注解信息ExcelProperty fieldAnnotation = field.getAnnotation(ExcelProperty.class);// 判斷當(dāng)前字段上是否存在ExcelProperty注解if (fieldAnnotation != null) {++count;i++;// 存在ExcelProperty注解則根據(jù)注解的index索引到表頭中獲取對應(yīng)的表頭名String headName = headMap.get(i);// 判斷表頭是否為空或是否和當(dāng)前字段設(shè)置的表頭名不相同String s = fieldAnnotation.value()[0];if (StringUtils.isEmpty(headName) || !headName.equals(s)) {errorMessageList.add(new ErrorMessage(lineNum, Collections.singleton("導(dǎo)入模板錯誤")));}}}// 判斷用戶導(dǎo)入表格的標(biāo)題頭是否完全符合模板if (count != headMap.size()) {errorMessageList.add(new ErrorMessage(lineNum, Collections.singleton("導(dǎo)入模板錯誤")));}}@Overridepublic void invoke(T t, AnalysisContext analysisContext) {lineNum++;Set<ConstraintViolation<Object>> violations = Validators.validate(t);if (!violations.isEmpty()) {Set<String> messageSet = (Set)violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());this.errorMessageList.add(new ErrorMessage(this.lineNum, messageSet));} else {this.list.add(t);}ErrorMessage vaild = ExcelValidUtil.vaild(t);if (null!=vaild){vaild.setLineNum(this.lineNum);this.errorMessageList.add(vaild);}}public void doAfterAllAnalysed(AnalysisContext analysisContext) {log.debug("Excel read analysed");}public List<Object> getList() {return this.list;}public List<ErrorMessage> getErrors() {return this.errorMessageList;} }導(dǎo)出優(yōu)化
實現(xiàn)前臺可選導(dǎo)出字段,字典自動轉(zhuǎn)化。
/*** 導(dǎo)出數(shù)據(jù)** @param* @return*/@GetMapping("/export")public void export(@RequestBody(required = false) DzdaQbztkBcDxsVO dzdaQbztkBcDxsVO , HttpServletResponse httpServletResponse) {List<DzdaQbztkBcDxsVO> list = dzdaQbztkBcDxsUtil.convertEntityList2VO(dzdaQbztkBcDxsService.list(WrapperUtil.getQueryWrapper(dzdaQbztkBcDxsVO, DzdaQbztkBcDxs.class)));ExportEasyExcelUtil.export(httpServletResponse,"Export",null,DzdaQbztkBcDxsVO.class,list);}null==list集合。可傳導(dǎo)出字段屬性的list集合,這里沒有傳,是全部導(dǎo)出,ExportEasyExcelUtil里面做了判斷。
總結(jié)
以上是生活随笔為你收集整理的关于EasyExcel 优化,实现格式自定义,数据字典自动转化。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 0421 AutoLayout的实践/基
- 下一篇: 网络游戏测试过程