Просмотр исходного кода

Update Excel模版动态数据下拉,泛型逻辑

Yue 1 неделя назад
Родитель
Сommit
204003f04a

+ 23 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-excel/src/main/java/com/vber/common/excel/annotation/ExcelDynamicOptions.java

@@ -0,0 +1,23 @@
+package com.vber.common.excel.annotation;
+
+import com.vber.common.excel.core.ExcelOptionsProvider;
+
+import java.lang.annotation.*;
+
+/**
+ * Excel动态下拉选项注解
+ *
+ * @author Iwb
+ */
+@Target({ ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface ExcelDynamicOptions {
+
+    /**
+     * 提供者类全限定名
+     * <p>
+     * {@link com.vber.common.excel.core.ExcelOptionsProvider} 接口实现类 class
+     */
+    Class<? extends ExcelOptionsProvider> providerClass();
+}

+ 41 - 30
SERVER/VberAdminPlusV3/vber-common/vber-common-excel/src/main/java/com/vber/common/excel/core/ExcelDownHandler.java

@@ -12,18 +12,19 @@ import cn.idev.excel.util.ClassUtils;
 import cn.idev.excel.write.handler.SheetWriteHandler;
 import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
 import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.ss.util.WorkbookUtil;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
 import com.vber.common.core.exception.ServiceException;
 import com.vber.common.core.service.DictService;
 import com.vber.common.core.utils.SpringUtils;
 import com.vber.common.core.utils.StreamUtils;
 import com.vber.common.core.utils.StringUtils;
 import com.vber.common.excel.annotation.ExcelDictFormat;
+import com.vber.common.excel.annotation.ExcelDynamicOptions;
 import com.vber.common.excel.annotation.ExcelEnumFormat;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddressList;
-import org.apache.poi.ss.util.WorkbookUtil;
-import org.apache.poi.xssf.usermodel.XSSFDataValidation;
 
 import java.lang.reflect.Field;
 import java.util.*;
@@ -34,7 +35,7 @@ import java.util.*;
  * <p>
  * 即只有前1000行的数据可以用下拉框,超出的自行通过限制数据量的形式,第二次输出
  *
- * @author Iwb
+ * @author Emil.Zhang
  */
 @Slf4j
 public class ExcelDownHandler implements SheetWriteHandler {
@@ -104,8 +105,8 @@ public class ExcelDownHandler implements SheetWriteHandler {
                 if (StringUtils.isNotBlank(dictType)) {
                     // 如果传递了字典名,则依据字典建立下拉
                     Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType))
-                            .orElseThrow(() -> new ServiceException("字典 {} 不存在", dictType))
-                            .values();
+                        .orElseThrow(() -> new ServiceException("字典 {} 不存在", dictType))
+                        .values();
                     options = new ArrayList<>(values);
                 } else if (StringUtils.isNotBlank(converterExp)) {
                     // 如果指定了确切的值,则直接解析确切的值
@@ -117,11 +118,21 @@ public class ExcelDownHandler implements SheetWriteHandler {
                 ExcelEnumFormat format = field.getDeclaredAnnotation(ExcelEnumFormat.class);
                 List<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField());
                 options = StreamUtils.toList(values, Convert::toStr);
+            } else if (field.isAnnotationPresent(ExcelDynamicOptions.class)) {
+                // 处理动态下拉选项
+                ExcelDynamicOptions dynamicOptions = field.getDeclaredAnnotation(ExcelDynamicOptions.class);
+                // 获取提供者实例
+                ExcelOptionsProvider provider = SpringUtils.getBean(dynamicOptions.providerClass());
+                Set<String> providerOptions = provider.getOptions();
+                if (CollUtil.isNotEmpty(providerOptions)) {
+                    options = new ArrayList<>(providerOptions);
+                }
             }
             if (ObjectUtil.isNotEmpty(options)) {
                 // 仅当下拉可选项不为空时执行
-                if (options.size() > 20) {
-                    // 这里限制如果可选项大于20,则使用额外表形式
+                int totalCharacter = options.stream().mapToInt(String::length).sum() + options.size();
+                if (options.size() > 20 || totalCharacter > 255) {
+                    // 这里限制如果可选项大于20 或 总字符数超过255,则使用额外表形式
                     dropDownWithSheet(helper, workbook, sheet, index, options);
                 } else {
                     // 否则使用固定值形式
@@ -186,7 +197,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
         for (int columnIndex = 0; columnIndex < firstOptions.size(); columnIndex++) {
             String columnName = firstOptions.get(columnIndex);
             firstRow.createCell(columnIndex)
-                    .setCellValue(columnName);
+                .setCellValue(columnName);
             columnNames.add(columnName);
         }
 
@@ -196,9 +207,9 @@ public class ExcelDownHandler implements SheetWriteHandler {
         name.setNameName(linkedOptionsSheetName);
         // 以横向第一行创建一级下拉拼接引用位置
         String firstOptionsFunction = String.format("%s!$%s$1:$%s$1",
-                linkedOptionsSheetName,
-                getExcelColumnName(0),
-                getExcelColumnName(firstOptions.size())
+            linkedOptionsSheetName,
+            getExcelColumnName(0),
+            getExcelColumnName(firstOptions.size())
         );
         // 设置名称管理器的引用位置
         name.setRefersToFormula(firstOptionsFunction);
@@ -218,12 +229,12 @@ public class ExcelDownHandler implements SheetWriteHandler {
             sonName.setNameName(thisFirstOptionsValue);
             // 以第二行该列数据拼接引用位置
             String sonFunction = String.format("%s!$%s$2:$%s$%d",
-                    linkedOptionsSheetName,
-                    firstOptionsColumnName,
-                    firstOptionsColumnName,
-                    // 二级选项存在则设置为(选项个数+1)行,否则设置为2行
-                    Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue))
-                            .orElseGet(ArrayList::new).size(), 1) + 1
+                linkedOptionsSheetName,
+                firstOptionsColumnName,
+                firstOptionsColumnName,
+                // 二级选项存在则设置为(选项个数+1)行,否则设置为2行
+                Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue))
+                    .orElseGet(ArrayList::new).size(), 1) + 1
             );
             // 设置名称管理器的引用位置
             sonName.setRefersToFormula(sonFunction);
@@ -276,7 +287,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
                 // 填充位置的部分不渲染
                 if (StrUtil.isNotBlank(rowValue)) {
                     row.createCell(columnIndex)
-                            .setCellValue(rowValue);
+                        .setCellValue(rowValue);
                 }
             }
         });
@@ -296,7 +307,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
         String tmpOptionsSheetName = OPTIONS_SHEET_NAME + "_" + currentOptionsColumnIndex;
         // 创建下拉数据表
         Sheet simpleDataSheet = Optional.ofNullable(workbook.getSheet(WorkbookUtil.createSafeSheetName(tmpOptionsSheetName)))
-                .orElseGet(() -> workbook.createSheet(WorkbookUtil.createSafeSheetName(tmpOptionsSheetName)));
+            .orElseGet(() -> workbook.createSheet(WorkbookUtil.createSafeSheetName(tmpOptionsSheetName)));
         // 将下拉表隐藏
         workbook.setSheetHidden(workbook.getSheetIndex(simpleDataSheet), true);
         // 完善纵向的一级选项数据表
@@ -304,10 +315,10 @@ public class ExcelDownHandler implements SheetWriteHandler {
             int finalI = i;
             // 获取每一选项行,如果没有则创建
             Row row = Optional.ofNullable(simpleDataSheet.getRow(i))
-                    .orElseGet(() -> simpleDataSheet.createRow(finalI));
+                .orElseGet(() -> simpleDataSheet.createRow(finalI));
             // 获取本级选项对应的选项列,如果没有则创建。上述采用多个sheet,默认索引为1列
             Cell cell = Optional.ofNullable(row.getCell(0))
-                    .orElseGet(() -> row.createCell(0));
+                .orElseGet(() -> row.createCell(0));
             // 设置值
             cell.setCellValue(value.get(i));
         }
@@ -319,10 +330,10 @@ public class ExcelDownHandler implements SheetWriteHandler {
         name.setNameName(nameName);
         // 以纵向第一列创建一级下拉拼接引用位置
         String function = String.format("%s!$%s$1:$%s$%d",
-                tmpOptionsSheetName,
-                getExcelColumnName(0),
-                getExcelColumnName(0),
-                value.size());
+            tmpOptionsSheetName,
+            getExcelColumnName(0),
+            getExcelColumnName(0),
+            value.size());
         // 设置名称管理器的引用位置
         name.setRefersToFormula(function);
         // 设置数据校验为序列模式,引用的是名称管理器中的别名
@@ -392,8 +403,8 @@ public class ExcelDownHandler implements SheetWriteHandler {
         int thisCircleColumnIndex = columnIndex % 26;
         // 26一循环的次数大于0,则视为栏名至少两位
         String columnPrefix = columnCircleCount == 0
-                ? StrUtil.EMPTY
-                : StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1);
+            ? StrUtil.EMPTY
+            : StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1);
         // 从26一循环内取对应的栏位名
         String columnNext = StrUtil.subWithLength(EXCEL_COLUMN_NAME, thisCircleColumnIndex, 1);
         // 将二者拼接即为最终的栏位名

+ 19 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-excel/src/main/java/com/vber/common/excel/core/ExcelOptionsProvider.java

@@ -0,0 +1,19 @@
+package com.vber.common.excel.core;
+
+import java.util.Set;
+
+/**
+ * Excel下拉选项数据提供接口
+ *
+ * @author Iwb
+ */
+public interface ExcelOptionsProvider {
+
+    /**
+     * 获取下拉选项数据
+     *
+     * @return 下拉选项列表
+     */
+    Set<String> getOptions();
+
+}