Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if date uses 1904 windowing with Apache POI XSSF eventmodel

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();
like image 670
SWilk Avatar asked Apr 18 '13 15:04

SWilk


2 Answers

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();
like image 162
Andrey Avatar answered Oct 11 '22 13:10

Andrey


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.

like image 40
rgettman Avatar answered Oct 11 '22 11:10

rgettman