gpt4 book ai didi

java - Apache Poi 无法读取工作表名称

转载 作者:行者123 更新时间:2023-12-04 20:08:45 25 4
gpt4 key购买 nike

我们在通过 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.CTSheetXSSFSheet.getSheetName 只返回 org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet.getName

如果返回 null 而不是名称,则可能使用了错误的类 org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet。对于 apache poi 5.0.0,它必须是来自 jar poi-ooxml-full-5.0.0.jarCTSheet > 或 poi-ooxml-lite-5.0.0.jar。它必须来自ooxml-schemas-*.jar 或任何poi-ooxml-schemas-*.jar,例如使用较低版本的apache poi。也许您的生产环境中的某些库发送或提取了任何 ooxml-schemas-*.jar?这与 apache poi 5.0.0 不兼容。

您可以在运行时询问 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.jarpoi-ooxml-lite-5.0.0.jar,您可能会得到至少不知道其他图书馆也运送或拉动那个类(class)。

如果这没有帮助,请同时检查 org.apache.xmlbeans.* 类的来源。 org.openxmlformats.schemas.* 类需要 XmlBeans

...
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);
...

使用 apache poi 5.0.0,这个类必须来自 xmlbeans-4.0.0.jar 它必须 来自任何其他版本的 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 中,可能在使用 Java 解析 XML 时出现问题?但这应该会抛出应该记录在某处的异常。

关于java - Apache Poi 无法读取工作表名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69100632/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com