EasyExcel导出设置下拉框和隐藏列

该文章已生成可运行项目,
        TimeInterval timer = DateUtil.timer();
        String fileName = "import_clue_template_" + TimeUtil.getDateTimeString() + ".xlsx";
        // 默认中文
        String language = servletResponse.getHeader("Accept-Language");
        String lang = StringUtils.isEmpty(language) ? "zh" : language.substring(0, 2);
        ExcelUtils.excelWriteResponse(fileName, servletResponse);
        EasyExcel.write(servletResponse.getOutputStream(), ClueImportExcelVO.class)
                .registerWriteHandler(new ExcelTitleHandler(this.getDropDownMap(), new int[]{10, 11}))
                .head(ExcelUtils.chooseLang(ClueImportExcelVO.class, lang))
                .sheet(fileName)
                .doWrite(ListUtil.toList());
        log.info("下载导入模板,花费{}毫秒", timer.intervalMs());
@Slf4j
public class ExcelTitleHandler implements SheetWriteHandler {

    /**
     * 下拉框值
     */
    private final Map<Integer, String[]> dropDownMap;

    private final int[] hideIndex;

    private final char[] alphabet = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

    /**
     * dropDownMap key 列索引从 0 开始 value 下拉框的值
     * hideIndex 需要隐藏的列索引从 0 开始
     **/
    public ExcelTitleHandler(Map<Integer, String[]> dropDownMap, int[] hideIndex) {
        this.dropDownMap = dropDownMap;
        this.hideIndex = hideIndex;
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 需要设置的sheet页
        Sheet sheet = writeSheetHolder.getSheet();

        for (int index : hideIndex) {
            sheet.setColumnHidden(index, true);
        }

        if (dropDownMap == null || dropDownMap.isEmpty()) {
            return;
        }

        //设置下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();

        for (Map.Entry<Integer, String[]> entry : dropDownMap.entrySet()) {
            //定义sheet的名称
            String hiddenName = "hidden" + entry.getKey();
            //1.创建一个隐藏的sheet 名称为 hidden
            Workbook workbook = writeWorkbookHolder.getWorkbook();
            Sheet hidden = workbook.createSheet(hiddenName);
            Name category1Name = workbook.createName();
            category1Name.setNameName(hiddenName);
            //下拉框的起始行(第2行,索引从0开始),结束行(Excel最大行1048575),起始列,结束列  
            CellRangeAddressList addressList = new CellRangeAddressList(1, 1048575, entry.getKey(), entry.getKey());
            //获取excel列名
            String excelLine = getExcelColumn(entry.getKey());
            //2.循环赋值
            String[] values = entry.getValue();
            for (int i = 0, length = values.length; i < length; i++) {
                // 3:表示你开始的行数  3表示 你开始的列数
                Row row = hidden.getRow(i);
                if (row == null) {
                    row = hidden.createRow(i);
                }
                row.createCell(entry.getKey()).setCellValue(values[i]);
            }
            //4.  =hidden!$H:$1:$H$50  sheet为hidden的 H1列开始H50行数据获取下拉数组
            String refers = "=" + hiddenName + "!$" + excelLine + "$1:$" + excelLine + "$" + (values.length);
            //5 将刚才设置的sheet引用到你的下拉列表中
            DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
            DataValidation dataValidation = helper.createValidation(constraint, addressList);
            // 阻止输入非下拉选项的值
            dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
            dataValidation.setShowErrorBox(true);
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.createErrorBox("title", "formal error");
            writeSheetHolder.getSheet().addValidationData(dataValidation);
            //设置列为隐藏
            int hiddenIndex = workbook.getSheetIndex(hiddenName);
            if (!workbook.isSheetHidden(hiddenIndex)) {
                workbook.setSheetHidden(hiddenIndex, true);
            }
        }
    }

    /**
     * 将数字列转化成为字母列
     */
    private String getExcelColumn(int num) {
        String nullStr = "";
        String column;
        int len = alphabet.length - 1;
        int first = num / len;
        int second = num % len;
        if (num <= len) {
            column = alphabet[num] + nullStr;
        } else {
            column = alphabet[first - 1] + nullStr;

            column = second == 0 ? column + alphabet[len] + nullStr : column + alphabet[second - 1] + nullStr;
        }
        return column;
    }

}

本文章已经生成可运行项目
<think> 嗯,用户询问的是使用EasyExcel导出下拉框选项的Excel模板的实现方法。根据提供的引用,特别是引用[1][2],需要解决下拉框选项过多的问题,因为Excel本身有限制:当选项超过255个字符时会出错。解决方案是将下拉框内容存储在另一个Sheet页,然后通过公式引用这些内容。 接下来考虑实现步骤。首先,创建两个Sheet:一个用于存储下拉数据的隐藏Sheet,另一个是用户可见的主Sheet。引用[1]提到避免直接使用超过255字符的字符串,而是用INDIRECT函数引用另一个Sheet的数据。例如,如果隐藏Sheet的名字是"DataSheet",下拉内容在A1到A100,那么数据验证的公式应该是=INDIRECT("DataSheet!$A$1:$A$100")。 然后,处理EasyExcel的依赖。根据引用[2],需要添加Maven依赖,版本是2.2.7。在代码中,要使用WriteSheetWriteTable来分别处理不同Sheet的写入。主Sheet的数据验证需要设置DataValidation对象,其验证条件为公式,指向隐藏Sheet的单元格范围。 需要注意的细节是隐藏Sheet的名称不能有空格,否则公式引用可能会出错。另外,当选项数量很大时,确保隐藏Sheet的行数足够,避免数据截断。测试时,验证下拉框是否正常显示,特别是当选项超过50个的情况是否被正确处理。 用户可能的问题包括:如何处理动态的下拉选项?这时可以在隐藏Sheet中预先留出足够行数,或者通过程序动态写入数据。导出后打开文件若下拉不显示,可能是公式错误或Sheet名称不匹配,需要检查INDIRECT函数中的引用路径是否正确。 最后,总结关键点:分离存储引用、使用公式避免长度限制、正确配置EasyExcel的写入结构。这样用户就能实现支持大量选项的下拉框模板了。 </think> 根据引用内容及EasyExcel特性,以下是实现带下拉框Excel模板的完整方案: ### 核心实现步骤 1. **解决下拉选项超限问题** Excel限制单个下拉框选项总字符数≤255。解决方案: ```java // 1. 创建隐藏Sheet存储下拉数据 WriteSheet dataSheet = EasyExcel.writerSheet("选项数据").build(); List<List<String>> options = Arrays.asList(Collections.singletonList("选项1"), ...); excelWriter.write(options, dataSheet); // 写入50+选项到隐藏Sheet // 2. 在主Sheet设置数据验证(引用隐藏Sheet) DataValidation validation = new DataValidation( new CellRangeAddressList(0, 1000, 0, 0), // 下拉范围:A1-A1000 new FormulaDataValidationConstraint("选项数据!$A$1:$A$" + options.size()) // 公式引用 ); WriteSheet mainSheet = EasyExcel.writerSheet("主表") .registerWriteHandler(new DataValidationHelper(validation)) .build(); ``` 2. **完整Maven依赖配置** ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> <!-- 推荐最新版 --> </dependency> ``` 3. **关键实现类说明** | 类名 | 作用 | |----------------------|-----------------------------| | `DataValidation` | 定义数据验证规则 | | `FormulaDataValidationConstraint` | 通过公式引用外部数据 | | `CellRangeAddressList` | 指定下拉框生效的单元格范围 | ### 注意事项 1. 公式引用时需确保: ```java // 正确格式:"Sheet名称!$开始$开始行:$结束$结束行" new FormulaDataValidationConstraint("选项数据!$A$1:$A$100") ``` 2. 隐藏Sheet命名**禁止包含空格**(如`选项数据`正确,`选项 数据`错误)[^1] 3. 当选项超1000个时,需拆分到多: ```java // 在隐藏Sheet横向扩展选项 List<List<String>> multiColOptions = Arrays.asList( Arrays.asList("选项1", "选项501"), // 第一行 Arrays.asList("选项2", "选项502") // 第二行 ); ``` ### 完整代码示例 ```java // 创建Excel写入器 ExcelWriter excelWriter = EasyExcel.write("template.xlsx").build(); // 1. 写入隐藏Sheet(存储选项) List<List<String>> options = new ArrayList<>(); for (int i = 1; i <= 200; i++) { options.add(Collections.singletonList("选项" + i)); } excelWriter.write(options, EasyExcel.writerSheet("选项数据").build()); // 2. 配置主Sheet下拉框 DataValidation validation = new DataValidation( new CellRangeAddressList(1, 999, 0, 0), // A1-A999 new FormulaDataValidationConstraint("选项数据!$A$1:$A$200") ); validation.setShowErrorBox(true); // 显示错误提示 // 3. 写入主Sheet List<List<String>> mainData = new ArrayList<>(); excelWriter.write(mainData, EasyExcel.writerSheet("主表") .registerWriteHandler(new DataValidationHelper(Collections.singletonList(validation))) .build() ); excelWriter.finish(); ``` ### 效果验证 导出后打开Excel: 1. 主表A单元格显示下拉箭头 2. 右键隐藏Sheet标签→取消隐藏,可查看存储的选项数据 3. 修改隐藏Sheet的选项值,主表下拉内容实时更新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值