easyExcel单一下拉框和级联下拉框

文章目录:

  • 单一下拉框
  • 级联下拉框

具体实现:

  • 单一下拉框
java 复制代码
public class BoolWriteHandler implements SheetWriteHandler {

    private List<String> dropDown;

    private List<Integer> indexList;

    public BoolWriteHandler(List<Integer> indexList,List<String> dropDown) {
        this.indexList = indexList;
        this.dropDown =dropDown;
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 定义一个map key是需要添加下拉框的列的index value是下拉框数据
        Map<Integer, String[]> mapDropDown = new HashMap<>(2);
        //下拉选项
        String[] downArray = dropDown.toArray(new String[dropDown.size()]);
        //下拉选在Excel中对应的列
        for (Integer index : indexList) {
            mapDropDown.put(index, downArray);
        }
        // 获取Sheet表
        Sheet st = writeSheetHolder.getSheet();
        //设置下拉框
        DataValidationHelper helper = st.getDataValidationHelper();
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
            // 起始行、终止行、起始列、终止列  起始行为1即表示表头不设置
            CellRangeAddressList addressList = new CellRangeAddressList(1, 999, entry.getKey(), entry.getKey());
            // 设置下拉框数据 (设置长度为0的数组会报错,所以这里需要判断)
            if (entry.getValue().length > 0) {
                //创建显式列表约束
                DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
                // 指定行列约束以及错误信息
                setValidation(st,helper,constraint,addressList,"提示","请选择下拉框中的值");
            }
        }
    }

    }
java 复制代码
	/**
	 * 字段校验
	 */
    private void setValidation(Sheet sheet, DataValidationHelper helper, DataValidationConstraint constraint, CellRangeAddressList addressList, String msgHead, String msgContext) {
        DataValidation dataValidation = helper.createValidation(constraint, addressList);
        dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
        dataValidation.setShowErrorBox(true);
        dataValidation.setSuppressDropDownArrow(true);
        dataValidation.createErrorBox(msgHead, msgContext);
        sheet.addValidationData(dataValidation);
  • 级联下拉框

  • 2级级联

java 复制代码
public class CascadeWriteHandler implements SheetWriteHandler {
    private static 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'};
    private List<String> dropDown;
    private List<String> cityList;
    Map<String, List<String>> cityCountyMap;

    private Integer provinceIndex;

    private Integer cityIndex;

    private Integer countyIndex;

    public CascadeWriteHandler(List<String> dropDown, List<String> cityList, Map<String, List<String>> cityCountyMap,Integer provinceIndex,Integer cityIndex,Integer countyIndex) {
        this.dropDown =dropDown;
        this.cityList = cityList;
        this.cityCountyMap = cityCountyMap;
        this.provinceIndex = provinceIndex;
        this.cityIndex = cityIndex;
        this.countyIndex = countyIndex;
    }

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

        // 省份固定
        // 定义一个map key是需要添加下拉框的列的index value是下拉框数据
        Map<Integer, String[]> mapDropDown = new HashMap<>(2);
        //下拉选项
        String[] downArray = dropDown.toArray(new String[dropDown.size()]);
        //下拉选在Excel中对应的列
        mapDropDown.put(provinceIndex, downArray);
        // 获取Sheet表
        Sheet st = writeSheetHolder.getSheet();
        //设置下拉框
        DataValidationHelper helper = st.getDataValidationHelper();
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
            // 起始行、终止行、起始列、终止列  起始行为1即表示表头不设置
            CellRangeAddressList addressList = new CellRangeAddressList(1, 999, entry.getKey(), entry.getKey());
            // 设置下拉框数据 (设置长度为0的数组会报错,所以这里需要判断)
            if (entry.getValue().length > 0) {
                //创建显式列表约束
                DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
                // 指定行列约束以及错误信息
                setValidation(st,helper,constraint,addressList,"提示","请选择下拉框中的值",true);
            }
        }

        //市区与县的级联关系
        Sheet sheet = writeSheetHolder.getSheet();
        Workbook book = writeWorkbookHolder.getWorkbook();
        //创建隐藏的sheet
        Sheet hideSheet = book.createSheet("site");
        book.setSheetHidden(book.getSheetIndex(hideSheet), true);
        int rowId = 0;
        Row cityRow = hideSheet.createRow(rowId++);
        cityRow.createCell(0).setCellValue("市区行");
        //放置市数据
        for (int i = 0; i < cityList.size(); i++) {
            Cell proviCell = cityRow.createCell(i + 1);
            proviCell.setCellValue(cityList.get(i));
        }

        //放置区数据
        Iterator<String> keyIterator = this.cityCountyMap.keySet().iterator();
        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            List<String> son = cityCountyMap.get(key);

            Row row = hideSheet.createRow(rowId++);
            row.createCell(0).setCellValue(key);
            for (int i = 0; i < son.size(); i++) {
                Cell cell = row.createCell(i + 1);
                cell.setCellValue(son.get(i));
            }

            //级联数据
            String range = getRange(1, rowId, son.size());
            Name name = book.createName();
            name.setNameName("_" + key);
            String formula = "site!" + range;
            name.setRefersToFormula(formula);
        }
        ///开始设置下拉框
        DataValidationHelper dvHelper = sheet.getDataValidationHelper();
        // 市下拉框
        DataValidationConstraint expConstraint = dvHelper.createExplicitListConstraint(cityList.toArray(new String[]{}));
        CellRangeAddressList expRangeAddressList = new CellRangeAddressList(1, 999, cityIndex, cityIndex);
        setValidation(sheet, dvHelper, expConstraint, expRangeAddressList, "提示", "请选择下拉框中的值",true);


        // 区规则
        // "INDIRECT($A$" + 2 + ")" 表示规则数据会从名称管理器中获取key与单元格 A2 值相同的数据,如果A2是浙江省,那么此处就是浙江省下面的市
        // 为了让每个单元格的公式能动态适应,使用循环挨个给公式。
        // 循环几次,就有几个单元格生效,次数要和上面的大类影响行数一一对应,要不然最后几个没对上的单元格实现不了级联
        for (int i = 2; i < 1000; i++) {
            CellRangeAddressList rangeAddressList = new CellRangeAddressList(i-1 , i-1, countyIndex, countyIndex);
            DataValidationConstraint formula = dvHelper.createFormulaListConstraint("INDIRECT(\"_\"&$"+getExcelColumn(countyIndex-1)+"$"+i+")");
            setValidation(sheet, dvHelper, formula, rangeAddressList, "提示", "请选择下拉框中的值",false);
        }
    }

代码过程说明:

1.创建一个隐藏的级联site表
想看隐藏sheet,只需true改为false

java 复制代码
    Sheet hideSheet = book.createSheet("site");
    book.setSheetHidden(book.getSheetIndex(hideSheet), true);

2.创建名称管理器

  • 以市为key,即为名称管理器的名称
    踩坑: 如果key为数字,则会提示名称管理器的名称不能以数字开头; 解决方案:数字前加下划线"_"
    踩坑:
    如果key为数字,则会提示名称管理器的名称不能以数字开头;
    解决方案:数字前加下划线"_",此时"INDIRECT"函数中必须加前缀: "下划线"&,而且下划线必须用双引号!!
java 复制代码
    String range = getRange(1, rowId, son.size());
    Name name = book.createName();
    name.setNameName("_" + key);
    String formula = "site!" + range;
    name.setRefersToFormula(formula);

3.填充级联数据

  • 1000代表1000行生效级联关系,可自行修改。
java 复制代码
    for (int i = 2; i < 1000; i++) {
        CellRangeAddressList rangeAddressList = new CellRangeAddressList(i-1 , i-1, countyIndex, countyIndex);
        DataValidationConstraint formula = dvHelper.createFormulaListConstraint("INDIRECT(\"_\"&$"+getExcelColumn(countyIndex-1)+"$"+i+")");
        setValidation(sheet, dvHelper, formula, rangeAddressList, "提示", "请选择下拉框中的值",false);
    }
  • 工具类:
    计算区域方法:
java 复制代码
    /**
     * @param offset   偏移量,如果给0,表示从A列开始,1,就是从B列
     * @param rowId    第几行
     * @param colCount 一共多少列
     * @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1
     */
    public String getRange(int offset, int rowId, int colCount) {
        char start = (char) ('A' + offset);
        if (colCount <= 25) {
            char end = (char) (start + colCount - 1);
            return "$" + start + "$" + rowId + ":$" + end + "$" + rowId;
        } else {
            char endPrefix = 'A';
            char endSuffix = 'A';
            if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之间,包括边界(仅两次字母表计算)
                if ((colCount - 25) % 26 == 0) {// 边界值
                    endSuffix = (char) ('A' + 25);
                } else {
                    endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
                }
            } else {// 51以上
                if ((colCount - 25) % 26 == 0) {
                    endSuffix = (char) ('A' + 25);
                    endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1);
                } else {
                    endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
                    endPrefix = (char) (endPrefix + (colCount - 25) / 26);
                }
            }
            return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId;
        }
    }

计算列编码:

java 复制代码
    private static String getExcelColumn(int num) {
        String column = "";
        int len = alphabet.length - 1;
        int first = num / len;
        int second = num % len;
        if (num <= len) {
            column = alphabet[num] + "";
        } else {
            column = alphabet[first - 1] + "";
            if (second == 0) {
                column = column + alphabet[len] + "";
            } else {
                column = column + alphabet[second - 1] + "";
            }
        }
        return column;
    }
相关推荐
c++之路20 分钟前
C++23概述
java·c++·c++23
专注API从业者1 小时前
Open Claw 京东商品监控选品实战:一键抓取、实时监控、高效选品
java·服务器·数据库
摇滚侠2 小时前
DBeaver 导入数据库 导入 SQL 文件 MySQL 备份恢复
java·数据库·mysql
keep one's resolveY2 小时前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克32 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠3 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌3 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局3 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源4 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it4 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java