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

时间:2013-10-16 19:43:43

标签: 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());

这将打印出来:

Sun Dec 31 00:00:00 CET 1899

我正在使用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);
}

产生:

Tue Jan 01 00:00:00 CET 2013

非常感谢。

1 个答案:

答案 0 :(得分:3)

您所描述的一切都是完全正确和预期的

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

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

但是,Excel中有一些特殊的公式函数,它们被定义为volatile。这些函数每次都返回一个不同的值,例如DATE,并且对于这些Excel,只是将一个虚拟值(例如0或-1)写入单元格,并在加载时重新计算它

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

Excel中的日期存储为自19/1年1月1日或1/1/1904以来的小数天(取决于标记)。值为-1是1899年12月31日,这就是当Excel写入-1并将其作为日期请求时所看到的内容