|
|
@@ -0,0 +1,406 @@
|
|
|
+package cn.hobbystocks.auc.common.easy.factory;
|
|
|
+
|
|
|
+import cn.hobbystocks.auc.common.easy.EasyConfig;
|
|
|
+import cn.hobbystocks.auc.common.easy.util.EasyExcelImportUtil;
|
|
|
+import cn.hobbystocks.auc.common.easy.util.EasyExcelUtil;
|
|
|
+import cn.hobbystocks.auc.common.utils.DateUtils;
|
|
|
+import cn.hobbystocks.auc.common.utils.Global;
|
|
|
+import cn.hobbystocks.auc.common.utils.ServletUtils;
|
|
|
+import cn.hobbystocks.auc.common.utils.StringUtils;
|
|
|
+import cn.hobbystocks.auc.dto.ExportFieldDto;
|
|
|
+import com.alibaba.excel.EasyExcel;
|
|
|
+import com.alibaba.excel.ExcelWriter;
|
|
|
+import com.alibaba.excel.annotation.ExcelProperty;
|
|
|
+import com.alibaba.excel.write.metadata.WriteSheet;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.collections4.list.TreeList;
|
|
|
+
|
|
|
+import javax.servlet.ServletOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.Method;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.util.*;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class EasyExcelFactory<T,R> {
|
|
|
+ private EasyExcelTypeEnums type;
|
|
|
+ private final int pageSize = 1000;
|
|
|
+ //调用对象
|
|
|
+ protected Object service;
|
|
|
+ //调用方法
|
|
|
+ protected String methodName;
|
|
|
+ //查询总数
|
|
|
+ protected String countMethodName;
|
|
|
+ //查询参数
|
|
|
+ protected Object param;
|
|
|
+ // 是否合并表头
|
|
|
+ private Boolean headMerge;
|
|
|
+
|
|
|
+ private EasyExcelUtil<T, Object> easyExcelUtil;
|
|
|
+ private EasyExcelImportUtil<T, T> importerUtil;
|
|
|
+ private List<T> list ;
|
|
|
+ private String path;
|
|
|
+ private Class<T> clazz;
|
|
|
+ private String sheetName;
|
|
|
+ private EasyColumnEnums columnsType;
|
|
|
+ private List<ExportFieldDto> exportFields;
|
|
|
+ private File file;
|
|
|
+ private EasyConfig easyConfig;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param type
|
|
|
+ * @param service
|
|
|
+ * @param methodName
|
|
|
+ * @param countMethodName
|
|
|
+ * @param param
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static EasyExcelFactory initConfig(EasyExcelTypeEnums type,Object service, String methodName,String countMethodName, Object param){
|
|
|
+ EasyExcelFactory factory = new EasyExcelFactory();
|
|
|
+ factory.type = type;
|
|
|
+ factory.service = service;
|
|
|
+ factory.methodName = methodName;
|
|
|
+ factory.countMethodName = countMethodName;
|
|
|
+ factory.param = param;
|
|
|
+ return factory;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param clazz
|
|
|
+ * @param name
|
|
|
+ * @param columnsType
|
|
|
+ * @param exportFields
|
|
|
+ * @param <T>
|
|
|
+ * @param <R>
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static <T, R> EasyExcelFactory<T,R> init(EasyExcelTypeEnums type,Class<T> clazz, String name,EasyColumnEnums columnsType, List<ExportFieldDto> exportFields){
|
|
|
+ EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
|
|
|
+ factory.type = type;
|
|
|
+ factory.clazz = clazz;
|
|
|
+ factory.sheetName = name;
|
|
|
+ factory.columnsType = columnsType;
|
|
|
+ factory.exportFields = exportFields;
|
|
|
+ return factory;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param type
|
|
|
+ * @param clazz
|
|
|
+ * @param url
|
|
|
+ * @param <T>
|
|
|
+ * @param <R>
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static <T, R> EasyExcelFactory<T, R> init(EasyExcelTypeEnums type,Class<T> clazz, String url){
|
|
|
+ EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
|
|
|
+ factory.type = type;
|
|
|
+ factory.clazz = clazz;
|
|
|
+ factory.path = url;
|
|
|
+ return factory;
|
|
|
+ }
|
|
|
+
|
|
|
+ public EasyExcelFactory<T,R> easyConfig(EasyConfig easyConfig){
|
|
|
+ this.easyConfig = easyConfig;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param headMerge
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public EasyExcelFactory<T,R> headMerge(boolean headMerge){
|
|
|
+ this.headMerge = headMerge;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param clazz
|
|
|
+ * @param <T>
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static<T> Object getExcelFields(Class<T> clazz) {
|
|
|
+ List<ExportFieldDto> exportFields = new ArrayList<>();
|
|
|
+ if(!Objects.isNull(clazz)){
|
|
|
+ Arrays.asList(clazz.getDeclaredFields()).forEach(field -> {
|
|
|
+ ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
|
|
+ if(!Objects.isNull(excelProperty)){
|
|
|
+ ExportFieldDto exportFieldDto = new ExportFieldDto(excelProperty.value()[0],false);
|
|
|
+ exportFields.add(exportFieldDto);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return exportFields;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public EasyExcelFactory<T,R> build(){
|
|
|
+ switch (type){
|
|
|
+ case EXPORT: //导出
|
|
|
+ path = Global.getDownloadPath() + "//easyDownload-" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date()) + "//" + this.sheetName + ".xlsx";
|
|
|
+ if(Objects.isNull(easyConfig)){
|
|
|
+ Set<String> exportColumns = name2Column(this.clazz, exportFields);
|
|
|
+ easyExcelUtil = EasyExcelUtil.init(this.clazz, this.sheetName)
|
|
|
+ .path(path)
|
|
|
+ .headMerge(!Objects.isNull(this.headMerge) && this.headMerge)
|
|
|
+ //设置包含选中的字段导出
|
|
|
+ .includeColumns(this.columnsType, exportColumns)
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case IMPORT: //导入
|
|
|
+ list = new ArrayList<>();
|
|
|
+ importerUtil = EasyExcelImportUtil.create(clazz, list::addAll, Function.identity())
|
|
|
+ .batch();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param tList
|
|
|
+ */
|
|
|
+ private void writeFile(List<T> tList){
|
|
|
+ try {
|
|
|
+ if (!Objects.isNull(tList)) {
|
|
|
+ easyExcelUtil.doWrite(tList);
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("导出excel失败",e);
|
|
|
+ } finally {
|
|
|
+ Optional.ofNullable(tList).orElseGet(ArrayList::new).clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出流
|
|
|
+ * @param tList
|
|
|
+ */
|
|
|
+ public void doWriteStream(List<T> tList){
|
|
|
+ try {
|
|
|
+ writeFile(tList);
|
|
|
+ if (!Objects.isNull(easyExcelUtil)) {
|
|
|
+ easyExcelUtil.finish();
|
|
|
+ ServletOutputStream outputStream = ServletUtils.getResponse().getOutputStream();
|
|
|
+ outputStream.write(easyExcelUtil.getBytes());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("easy导出excel失败",e);
|
|
|
+ } finally {
|
|
|
+ clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public void finish(){
|
|
|
+ if(!Objects.isNull(easyExcelUtil)) {
|
|
|
+ easyExcelUtil.finish();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public void clear(){
|
|
|
+ if(!Objects.isNull(easyExcelUtil)) {
|
|
|
+ easyExcelUtil.clear();
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotBlank(path) && !path.startsWith("http")){
|
|
|
+ try {
|
|
|
+ File file = new File(path);
|
|
|
+ if(file.exists()){
|
|
|
+ file.delete();
|
|
|
+ }
|
|
|
+ if(file.getParentFile().exists()){
|
|
|
+ file.getParentFile().delete();
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("删除文件失败",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private int searchCount(){
|
|
|
+ try {
|
|
|
+ Method method = service.getClass().getMethod(countMethodName, param.getClass());
|
|
|
+ return (int) method.invoke(service, param);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * @param fieldName
|
|
|
+ * @param clazz
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Object getValueByField(String fieldName,Class<?> clazz) {
|
|
|
+ try {
|
|
|
+ Field field = this.param.getClass().getDeclaredField(fieldName);
|
|
|
+ field.setAccessible(true);
|
|
|
+ Object value = field.get(this.param);
|
|
|
+ if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ return field.get(this.param);
|
|
|
+ } catch (NoSuchFieldException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ try {
|
|
|
+ Field field = this.param.getClass().getSuperclass().getDeclaredField(fieldName);
|
|
|
+ field.setAccessible(true);
|
|
|
+ Object value = field.get(this.param);
|
|
|
+ if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ return field.get(this.param);
|
|
|
+ } catch (NoSuchFieldException | IllegalAccessException ex) {
|
|
|
+ throw new RuntimeException(ex);
|
|
|
+ }
|
|
|
+ } catch (IllegalAccessException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List searchList() {
|
|
|
+ try {
|
|
|
+ Method method = service.getClass().getMethod(methodName, param.getClass());
|
|
|
+ return (List) method.invoke(service, param);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ private Set<String> name2Column(Class<T> claszz, List<ExportFieldDto> exportFields) {
|
|
|
+ Set<String> columns = new HashSet<>();
|
|
|
+ Field[] fields = claszz.getDeclaredFields();
|
|
|
+ Set<String> sets = Optional.ofNullable(exportFields).orElse(new ArrayList<>()).stream().map(ExportFieldDto::getName).collect(Collectors.toSet());
|
|
|
+ for (Field field : fields) {
|
|
|
+ field.setAccessible(true);
|
|
|
+ //获取属性名
|
|
|
+ //是否存在注解
|
|
|
+ if(field.isAnnotationPresent(ExcelProperty.class)) {
|
|
|
+ ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
|
|
+ if (CollectionUtils.isEmpty(exportFields) || sets.contains(Optional.ofNullable(excelProperty.value()).orElse(new String[]{"default"})[0])){
|
|
|
+ columns.add(field.getName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return columns;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param easyConfig
|
|
|
+ * @param excelWriter
|
|
|
+ */
|
|
|
+ public void doWriteBySheetFinal(EasyConfig easyConfig, ExcelWriter excelWriter){
|
|
|
+ if (Objects.nonNull(easyConfig) && CollectionUtils.isNotEmpty(easyConfig.getSheet())) {
|
|
|
+ List<EasyConfig.Sheet> sheets = easyConfig.getSheet();
|
|
|
+ for (int i = 0; i < sheets.size(); i++) {
|
|
|
+ EasyConfig.Sheet sheet = sheets.get(i);
|
|
|
+ if (StringUtils.isNotBlank(sheet.getType())) {
|
|
|
+ if (Objects.equals(sheet.getType(), "map")) {
|
|
|
+ //header 按照key值正序排序 转成List<List<String>>
|
|
|
+ Map<String, String> headerMap = sheet.getHeader();
|
|
|
+ List<List<String>> header = headerMap.entrySet()
|
|
|
+ .stream()
|
|
|
+ .sorted(Map.Entry.comparingByKey())
|
|
|
+ .map(item -> {
|
|
|
+ String value = item.getValue();
|
|
|
+ return Collections.singletonList(value);
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<String> headerKeys = headerMap.entrySet()
|
|
|
+ .stream()
|
|
|
+ .sorted(Map.Entry.comparingByKey())
|
|
|
+ .map(Map.Entry::getKey)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<Map<String, String>> i18nSheetDatas = sheet.getData();
|
|
|
+ //以header 对 i8nSheetData 进行排序 并返回 List<List<String>>
|
|
|
+ List<List<String>> i18nSheetData = i18nSheetDatas.stream()
|
|
|
+ //根据headerKeys 值进行排序
|
|
|
+ .sorted(Comparator.comparing(item -> {
|
|
|
+ //判断头部是否存在 如果不存在则在最后添加一条
|
|
|
+ //获取 item key value
|
|
|
+ Set<String> keySet = item.keySet();
|
|
|
+ keySet.forEach(key -> {
|
|
|
+ if (!headerKeys.contains(key)) {
|
|
|
+ headerKeys.add(key);
|
|
|
+ header.add(Collections.singletonList(key));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return Optional.ofNullable(item.get(headerKeys.iterator()
|
|
|
+ .next()))
|
|
|
+ .orElse("");
|
|
|
+ }))
|
|
|
+ .map(item -> {
|
|
|
+ List<String> dataList = new TreeList();
|
|
|
+ headerKeys.forEach(kk -> {
|
|
|
+ String vv = item.get(kk);
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isEmpty(vv)) {
|
|
|
+ vv = "";
|
|
|
+ }
|
|
|
+ dataList.add(vv);
|
|
|
+ });
|
|
|
+ return dataList;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ //对i18nSheetData 做去重处理
|
|
|
+ i18nSheetData = i18nSheetData.stream()
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet.getName())
|
|
|
+ .head(header)
|
|
|
+ .useDefaultStyle(true)
|
|
|
+ .build();
|
|
|
+ excelWriter.write(i18nSheetData, writeSheet);
|
|
|
+ } else {
|
|
|
+ List<Object> beanDatas = sheet.getBeanDatas();
|
|
|
+ List<String> fieldNames = null;
|
|
|
+ if(CollectionUtils.isNotEmpty(sheet.getExcelFields())){
|
|
|
+ fieldNames = sheet.getExcelFields()
|
|
|
+ .stream()
|
|
|
+ .map(ExportFieldDto::getName)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ Object beanData = beanDatas.get(0);
|
|
|
+ WriteSheet writeSheet;
|
|
|
+ if (CollectionUtils.isNotEmpty(fieldNames)) {
|
|
|
+ writeSheet = EasyExcel.writerSheet(i, sheet.getName())
|
|
|
+ .head(beanData.getClass())
|
|
|
+ .useDefaultStyle(true)
|
|
|
+ //设置包含选中的字段导出
|
|
|
+ .includeColumnFieldNames(fieldNames)
|
|
|
+ .build();
|
|
|
+ } else {
|
|
|
+ writeSheet = EasyExcel.writerSheet(i, sheet.getName())
|
|
|
+ .head(beanData.getClass())
|
|
|
+ .useDefaultStyle(true)
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+ excelWriter.write(beanDatas, writeSheet);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|