poi中导入excel时,获取下拉选项、解析从子表引用的下拉选项

news2024/11/14 18:06:25

我们导入excel表,解析数据时,有的时候需要把单元格是下拉框的所有下拉项拿到,有的下拉项是直接在单元格里面添加的下拉列表,还有的下拉项则是从其它表引用过来的,如下图:

在这里插入图片描述

在这里插入图片描述

那我们要怎么读取这两种不同方式添加的下拉列表数据呢?

如果是在当前表的单元格里添加的下拉列表,获取方式则比较简单,poi有专门的方法可以拿到指定sheet的所有下拉列表。

如果是从别的表引用过来的,则比较麻烦,poi那个方法拿到的被引用过来的下拉列表,拿到的并不是那些下拉项,而是范围区域字符串。例如:Sheet1!$A$1:$A$3Sheet1!$F$1:$F$4Sheet1!$B$1:$E$1 是这样的字符串,这个时候就需要我们自己解析这串字符,并根据范围去取数据。

实现

/**
 * 获取下拉项
 */
public static Map<Integer,String> getSelectOption(Workbook workbook,Sheet sheet){
    Map<Integer,String> validations = new HashMap<>(); // 是下拉框的字段的列索引和下拉项(key为列索引,value为下拉项)
    // 通过正则表达式来解析引用的范围,获得被引用的sheet名和单元格范围
    // 这个正则表达式可以匹配包含中文、数字、字母、下划线的sheet名,但是不允许包含空格和其它特殊字符
    Pattern pattern = Pattern.compile("([^\\/:\\?\\*\\[\\]\\']+)!\\$(\\w+)\\$(\\d+)\\:\\$(\\w+)\\$(\\d+)");
    //DataValidationHelper validationHelper = sheet.getDataValidationHelper();
    // 获取下拉框数据
    for (DataValidation validation : sheet.getDataValidations()) {
        DataValidationConstraint constraint = validation.getValidationConstraint();
        CellRangeAddress cellRangeAddress = validation.getRegions().getCellRangeAddress(0);
        String selectOption = constraint.getFormula1().replaceAll("\"", "");
        Matcher matcher = pattern.matcher(selectOption);
        if (matcher.find()) {
            selectOption = selectOption(workbook,matcher,selectOption);
        }
        System.out.println("下拉数据:" + selectOption);
        validations.put(cellRangeAddress.getFirstColumn(),selectOption);
    }
    return headers;
}

/**
 * 解析子表引用的下拉选项
 */
public static String selectOption(Workbook workbook,Matcher matcher,String selectOption){
    String sheetName = matcher.group(1); // 被引用的sheet名称
    String startColumnName = matcher.group(2); // 开始的列名
    int startRowNum = Integer.parseInt(matcher.group(3)); // 开始的行号
    String endColumnName = matcher.group(4); // 结束的列名
    int endRowNum = Integer.parseInt(matcher.group(5)); // 结束的行号

    List<String> options = new ArrayList<>();
    Sheet child = workbook.getSheet(sheetName);
    if (startColumnName.equals(endColumnName)){ // 同一列不同行
        int colIndex = columnIndexFromName(startColumnName); // 获取列索引
        for (int rowNum = startRowNum - 1; rowNum < endRowNum; rowNum++) {
            Row row = child.getRow(rowNum);
            if (row != null) {
                Cell cell = row.getCell(colIndex);
                options.add(getCellValue(cell));
            }
        }
    }else if (!startColumnName.equals(endColumnName) && startRowNum == endRowNum){ // 同一行不同列
        Row row = child.getRow(startRowNum - 1); // 获取行索引
        int startColIndex = columnIndexFromName(startColumnName); // 获取开始的列索引
        int endColIndex = columnIndexFromName(endColumnName); // 获取结束的列索引
        for (int col = startColIndex; col <= endColIndex; col++) {
            Cell cell = row.getCell(col);
            options.add(getCellValue(cell));
        }
    }else {
        throw new ExceptionVo(-1,"下拉项的子表引用【 " + selectOption + " 】无法解析");
    }
    return StrUtil.join(",",options);
}

/**
 * 根据列名获取列索引
 */
public static int columnIndexFromName(String columnName) {
    int sum = 0;
    for (char ch : columnName.toCharArray()) {
        sum = sum * 26 + (ch - 'A' + 1);
    }
    return sum - 1; // 因为索引是从0开始的,而Excel的列名是从1开始的"感觉"
}

/**
 * 获取单元格的值
 */
public static String getCellValue(Cell cell){
    String cellValue = "";
    if (cell != null){
        switch (cell.getCellType()) {
            case STRING:
                cellValue = cell.getStringCellValue();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    // 处理日期类型
                    Date dateValue = cell.getDateCellValue();
                    // 这里你可以根据需要将日期转换为字符串或其他格式
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    cellValue = dateFormat.format(dateValue);
                } else {
                    cell.setCellType(CellType.STRING); // 将单元格内容以字符串形式获取
                    // 处理数值类型
                    //double numericValue = cell.getNumericCellValue();
                    //cellValue = String.valueOf(numericValue);
                    cellValue = cell.getStringCellValue();
                }
                break;
            // 其他类型的单元格可以根据需要进一步处理
            case BOOLEAN:
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case BLANK:
                // 处理空单元格
                cellValue = "";
                break;
            default:
                // 处理其他类型的单元格
                throw new ExceptionVo(-1,"不支持的单元格类型");
        }
    }
    return cellValue;
}

获取结果

在这里插入图片描述

这样我们就可以完美获取这些下拉数据啦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2097374.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 通过邮件合并(Mail Merge)批量生成Word文档

目录 使用工具 创建邮件合并模板 使用 Python 在 Word 中执行邮件合并 使用 Python 在 Word 中通过邮件合并一次性生成多个文档 使用 Python 获取 Word 中的合并域的名称 邮件合并是 Microsoft Word 中一项非常有用的功能&#xff0c;它让用户能够将事先设计好的模板与数据…

华为云征文 | 华为云Flexus云服务器X实例全面使用操作指南

文章目录 一、华为云Flexus云服务器X实例⛅华为云Flexus云服务器X实例特点☁️为什么选择华为云Flexus云服务器X实例&#xff1f;☀️基于业务负载&#xff0c;灵活调配产品价格 二、快速上手华为云Flexus云服务器X实例⚡注册华为云账号⌚进入Flexus云服务器X实例介绍页面⏰购买…

苹果手机怎么开定位?2个神操作,快速打开定位

网上一直流行着这样一句玩笑话&#xff1a;“出门不开定位导航&#xff0c;就会变成下一个失踪人口。” 这句话也从侧面反映出手机的定位服务对于大部分用户来说非常重要。那么&#xff0c;对于苹果用户来说&#xff0c;苹果手机怎么开定位呢&#xff1f;今天&#xff0c;小编…

利用固定窗口计数算法限流,精准控制第三方 API 调用频率

文章目录 使用场景使用固定窗口计数算法管理调用频率使用测试一秒钟执行五次适用场景 使用场景 在调用第三方 API 时&#xff0c;我们通常会在 API 文档中看到对接口访问频率的限制。为了确保不超出这些限制&#xff0c;使用限流算法来控制 API 调用频率是至关重要的。 在作为…

Spike-in:微生态16S扩增子绝对定量重磅上线!

16S扩增子测序是一种广泛应用于微生物群落分析的技术&#xff0c;主要用于研究环境样本中微生物的种类、丰度及其生态关系。 然而&#xff0c;传统的16S扩增子测序通常只能提供相对丰度数据&#xff0c;无法准确反映样本中各微生物的绝对数量&#xff0c;导致在一定程度上掩盖…

论文理解【LLM-agent】—— 【Reflexion】Language Agents with Verbal Reinforcement Learning

文章链接&#xff1a;Reflexion: Language Agents with Verbal Reinforcement Learning代码&#xff1a;GitHub - noahshinn/reflexion发表&#xff1a;NIPS 2023领域&#xff1a;LLM agent一句话总结&#xff1a;传统强化学习 Agent 通过和环境交互进行试错学习&#xff0c;但…

python-比身高

题目描述 班上有n个同学。现在同学们排成了一队&#xff0c;每个同学都想知道在自己前面有多少个同学比自己高。现在告诉你班上同学们排好队后每个同学的身高&#xff0c;请告诉每个人在他们前面有多少人比他们高。输入&#xff1a; 输入共两行。 第一行一个整数n。 第二行n个整…

实战|任意用户漏洞挖掘分享

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330&scene21#wechat_redirect 《网安面试指南》…

变压器电压调节

电压调节是衡量变压器在不同负载条件下维持恒定次级电压的能力的标准&#xff0c;因为输出次级电压可能不是我们所期望的。 当变压器的初级绕组通电时&#xff0c;它会产生次级电压和电流&#xff0c;其量由变压器匝数比 (TR) 决定。如果单相变压器的降压匝数比为 2:1&#xf…

【论文阅读】一种针对多核神经网络处理器的窃取攻击(2020)

摘要 攻击者可以通过侧信道信息(Side-channel)完成模型窃取攻击[17]. [17] Hua W Z, Zhang Z R, Suh G E. Reverse Engineering Convolutional Neural Networks through Side-channel Information Leaks[C]. 2018 55th ACM/ESDA/IEEE Design Automation Conference (DAC), 2018…

Large Language Models(LLMs) Concepts

1、Introduction to Large Language Models(LLM) 1.1、Definition of LLMs Large: Training data and resources.Language: Human-like text.Models: Learn complex patterns using text data. The LLM is considered the defining moment in the history of AI. Some appl…

HMI触屏网关-VISION如何与Modbus TCP从机通信

上文&#xff1a;HMI触屏网关-VISION如何与Modbus RTU从机通信-CSDN博客 1. 硬件连接 Modbus TCP协议采用网口通信的方式&#xff0c;因此&#xff0c;只需要保证网关的LAN口IP和Modbus TCP从机的IP在同一网段即可。 Modbus TCP从机参数说明&#xff1a; 2. VISION创建Modbu…

怎么将ts格式转mp4?必须掌握的4种视频转换方法

当今&#xff0c;视频格式转换变得愈发重要。当我们面对不太常见的ts格式&#xff0c;想要将其转换为更通用的mp4时&#xff0c;掌握正确的转换方法尤为关键。今天&#xff0c;我们将分享4种实现ts格式转mp4的必备方法。每一种方法都有其独特优势&#xff0c;满足不同需求。 我…

027、架构_资源_GTM

系统级GTM:默认的GTM,当创建分片集群时,如果不创建实例级GTM,则会用系统级GTM 本章节主要介绍GTM 集群的新增、删除、配置、绑定等管理操作。 新增GTM集群 摘要新增GTM集群,与租户相绑定,可查看绑定租户与配置集群参数设置,租户可重绑定其他正常可用的GTM集群。 步骤1.…

windows 编译libx264报错问题之解决

编译过程参考&#xff1a;Win10环境下 编译 和 运行 x264_x.264下载使用教程-CSDN博客 一、gcc not found 在https://www.msys2.org/ 下载Mingw后&#xff0c;安装 pacman -S mingw-w64-x86_64-gcc 安装完成后&#xff0c;执行gcc -v提示找不到gcc 解决办法&#xff1a; …

迎接开学第一天!请查收这份2024开学必备好物清单!

新的学期正悄然来临&#xff0c;开学第一天校园里即将迎来一张张充满朝气的面孔。无论是重返课堂的老生还是满怀期待的新生&#xff0c;开学季总是充满了新的希望与挑战。为了帮助学生们更好地适应即将到来的学习生活&#xff0c;我们精心准备了这份2024开学必备好物清单。从提…

Java提高篇——Java 异常处理

阅读目录 异常的概念异常的体系结构Java 异常的处理机制异常处理的基本语法异常链自定义异常总结 回到顶部 异常的概念 异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的。 比如说&#xff0c;你的代码少了一个分号&…

FreeRTOS指南 -- 基础知识

裸机 / OS 裸机编程&#xff1a;单任务系统的方式&#xff0c;框架是在main( )函数中循环的处理&#xff0c;实时性差&#xff0c;在大循环中再紧急的函数没轮到只能等着&#xff0c;虽然在中断中处理一些紧急任务&#xff0c;但是在大型嵌入式系统中&#xff0c;这样的单任务系…

深入探索MySQL数据库结构设计:实战案例解析,打造高效、可扩展的数据存储方案

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 前言&#xff1a;…

BERT 高频面试题八股文——基础知识篇

基础知识 1. 问&#xff1a;请简述自然语言处理(NLP)的主要研究目标是什么&#xff1f; 答&#xff1a;NLP的主要研究目标是使计算机能够理解、解释和生成人类语言。 2. 问&#xff1a;什么是BERT模型&#xff0c;它为什么重要&#xff1f; 答&#xff1a;BERT是一种预训练…