Java Apache POI 错误

Java Apache POI Bug

在使用 Apache POI 实现时,我 运行 陷入了 st运行ge 行为。我无法解释原因,所以如果有人可以提供一些提示,我很乐意听取他们的意见。对于我正在解决的问题,它甚至不是一个大障碍——在这一点上,它更像是一件好奇的事情。所以这里是:

public static void main(String[] args) throws EcatException, SQLException, IOException, Exception {

    long ts = System.currentTimeMillis();
    SXSSFWorkbook wb = new SXSSFWorkbook();
    SXSSFSheet test = wb.createSheet("Test");
    SXSSFRow r = test.createRow(0);
    Cell c = r.createCell(0);
    c.setCellValue("TEST");

    wb.write(new FileOutputStream("D:/wb-" + ts + ".xlsx"));
    wb.close();

    XSSFWorkbook wb2 = new XSSFWorkbook("D:/wb-" + ts + ".xlsx");
    XSSFSheet s = wb2.getSheet("Test");

    s.getRow(0).getCell(0).setCellType(CellType.STRING);
    System.out.println(s.getRow(0).getCell(0).getStringCellValue());
    wb2.close();

  }

如您所见,这将创建一个 SXSSFWorkbook,其中一行和一个单元格的值为“TEST”。 然后再次打开工作簿,并将该单元格的内容打印到控制台。

我希望在控制台上看到“TEST”,但我没有。输出为空。

s.getRow(0).getCell(0).setCellType(CellType.STRING);

输出符合预期。

有人对此有解释吗? 顺便提一句。我尝试了不同版本的 POI,每次都有相同的结果。

问题是 SXSSFWorkbook 默认使用内联字符串,因为这更适合流式传输方法。但是 XSSFWorkbook 期望当单元格类型为 CellType.STRING.

时将字符串存储在共享字符串 table 中

因此,在创建 SXSSFWorkbook 后,sheet1.xml 中的单元格 XML 看起来像

<c r="A1" t="inlineStr">
 <is>
  <t>TEST</t>
 </is>
</c>

类型 tinlineStr。并且单元格的值直接是字符串TEST。

但在 Cell.setCellType(CellType.STRING) 之后,类型 t 设置为 s。这期望该值是一个数字,它是共享字符串 table 中字符串的索引。但是没有这样的。这就是 System.out.println(s.getRow(0).getCell(0).getStringCellValue()); 无法打印任何内容的原因。

您可以 SXSSFWorkbook wb = new SXSSFWorkbook(null, 100, true, true) 强制 SXSSFWorkbook 也使用共享字符串 table。但这会降低流式方法的性能,因为所有字符串都需要存储在该共享字符串中 table 而不是直接将它们存储在单元格中。

共享字符串的好处 table 是节省内存,因为所有字符串只存储一次,当多个单元格使用相同的字符串时,只有它们的索引存储在单元格中。

Excel 本身从不使用内联字符串而不是共享字符串 table 来存储工作簿。因此,在 Excel 中打开并重新保存后,内联字符串被共享字符串 table 中的字符串索引替换,并且单元格类型始终为 s 而不是 inlineStr。这就是为什么 Cell.setCellType(CellType.STRING) 将不再具有这种效果。