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

Apache poi apache poi从excel日期读取日期()函数给出错误的日期,apache-poi,Apache Poi,Im使用的xlsx文件包含单元格中的日期(年、月、日)公式。此单元格的格式为日期,因此Excel/OpenOffice会显示正确的日期。 e、 g.单元格内容为'=DATE(2013;1;1),生成:'01.01.2013' 到目前为止,一切都很好 使用poi库读取此文件时,我执行以下操作: XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File("/home/detlef/temp/test.xlsx")));

Im使用的xlsx文件包含单元格中的
日期(年、月、日)
公式。此单元格的格式为日期,因此Excel/OpenOffice会显示正确的日期。 e、 g.单元格内容为
'=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

无论如何,谢谢。

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

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

这就是为什么在使用ApachePOI对excel文件进行更改时,需要运行一个计算来更新所有缓存的公式值,以便在转到该单元格之前,它在excel中显示正确

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

在POI中读取公式单元格的数值时,它会返回缓存的值。如果你想让POI计算公式,你需要要求它,就像你正在做的那样

Excel中的日期存储为1900年1月1日或1904年1月1日后的小数天(取决于标志)。值-1是1899年12月31日,这就是Excel写入-1并请求将其作为日期时所看到的