I'm using POI HSSF API for my excel manipulations in Java. I've a date value "8/1/2009" in one of my excel cell and while I try to read this value using HSSF API, it detects the cell type as Numeric and returns the 'Double' value of my date. See the sample code below:
cell = row.getCell(); // date in the cell '8/1/2009'
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
cellValue = cell.getRichStringCellValue().getString();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
cellValue = new Double(cell.getNumericCellValue()).toString();
break;
default:
}
Cell.getCellType() returns NUMERIC_TYPE and thus this code converts the date to double! :(
Is there any way to read the date as it is in HSSF POI !?
You could take a look at:
HSSFDateUtil.isCellDateFormatted()
See the POI Horrible Spreadsheet Format API for more details on HSSFDateUtil:
http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFDateUtil.html
That also provides some helper methods for returning Excel getExcelDate() and Java dates getJavaDate(). You need to be somewhat wary of different date formats though...
If you want to reference the date in the same format in as in the Excel file, you should use the CellDateFormatter. Sample code:
CellValue cValue = formulaEv.evaluate(cell);
double dv = cValue.getNumberValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = HSSFDateUtil.getJavaDate(dv);
String dateFmt = cell.getCellStyle().getDataFormatString();
/* strValue = new SimpleDateFormat(dateFmt).format(date); - won't work as
Java fmt differs from Excel fmt. If Excel date format is mm/dd/yyyy, Java
will always be 00 for date since "m" is minutes of the hour.*/
strValue = new CellDateFormatter(dateFmt).format(date);
// takes care of idiosyncrasies of Excel
}
Excel treats dates and times as numbers... Jon said it better, so I won't echo him here...
However, sample code for what you've put in the question is at http://poi.apache.org/spreadsheet/quick-guide.html#CellContents
If you using the POI 3.5 you can use the following
cell.getDateCellValue() method. This will work for excel 2007 as well.
Since POI 3.15 beta3 some functions are deprecated.
You can check data format and retrieve as Java Date.
SimpleDateFormat format = new SimpleDateFormat("");
String cellValue;
if(cell != null && cell.getCellTypeEnum() != CellType.STRING &&
cell.getCellTypeEnum() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)){
cellValue = format.format(cell.getDateCellValue());
}
Related
Below shows the highlighted cell which display as - (hyphen) but actually has 0 value inside it.
It's a formula cell with following custom formatting.
It's a formula cell but when the result is 0, it displays as -.
My requirement is to fetch - instead of 0.
cell2Update = sheet.getRow(4).getCell(3);
cell2Update.setCellType(Cell.CELL_TYPE_NUMERIC);
System.out.println(cell2Update.getStringCellValue());//Exception
System.out.println(cell2Update.getNumericCellValue());//Display as 0
Please help me with this doubt. I want to display the value which is displayed in Spreadsheet (-).
Do using a DataFormatter as shown in Getting the cell contents. And because the value might be result of a formula. Do using using a DataFormatter together with a FormulaEvaluator:
...
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
...
cell2Update = sheet.getRow(4).getCell(3);
...
String value = formatter.formatCellValue(cell2Update, evaluator);
System.out.println(value);
...
I have an Excel Sheet where the Date Cell is assigned with the Date Formula in Excel TODAY() + 1. So basically today it's showing as 03/10/2018 by default. I've created a code to read the data from Excel which has the formula in it but when I'm getting the date it's coming differently.
Code :
Cell c = CellUtil.getCell(r, columnIndex);
CellType type = c.getCellType();
if (type == CellType.FORMULA) {
switch (c.getCachedFormulaResultType()) {
case NUMERIC:
if (DateUtil.isCellDateFormatted(c)) {
value = (new SimpleDateFormat("dd-MM-yyyy").format(c.getDateCellValue()));
data.add(value); // Date should display 03-10-2018 but it's showing 23-01-2018
} else {
value = (c.getNumericCellValue()) + "";
data.add(value);
}
break;
case STRING:
value = c.getStringCellValue();
data = new LinkedList <String>(Arrays.asList(value.split(";")));
break;
}
}
I don't know why it's showing date from January with the formula applied TODAY() + 1
Similar to this another function TODAY() + 15 returning the 22-04-2018.
As stated in Formula Evaluation:
"The Excel file format (both .xls and .xlsx) stores a "cached" result
for every formula along with the formula itself. This means that when
the file is opened, it can be quickly displayed, without needing to
spend a long time calculating all of the formula results. It also
means that when reading a file through Apache POI, the result is
quickly available to you too!"
So all formulas will have cached results stored from the last time they were evaluated. This is either the last time the workbook was opened in Excel, recalculated and saved or from the last time an evaluation was be done outside of Excel.
So if a cell having the formula =TODAY() has a cached result of 22-01-2018 stored, then the workbook was evaluated on January 22, 2018 the last time.
To get always current formula results you need evaluating the formulas first before reading. Simplest way:
...
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
...
Or you are using a DataFormatter together with a FormulaEvaluator:
...
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
...
Cell cell = CellUtil.getCell(...);
...
String value = formatter.formatCellValue(cell, evaluator);
...
In my excel sheet many cells contain formulas, i don't want to recalculate these formulas when i read the excel with Apache POI.
The way i do that:
if(cell.getCellType() == XSSFCell.CELL_TYPE_FORMULA) {
//System.out.println("Formula is " + cell.getCellFormula());
switch(cell.getCachedFormulaResultType()) {
case XSSFCell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() +" ");
break;
case XSSFCell.CELL_TYPE_STRING:
System.out.print(cell.getRichStringCellValue()+" ");
break;
}
}
This helps me in getting the raw value in the cell.
For example if the cell has value 19.5%, this will give me 0.195456 .
I want to get the formatted value.
One way to get the formatted value is:
DataFormatter formatter = new DataFormatter();
System.out.print(formatter.formatCellValue(cell));
This works well for regular cells, but for cells with formulas, this actually gets the formula string and displays it, i.e., it does not get the cached value and formats it, rather it just returns the formula string.
Is there a way to format a value after retrieving it from CELL_TYPE_FORMULA
It's possible to directly format the cached value of a cell without using an evaluator. It's useful in case of values that cannot be recalculated because of third party plugin or unavailable external Data in the cell formula.
This code can be used to do that:
final DataFormatter dataFormatter = new DataFormatter();
final CellStyle cellStyle = cell.getCellStyle();
final String formtatedValue = dataFormatter.formatRawCellContents(cell.getNumericCellValue(), cellStyle.getDataFormat(), cellStyle.getDataFormatString());
System.out.println(formattedValue);
A formatter is still used but the method formatRawCellContents is called to manually format the cell cached value with its style.
It should work if you pass in a FormulaEvaluator in the call to formatCellValue, i.e.
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
System.out.print(formatter.formatCellValue(cell, evaluator));
We have one existing application where we read one text file and write into excel using java. Text file will have first row as header and subsequent rows as records which is fetched from database.
Currently while writing into excel, all the columns are getting converted into text format. We want to convert one column(consider column Z) as number.
String [] column = line.split("\\|~");
for (int i = 0; i < column.length; i++) {
Cell tmpCell = row.createCell(i);
tmpCell.setCellValue(new HSSFRichTextString(column[i].trim()));
}
I am new to java, need your help in resolving this issue.
Thanks
Santhosh
You can write to cell like this
cell.setCellValue(12345.00000)
But this alone will not be enough in case where you don't want to truncate. Using style and dataformats, you can avoid truncation. E.g.
CellStyle cellStyle = wb.createCellStyle();
DataFormat df = wb.createDataFormat();
cellStyle.setDataFormat(df.getFormat("0.0")); //you can adjust it as per your requirments
cell.setCellStyle(cellStyle);
I'm able to get cells to format as Dates, but I've been unable to get cells to format as currency... Anyone have an example of how to create a style to get this to work? My code below show the styles I'm creating... the styleDateFormat works like a champ while styleCurrencyFormat has no affect on the cell.
private HSSFWorkbook wb;
private HSSFCellStyle styleDateFormat = null;
private HSSFCellStyle styleCurrencyFormat = null;
......
public CouponicsReportBean(){
wb = new HSSFWorkbook();
InitializeFonts();
}
public void InitializeFonts()
{
styleDateFormat = wb.createCellStyle();
styleDateFormat.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
styleCurrencyFormat = wb.createCellStyle();
styleCurrencyFormat.setDataFormat(HSSFDataFormat.getBuiltinFormat("$#,##0.00"));
}
After digging through the documentation a bit more, I found the answer:
http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFDataFormat.html
Just need to find an appropriate pre-set format and supply the code.
styleCurrencyFormat.setDataFormat((short)8); //8 = "($#,##0.00_);[Red]($#,##0.00)"
Here are more examples:
http://www.roseindia.net/java/poi/setDataFormat.shtml
For at least Excel 2010:
Go into Excel. Format a cell they way you want it.
Then go back into the format dialogue. Select custom.
Copy paste the text it has on the top row under Type: into
createHelper.createDataFormat().getFormat("<here>");
Example:
createHelper.createDataFormat().getFormat("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(#_)"); //is the "Accounting" format.
Make sure you set your populate your cells by using a double.
Using the index may cause problems with different versions of Excel. Note that the new format you create above ends up in the custom dialogue from step two.
Just an update to above reply. short '8' doesn't work for me but the '7' does.
cell.setCellValue(416.17);
cellStyle.setDataFormat((short)7);
cell.setCellStyle(cellStyle);
O/P is $416.00
You can try this code to format your cell with currency mode (with thowsand separator like used in Brazil or Germany. Eg. 12.345,67):
HSSFCellStyle cell = yourWorkBook.createCellStyle();
CreationHelper ch = yourWorkBook.getCreationHelper();
cell.setDataFormat(ch.createDataFormat().getFormat("#,##0.00;\\-#,##0.00"));