apache poi 从 excel date() 函数读取日期给出了错误的日期

use*_*353 2 apache-poi

我使用的 xlsx 文件包含DATE(year, month, day)单元格内的公式。该单元格的格式为日期,因此 Excel/OpenOffice 显示正确的日期。例如,细胞内容'=DATE(2013;1;1)'产生:'01.01.2013' 到目前为止 - 很好。

当使用 poi 库读取此文件时,我会执行以下操作:

XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File("/home/detlef/temp/test.xlsx")));
XSSFSheet sheet = workbook.getSheet("Sheet A");
XSSFCell cell = sheet.getRow(0).getCell(0);
System.out.println(cell.getDateCellValue());
Run Code Online (Sandbox Code Playgroud)

这将打印出:

Sun Dec 31 00:00:00 CET 1899
Run Code Online (Sandbox Code Playgroud)

我使用的是 POI 3.9。

谁能告诉我为什么会发生这种情况?

找到了一种方法来做到这一点:

if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
   FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
   CellValue evaluate = evaluator.evaluate(cell);
   Date date = DateUtil.getJavaDate(evaluate.getNumberValue());
   System.out.println(date);
}
Run Code Online (Sandbox Code Playgroud)

这会产生:

Tue Jan 01 00:00:00 CET 2013
Run Code Online (Sandbox Code Playgroud)

不管怎么说,还是要谢谢你。

Gag*_*arr 5

您所描述的一切都是完全正确且符合预期的

当 Excel 在单元格中存储公式时,它不仅存储公式本身(.xlsx 中的字符串,或 .xls 的解析标记形式),还存储该公式的最后计算的答案。这意味着当 Excel 加载时,它不必花很长时间计算要显示的公式结果,它可以像任何其他单元格一样使用最后一个值来呈现它们。

这就是为什么当您使用 Apache POI 更改 Excel 文件时,您需要运行评估来更新所有这些缓存的公式值,以便在您转到该单元格之前它在 Excel 中看起来正确

然而,Excel中有一些特殊的公式函数,它们被定义为易失性的。这些函数每次总是返回不同的值,例如DATE这些函数,Excel 只是将虚拟值(例如 0 或 -1)写入单元格,并在加载时重新评估它

当您读取 POI 中公式单元格的数值时,它会返回缓存的值。如果您希望 POI 评估公式,您需要要求它,就像您正在做的那样

Excel 中的日期存储为自 1/1/1900 或 1/1/1904(取决于标志)以来的小数天数。值 -1 是 1899 年 12 月 31 日,因此这就是当 Excel 写入 -1 并且您请求将其作为日期时看到的结果