删除公式时出现 XmlValueDisconnectedException

XmlValueDisconnectedException when remove Formula

我正在尝试用 java poi 读取一个 Excel 文件。我遍历行,然后遍历单元格。要读取单元格,我使用此方法:

  private String readCell(Cell cell) {
        try {
            switch (cell.getCellType()) {
                case NUMERIC:
                    if (format.isParseNumbersToInt()) {
                        return ((int) cell.getNumericCellValue()) + "";
                    } else {
                        return cell.getNumericCellValue() + "";
                    }
                case STRING:
                case _NONE:
                    return cell.getStringCellValue();
                case FORMULA:
                    if (format.isUseCashedFormulaValue()) {
                        cell.removeFormula();
                        return readCell(cell);
                    } else {
                        return cell.getCellFormula() + "";
                    }
                case BLANK:
                    return format.getBlankValue();
                case BOOLEAN:
                    return cell.getBooleanCellValue() + "";
                case ERROR:
                    if (format.isReadErrorCells()) {
                        return "ERROR_" + cell.getErrorCellValue();
                    } else {
                        return format.getErrorCellValue();
                    }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("Failed to read cell: " + cell.getAddress(), e);
        }
        throw new IllegalStateException("Unknown CellType: " + cell.getCellType().name());
    }

在某一时刻 XmlValueDisconnectedException 抛出:

Caused by: org.apache.xmlbeans.impl.values.XmlValueDisconnectedException
    at org.apache.xmlbeans.impl.values.XmlObjectBase.check_dated(XmlObjectBase.java:1274)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.getStringValue(XmlObjectBase.java:1529)
    at org.apache.poi.xssf.usermodel.XSSFCell.convertSharedFormula(XSSFCell.java:491)
    at org.apache.poi.xssf.usermodel.XSSFCell.getCellFormula(XSSFCell.java:469)
    at org.apache.poi.xssf.usermodel.XSSFSheet.onDeleteFormula(XSSFSheet.java:4654)
    at org.apache.poi.xssf.usermodel.XSSFCell.removeFormulaImpl(XSSFCell.java:571)
    at org.apache.poi.ss.usermodel.CellBase.removeFormula(CellBase.java:182)
    at de.heuboe.base.excel.controller.reader.ExcelReader.readCell(ExcelReader.java:356)
    ... 89 more

这个点看起来和其他点一样。文件要点: enter image description here

在 D219 中,以下单元格中的字符串是对上一行单元格的引用,例如D220:“=D219”和 D221:“=D220”。 E、F 和 G 列相同。

孔文件看起来像这样并且可以工作,但此时程序崩溃了。我也不知道为什么。

根据 StackTrace,共享公式存在问题。

如果列中有公式 =D6=D7=D8、... =D219=D220、...等D,则并非所有单元格都存储了完整的公式。相反,只有一个单元格存储完整的公式,后面的单元格仅存储对公式的共享引用。

OOXML 中看起来是这样的 :

在单元格 D8XML 中:<f ref="D8:D300" t="shared" si="1">D7</f>

在单元格 D9:D300XML 中:<f t="shared" si="1"/>

如果 Excel 操作包含此类共享公式的行,则此 Excel 行为往往很脆弱。

Cell.removeFormulaapache poi 中的一项相当新的功能。这可能是越野车。但在设计时,它应该了解此类共享公式并尊重这些公式。因此,要获得真正导致 XmlValueDisconnectedException 的内容,需要 Excel 文件。可以查看 sheet 的 XML 并检查共享公式 XML 中的某些内容是否与 XSSFCell.convertSharedFormula 预期的默认值不同。

但是你真的需要Cell.removeFormula吗?因为如果目标只是获取已兑现的公式值而不是公式字符串本身但要避免求值,那么可以使用与其他单元格值相同的方式获取已兑现的公式值,但取决于缓存的公式结果类型。

示例:

...
case FORMULA:
 if (isUseCashedFormulaValue) {
  //cell.removeFormula();
  //return readCell(cell);
  switch (cell.getCachedFormulaResultType()) {
   case NUMERIC:
    return String.valueOf(cell.getNumericCellValue());
   case STRING:
    return cell.getStringCellValue();
   case BOOLEAN:
    return String.valueOf(cell.getBooleanCellValue());
   case ERROR:
    return "ERROR_" + cell.getErrorCellValue();
  }
 } else {
  return cell.getCellFormula();
 }
...