How to read Excel cell having Date with Apache POI? - java

I'm using Apache POI 3.6, I want to read an excel file which has a date like this 8/23/1991.
switch (cell.getCellType()) {
...
...
case HSSFCell.CELL_TYPE_NUMERIC:
value = "NUMERIC value=" + cell.getNumericCellValue();
break;
...
}
But it takes the numeric value type and returns the value like this 33473.0.
I've tried to use Numeric Cell Type although with no luck.
dbltemp=row.getCell(c, Row.CREATE_NULL_AS_BLANK).getNumericCellValue();
if (c == 6 || c == 9) {
strTemp= new String(dbltemp.toString().trim());
long tempDate = Long.parseLong(strTemp);
Date date = new Date(tempDate);
strVal = date.toString();
}
How can I fix my problem?

NOTE: HSSFDateUtil is deprecated
If you know which cell i.e. column position say 0 in each row is going to be a date, you can go for
row.getCell(0).getDateCellValue() directly.
http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFCell.html#getDateCellValue()
UPDATE: Here is an example - you can apply this in your switch case code above. I am checking and printing the Numeric as well as Date value. In this case the first column in my sheet has dates, hence I use row.getCell(0).
You can use the if (HSSFDateUtil.isCellDateFormatted .. code block directly in your switch case.
if (row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_NUMERIC)
System.out.println ("Row No.: " + row.getRowNum ()+ " " +
row.getCell(0).getNumericCellValue());
if (HSSFDateUtil.isCellDateFormatted(row.getCell(0))) {
System.out.println ("Row No.: " + row.getRowNum ()+ " " +
row.getCell(0).getDateCellValue());
}
}
The output is
Row No.: 0 39281.0
Row No.: 0 Wed Jul 18 00:00:00 IST 2007
Row No.: 1 39491.0
Row No.: 1 Wed Feb 13 00:00:00 IST 2008
Row No.: 2 39311.0
Row No.: 2 Fri Aug 17 00:00:00 IST 2007

Yes, I understood your problem.
If is difficult to identify cell has Numeric or Data value.
If you want data in format that shows in Excel, you just need to format cell using DataFormatter class.
DataFormatter dataFormatter = new DataFormatter();
String cellStringValue = dataFormatter.formatCellValue(row.getCell(0));
System.out.println ("Is shows data as show in Excel file" + cellStringValue); // Here it automcatically format data based on that cell format.
// No need for extra efforts

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
if(cell.getCellTypeEnum() == CellType.NUMERIC||cell.getCellTypeEnum() == CellType.FORMULA)
{
String cellValue=String.valueOf(cell.getNumericCellValue());
if(HSSFDateUtil.isCellDateFormatted(cell))
{
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date date = cell.getDateCellValue();
cellValue = df.format(date);
}
System.out.println(cellValue);
}

For reading date cells this method has proven to be robust so far:
private LocalDate readCellAsDate(final Row row, final int pos) {
if (pos == -1) {
return null;
}
final Cell cell = row.getCell(pos - 1);
if (cell != null) {
cell.setCellType(CellType.NUMERIC);
} else {
return null;
}
if (DateUtil.isCellDateFormatted(cell)) {
try {
return cell.getDateCellValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
} catch (final NullPointerException e) {
logger.error(e.getMessage());
return null;
}
}
return null;
}

You need the DateUtils: see this article for details.
Or, better yet, use Andy Khan's JExcel instead of POI.

Apache Poi has a DateUtil.isCellDateFormatted(XSSFCell) it works great.
Object objData = switch (cell.getCellType()){
case NUMERIC ->{
if(DateUtil.isCellDateFormatted(cell)){
yield cell.getDateCellValue();
}else{
yield cell.getNumericCellValue();
}
} //The rest of the cellTypes need to be implemented.
}
objData can now be tested for Date or Double.

You can use CellDateFormatter to fetch the Date in the same format as in excel cell. See the following code:
CellValue cv = formulaEv.evaluate(cell);
double dv = cv.getNumberValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = HSSFDateUtil.getJavaDate(dv);
String df = cell.getCellStyle().getDataFormatString();
strValue = new CellDateFormatter(df).format(date);
}

If you know the cell number, then i would recommend using getDateCellValue() method
Here's an example for the same that worked for me -
java.util.Date date = row.getCell().getDateCellValue();
System.out.println(date);

Try this code.
XSSFWorkbook workbook = new XSSFWorkbook(new File(result));
XSSFSheet sheet = workbook.getSheetAt(0);
// Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
// For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
if (cell.getNumericCellValue() != 0) {
//Get date
Date date = row.getCell(0).getDateCellValue();
//Get datetime
cell.getDateCellValue()
System.out.println(date.getTime());
}
break;
}
}
}
Hope is help.

Related

Get raw date value with Apache POI from a excel cell

I have a excel with a date "30.08.2022", and this excel field is formatted as date.
But when I try to get a raw value i only get "44803".
No matter what I try I don't get the raw string. I just want to have the direct string.
I have already tried with formatter.formatCellValue(cell); but then I get a formatted String value 8/30/22 . But I need the same value like in the cell
public class Main {
public static void main(String[] args) throws IOException {
String excelName = "<path to exce>";
String excelSheet = "<sheetname>";
try (XSSFWorkbook workbook = new XSSFWorkbook(excelName)) {
DataFormatter formatter = new DataFormatter();
XSSFSheet sheet = workbook.getSheet(excelSheet);
XSSFRow row1 = sheet.getRow(0);
//Date
XSSFCell cell1 = row1.getCell(0);
System.out.println(cell1.getRawValue());//44803
System.out.println( formatter.formatCellValue(cell1));//8/30/22
}
}
}
As shown here, the value 44803 is the correct number of days since the Excel epoch. You can use getDataFormatString() from the cell's style to obtain the format string used by Excel to display the value. The output below includes the formatted Date, followed by [the raw data : the data format index : and corresponding format string]:
Tue Aug 30 00:00:00 EDT 2022 [44803:59:m/d/yyyy]
if (DateUtil.isCellDateFormatted(cell)) {
System.out.print(cell.getDateCellValue() + getFormat(cell));
}
…
private static String getFormat(Cell cell) {
return " ["
+ (int) cell.getNumericCellValue() + ":"
+ cell.getCellStyle().getDataFormat() + ":"
+ cell.getCellStyle().getDataFormatString() + "]";
}
Conversely, given an instance of DataFormatter, you can format the raw date with the specified format, yielding 8/30/2022:
var df = new DataFormatter();
System.out.println(df.formatRawCellContents(44803, 59, "m/d/yyyy"));

Get Date value of cell with date formula from Excel using Apache POI Java

I was trying to read from excel file everything work good with normal cell values. But when came to formulas, especially Date fields, I am not able to get any Date values.
How can i check for date type in Evaluated CellValue?? and how to get date value?
My code is given below.
Cell cell = nextRow.getCell(cellIndex, Row.CREATE_NULL_AS_BLANK);
if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
CellValue formulaValue = evaluator.evaluate(cell);
switch (formulaValue.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: {
int numbericValue = formulaValue.getNumericValue(); // 42909.0
if (isCellDate?) { //What should i check here?
// DATE THINGS
// how to convert numeric value 42909.0 to date??
} else {
// NUMERIC THINGS
}
break;
}
default:
// STRING - ERROR - BLANK - NUMERIC THINGS
break;
}
}
HSSFDateUtil : Helped to solve my issue. my solution is :
case Cell.CELL_TYPE_NUMERIC: {
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = HSSFDateUtil.getJavaDate(formulaValue.getNumberValue());
System.out.println(date);
} else {
System.out.println(cell.getNumericCellValue());
}
break;
}

Blank rows is skipped while reading data from the excel sheet

i try to read the data from excel and store in vector list. But i'm having two issue when applied the following code in my system, hope can get some guidance.
1) When i run the system it will read all the data from the excel file but it skipped those blank data. How can i make it as empty string rather than skipped. Result : from this Excel file you can see that between value 145 and 2DHatchback is blank data, but system will skipped it, how can i make it as empty string " "?.
[PAS, 04/01/2015, ALFA ROMEO, 145, 2D HATCHBACK, 5 SP MANUAL, 1598.42, GZ095G, 02, 01, 02, MULTI POINT F/INJ, ITALY, 9400, 7800]
2) When i tried to deleted few rows of data in excel, my vector result still will keep the deleted data but remain as empty.
Result: from this Excel file if i manually delete row 11 and row 12, when i system.out.println the vector result it will show as [, , ] , [, , ] for deleted rows.
Readexcel.java
public Vector getexcel(String filename)
{
String filetype = filename.substring(filename.lastIndexOf(".")+1);
Vector cellVectorHolder = new Vector();
try
{
Workbook workBook = WorkbookFactory.create(new FileInputStream(filename));
Sheet sheet = workBook.getSheetAt(0);
Iterator rowIter = sheet.rowIterator();
if(filetype.equals("xlsx"))
{
while(rowIter.hasNext())
{
XSSFRow row = (XSSFRow) rowIter.next();
Iterator cellIter = row.cellIterator();
Vector cellStoreVector=new Vector();
if(row.getRowNum()>1)
{
while(cellIter.hasNext())
{
XSSFCell cell = (XSSFCell) cellIter.next();
Integer cellType = cell.getCellType();
String cellTypeDesc = "";
String cellValue = "";
switch (cellType)
{
case 0:
cellTypeDesc = "NUMERIC";
String doubleValue = cell.getRawValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
if (HSSFDateUtil.isValidExcelDate(Double.parseDouble(doubleValue))) {
Date date = HSSFDateUtil.getJavaDate(Double.parseDouble(doubleValue));
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
cellValue = df.format(date);
}
} else {
cellValue = String.valueOf(doubleValue);
}
break;
case 1:
cellTypeDesc = "STRING";
cellValue = cell.getStringCellValue();
break;
case 3:
cellTypeDesc = "BLANK";
cellValue = "";
break;
}
cellStoreVector.addElement(cellValue);
}
}
cellVectorHolder.addElement(cellStoreVector);
}
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
return cellVectorHolder;
}
Excel stores empty fields, so you need to do manual checking
You should check for rows containing only empty cells. Just write a check before you add it to the cellStoreVector
Also, if the rowNumber increases by more than 1, you could add empty row-vectors yourself. So store the previous rowNumber and compare to the current rowNumber

Excel changing the number format to date when the month starts with zero.Is it a bizzare bug?

I have a date in the format 04/08/2014(dd/mm/yyy). I copied the string and placed it in excel it gets turned it into 04-08-2014. For other dates where the "mm" doesn't starts with 0 its normal for Example if i copied 12/11/2013 and placed it in excel it gets normally pasted as 12/13/2014.
Actually i am trying to generate an excel with java the code is attached below
public void exportExcel(){
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
String filename = "ExcelList.csv";
try{
ec.responseReset();
ec.setResponseContentType("text/csv");
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Writer writer = ec.getResponseOutputWriter();
if(PageList != null && PageList.size() > 0){
writer.append(toCsvField("Name")).append(',')
.append(toCsvField("Code")).append(',')
.append(toCsvField("Description")).append(',')
.append('\n');
for (PageBean View : PageList) {
writer.append(toCsvField(View.Name)).append(',')
.append(toCsvField(View.Number)).append(',')
.append(toCsvField(View.Description)).append(',');
}
}
fc.responseComplete();
}catch(Exception e){
}
}
public static String toCsvField(Object value) {
if (value == null) {
return "";
}
String field = String.valueOf(value).replace("\"", "\"\"");
if (field.indexOf(',') > -1 || field.indexOf('"') > -1) {
field = '"' + field + '"';
}
return field;
}
whats wrong with the month field gets starts with 0. Please help.
Steps to follow:
get the locale of client that is set as browser language
format the data based on client locale
write formatted data in csv
Note: csv file must be opened in the same locale of the system in which it is download.
If csv is download in German locale (read from browser) and you are tring to open it in French locale (read from system regional & language settings) then it will mismatch/corrupt the data in excel.
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Locale;
// 04/08/2014(dd/mm/yyy)
Calendar cal = Calendar.getInstance();
cal.set(2014, 7, 4, 0, 0, 0);
double no = 123456.7890;
Date date = cal.getTime();
System.out.println(date);
for (Locale locale : Locale.getAvailableLocales()) {
NumberFormat numberFormat = DecimalFormat.getNumberInstance(locale);
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale);
System.out.println("========================================");
System.out.println(locale.getDisplayCountry() + " - " + locale.toString());
System.out.println(numberFormat.format(no));
System.out.println(dateFormat.format(date));
}
Output for Portugal is 04-08-2014
It means if your system's regional & language setting is set for Portugal and you try to paste 04/08/2014(dd/mm/yyy) in excel then it will be automatically converted to 04-08-2014.
Add sep=; at the first line of csv so that excel can read it to split the columns into cells because by default comma(,) is used as separator but it creates problem in few locales where comma is used as grouping separator or decimal separator in numbers.
Your csv will look like this for Portugal locale:
sep=;
"Name";"Number";"DOB"
"A";"123.456,789";"04-08-2014"
"B";"123.456,789";"12-11-2013"
Links to read client's locale:
In JSF - Getting the Client's Locale (To Display time in browser's timezone)
How to detect client locale in JSF application?
Try the below code using apache poi framework this should help.
public void exportExcel(){
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
String filename = "ExportList.xlsx";
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Export Data");
int rownum = 0;
Row headRow = sheet.createRow(rownum++);
Cell cell1 = headRow.createCell(0);
Cell cell2 = headRow.createCell(1);
Cell cell3 = headRow.createCell(2);
Cell cell4 = headRow.createCell(3);
cell1.setCellValue("Name");
cell2.setCellValue("Age");
cell3.setCellValue("Sex");
for(Bean view : list){
int cellnum = 0;
Row row = sheet.createRow(rownum++);
row.createCell(cellnum++).setCellValue(view.name);
row.createCell(cellnum++).setCellValue(view.age);
row.createCell(cellnum++).setCellValue(view.sex);
}
try{
ec.responseReset();
ec.setResponseContentType("text/xlsx");
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
//to align column vertically
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
sheet.autoSizeColumn(3);
workbook.write(ec.getResponseOutputStream());
fc.responseComplete();
}
catch (Exception e){
e.printStackTrace();
}
}

DataFormatter on cell containing date renders two digits years

I needed to get cell data from Excel files as they look like and bumped to DataFormatter class of Apache PO. This works like a charm except for cells containing date. Below is my code:
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
StringBuilder rowDataBuilder = new StringBuilder();
int iCellCount = row.getLastCellNum();
for (int i = 0; i < iCellCount; i++)
{
Cell cell = row.getCell(i, Row.CREATE_NULL_AS_BLANK);
rowDataBuilder.append(dataFormatter.formatCellValue(cell));
rowDataBuilder.append(" | ");
}
_LOG.info("-----> row data: " + rowDataBuilder.toString());
}
For example, a cell contains 5/3/2013, I only get 5/3/13. Would there be any solutions for this?
For fetching the date in desired format you can use following:
SimpleDateFormat DtFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date=Test.getRow(RowNum).getCell(CellNum).getDateCellValue();
System.out.println(DtFormat.format(date).toString());
And now if the cell value is 05/03/2013, it will give o/p as 05/03/2013. I hope this will resolve your problem.

Categories

Resources