Apache Poi 无法读取工作表名称

2024-04-27

我们在通过 Apache Poi 读取 Excel 工作表时遇到了一个奇怪的错误。我们使用的是5.0版本。

该代码以前可以工作,但现在已停止在我们所有的生产环境中工作。它在本地测试时仍然有效,因此事实证明这很难调试。

问题是我们返回了空工作表名称,因此无法正确加载所需的工作表。

try (XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(venueListFile))) {

        LOGGER.info("Found {} sheets", wb.getNumberOfSheets());

        // First setup venues
        Sheet venueSetUpSheet = wb.getSheet("Store Set Up");
        List<String> sheetNames = new ArrayList<>();
        for (Iterator<Sheet> it = wb.sheetIterator(); it.hasNext(); ) {
            sheetNames.add(it.next().getSheetName());
        }

        if (venueSetUpSheet == null) {

            LOGGER.warn("Sheet 'Store Set Up' not found, available sheets: '" + String.join("','", sheetNames) + "'");
        } else {
            LOGGER.info("Found sheets: " + String.join("','", sheetNames) + "'");

在本地返回:

Found 5 sheets
Found sheets: Store Set Up','Store Open Hours','Staff Setup','TV Configurations','Sheet3'

在生产中,它返回相同的 Excel 文件:

Found 5 sheets
Sheet 'Store Set Up' not found, available sheets: 'null','null','null','null','null'

看来文件已读取,并且我们已经测试服务器上上传的文件没有损坏。有人知道 Poi 的一个已知问题会导致工作表名称为空吗?


XSSFSheet基于底层的org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet. And XSSFSheet.getSheetName只是返回org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet.getName.

如果返回null而不是名字,那么可能是错误的类org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet用来。为了apache poi 5.0.0 it must be CTSheet从罐子里poi-ooxml-full-5.0.0.jar or poi-ooxml-lite-5.0.0.jar。它必须not来自ooxml-schemas-*.jar or any poi-ooxml-schemas-*.jar就像使用较低版本的apache poi。也许您的生产环境中的某个图书馆发布或提取了任何ooxml-schemas-*.jar?这是不兼容的apache poi 5.0.0 then.

您可以询问ClassLoader其中一个特殊类(org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet在你的情况下)来自运行时:

...
  ClassLoader classloader = org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet.class.getClassLoader();
  java.net.URL res = classloader.getResource("org/openxmlformats/schemas/spreadsheetml/x2006/main/CTSheet.class");
  String path = res.getPath();
  System.out.println("CTSheet came from " + path);
...

如果那不是poi-ooxml-full-5.0.0.jar or poi-ooxml-lite-5.0.0.jar,您可能至少知道其他图书馆也发布或提取了该类。

如果这没有帮助,还请检查哪里org.apache.xmlbeans.*类来自。XmlBeans需要用于org.openxmlformats.schemas.*类。

...
  classloader = org.apache.xmlbeans.XmlObject.class.getClassLoader();
  res = classloader.getResource("org/apache/xmlbeans/XmlObject.class");
  path = res.getPath();
  System.out.println("XmlObject came from " + path);     
...

Using apache poi 5.0.0, 这个班must来自xmlbeans-4.0.0.jar它必须not来自任何其他版本XmlBeans.

如果都没有帮助,您还可以以同样的方式检查是否org.apache.poi.xssf.usermodel.XSSFSheet确实来自apache poi 5.0.0 (poi-ooxml-5.0.0.jar)。也许有多个apache poi您的生产环境中的版本。这也不支持:

...
  classloader = org.apache.poi.xssf.usermodel.XSSFSheet.class.getClassLoader();
  res = classloader.getResource("org/apache/poi/xssf/usermodel/XSSFSheet.class");
  path = res.getPath();
  System.out.println("XSSFSheet came from " + path);     
...

最后,您可以尝试从底层获取工作表名称CTSheet像这样的对象:

...
  try (Workbook wb = WorkbookFactory.create(new FileInputStream("./test.xlsx"));) {

   List<String> sheetNames = new ArrayList<>();
   for (Iterator<Sheet> it = wb.sheetIterator(); it.hasNext(); ) {
    Sheet sheet = it.next();
    if (sheet instanceof org.apache.poi.xssf.usermodel.XSSFSheet) {
     java.lang.reflect.Field _sheet = org.apache.poi.xssf.usermodel.XSSFSheet.class.getDeclaredField("sheet");
     _sheet.setAccessible(true);
     org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet ctSheet = 
      (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet)_sheet.get((org.apache.poi.xssf.usermodel.XSSFSheet)sheet);
     org.apache.xmlbeans.impl.values.TypeStore store = ((org.apache.xmlbeans.impl.values.XmlObjectBase)ctSheet).get_store();
     System.out.println(store);
     org.apache.xmlbeans.SimpleValue target = (org.apache.xmlbeans.SimpleValue)store.find_attribute_user(new javax.xml.namespace.QName("", "name"));
     System.out.println(target.getStringValue());
    }
    sheetNames.add(sheet.getSheetName());
   }
  
   System.out.println(sheetNames);
  }
...

那样有用吗?或者是抛出异常?如果有,是哪一个?

当然,请检查所有错误日志中是否有错误。自从Office Open XML将数据存储在XML,可能解析的时候有问题XML using Java?但这应该会引发异常,这些异常应该记录在某处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apache Poi 无法读取工作表名称 的相关文章

  • 在多个不同线程之间共享变量

    我想在多个线程之间共享一个变量 如下所示 boolean flag true T1 main new T1 T2 help new T2 main start help start 我想分享flag在主线程和帮助线程之间 这是我创建的两个不
  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • Android 在 ROOM 数据库中插入大量数据

    我有大约 10 个模型 每个模型都有超过 120K 行和 90 列的记录 其中包含双数组值 在 Room 中插入任何模型都需要超过 125 130 秒 任何人都可以建议我需要做什么才能使用一些批量插入技术来保存所有这些 120K 该技术大约
  • getAnnotations() 为空

    我想在我的应用程序中使用注释 因此 我为注释创建了 hello world 如下示例 public class HelloAnnotation Foo bar Hello World public String str public sta
  • 使用 Morphia 配置 Spring Boot?

    我不想利用 Spring DATA MongoDB 支持 我想利用名为 Morphia 的 MongoDB ORM https github com mongodb morphia https github com mongodb morp
  • Java RMI 通过互联网

    我正在用 Java 开发一个游戏 使用 RMI 进行所有网络通信 RMI 允许我调用服务器上的方法 但这对我来说还不够 我还希望服务器能够在连接的客户端之间传播消息 我的客户端查找服务器 它的接口扩展了远程 并在其上注册 它允许服务器知道谁
  • Android - Firebase - 保存新数据而不覆盖旧数据

    创建此问题是因为我之前的问题包含 2 个问题 而不是将其缩小到 1 Aim 用户将能够存储新数据而不会覆盖之前提交的数据 描述 目前 当用户输入新报告时 事件报告节点中的用户事件报告数据将被覆盖 用户发送的旧事件报告中的数据应与新数据一起保
  • 二维数组中的寻路

    假设我有这个二维数组地图 0 0 0 0 7 1 1 1 1 1 1 1 1 0 7 7 7 7 1 1 1 24 1 1 1 1 0 7 24 24 24 24 24 24 24 1 1 3 1 0 7 23 23 23 23 23 23
  • Clojure Web 应用程序 - 我从哪里开始?

    最近我一直在研究 Clojure 我喜欢这门语言 我想看看我是否可以在其中制作一个小型网络应用程序 只是为了挑战自己 但是 我完全没有设置任何与 Java 相关的 Web 应用程序的经验 事实上 我对 Java 并没有太多的经验 我从哪说起
  • 如何正确安装mysqlconnecter java?

    上网冲浪后 我意识到我应该在系统环境变量中设置类路径连接器 jar 文件的路径文件我这样做了 并在命令行中输入此命令我有这个 C Users User gt echo classpath D classpath mysql connecto
  • 获取运行时提供的类名的 n 维数组的类

    给定一个完全限定的类名和多个维度 我想获取该类的类名 我相信我可以这样做 public Class elementType Class forName className return Array newInstance elementTy
  • 想要从 beanIO 字段名称标签在 csv 中写入标题

    我想在 csv 文件中写入标题 因为我的文本文件不包含任何标题 所以我想从 beanIO 字段名称标签写入它 我有一个 beanIO 有两个流 一个用于读取 另一个用于写入 这是输入文件 文本输入 txt 1 约翰 露 BA xxx1萨姆
  • 将 JAR 文件打包为 WAR 文件

    我有一系列依赖的Java项目 我想将它们打包成一个 JAR 文件 以便在我的 WAR 文件中使用 这些项目依赖于大量的外部库和项目 如log4j apache commons等 我选择 Eclipse 中的所有项目并导出为 JAR 文件 然
  • 与 Java 中的同步块相比,新的 Lock 接口有什么优势?

    与 Java 中的同步块相比 新的 Lock 接口有什么优势 您需要实现一个高性能缓存 允许多个读取器但单个写入器保持完整性 您将如何实现它 锁的优点是 让他们公平是可能的 可以使线程在等待 Lock 对象时响应中断 可以尝试获取锁 但如果
  • 如何告诉杰克逊在反序列化期间忽略空对象?

    在反序列化过程中 据我理解是将JSON数据转换为Java对象的过程 我如何告诉Jackson 当它读取不包含数据的对象时 应该忽略它 我正在使用 Jackson 2 6 6 和 Spring 4 2 6 我的控制器收到的JSON数据如下 i
  • 在 init 之外在 java 中创建对象

    因此 对于我正在创建的游戏 我有一些扩展 GameDriver 的类 到目前为止 在所有其他类上我都能够扩展 GameDriver 然后在 GameDriver 中我可以执行以下操作 ArrayList
  • 使用服务器 java api 从 jasperserver 存储库检索资源

    我正在尝试使用其 java API 从 Jasperserver 存储库检索资源 根据jasper 报表服务器终极指南 https community jaspersoft com documentation jasperreports s
  • 使用 System.currentTimeMillis() 每秒运行一次代码

    我试图使用 System currentTimeMillis 每秒运行一行代码 代码 while true long var System currentTimeMillis 1000 double var2 var 2 if var2 1
  • 如何为 Weblogic 10.3.6 启用 Java 持久性 2.0

    我正在使用 eclipse 和 weblogic 服务器 为了将项目添加到 weblogic 服务器 它需要支持 Java Persistance 2 0 但是当尝试安装它时 我不断收到此消息 在 Weblogic Server 安装中启用
  • ByteBuddy 变基、合成类型和 OSGi

    我为 byte buddy 开发了以下拦截器 public class SecurityInterceptor RuntimeType public static Object intercept SuperCall Callable su

随机推荐

  • 如何阻止 Apache CXF 发送响应消息?

    如果给定的 SOAP 标头元素具有给定值 例如 如果标头标记 response 的值为 0 我根本不希望 Apache CXF 返回响应 我怎样才能做到这一点 CXF 似乎假设所有呼叫都会收到响应 我知道这在 Web 服务上下文中看起来很奇
  • 如何在生产环境中运行 spring boot 可执行 jar?

    Spring Boot 的首选部署方法是通过内部包含 tomcat 的可执行 jar 文件 它是从一个简单的开始java jar myapp jar 现在 我想将该 jar 部署到 EC2 上的 Linux 服务器上 我是否遗漏了某些内容
  • 如何在 Bullet 物理引擎中对物体应用旋转?

    我有旋转值 滚动 俯仰 偏航 我想将这种旋转应用于身体 但我不知道该怎么做 最直接的方法是通过运动状态或直接设置来直接设置刚体的世界变换 要获得横滚 俯仰和偏航的变换 您可以使用 btRigidBody rigidBody btTransf
  • 检查变量是否为 double 数据类型

    我需要检查我拥有的变量是否属于该数据类型double 这是我尝试过的 try double price Convert ToDouble txtPrice Text catch FormatException MessageBox Show
  • cs0030:无法生成临时类

    我有一个 Web 服务 当我尝试生成它的对象时 出现以下错误 无法生成临时类 结果 1 错误 CS0030 无法将类型 ShortSell ShortSellRQOriginDestinationInformationFlightSegme
  • 消息通知产生“此内容无法显示”

    我正在通过网络挂钩向 Slack 发送消息 使用单个 文本 JSON 元素的消息通知可通过适用于 OS X 和 iOS 的 Slack 应用程序生成正确的通知文本 频道中的消息文本也是正确的 但是 当使用新的 阻止 方法时 通知文本变为 无
  • 发布时错误元数据文件dll无法找到CSC

    我有一个 Visual Studio 解决方案 其中包含多个项目 特别是 DotNet5 asp net 应用程序 其中有多个 netstandard 2 0 引用 它在调试器中构建并运行良好 但不断抛出元数据错误 它不断特别引用在 net
  • 谷歌分析 SDK iOS10

    我已经从 cocoa pod 版本 3 14 安装了 Google Analytics id
  • 如何在Spring boot中使用注释来使用参数解析器?

    我想用argument resolvers在 Spring 启动中 我该怎么办 它是在 XML 中完成的 如下所示
  • 快速移动的球与鼠标控制的球拍的碰撞检测问题

    在统一中 我有一个应该击球的球拍 并且球拍直接由鼠标控制 即鼠标使用鼠标轴移动球棒并使用 translate 函数移动球拍 我预计 Unity3d 的物理特性不会直接通过鼠标正确地转换球拍的运动并相应地影响球 我必须编写一些自定义的内容 结
  • 为什么负边距会影响我的页面宽度?

    请参考以下内容example http jsfiddle net wdm954 Fcznp 9 其中 200px 宽的外部 div 旨在确定我们的页面宽度 它包含一个 400px 宽的内部 div 但左 右负边距为 100px 我预期的最终
  • C++ / C++11 中的函数组合

    我目前正在使用 C 11 编写一些需要大量函数组合的密码算法 我必须处理两种类型的构图 自行编写一个函数 次数可变 数学上 对于某个函数 F F n x F n 1 o F x F n 1 F x 将不同的函数组合在一起 例如 对于某些相同
  • Jackson @JsonRawValue 获取地图的值

    我有以下 Java bean 类 使用 Jackson 将其转换为 JSON public class Thing public String name JsonRawValue public Map content new HashMap
  • 将 asp.net 5 测试放在单独的程序集中

    我使用 Microsoft AspNet TestHost 来托管 xunit 集成测试 只要测试与 asp net 5 solution 位于同一项目中 一切都会正常进行 但我想将测试放入单独的程序集中 将它们与解决方案分开 但是 当我尝
  • 如何处理 pcntl_fork(): 错误 35?

    我有 php7 CLI 守护进程 它连续解析文件大小超过 50M 的 json 我试图使用 pcntl fork 的单独进程将每 1000 个解析数据条目保存到 mysql 对于约 200k 行 它工作得很好 然后我得到pcntl fork
  • “修补”rails 渲染函数来编辑默认选项

    当我在 Rails 中渲染 xml 时 我总是想要 dasherize gt false 选项 有没有办法将其设置为应用程序范围的默认值 当然无需修改 Rails 源代码 也许一个渲染函数以某种方式优先于第一个函数 然后使用此选项调用它 这
  • 如何隔离特定的颠覆修订版?

    我有一个已提交给 SVN trunk 的修订版 我想回滚它 但是 我想以某种方式保留更改 例如分支甚至补丁文件 有什么建议么 反向合并 我认为这就是这个术语 提交 仅此而已 对于 反向合并 部分 TSVN 有一个很酷的功能 称为 恢复到此版
  • 什么时候使用nonlocal关键字? [复制]

    这个问题在这里已经有答案了 我不明白为什么我可以在这里使用系列变量 def calculate mean series def mean new value series append new value total sum series
  • 在 Node.js 中获取父目录名称

    我正在使用 Node js 并且我想获取某个目录的父目录名称 文件 我有文件 test1 folder1 FolderIWant test txt 我想要得到 FolderIWant 我努力了 var path require path v
  • Apache Poi 无法读取工作表名称

    我们在通过 Apache Poi 读取 Excel 工作表时遇到了一个奇怪的错误 我们使用的是5 0版本 该代码以前可以工作 但现在已停止在我们所有的生产环境中工作 它在本地测试时仍然有效 因此事实证明这很难调试 问题是我们返回了空工作表名