Java技术栈2024-10-23 · 约 10 分钟

Springboot中解决EasyExcel导出的下拉框总字符超过255就打不开

陈34 阅读2 赞0 评论最后更新 2026-09-16

1. 自定义SheetWriteHandler

java 复制代码
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;

import java.util.Map;

/**
 * 多列需要下拉框用Map来装数据,key为需要下拉框的列,value为该列下拉框的值;这里设置了序号为1到5000的行需要下拉框;
 */
public class CustomSheetWriteHandler implements SheetWriteHandler {

    private Map<Integer, String[]> map;
    private int index;

    public CustomSheetWriteHandler(Map<Integer, String[]> map) {
        this.map = map;
        this.index = 0;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();

        // k 为存在下拉数据集的单元格下表 v为下拉数据集
        map.forEach((k, v) -> {
            // 创建sheet,突破下拉框255的限制
            // 获取一个workbook
            Workbook workbook = writeWorkbookHolder.getWorkbook();
            // 定义sheet的名称
            String sheetName = "sheet" + k;
            // 1.创建一个隐藏的sheet 名称为 proviceSheet
            Sheet proviceSheet = workbook.createSheet(sheetName);
            // 从第二个工作簿开始隐藏
            this.index++;
            // 设置隐藏
            workbook.setSheetHidden(this.index, true);
            // 2.循环赋值(为了防止下拉框的行数与隐藏域的行数相对应,将隐藏域加到结束行之后)
            for (int i = 0, length = v.length; i < length; i++) {
                // i:表示你开始的行数 0表示你开始的列数
                proviceSheet.createRow(i).createCell(0).setCellValue(v[i]);
            }
            Name category1Name = workbook.createName();
            category1Name.setNameName(sheetName);
            // 4 $A$1:$A$N代表 以A列1行开始获取N行下拉数据
            category1Name.setRefersToFormula(sheetName + "!$A$1:$A$" + (v.length));
            // 5 将刚才设置的sheet引用到你的下拉列表中,1表示从行的序号1开始(开始行,通常行的序号为0的行是表头),5000表示行的序号5000(结束行),表示从行的序号1到5000,k表示开始列序号和结束列序号
            CellRangeAddressList addressList = new CellRangeAddressList(1, 5000, k, k);
            DataValidationConstraint constraint = helper.createFormulaListConstraint(sheetName);
            DataValidation dataValidation = helper.createValidation(constraint, addressList);

            dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
            dataValidation.setShowErrorBox(true);
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.createErrorBox("提示", "请输入下拉选项中的内容");
            writeSheetHolder.getSheet().addValidationData(dataValidation);

        });
    }
}

2. 具体用法

java 复制代码
@Override
public void templateDownload() {
    HashMap<Integer, String[]> map = new HashMap<>();
    //性别
    String[] genders = {"男", "女"};
    map.put(3, genders);

    //身份
    List<UserIdentity> identityList = getIdentityList();
    String[] identityNames = identityList.stream().map(UserIdentity::getName).toArray(String[]::new);
    map.put(4, identityNames);

     try {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + "downloadTemplate.xlsx");
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        WriteSheet sheet = EasyExcel
                .writerSheet("全部")
                .registerWriteHandler(new CustomSheetWriteHandler(map))
                .head(ExcelObjectTemplate.class).build();

        List<ExcelObjectTemplate> list = Arrays.asList(new ExcelObjectTemplate());
        excelWriter.write(list, sheet).finish();
    } catch (Exception e) {
        log.error("下载模板异常,{}", e.getMessage());
    }
}
觉得有用就点个赞吧
评论 0 条
0 / 300
还没有评论,来说第一句吧