我使用的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
非常感谢。
答案 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并将其作为日期请求时所看到的内容