# Excel快速导出 ## 功能介绍 - 在对应实现类上加上自定义注解`@Excel`后,在编写web接口是调用ExcelUtil.exportExcel即可实现对应实体Excel的快速导出 ## 实现原理 - 主要使用到Java反射机制,获取到目标实体的Class对象后通过java发射获取到每个字段,并且获取到对应字段上的@Excel注解,将注解中的数据记录下来作为Excel中的表头。再通过java反射获取到对应的数据并做好与标表头的映射关系,最终使用ease-excel实现Excel的渲染 ## 代码展示 ```java package cn.odliken.security.utils; import cn.odliken.admin.api.entity.DictData; import cn.odliken.admin.api.fegin.DictDataService; import cn.odliken.common.core.constant.ResultConstant; import cn.odliken.common.core.constant.SecurityConstants; import cn.odliken.common.core.exception.CustomException; import cn.odliken.common.core.result.Result; import cn.odliken.common.core.utils.DateUtils; import cn.odliken.common.core.utils.SpringContextHolder; import cn.odliken.common.core.utils.StringUtils; import cn.odliken.common.core.utils.reflect.ReflectUtils; import cn.odliken.security.annotation.Excel; import cn.odliken.security.annotation.Excels; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.support.ExcelTypeEnum; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; /** * @author Clay * @date 2022/12/19 */ public class ExcelUtil { public static List assistList = new ArrayList<>(); public static Map> dictDataMap; private static DictDataService getBean() { return SpringContextHolder.getBean(DictDataService.class); } /** * 获取到数据列表 * * @param list * @return */ private static List> getDataList(List list) { return list.stream().map(object -> assistList.stream().map(assist -> { Field field = assist.getField(); Excel excel = assist.getExcel(); Object value = null; if (StringUtils.isEmpty(assist.getObjectFieldName())) { value = getData(object, excel, field); } else { Object sunValue = null; try { sunValue = ReflectUtils.invokeGetter(object, assist.getObjectFieldName()); } catch (Exception e) { return null; } if (null != sunValue) { value = getData(object, excel, field); } } return value; }).collect(Collectors.toList()) ).collect(Collectors.toList()); } /** * 获取到对象中的数据 * * @param object * @param excel * @param field * @return */ private static Object getData(Object object, Excel excel, Field field) { try { Object objectValue = ReflectUtils.invokeGetter(object, field.getName()); if (objectValue instanceof Date) { objectValue = DateUtils.parseDateToStr(excel.dateFormat(), (Date) objectValue); } String dictType = excel.dictType(); if (StringUtils.isNotEmpty(dictType)){ Map dictMap = dictDataMap.get(dictType); if (null != dictMap){ DictData dictData = dictMap.get(objectValue.toString()); if (null!= dictData){ objectValue = dictData.getDictLabel(); } } } return objectValue; } catch (Exception e) { return null; } } /** * 初始化header数据 * * @param clazz * @param assist */ private static void initHeader(Class clazz, ExcelAssist assist) { for (Field field : clazz.getDeclaredFields()) { Excel excel = field.getAnnotation(Excel.class); if (null != excel) { assistList.add(new ExcelAssist(field, excel, assist)); } else { Excels excels = field.getAnnotation(Excels.class); if (excels == null) { continue; } Class objectValue = field.getType(); if (clazz == objectValue) { throw new CustomException("不允许嵌套对象导出Excel"); } ExcelAssist excelAssist = new ExcelAssist(field, excels); initHeader(objectValue, excelAssist); } } } public static void exportExcel(List list, Class clazz) { exportExcel(list, clazz, null); } /** * 导出数据Excel * * @param list * @param clazz * @param sheetName */ public static void exportExcel(List list, Class clazz, String sheetName) { Set dictList = new HashSet<>(); initHeader(clazz, null); List> headerList = new ArrayList<>(assistList.size()); assistList = assistList.stream().sorted(Comparator.comparing(ExcelAssist::getOrder)) .peek(assist -> headerList.add(Collections.singletonList(assist.getExcel().value()))) .peek(assist -> { String dictType = assist.getExcel().dictType(); if (StringUtils.isNotEmpty(dictType)) { dictList.add(dictType); } }) .collect(Collectors.toList()); if (dictList.size() > 0) { getDictData(new ArrayList<>(dictList)); } List> dataList = getDataList(list); try { sheetName = StringUtils.isEmpty(sheetName) ? "sheet" : sheetName; HttpServletResponse response = getResponse(sheetName); EasyExcel.write(response.getOutputStream()) .head(headerList) .excelType(ExcelTypeEnum.XLSX) .sheet(StringUtils.isEmpty(sheetName) ? "sheet" : sheetName) .doWrite(dataList); } catch (IOException e) { throw new CustomException("Excel导出失败!"); } } private static HttpServletResponse getResponse(String sheetName){ HttpServletResponse response = SecurityUtils.getResponse(); response.setCharacterEncoding("utf-8"); response.setContentType("multipart/form-data"); response.setHeader("Content-Disposition" , "attachment;fileName=" + sheetName + UUID.randomUUID() + ".xlsx"); return response; } private static void getDictData(List dictList) { DictDataService dictDataService = getBean(); Result>> result = dictDataService.searchDictDataCacheKeys(dictList, SecurityConstants.FROM_IN); System.out.println(result); if (result.getCode() == ResultConstant.SUCCESS_CODE){ dictDataMap = result.getData(); } } } ``` ## 使用demo ```java @ApiOperation("导出excel数据") @GetMapping("/export") @PreAuthorize("@ss.hasPermission('code:goods:export')") public void export(DemoGoodsQuery query){ List list = demoGoodsService.exportDemoGoodsList(query); ExcelUtil.exportExcel(list,DemoGoodsVo.class); } ```