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"));
Related
I am going crazy trying to parse an Excel from Java using Apache POI and I ami finding the following problem parsing a specific column containin dates.
This is the column into my Excel file:
As you can see this column contains date fields but some cells of this column contains number values some other celles contains text values (I can see it using the TYPE() Excel function). I really don't know how it is possible because all the cell contains date fields. Some idea?
Anyway in my code I am trying to handle this strange situation in this way:
if(currentRow.getCell(20) != null && !currentRow.getCell(20).toString().trim().isEmpty()) {
if(currentRow.getCell(20).getCellType().toString().equals("STRING")) {
System.out.println("Data sottoscrizione contratto è STRING: " + currentRow.getCell(20).toString());
}
else if(currentRow.getCell(20).getCellType().toString().equals("NUMERIC")) {
System.out.println("Data sottoscrizione contratto è NUMERIC");
String dateAsString = currentRow.getCell(20).toString();
System.out.println("DATA SOTTOSCRIZIONE CONTRATTO: " + currentRow.getCell(20).toString());
}
}
In this way I can handle both the case trying to convert to a date.
And here my problem. When it found an Excel numeric value in enter into the if NUMERIC case
and printing the cell value by:
System.out.println("DATA SOTTOSCRIZIONE CONTRATTO: " + currentRow.getCell(20).toString());
I obtain printed the value 16-ott-2017 related to the date value 16/10/2017
And here some doubts: Why am I obtaining in this format instead something like 16/10/2017.
16-ott-2017 should be the italian formattation of the date. How can I convert it into a propper Date object?
Buon giorno!
You are currently using the toString() method of the cell, which will not be very accurate in returning numeric values or even dates. It might work sometimes, but it won't do always.
Use the methods that get you a real value, like Cell.getNumericCellValue(), Cell.getDateCellValue() (outdated because it returns a java.util.Date) or Cell.getLocalDateTimeCellValue(). If your cell just contains text, like "16-ott-2020", use the getStringCellValue() and convert the value returned to a LocalDate (or LocalDateTime depends on if time of day matters for you).
Here's an example of the conversion (to a LocalDate):
public static void main(String[] args) {
// assuming you alread received the value as String
String cellStringValue = "16-ott-2020";
// provice a formatter that can parse Italian month names (or days of week)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.ITALIAN);
// parse the String to a LocalDate
LocalDate sediciOttobreDuemilaEVenti = LocalDate.parse(cellStringValue, dtf);
// and print its default value
System.out.println(sediciOttobreDuemilaEVenti);
// alternatively use the same formatter for output
System.out.println(sediciOttobreDuemilaEVenti.format(dtf));
}
The output of that code is
2020-10-16
16-ott-2020
case NUMERIC:
if(Cell.getLocalDateTimeCellValue()!=null) {
LocalDateTime actualdate = Cell.getLocalDateTimeCellValue();
String formattedDate = actualdate.format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
System.out.println(formattedDate);
}
break;
switch (Cell.getCellType()) {
case STRING:
System.out.print(Cell.getStringCellValue());
break;
case NUMERIC:
DataFormatter df = new DataFormatter();
String CellValue = df.formatCellValue(Cell);
System.out.println(CellValue);
break;
case BOOLEAN:
System.out.print(Cell.getBooleanCellValue());
break;
case BLANK:
System.out.println("");
}
System.out.print(" | ");
}
This question already has answers here:
Using Apache POI how to read a specific excel column
(7 answers)
Closed 4 years ago.
Actually i have many column and rows rumber in excel which are hard to count.But in my program i have tried to print for column 0,1,2,3.I am able to print upto the column i can count.But when i move further i cannot get the required information about that column to print the data. Suppose the datas are located in GQ column then how can i only print the datas of GQ column??The code i have posted here prints all the columns and rows.But i need only specific of GQ column.
public class Program {
public static final String SAMPLE_XLSX_FILE_PATH = "D:\\Book1.xlsx";
public static void main(String[] args) throws IOException, InvalidFormatException {
// Creating a Workbook from an Excel file (.xls or .xlsx)
Workbook workbook = WorkbookFactory.create(new File(SAMPLE_XLSX_FILE_PATH));
// Retrieving the number of sheets in the Workbook
System.out.println("Workbook has " + workbook.getNumberOfSheets() + " Sheets : ");
// 2. Or you can use a for-each loop
System.out.println("Retrieving Sheets using for-each loop");
for(Sheet sheet: workbook) {
System.out.println("=> " + sheet.getSheetName());
}
// Getting the Sheet at index zero
Sheet sheet = workbook.getSheetAt(0);
// Create a DataFormatter to format and get each cell's value as String
DataFormatter dataFormatter = new DataFormatter();
// using for each loop to iterate over rows and colums
System.out.println("\n\nIterating over Rows and Columns using for-each loop\n");
for (Row row: sheet) {
//System.out.println(row.getCell(0));
for(Cell cell: row) {
String cellValue = dataFormatter.formatCellValue(cell);
System.out.print(cellValue + "\t");
}
System.out.println();
}
// Closing the workbook
workbook.close();
}
}
To convert the column type to numeric, try the following code
CellStyle numericStyle = workbook.createCellStyle();
numericStyle.setDataFormat(BuiltinFormats.getBuiltinFormat(2)); // 2 For Number
worksheet.setDefaultColumnStyle(<id_for_GQ>, numericStyle);
The complete list of BuiltinFormats formats can be seen, here
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();
}
}
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.
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.