apache POI reads text column as numeric - java

I'm working on a function where I have to store numbers received via uploading an excel file. It's written in Java, using apache poi library, under Spring framework (which is irrelevant).
The file which I'm trying to upload (Note that the column has already been set to Text) :
Code is as follow :
// function accepts "MultipartFile inputFile"
InputStream is = inputFile.getInputStream();
StreamingReader reader = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).sheetIndex(0)
.read(is);
for (Row row : reader) {
System.out.println("Reading next row.");
System.out.println("row[0] is of type " + row.getCell(0).getCellType());
Cell cell = row.getCell(0);
String value = "";
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
value = cell.getStringCellValue().replaceAll("[\\D]", "");
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
value = NumberToTextConverter.toText(cell.getNumericCellValue());
}
System.out.println("Value is " + value);
}
And I'm getting below output :
Reading next row.
row[0] is of type 0 // Which is equals to Cell.CELL_TYPE_NUMERIC
Value is 166609999
Issue is that I'd require to read it as '0166609999' instead of '166609999', strangely this only happens to xlsx file, if I save it as xls format and re-upload the file, I have no issue with detecting its cell type. Any ideas?
Edited for being marked as duplication:
Given answer https://stackoverflow.com/a/19401902/1131470 uses DataFormatter class which is not supported when we are streaming the sheet, as the Cell object retrieved is going to be a StreamingCell object, which throws an exception if we make a call to getCellStyle() function.
As of 29th Mar 2016
Seems that the class StreamingCell does not support DataFormatter, where DataFormatter is the only class available at the moment to grab what Excel displays. So current solution would be sticking back to reading the whole Excel file into memory. If anyone found an answer in future you may please post an answer here, I'd greatly appreciate that, as current solution is an absolutely terrible one.
As of 31st Mar 2016
Special thanks to Axel who pointed out its library version issue, updating streamer jar file to 0.2.12 solves the problem. Thanks!

Downloaded your file. Downloaded xlsx-streamer-0.2.12.jar, slf4j-api-1.7.20.jar and slf4j-nop-1.7.20.jar and placed in class path.
Having following code:
import com.monitorjbl.xlsx.*;
import org.apache.poi.ss.usermodel.*;
import java.io.*;
class StreamingReaderTest {
public static void main(String[] args) throws Exception {
try (
InputStream is = new FileInputStream(new File("/home/axel/Downloads/test_formatted_number.xlsx"));
StreamingReader reader = StreamingReader.builder()
.rowCacheSize(100)
.bufferSize(4096)
.sheetIndex(0)
.read(is);
) {
for (Row row : reader) {
System.out.println("row[0] is of type " + row.getCell(0).getCellType());
Cell cell = row.getCell(0);
String value = "";
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
value = cell.getStringCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
value = "" + cell.getNumericCellValue();
}
System.out.println("Value is " + value);
}
}
}
}
Gives me:
So no problem here.
If I use DataFormatter with numeric cell values:
import com.monitorjbl.xlsx.*;
import org.apache.poi.ss.usermodel.*;
import java.io.*;
class StreamingReaderTest {
public static void main(String[] args) throws Exception {
try (
InputStream is = new FileInputStream(new File("/home/axel/Downloads/test_formatted_number.xlsx"));
StreamingReader reader = StreamingReader.builder()
.rowCacheSize(100)
.bufferSize(4096)
.sheetIndex(0)
.read(is);
) {
for (Row row : reader) {
System.out.println("row[0] is of type " + row.getCell(0).getCellType());
Cell cell = row.getCell(0);
String value = "";
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
value = cell.getStringCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
value = new DataFormatter().formatCellValue(cell);
}
System.out.println("Value is " + value);
}
}
}
}
and put the number 166609647 in A2 formatted as 0000000000. then I get:

Why
.replaceAll("[\D]", "");
Works fine for me, just tried.
Wonder what the issue is here.
fis = new FileInputStream(inputFile);
XSSFWorkbook inputWorkBook = new XSSFWorkbook (fis);
XSSFSheet inputSheet = inputWorkBook.getSheetAt(0);
Iterator<Row> rowIterator = inputSheet.iterator();
while(rowIterator.hasNext())
{
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
switch (cell.getCellType())
{
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t");
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t");
break;
default :
}
}
System.out.println("");
}

Related

Apache POI: non-deprecated way to get cell content? [duplicate]

I'm reading an excel-file (file extension xlsx) using org.apache.poi 3.15.
This is my code:
try (FileInputStream fileInputStream = new FileInputStream(file); XSSFWorkbook workbook = new XSSFWorkbook(file)) {
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "(Integer)\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "(String)\t");
break;
}
}
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
I get a warning that cell.getCellType() is deprecated. Can anyone tell me the alternative?
The accepted answer shows the reason for the deprecation but misses to name the alternative:
CellType getCellTypeEnum()
where the CellType is the enum decribing the type of the cell.
The plan is to rename getCellTypeEnum() back to getCellType() in POI 4.0.
You can use:
cell.getCellTypeEnum()
Further to compare the cell type, you have to use CellType as follows:-
if(cell.getCellTypeEnum() == CellType.STRING){
.
.
.
}
You can Refer to the documentation. Its pretty helpful:-
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
Use getCellType()
switch (cell.getCellType()) {
case BOOLEAN :
//To-do
break;
case NUMERIC:
//To-do
break;
case STRING:
//To-do
break;
}
FileInputStream fis = new FileInputStream(new File("C:/Test.xlsx"));
//create workbook instance
XSSFWorkbook wb = new XSSFWorkbook(fis);
//create a sheet object to retrieve the sheet
XSSFSheet sheet = wb.getSheetAt(0);
//to evaluate cell type
FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
for(Row row : sheet)
{
for(Cell cell : row)
{
switch(formulaEvaluator.evaluateInCell(cell).getCellTypeEnum())
{
case NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t");
break;
case STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
default:
break;
}
}
System.out.println();
}
This code will work fine. Use getCellTypeEnum() and to compare use just NUMERIC or STRING.
From the documentation:
int getCellType()
Deprecated. POI 3.15. Will return a CellType enum in the future.
Return the cell type. Will return CellType in version 4.0 of POI. For forwards compatibility, do not hard-code cell type literals in your code.
It looks that 3.15 offers no satisfying solution: either one uses the old style with Cell.CELL_TYPE_*, or we use the method getCellTypeEnum() which is marked as deprecated.
A lot of disturbances for little add value...
For POI 3.17 this worked for me
switch (cellh.getCellTypeEnum()) {
case FORMULA:
if (cellh.getCellFormula().indexOf("LINEST") >= 0) {
value = Double.toString(cellh.getNumericCellValue());
} else {
value = XLS_getDataFromCellValue(evaluator.evaluate(cellh));
}
break;
case NUMERIC:
value = Double.toString(cellh.getNumericCellValue());
break;
case STRING:
value = cellh.getStringCellValue();
break;
case BOOLEAN:
if(cellh.getBooleanCellValue()){
value = "true";
} else {
value = "false";
}
break;
default:
value = "";
break;
}
You can do this:
private String cellToString(HSSFCell cell) {
CellType type;
Object result;
type = cell.getCellType();
switch (type) {
case NUMERIC : //numeric value in excel
result = cell.getNumericCellValue();
break;
case STRING : //String Value in Excel
result = cell.getStringCellValue();
break;
default :
throw new RuntimeException("There is no support for this type of value in Apche POI");
}
return result.toString();
}

Alternative to deprecated getCellType

I'm reading an excel-file (file extension xlsx) using org.apache.poi 3.15.
This is my code:
try (FileInputStream fileInputStream = new FileInputStream(file); XSSFWorkbook workbook = new XSSFWorkbook(file)) {
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "(Integer)\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "(String)\t");
break;
}
}
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
I get a warning that cell.getCellType() is deprecated. Can anyone tell me the alternative?
The accepted answer shows the reason for the deprecation but misses to name the alternative:
CellType getCellTypeEnum()
where the CellType is the enum decribing the type of the cell.
The plan is to rename getCellTypeEnum() back to getCellType() in POI 4.0.
You can use:
cell.getCellTypeEnum()
Further to compare the cell type, you have to use CellType as follows:-
if(cell.getCellTypeEnum() == CellType.STRING){
.
.
.
}
You can Refer to the documentation. Its pretty helpful:-
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
Use getCellType()
switch (cell.getCellType()) {
case BOOLEAN :
//To-do
break;
case NUMERIC:
//To-do
break;
case STRING:
//To-do
break;
}
FileInputStream fis = new FileInputStream(new File("C:/Test.xlsx"));
//create workbook instance
XSSFWorkbook wb = new XSSFWorkbook(fis);
//create a sheet object to retrieve the sheet
XSSFSheet sheet = wb.getSheetAt(0);
//to evaluate cell type
FormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
for(Row row : sheet)
{
for(Cell cell : row)
{
switch(formulaEvaluator.evaluateInCell(cell).getCellTypeEnum())
{
case NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t");
break;
case STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
default:
break;
}
}
System.out.println();
}
This code will work fine. Use getCellTypeEnum() and to compare use just NUMERIC or STRING.
From the documentation:
int getCellType()
Deprecated. POI 3.15. Will return a CellType enum in the future.
Return the cell type. Will return CellType in version 4.0 of POI. For forwards compatibility, do not hard-code cell type literals in your code.
It looks that 3.15 offers no satisfying solution: either one uses the old style with Cell.CELL_TYPE_*, or we use the method getCellTypeEnum() which is marked as deprecated.
A lot of disturbances for little add value...
For POI 3.17 this worked for me
switch (cellh.getCellTypeEnum()) {
case FORMULA:
if (cellh.getCellFormula().indexOf("LINEST") >= 0) {
value = Double.toString(cellh.getNumericCellValue());
} else {
value = XLS_getDataFromCellValue(evaluator.evaluate(cellh));
}
break;
case NUMERIC:
value = Double.toString(cellh.getNumericCellValue());
break;
case STRING:
value = cellh.getStringCellValue();
break;
case BOOLEAN:
if(cellh.getBooleanCellValue()){
value = "true";
} else {
value = "false";
}
break;
default:
value = "";
break;
}
You can do this:
private String cellToString(HSSFCell cell) {
CellType type;
Object result;
type = cell.getCellType();
switch (type) {
case NUMERIC : //numeric value in excel
result = cell.getNumericCellValue();
break;
case STRING : //String Value in Excel
result = cell.getStringCellValue();
break;
default :
throw new RuntimeException("There is no support for this type of value in Apche POI");
}
return result.toString();
}

How to check if excel file is blank?

I have excel file (*.xls or *.xlxs) which can have records or no records. First I store the file in some temp location, then copy the contents of the file and then tried to read the file. This scenario works fine if the excel sheet contains records but if the sheet has no record and the file is empty. This scenario does not work. I am using apache-poi to read the excel file contents.
public static boolean isRowEmpty(Row row) {
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
Cell cell = row.getCell(c);
if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
return false;
}
}
return true;
}
I get IOException : unable to read entire header 0 bytes read expected 512 bytes. Can somebody suggest me a way to get rid of this exception and check the excel file is empty?
Googling and some experiments with org.apache.poi library suggest to me that it is abnormal to check if xls file is empty without knowing even approximately the data structure within it. It's as hard as to say if, for example, Oracle BD is empty.
Any way, you are able to fetch quantity of sheets then iterate over all of them, check rows and cells and consider file is empty if you found nothing.
HSSFWorkbook wBook = new HSSFWorkbook(new FileInputStream("your_path"));
for(int i = 0; i < wBook.getNumberOfSheets(); i++){
System.out.println("Sheet " + i + " has data: " + isSheetEmpty(wBook.getSheetAt(i)));
}
boolean isSheetEmpty(HSSFSheet sheet){
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
if(!cell.getStringCellValue().isEmpty()){
return true;
}
}
}
return false;
}
Using Apache Poi (org.apache.poi) for the solution and skipping the parts where I actually get the Workbook (excel) and get access to it's sheets.
If you want to know if sheet is empty use this, modify the solution to loop through sheets to find out if all of the sheets in the file are empty.
if (sheet.getLastRowNum() == 0 && sheet.getRow(0) == null) {
// This is the case when the sheet is empty!
}
getLastRowNum() - returns 0 in case of empty sheet or if there is only data in the first row
getRow(0) - returns null if there is no data in the row
NOTE: the solution doesn't take empty strings, spaces, empty lines and etc. into account
Below code worked for me.
import java.util.Iterator;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
XSSFSheet sheet = wb.getSheetAt(0);
private boolean isSheetEmpty(XSSFSheet sheet) {
Iterator rows = sheet.rowIterator();
Row row = null;
Cell cell = null;
while (rows.hasNext()) {
row = (Row) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext()) {
cell = (Cell) cells.next();
if (!cell.getStringCellValue().isEmpty()) {
return true;
}
}
}
return false;
}
if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return true;
}
return false;
Try this one !

read excel file using Apache POI

I have created this code to read the contents of excel files using Apache POI. I am using eclipse as editor but when i ran the code i have problem in the line that I have in bold. What's the problem?
The content of excel is the following:
Emp ID Name Salary
1.0 john 2000000.0
2.0 dean 4200000.0
3.0 sam 2800000.0
4.0 cass 600000.0
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public class ExcelRead {
public static void main(String[] args) throws Exception {
File excel = new File ("C:\\Users\\Efi\\Documents\\test.xls");
FileInputStream fis = new FileInputStream(excel);
HSSFWorkbook wb = new HSSFWorkbook(fis);
HSSFSheet ws = wb.getSheet("Input");
int rowNum = ws.getLastRowNum()+1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[rowNum][colNum];
for (int i=0; i<rowNum; i++){
HSSFRow row = ws.getRow(i);
for (int j=0; j<colNum; j++){
HSSFCell cell = row.getCell(j);
String value = cellToString(cell);
data[i][j] = value;
System.out.println("The value is" + value);
}
}
}
public static String cellToString (HSSFCell cell){
int type;
Object result;
type = cell.getCellType();
switch(type) {
case 0://numeric value in excel
result = cell.getNumericCellValue();
break;
case 1: //string value in excel
result = cell.getStringCellValue();
break;
case 2: //boolean value in excel
result = cell.getBooleanCellValue ();
break;
default:
***throw new RunTimeException("There are not support for this type of
cell");***
}
return result.toString();
}
}
There are additional cell types besides the ones you are capturing in your switch statement. You have cases for 0 (CELL_TYPE_NUMERIC), 1 (CELL_TYPE_STRING), and 2, but 2 is CELL_TYPE_FORMULA. Here are the additional possible values:
3: CELL_TYPE_BLANK
4: CELL_TYPE_BOOLEAN
5: CELL_TYPE_ERROR
Use the Cell constants for the cell type in your switch statement instead of integer literals, and use all 6 of them to capture all possible cases.
And as #Vash has already suggested, include the actual cell type in your RuntimeException message.
Check this library that I've created for reading both XLSX, XLS and CSV files pretty easily. It uses Apache POI for processing excel files and converts excel rows into a list of Java beans based on your configuration.
Here is an example:
RowConverter<Country> converter = (row) -> new Country(row[0], row[1]);
ExcelReader<Country> reader = ExcelReader.builder(Country.class)
.converter(converter)
.withHeader()
.csvDelimiter(';')
.sheets(1)
.build();
List<Country> list;
list = reader.read("src/test/resources/CountryCodes.xlsx");
list = reader.read("src/test/resources/CountryCodes.xls");
list = reader.read("src/test/resources/CountryCodes.csv");
With following excel and bean files:
public static class Country {
public String shortCode;
public String name;
public Country(String shortCode, String name) {
this.shortCode = shortCode;
this.name = name;
}
}
Excel:
Code Country
ad Andorra
ae United Arab Emirates
af Afghanistan
ag Antigua and Barbuda
...
Using XSSFWorkbook and XSSFSheet did not help me read .xls, but I used this code and it helps me read the .xls and xlsx files:
public static void readExcelFile(File file) throws IOException, InvalidFormatException {
Workbook workbook = WorkbookFactory.create(new File(file.toString()));
Integer sheet = workbook.getNumberOfSheets();
DataFormatter dataFormatter = new DataFormatter();
for (int i = 0; i < sheet; i++) {
Sheet s = workbook.getSheetAt(i);
Iterator<Row> rowIterator = s.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
printCellValue(cell);
// both work perfect
// printCellValue(cell);
/*String cellValue = dataFormatter.formatCellValue(cell);
System.out.print(cellValue + "\t");*/
}
System.out.println();
}
}
}
public static void printCellValue(Cell cell) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
System.out.print(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getRichStringCellValue().getString());
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.print(cell.getDateCellValue());
} else {
System.out.print(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_FORMULA:
System.out.print(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK:
System.out.print(" ");
break;
default:
System.out.print("");
}
System.out.print("\t");
}
You should amend that RuntimeException with information about what type is not supported with your switch statement. Then you will be able to add support for it, so no exception will be thrown.
So to see the picture of what your program is doing instead of
throw new RunTimeException("There are not support for this type of cell");
you should add
throw new RunTimeException("There are not support for type with id ["+type+"] of cell");
This will only, inform you what do you miss. How to handle this situation is up to you.

When getting cell content using Apache-POI Library, I get both "Cannot get a numeric value from a text cell" and the reverse of that. How do I fix it?

I realize the question is a little confusing, but I didn't know how else to word it. Anyway, here is the original code:
private void readFile(String excelFileName) throws FileNotFoundException, IOException {
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(excelFileName));
if (workbook.getNumberOfSheets() > 1){
System.out.println("Please make sure there is only one sheet in the excel workbook.");
}
XSSFSheet sheet = workbook.getSheetAt(0);
int numOfPhysRows = sheet.getPhysicalNumberOfRows();
XSSFRow row;
XSSFCell num;
for(int y = 1;y < numOfPhysRows;y++){ //start at the 2nd row since 1st should be category names
row = sheet.getRow(y);
poNum = row.getCell(1);
item = new Item(Integer.parseInt(poNum.getStringCellValue());
itemList.add(item);
y++;
}
}
private int poiConvertFromStringtoInt(XSSFCell cell){
int x = Integer.parseInt(Double.toString(cell.getNumericCellValue()));
return x;
}
I am getting the following error:
Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a text cell
at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781)
at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199)
Even if I change it to get either a string using XSSFCell.getStringCellValue() or even XFFSCell.getRichTextValue, I get the reverse of the above error message (and I am making sure to ultimately make it an int using Integer.parseInt(XSSFCell.getStringCellValue()).
The error then reads:
Exception in thread "main" java.lang.IllegalStateException: Cannot get a text value from a numeric cell
at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781)
at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199)
I know for a fact that the excel spreadsheet column is in fact a string. I can't change the excel sheet as it is uploaded else where always using the same format and formatting each column first takes up to much processing time.
Any suggestions?
[Solution] Here is the solution code I came up with from #Wivani's help:
private long poiGetCellValue(XSSFCell cell){
long x;
if(cell.getCellType() == 0)
x = (long)cell.getNumericCellValue();
else if(cell.getCellType() == 1)
x = Long.parseLong(cell.getStringCellValue());
else
x = -1;
return x;
}
Use This as reference
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.println(cell.getRichStringCellValue().getString());
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.println(cell.getDateCellValue());
} else {
System.out.println(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.println(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
System.out.println(cell.getCellFormula());
break;
default:
System.out.println();
}
You can get value as String using the format defined for this cell :
final DataFormatter df = new DataFormatter();
final XSSFCell cell = row.getCell(cellIndex);
String valueAsString = df.formatCellValue(cell);
Thanks to this answer.
Just use cell.setCellType(1); before reading cell value and get it as String always, after that you can use it in your own format(type).
Ravi
Use the below code to read any data type from xcels using poi.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* #author nirmal
*/
public class ReadWriteExcel {
public static void main(String ar[]) {
ReadWriteExcel rw = new ReadWriteExcel();
rw.readDataFromExcel();
}
Object[][] data = null;
public File getFile() throws FileNotFoundException {
File here = new File("test/com/javaant/ssg/tests/test/data.xlsx");
return new File(here.getAbsolutePath());
}
public Object[][] readDataFromExcel() {
final DataFormatter df = new DataFormatter();
try {
FileInputStream file = new FileInputStream(getFile());
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
int rownum = 0;
int colnum = 0;
Row r=rowIterator.next();
int rowcount=sheet.getLastRowNum();
int colcount=r.getPhysicalNumberOfCells();
data = new Object[rowcount][colcount];
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
colnum = 0;
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
data[rownum][colnum] = df.formatCellValue(cell);
System.out.print(df.formatCellValue(cell));
colnum++;
System.out.println("-");
}
rownum++;
System.out.println("");
}
file.close();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
}
I got also this bug with POI version 3.12final.
I think that the bug is registered there : https://bz.apache.org/bugzilla/show_bug.cgi?id=56702 and I put a comment there with my analysis.
Here is the workaround I used : The exception was risen by HSSFCell.getNumericCellValue which was called by DateUtil.isCellDateFormatted. DateUtil.isCellDateFormatted does 2 things :
1) check the value type of the cell by calling HSSFCell.getNumericCellValue and then DateUtil.isValidExcelDate(), which is almost pointless here I think.
2) check if the format of the cell is a date format
I copied the code of topic 2) above in a new function 'myIsADateFormat' and used it instead of DateUtil.isCellDateFormatted (that is quite dirty to copy library code, but it works...) :
private boolean myIsADateFormat(Cell cell){
CellStyle style = cell.getCellStyle();
if(style == null) return false;
int formatNo = style.getDataFormat();
String formatString = style.getDataFormatString();
boolean result = DateUtil.isADateFormat(formatNo, formatString);
return result;
}
If you need to check the value type first, you can use this too :
CellValue cellValue = evaluator.evaluate(cell);
int cellValueType = cellValue.getCellType();
if(cellValueType == Cell.CELL_TYPE_NUMERIC){
if(myIsADateFormat(cell){
....
}
}
Documentation clearly says not to setCellType to 1 instead use the DataFormatter like how Thierry has explained:
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType(int)
Ravi's solution works :
Just use cell.setCellType(1); before reading cell value and get it as String always, after that you can use it in your own format(type).

Categories