7
votes

I am writing a program that imports xlsx files with Apache POI eventmodel (SAX/XSSF). I am almost done, but I can't get the correct dates.

I am parsing a cell with date value

<c r="D1" s="1">
    <v>41319.558333333334</v>
</c>

I am using the org.apache.poi.ss.usermodel.DateUtil class to get the date:

DateUtil.getJavaCalendar(doble date, bool use1904windowing);

What should I pass as use1904windowing to get correct dates? Temporarily I use false, as this gives me correct dates with my test workbook, but I know I should read that value from somewhere.

There is a record DateWindow1904Record in binary xls format, which I read using HSSF. What is its counterpart in XSSF? Or should I always use false?

EDIT: @rgettman answer pointed me to the solution, but it's not complete. In event model you do not have xssfWorkbook object and you can't just getCTWorkbook() of it.

Instead you can create CTWorkbook directly form InputStream:

OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
InputStream workbookXml = r.getWorkbookData();
CTWorkbook ctWorkbook = CTWorkbook.Factory.parse(workbookXml);
boolean isDate1904 = ctWorkbook.getWorkbookPr().getDate1904();
2
added an example in context of event model.SWilk
EDIT has failing code. Check Andrey's comment below.user517708

2 Answers

5
votes

Code described in EDIT section compiles, but always return null CTWorkbookPr in POI 3.9 Code below actually parses workbook prefix:

OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
InputStream workbookXml = r.getWorkbookData();
WorkbookDocument doc = WorkbookDocument.Factory.parse(workbookXml);
CTWorkbook wb = doc.getWorkbook();
CTWorkbookPr prefix = wb.getWorkbookPr();
boolean isDate1904 = prefix.getDate1904();
pkg.close();
4
votes

It is possible to determine if the 1904 date format is set in XSSF. Unfortunately, the isDate1904() is protected in XSSFWorkbook. But there is a workaround, made possible because XSSFWorkbook exposes its underlying XML bean with the getCTWorkbook() method.

boolean isDate1904 = false;
CTWorkbook internalWorkbook = xssfWorkbook.getCTWorkbook();
CTWorkbookPr workbookPr = internalWorkbook.getWorkbookPr();
if (workbookPr != null)
{
    isDate1904 = workbookPr.getDate1904();
}

This code examines the underlying XML beans to determine if the date1904 attribute it set. It is also possible to set that flag with that same XML bean (CTWorkbookPr) with the setDate1904(boolean) method.