EasyExcel导出excel模板的几种解决方案

EasyExcel导出excel模板的几种解决方案

1、导出含有下拉框的excel

1.1、解决思路

​ excel下拉框包含两种情况,一种是固定内容的下拉框,一种是动态内容的下拉框,所以在设计的时候要考虑这两种情况。实现方式是通过自定义注解和自定义处理器的方式结合easyExcel进行模板下载,自定义注解应用到具体的字段中,在字段中传入相关参数,如果是固定内容的下拉框,则字段的参数直接传具体内容的数组即可,若是动态内容的下拉框则需要具体实现类以及数据类型,在实现类中通过参数来查询动态数据并以数组的方式返回。在注解解析工具类判断该字段是固定内容还是动态内容,并将内容进行解析和返回。在自定义处理器中将解析出的数据写入到一张sheet表中作为下拉框的数据源表,然后再隐藏,将下拉框数据设置到指定行列之后,统一设置下拉框表格除下拉列表意外的所有值都禁止输入。

1.2、核心代码实现

​ 自定义注解

/**
 * 动态下拉框注解
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelSelected {
   
    /**
     * 固定下拉内容
     */
    String[] source() default {
   };

    /**
     * 动态下拉内容
     */
    Class<? extends ExcelDynamicSelect>[] sourceClass() default {
   };

    /**
     * 参数
     *
     * @return
     */
    String params() default "";

    /**
     * 设置下拉框的起始行,默认为第二行
     */
    int firstRow() default 1;

    /**
     * 设置下拉框的结束行,默认为最后一行
     */
    int lastRow() default 0x10000;
}

注解解析工具类

/**
 * 解析下拉内容
 */
@Data
@Slf4j
public class ExcelSelectedResolveUtil {
   
    /**
     * 下拉内容
     */
    private String[] source;

    /**
     * 设置下拉框的起始行,默认为第二行
     */
    private int firstRow;

    /**
     * 设置下拉框的结束行,默认为最后一行
     */
    private int lastRow;

    public String[] resolveSelectedSource(ExcelSelected excelSelected) {
   
        if (excelSelected == null) {
   
            return null;
        }

        // 获取固定下拉框的内容
        String[] source = excelSelected.source();
        if (source.length > 0) {
   
            return source;
        }
        // 获取动态下拉框的内容
        Class<? extends ExcelDynamicSelect>[] classes = excelSelected.sourceClass();
        String params = excelSelected.params();
        if (classes.length > 0) {
   
            try {
   
                ExcelDynamicSelect excelDynamicSelect = classes[0].newInstance();
                String[] dynamicSelectSource = excelDynamicSelect.getSource(params);
                if (dynamicSelectSource != null && dynamicSelectSource.length > 0) {
   
                    return dynamicSelectSource;
                }
            } catch (InstantiationException | IllegalAccessException e) {
   
                log.error("解析动态下拉框数据异常", e);
            }
        }
        return null;
    }
}

easyExcel处理器

@Data
@AllArgsConstructor
public class SelectedSheetWriteHandler implements SheetWriteHandler {
   
    private final Map<Integer, ExcelSelectedResolveUtil> selectedMap;

    /**
     * 设置阈值,避免生成的导入模板下拉值获取不到,可自行设置数量大小
     */
    private static final Integer LIMIT_NUMBER = 30;

    /**
     * Called before create the sheet
     */
    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
   

    }

    /**
     * Called after the sheet is created
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
   
        // 这里可以对cell进行任何操作
        Sheet sheet = writeSheetHolder.getSheet();
        DataValidationHelper helper = sheet.getDataValidationHelper();
        selectedMap.forEach((k, v) -> {
   
            // 设置下拉列表的行: 首行,末行,首列,末列
            CellRangeAddressList rangeList = new CellRangeAddressList(v.getFirstRow(), v.getLastRow(), k, k);
            // 如果下拉值总数大于25,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到
            if (v.getSource().length > LIMIT_NUMBER) {
   
                //定义sheet的名称
                //1.创建一个隐藏的sheet 名称为 hidden + k
                String sheetName = "hidden" + k;
                Workbook workbook = writeWorkbookHolder.getWorkbook();
                Sheet hiddenSheet = workbook.createSheet(sheetName);
                for (int i = 0, length = v.getSource().length; i < length; i++) {
   
                    // 开始的行数i,列数k
                    hiddenSheet.createRow(i).createCell(k).setCellValue(v.getSource()[i]);
                }
                Name category1Name = workbook.createName();
                category1Name.setNameName(sheetName);
                String excelLine = getExcelLine(k);
                // =hidden!$H:$1:$H$50  sheet为hidden的 H1列开始H50行数据获取下拉数组
                String refers = "=" + sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.getSource().length + 1);
                // 将刚才设置的sheet引用到你的下拉列表中
                DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
                DataValidation dataValidation = helper.createValidation(constraint, rangeList);
                writeSheetHolder.getSheet().addValidationData(dataValidation);
                // 设置存储下拉列值得sheet为隐藏
                int hiddenIndex = workbook.getSheetIndex(sheetName);
                if (!workbook.isSheetHidden(hiddenIndex)

你可能感兴趣的:(java,excel)