Apache Poi 实现Excel多级联动下拉框

这篇具有很好参考价值的文章主要介绍了Apache Poi 实现Excel多级联动下拉框。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

由于最近做的功能,需要将接口返回的数据列表,输出到excel中,以供后续导入,且网上现有的封装,使用起来都较为麻烦,故参考已有做法封装了工具类。

使用apache poi实现excel联动下拉框思路

  1. 创建隐藏单元格,存储下拉数据
  2. 创建名称管理器
  3. 使用indirect表达式进行联动

添加依赖

<!--Java程序对Microsoft Office格式档案读和写的功能-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.2</version>
</dependency>

直接上代码

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;

import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * excel验证工具类
 *
 * @author chenchuancheng github.com/meethigher
 * @since 2023/08/20 23:55
 */
public class ExcelValidationUtils {


    private static final int minRow = 1;

    private static final int maxRow = 100;

    private static final boolean debugHideSheet = true;


    /**
     * 创建一个xlsx
     *
     * @return {@link XSSFWorkbook}
     */
    public static XSSFWorkbook createOneXLSX() {
        return new XSSFWorkbook();
    }

    /**
     * 为xlsx添加一个sheet
     *
     * @param wb        xlsx
     * @param sheetName sheet名
     * @param headers   首行标题头
     * @return sheet
     */
    public static XSSFSheet addOneSheet(XSSFWorkbook wb, String sheetName, String[] headers) {
        XSSFSheet st = wb.createSheet(sheetName);
        //表头样式
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
        //字体样式
        Font fontStyle = wb.createFont();
        fontStyle.setFontName("微软雅黑");
        fontStyle.setFontHeightInPoints((short) 12);
        style.setFont(fontStyle);
        //单元格格式为文本
        XSSFDataFormat format = wb.createDataFormat();
        style.setDataFormat(format.getFormat("@"));
        //写标题
        XSSFRow row = st.createRow(0);
        st.createFreezePane(0, 1, 0, 1);
        for (int i = 0; i < headers.length; i++) {
            String value = headers[i];
            XSSFCell cell = row.createCell(i);
            st.setColumnWidth(i, value.length() * 1000);
            cell.setCellStyle(style);
            st.setDefaultColumnStyle(i, style);
            cell.setCellValue(value);
        }
        return st;
    }


    /**
     * 添加两层级联数据
     *
     * @param wb                  xlsx
     * @param targetSheet         目标sheet
     * @param linkageData         两层级联数据
     * @param parentCol           父列
     * @param childCol            孩子列
     * @param parentColIdentifier 父列标识符
     * @return {@link XSSFSheet}
     */
    public static XSSFSheet addLinkageDataValidation(XSSFWorkbook wb, XSSFSheet targetSheet, Map<String, List<String>> linkageData,
                                                     int parentCol, int childCol, String parentColIdentifier) {
        XSSFSheet hideSt = wb.createSheet();
        wb.setSheetHidden(wb.getSheetIndex(hideSt), !debugHideSheet);
        int rowId = 0;
        Set<String> keySet = linkageData.keySet();
        for (String parent : keySet) {
            List<String> sonList = linkageData.get(parent);
            XSSFRow row = hideSt.createRow(rowId++);
            row.createCell(0).setCellValue(parent);
            for (int i = 0; i < sonList.size(); i++) {
                XSSFCell cell = row.createCell(i + 1);
                cell.setCellValue(sonList.get(i));
            }
            // 添加名称管理器,1表示b列,从b列开始往后,都是子级
            String range = getRange(1, rowId, sonList.size());
            Name name = wb.createName();
            name.setNameName(parent);
            String formula = hideSt.getSheetName() + "!" + range;
            name.setRefersToFormula(formula);
        }
        //创建表达式校验
        XSSFDataValidationHelper helper = new XSSFDataValidationHelper(targetSheet);

//        //父级校验,如需生成更多,用户手动拖拽下拉即可。此操作会导致数组内容总长度超过255时报错
//        DataValidation parentValidation = helper.createValidation(helper.createExplicitListConstraint(keySet.toArray(new String[0])),
//                new CellRangeAddressList(minRow, maxRow, parentCol, parentCol));
//        parentValidation.createErrorBox("错误", "请选择正确的父级类型");
//        parentValidation.setShowErrorBox(true);
//        parentValidation.setSuppressDropDownArrow(true);
//        targetSheet.addValidationData(parentValidation);

        //解决长度为255的问题
        Name name = wb.createName();
        name.setNameName(hideSt.getSheetName());
        name.setRefersToFormula(hideSt.getSheetName() + "!$A$1:$A$" + keySet.size());
        DataValidation parentValidation = helper.createValidation(helper.createFormulaListConstraint(hideSt.getSheetName()), new CellRangeAddressList(minRow, maxRow, parentCol, parentCol));
        parentValidation.createErrorBox("错误", "请选择正确的父级类型");
        parentValidation.setShowErrorBox(true);
        targetSheet.addValidationData(parentValidation);

        //子级校验,如需生成更多,用户手动拖拽下拉即可
        for (int i = minRow; i < maxRow; i++) {
            DataValidation childValidation = helper.createValidation(helper.createFormulaListConstraint("INDIRECT(" + parentColIdentifier + "" + (i + 1) + ")"),
                    new CellRangeAddressList(i, i, childCol, childCol));
            childValidation.createErrorBox("错误", "请选择正确的子级类型");
            childValidation.setShowErrorBox(true);
            childValidation.setSuppressDropDownArrow(true);
            targetSheet.addValidationData(childValidation);
        }

        return hideSt;
    }

    /**
     * 添加简单下拉列表验证-下拉列表总内容不超过255字符
     *
     * @param st           sheet
     * @param dropDownList 下拉列表数据
     * @param firstCol     开始列,从0开始
     * @param lastCol      结束列,从0开始
     */
    public static void addSimpleDropDownListValidation(XSSFSheet st, String[] dropDownList, int firstCol, int lastCol) {
        XSSFDataValidationHelper helper = new XSSFDataValidationHelper(st);
        XSSFDataValidationConstraint constraint = (XSSFDataValidationConstraint) helper.createExplicitListConstraint(dropDownList);
        CellRangeAddressList addressList = new CellRangeAddressList(minRow, maxRow, firstCol, lastCol);
        XSSFDataValidation validation = (XSSFDataValidation) helper.createValidation(constraint, addressList);
        validation.setSuppressDropDownArrow(true);
        validation.setShowErrorBox(true);
        st.addValidationData(validation);
    }


    /**
     * 添加复杂下拉列表验证-下拉列表总内容允许超过255字符
     *
     * @param wb           xlsx
     * @param dropDownList 下拉列表数据
     * @param firstCol     开始列,从0开始
     * @param lastCol      结束列,从0开始
     */
    public static void addComplexDropDownListValidation(XSSFWorkbook wb, XSSFSheet st, String[] dropDownList, int firstCol, int lastCol) {
        XSSFSheet hideSt = wb.createSheet();
        wb.setSheetHidden(wb.getSheetIndex(hideSt), !debugHideSheet);
        XSSFDataValidationHelper helper = new XSSFDataValidationHelper(st);
        for (int i = 0, length = dropDownList.length; i < length; i++) {
            String value = dropDownList[i];
            XSSFRow row = hideSt.createRow(i);
            XSSFCell cell = row.createCell(0);
            cell.setCellValue(value);
        }
        //解决长度为255的问题
        Name name = wb.createName();
        name.setNameName(hideSt.getSheetName());
        name.setRefersToFormula(hideSt.getSheetName() + "!$A$1:$A$" + dropDownList.length);
        DataValidation parentValidation = helper.createValidation(helper.createFormulaListConstraint(hideSt.getSheetName()), new CellRangeAddressList(minRow, maxRow, firstCol, lastCol));
        parentValidation.createErrorBox("错误", "请选择正确的类型");
        parentValidation.setShowErrorBox(true);
        st.addValidationData(parentValidation);
    }


    /**
     * 计算formula
     *
     * @param offset   偏移量,如果给0,表示从A列开始,1,就是从B列
     * @param rowId    第几行
     * @param colCount 一共多少列
     * @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1
     */
    private static 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', endSuffix;
            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;
        }
    }
}

使用示例

public class TestExportExcelWithValidation {


    private final static String[] headers = new String[]{
            "性别",
            "省",
            "市",
            "区",
    };


    private static Map<String, List<String>> 省级() {
        Map<String, List<String>> map = new HashMap<>();
        map.put("湖北省", Arrays.asList("武汉市", "襄阳市"));
        map.put("吉林省", Arrays.asList("长春市", "吉林市"));
        return map;
    }

    private static Map<String, List<String>> 市级() {
        Map<String, List<String>> map = new HashMap<>();
        map.put("武汉市", Arrays.asList("洪山区", "江夏区"));
        map.put("长春市", Arrays.asList("宽城区", "南关区"));
        return map;
    }

    public static void main(String[] args) throws Exception {
        XSSFWorkbook wb = createOneXLSX();
        XSSFSheet st = addOneSheet(wb, "data", headers);
        addSimpleDropDownListValidation(st, new String[]{"男", "女"}, 0, 0);
        addLinkageDataValidation(wb, st, 省级(), 1, 2, "B");
        addLinkageDataValidation(wb, st, 市级(), 2, 3, "C");


        wb.write(new FileOutputStream("aaa.xlsx"));
    }
}

最终结果展示如图

Apache Poi 实现Excel多级联动下拉框,apache,excel文章来源地址https://www.toymoban.com/news/detail-675359.html

到了这里,关于Apache Poi 实现Excel多级联动下拉框的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • EasyExcel+POI制作带有有效性校验及下拉联动的Excel模板

    最近在做一个CRM系统的人员销售目标导入的相关需求,需要将销售人员的目标导入到系统中,就要求在Excel导入模板中 填写销售人员Id 和销售人员姓名。在使用的时候,这是一个易错的点,因为这两个字段交给了使用者去自由填写的话,是很容易填错的。除了文字本身填多填

    2024年02月11日
    浏览(42)
  • 苍穹外卖集成 Apache POI Java实现Excel文件的读写下载

    Apache POI - the Java API for Microsoft Documents Project News 16 September 2022 - POI 5.2.3 available The Apache POI team is pleased to announce the release of 5.2.3. Several dependencies were updated to their latest versions to pick up security fixes and other improvements. A summary of changes is available in the Release Notes. A full list of changes is a

    2024年02月09日
    浏览(58)
  • Apache POI 导出Excel报表

    大家好我是苏麟 , 今天聊聊Apache POI . 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下,POI 都是用于操作 Excel 文件。 官网 : Apache POI - the Java API for Microsoft Do

    2024年01月17日
    浏览(44)
  • Apache POI Excel的读写

    Apache POI是用Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java程 序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文 件。 jxl:专门操作Excel maven坐标: POI结构: 2.1   从 Excel 文件读取数据 使用POI可以从一个已经存在的Excel文件中读取数据

    2024年03月12日
    浏览(48)
  • Apache POI操作Excel文件

            Apache POI是用Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用 POI操作Excel文件 。 POI结构: 我们使用:XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能 POI操作Excel表格封装了几个核心

    2024年02月10日
    浏览(66)
  • Apache POI 以及 导出Excel表

    Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下,POI 都是用于操作 Excel 文件。 导依赖 将数据写入Excel文件 读取Excel文件数据 学习

    2024年02月11日
    浏览(39)
  • Apache POI 操作Excel常用方法

    一、Java使用Apache POI导出excel 二、Apache POI 操作Excel常用方法 三、Apache poi 拆分单元格并赋值 四、使用easypoi模板方法导出excel 五、Apache poi给excel单元格添加下拉框或数据验证 POI提供了HSSF、XSSF以及SXSSF三种方式操作Excel。 HSSF:Excel97-2003版本,扩展名为.xls。一个sheet最大行数6

    2024年02月09日
    浏览(54)
  • 基于Apache POI-操作Excel数据-读写

    实现: 读(获取) 写(导入) 2.1 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下,POI 都是用于操作 Excel 文件。 Apache POI 的应用场景: 银行网银系统导出交

    2024年01月16日
    浏览(39)
  • Apache POI 解析复杂的excel表格

    一:场景说明        最近接到一个需求,让我解析Excel表。这要是简单常规的Excel表,那我还能摸一摸鱼给他整出来,主要是给我的Excel表长得跟下图中的Excel表一样复杂难搞,这可把我难倒了。于是开启了我的百度之旅,有可能是我不会百度或者理解能力太差,反正就是

    2024年02月04日
    浏览(42)
  • Apache POI | Java操作Excel文件

    目录 1、介绍 2、代码示例 2.1、将数据写入Excel文件 2.2、读取Excel文件中的数据 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。 🦅主页:@逐梦苍穹 📕您的一

    2024年02月20日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包