使用Apache POI打开XSSFWorkbook时遇XmlValueOutOfRangeException问题求助
问题描述
使用Apache POI官方指南的标准方法打开XSSF工作簿时,加载报错:XmlValueOutOfRangeException: Invalid double value。
从调用栈可知,构造函数读取列宽时遇到无法处理的数值(错误信息显示为20,714285714285715,逗号作为小数点分隔符导致解析失败),但业务上不需要列宽信息。手动修改Excel列宽可解决但不可行,求替代方案。
当前初始化代码:
OPCPackage pkg = OPCPackage.open(fileInputStream); XSSFWorkbook wb = new XSSFWorkbook(pkg); ... pkg.close()
报错栈:
org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException: Invalid double value: 20,714285714285715 at org.apache.xmlbeans.impl.values.XmlObjectBase$ValueOutOfRangeValidationContext.invalid(XmlObjectBase.java:328) ~[xmlbeans-3.1.0.jar:na] at org.apache.xmlbeans.impl.values.JavaDoubleHolder.validateLexical(JavaDoubleHolder.java:63) ~[xmlbeans-3.1.0.jar:na] at org.apache.xmlbeans.impl.values.JavaDoubleHolder.set_text(JavaDoubleHolder.java:53) ~[xmlbeans-3.1.0.jar:na] at org.apache.xmlbeans.impl.values.XmlObjectBase.update_from_wscanon_text(XmlObjectBase.java:1180) ~[xmlbeans-3.1.0.jar:na] at org.apache.xmlbeans.impl.values.XmlObjectBase.check_dated(XmlObjectBase.java:1319) ~[xmlbeans-3.1.0.jar:na] at org.apache.xmlbeans.impl.values.JavaDoubleHolder.getDoubleValue(JavaDoubleHolder.java:75) ~[xmlbeans-3.1.0.jar:na] at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTColImpl.getWidth(Unknown Source) ~[ooxml-schemas-1.4.jar:na] at org.apache.poi.xssf.usermodel.helpers.ColumnHelper.setColumnAttributes(ColumnHelper.java:254) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.helpers.ColumnHelper.cloneCol(ColumnHelper.java:165) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.helpers.ColumnHelper.addCleanColIntoCols(ColumnHelper.java:85) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.helpers.ColumnHelper.cleanColumns(ColumnHelper.java:57) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.helpers.ColumnHelper.<init>(ColumnHelper.java:46) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:232) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:218) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.XSSFWorkbook.parseSheet(XSSFWorkbook.java:454) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:419) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.ooxml.POIXMLDocument.load(POIXMLDocument.java:184) ~[poi-ooxml-4.1.2.jar:4.1.2] at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:288) ~[poi-ooxml-4.1.2.jar:4.1.2]
解决方案
方案1:升级Apache POI版本
当前使用的POI 4.1.2对区域设置导致的数值格式(逗号作为小数点)兼容性较差。升级到POI 5.0.0及以上版本,官方已修复此类数值解析问题,无需修改代码即可正常加载文件。
方案2:关闭XMLBeans严格验证(临时快速解决)
在初始化工作簿前添加以下系统属性,关闭XMLBeans的数值验证逻辑,跳过列宽的合法性检查:
// 全局关闭XMLBeans验证,需在加载工作簿前调用 System.setProperty("org.apache.xmlbeans.impl.values.XmlObjectBase.disableValidation", "true"); OPCPackage pkg = OPCPackage.open(fileInputStream); XSSFWorkbook wb = new XSSFWorkbook(pkg); // ... pkg.close()
注意:此设置为全局生效,可能影响其他XML解析场景的验证逻辑,仅建议作为临时方案使用。
方案3:使用SAX模式跳过列宽解析(精准跳过)
如果不需要列宽信息,可通过自定义SAX处理器,在解析Excel的XML内容时跳过<col>标签的解析,避免触发列宽读取逻辑:
OPCPackage pkg = OPCPackage.open(fileInputStream); XSSFReader reader = new XSSFReader(pkg); SharedStringsTable sst = reader.getSharedStringsTable(); // 自定义Sheet处理器,跳过col标签 XMLReader sheetParser = XMLReaderFactory.createXMLReader(); sheetParser.setContentHandler(new DefaultHandler() { private SharedStringsTable sharedStrings; public void setSharedStringsTable(SharedStringsTable sst) { this.sharedStrings = sst; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 跳过列定义标签,不处理列宽 if ("col".equals(localName)) { return; } // 处理其他需要的标签(如row、c等) // ... 这里根据业务需求实现单元格数据读取逻辑 } }); // 遍历所有Sheet并解析 Iterator<InputStream> sheets = reader.getSheetsData(); while (sheets.hasNext()) { try (InputStream sheetStream = sheets.next()) { sheetParser.parse(new InputSource(sheetStream)); } } pkg.close();
此方法仅读取业务需要的内容,完全跳过列宽解析,适合不需要格式信息的场景,但需要自行实现数据读取逻辑。
内容的提问来源于stack exchange,提问作者Ilya Khlopov
相关产品推荐
相关产品推荐

