You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:05:58