cloud-security-wiki/docs/util/excel/README.md

208 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<ExcelAssist> assistList = new ArrayList<>();
public static Map<String,Map<String,DictData>> dictDataMap;
private static DictDataService getBean() {
return SpringContextHolder.getBean(DictDataService.class);
}
/**
* 获取到数据列表
*
* @param list
* @return
*/
private static List<List<Object>> 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<String,DictData> 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<String> dictList = new HashSet<>();
initHeader(clazz, null);
List<List<String>> 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<List<Object>> 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<String> dictList) {
DictDataService dictDataService = getBean();
Result<Map<String, Map<String,DictData>>> 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<DemoGoodsVo> list = demoGoodsService.exportDemoGoodsList(query);
ExcelUtil.exportExcel(list,DemoGoodsVo.class);
}
```