【探讨】Java POI 处理 Excel 中的名称管理器

news2024/11/16 6:53:12

前言

最近遇到了一些导表的问题。原本的导表工具导不了使用名称管理器的Excel。
首先我们有两个Sheet。B1用的是名称管理器中的AAA, 而B2用的对应的公式。
在这里插入图片描述
在这里插入图片描述
第二个sheet,名为Test2:
在这里插入图片描述

这是一段简化的代码:

public class Main {
    public static void main(String[] args) {
        var inputFile = new File("src/main/java/poi/test.xlsx");
        var dataFormatter = new DataFormatter();
        try (var wb = new XSSFWorkbook(new FileInputStream(inputFile))) {
            wb.setForceFormulaRecalculation(true);
            var sheet = wb.getSheet("Test");
            var formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
            for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
                var row = sheet.getRow(i);
                var list = new ArrayList<String>();
                for (var cell : row) {
                    list.add(format(dataFormatter, formulaEvaluator, cell));
                }
                System.out.println(String.join(", ", list));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public static String format(DataFormatter dataFormatter, XSSFFormulaEvaluator formulaEvaluator, Cell cell) {
        return dataFormatter.formatCellValue(cell, formulaEvaluator);
    }
}

控制台的输出为:

1, #N/A
2, b

这意味着无法解析这个命名统计后的值。

为啥公式可以执行。但是从名称管理器拿不到?是否可以通过拿名称对应的公式来计算出相应的结果?

通过修改formatter:

    public static String format(DataFormatter dataFormatter, XSSFFormulaEvaluator formulaEvaluator, Cell cell) {
        if (cell.getCellType() == CellType.FORMULA) {
            System.out.println("Formula: " + cell.getCellFormula());
            System.out.println("RichString: " + cell.getRichStringCellValue().getString());
            System.out.println("Cache result type: " + cell.getCachedFormulaResultType());
        }
        return dataFormatter.formatCellValue(cell, formulaEvaluator);
    }

我们可以得到输出:

Formula: AAA
RichString: a
Cache result type: STRING
1, #N/A
---------------------------------------
Formula: VLOOKUP(A2,Test2!$A$1:$B$5,2)
RichString: b
Cache result type: STRING
2, b
---------------------------------------

这么看来RichString可以拿到我们想要的值。
但是当我把Sheet2中对应的值改为数字:
在这里插入图片描述

得到的一个保存的结果:

Formula: AAA
Exception in thread "main" java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC formula cell
	at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:946)
	at org.apache.poi.xssf.usermodel.XSSFCell.getRichStringCellValue(XSSFCell.java:330)
	at org.apache.poi.xssf.usermodel.XSSFCell.getRichStringCellValue(XSSFCell.java:77)
	at poi.Main.format(Main.java:43)
	at poi.Main.main(Main.java:29)

这里我想拿到一个可以区分是Name还是Formula的属性。但是我看了下从cell的方法好像没办法拿到。

一个解决方案

package poi;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        var inputFile = new File("src/main/java/poi/test.xlsx");
        var dataFormatter = new DataFormatter();
        try (var wb = new XSSFWorkbook(new FileInputStream(inputFile))) {
            wb.setForceFormulaRecalculation(true);
            var sheet = wb.getSheet("Test");
            var formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
            for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
                var row = sheet.getRow(i);
                var list = new ArrayList<String>();
                for (var cell : row) {
                    list.add(format(dataFormatter, formulaEvaluator, cell));
                }
                System.out.println(String.join(", ", list));
                System.out.println("---------------------------------------");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public static String format(DataFormatter dataFormatter, XSSFFormulaEvaluator formulaEvaluator, Cell cell) {
        if (cell.getCellType() == CellType.FORMULA) {
            System.out.println("Formula: " + cell.getCellFormula());
            System.out.println("Cache result type: " + cell.getCachedFormulaResultType());
            if (cell.getCachedFormulaResultType() == CellType.STRING) {
                return cell.getRichStringCellValue().getString();
            } else {
                return String.valueOf(cell.getNumericCellValue());
            }
        }
        return dataFormatter.formatCellValue(cell, formulaEvaluator);
    }
}

执行后得到结果:

Formula: AAA
Cache result type: NUMERIC
1, 1.0
---------------------------------------
Formula: VLOOKUP(A2,Test2!$A$1:$B$5,2)
Cache result type: NUMERIC
2, 2.0
---------------------------------------

这样结果勉强可以用,但是感觉上这段代码是有BUG的,但是对POI的了解不是太透,本文相当于抛砖引玉,如果有懂的可以探讨下。

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

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

相关文章

Rust ESP32C3开发

Rust ESP32C3开发 系统开发逐步使用Rust语言&#xff0c;在嵌入式领域Rust也逐步完善&#xff0c;本着学习Rust和ESP32的目的&#xff0c;搭建了ESP32C3的环境&#xff0c;过程中遇到了不少问题&#xff0c;予以记录。 ESP-IDF开发ESP32 这一部分可跳过&#xff0c;是使用C开…

浏览器中的Markdown编辑器StackEdit

目前博客的 Pageviews 大约是之前的 10%&#xff0c;而 Uniques 则大约是 15% 左右。看来很多同学已经彻底迷路了 大家可以关注CSDN&#xff0c;地址&#xff1a; https://blog.csdn.net/wbsu2004 微信公众号也可以关注起来 什么是 StackEdit &#xff1f; StackEdit 是基于 P…

pyspark 笔记 cast 转换列的类型

1 不借助 pyspark.sql.types from pyspark.sql.functions import coldata [("Alice", "28"), ("Bob", "22"), ("Charlie", "30")] columns ["name", "age_str"] df spark.createDataFram…

如何使用vscode连接远程服务器

1、安装remote-ssh 在应用商店搜索remote-ssh&#xff0c;安装remote-ssh 2、安装完成后会出现远程资源管理器 3、点击远程资源管理器 --ssh的➕号&#xff0c;在输出框内输入要连接的服务器ip及账户名 如&#xff1a;ssh 账户名ip地址 4、输入后回车保存 5、保存后刷新一下 6…

SOLIDWORKS磁力配合工具

在我们平常的工作中&#xff0c;很多人都会面临大型装配体相互配合的问题。有很多用户&#xff0c;由于设计的产品体积很大&#xff0c;零件数量非常多。即使将设备分成不同的部件进行组装&#xff0c;不同的部件之间进行配合也非常困难。因为这种时候软件运行的速度会变得非常…

【UE5 多人联机教程】06-显示玩家名称

效果 可以看到玩家输入各自的名称&#xff0c;会显示到自己控制的角色头上。但是目前有一个BUG就是&#xff0c;当客户端加入游戏时会多创建一个服务端的角色。 步骤 1. 打开“BP_ThirdPersonCharacter”&#xff0c;添加一个控件组件&#xff0c;用于显示玩家名称 作为网格体…

国产内存惹人爱,光威的价格战太凶猛,海外品牌已无力招架

现阶段&#xff0c;真的很适合升级内存条和SSD&#xff01;当然了&#xff0c;我说的是国产的品牌&#xff0c;经过这几年的发展&#xff0c;国产内存和SSD的表现都有了质的飞跃&#xff0c;像是光威之类的品牌&#xff0c;更是成功在玩家群体中获得了良好的口碑&#xff0c;而…

数据库的介绍

无处不在的数据库 信息化社会&#xff0c;无处不在的就是数据。 编程语言可以归纳为&#xff0c;数据的计算一类。 那数据的存储呢? 数据库就是存储数据的库&#xff0c;那么它是如何组织数据并存储的呢? 数据库如何存储数据 我们先来看看&#xff0c;生活中&#xff0c;…

通过社区参与解锁早期增长:Maven 远程医疗平台概览

Maven通过用户导向的渐进式验证&#xff0c;找到了一个被忽视的巨大女性医疗服务市场&#xff0c;作为女性医疗保健的先行者&#xff0c;已服务超过1500万用户&#xff0c;目前估值已达$14亿。本文将深入探索Maven实现产品市场匹配的三个阶段&#xff0c;从如何验证初始的市场机…

Junit5 + YAML 轻松实现参数化和数据驱动(一)

登录&#xff1a;不同的用户名&#xff0c;不同的密码&#xff0c;不同的组合都需要做登录场景的测试&#xff0c;正常的排列组合下可能会产生多个用例 搜索&#xff1a;不同的搜索条件产生不同的搜索结果&#xff0c;搜索也是常见的测试项&#xff0c;单个搜索参数或者多种搜…

手动搭建gateway,项目集成gateway实现Token效果

目录 背景步骤1、首先创建springboot项目2、引入依赖3、配置文件&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;超级重要&#xff01;&#xff01;&#xff01;根据自己的需要进行配置&#xff09;4、相关类我们在服务中进行的白名单中接口的操作如…

Java8 LocalDate、Date、LocalDateTime、时间戳的转换

文章目录 LocalDateplusminus比较日期 LocalDate、Date、LocalDateTime、时间戳的转换 LocalDate plus LocalDate localDate2 localDate1.plus(15, ChronoUnit.DAYS);LocalDate localDate2 localDate1.plus(Period.ofDays(15));minus LocalDate localDate2 localDate1.minu…

电缆振荡波局部放电检测定位技术

电缆振荡波检测技术主要用于交联聚乙烯电力电缆检测&#xff0c;是属于离线检测的一种有效形式 。该技术基于LCR阻尼振荡原理&#xff0c;在完成电缆直流充电的基础上&#xff0c;通过内置的高压电抗器、高压实时固态开关与试品电缆形成阻尼振荡电压波&#xff0c;在试品电缆上…

新品发布| PPS Tester同步精度测试仪

产品简介 Product introduction 产品概述 PPS 同步精度测试仪&#xff0c;即PPS Tester&#xff0c;是怿星科技开发的一款基于1PPS测量方法的系统时钟同步精度测试设备。它由硬件模块ETS2110、上位机软件ePPSTester以及相关附件组成。PPS Tester支持24路*24小时PPS信号的持续…

NodeJs后端项目使用docker打包部署

docker安装看之前的文章 默认已经安装好docker并且配置没有问题 拉取项目 https://gitee.com/coder-msc/docker-node 本地跑一个看看 pnpm install pnpm start 本地访问 http://localhost:1301/getname?name%E5%93%88%E5%88%A9%E6%B3%A2%E7%89%B9项目整个上传服务器 查看…

8.10 PowerBI系列之DAX函数专题-TopN中实现动态指标

需求 实现 建立一个辅助表供切片器选择 2 建立条件判断度量值top_measure swich(true(),selectedvalue(table[tope_type])"按数量top",sum(order_2[产品数量]),selectedvalue(table[tope_type])"按金额top",sum(order_2[订单金额]),selectedvalue(table…

字符指针和常量字符指针

用来存放字符的地址的指针 还有一种比较特殊的字符指针 有这样一道题&#xff1a;

最小时间差(力扣)排序 + 思维 JAVA

给定一个 24 小时制&#xff08;小时:分钟 “HH:MM”&#xff09;的时间列表&#xff0c;找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1&#xff1a; 输入&#xff1a;timePoints [“23:59”,“00:00”] 输出&#xff1a;1 示例 2&#xff1a; 输入&#xff1a;…

css实现有缺口的border

css实现有缺口的border 1.问题回溯2.css实现有缺口的border 1.问题回溯 通常会有那种两个div都有border重叠在一起就会有种加粗的效果。 div1,div2,div3都有个1px的border&#xff0c;箭头标记的地方是没有处理解决的&#xff0c;很明显看着是有加粗效果的。其实这种感觉把di…

python爬虫-加速乐cookie混淆解析实例小记

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 第一步&#xff1a;抓包工具第一次请求页面&#xff0c;得到响应。本次我使用的fiddle进行抓包&#…