XSSFSheet
基于底层的org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet
。而XSSFSheet.getSheetName
仅仅返回org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet.getName
。
如果它返回null
而不是名称,则可能使用了错误的类org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet
。对于apache poi 5.0.0
,它必须来自poi-ooxml-full-5.0.0.jar
或poi-ooxml-lite-5.0.0.jar
中的CTSheet
。它不能来自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.jar
或者
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);
...
使用
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
可能会出现问题。但是应该会抛出异常,需要在某个地方记录下来。