How to check if an excel cell is empty using Apache POI? - java

I am taking input from an excel sheet using Poi.jar and wanted to know how to check if a cell is empty or not.
Right now I m using the below code.
cell = myRow.getCell(3);
if (cell != null) {
cell.setCellType(Cell.CELL_TYPE_STRING);
//System.out.print(cell.getStringCellValue() + "\t\t");
if (cell.getStringCellValue() != "")
depend[p] = Integer.parseInt(cell.getStringCellValue());
}
}

If you're using Apache POI 4.x, you can do that with:
Cell c = row.getCell(3);
if (c == null || c.getCellType() == CellType.Blank) {
// This cell is empty
}
For older Apache POI 3.x versions, which predate the move to the CellType enum, it's:
Cell c = row.getCell(3);
if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK) {
// This cell is empty
}
Don't forget to check if the Row is null though - if the row has never been used with no cells ever used or styled, the row itself might be null!

Gagravarr's answer is quite good!
Check if an excel cell is empty
But if you assume that a cell is also empty if it contains an empty String (""), you need some additional code. This can happen, if a cell was edited and then not cleared properly (for how to clear a cell properly, see further below).
I wrote myself a helper to check if an XSSFCell is empty (including an empty String).
/**
* Checks if the value of a given {#link XSSFCell} is empty.
*
* #param cell
* The {#link XSSFCell}.
* #return {#code true} if the {#link XSSFCell} is empty. {#code false}
* otherwise.
*/
public static boolean isCellEmpty(final XSSFCell cell) {
if (cell == null) { // use row.getCell(x, Row.CREATE_NULL_AS_BLANK) to avoid null cells
return true;
}
if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return true;
}
if (cell.getCellType() == Cell.CELL_TYPE_STRING && cell.getStringCellValue().trim().isEmpty()) {
return true;
}
return false;
}
Pay attention for newer POI Version
They first changed getCellType() to getCellTypeEnum() as of Version 3.15 Beta 3 and then moved back to getCellType() as of Version 4.0.
Version >= 3.15 Beta 3:
Use CellType.BLANK and CellType.STRING instead of Cell.CELL_TYPE_BLANK and Cell.CELL_TYPE_STRING
Version >= 3.15 Beta 3 && Version < 4.0
Use Cell.getCellTypeEnum() instead of Cell.getCellType()
But better double check yourself, because they planned to change it back in future releases.
Example
This JUnit test shows the case in which the additional empty check is needed.
Scenario: the content of a cell is changed within a Java program. Later on, in the same Java program, the cell is checked for emptiness. The test will fail if the isCellEmpty(XSSFCell cell) function doesn't check for empty Strings.
#Test
public void testIsCellEmpty_CellHasEmptyString_ReturnTrue() {
// Arrange
XSSFCell cell = new XSSFWorkbook().createSheet().createRow(0).createCell(0);
boolean expectedValue = true;
boolean actualValue;
// Act
cell.setCellValue("foo");
cell.setCellValue("bar");
cell.setCellValue(" ");
actualValue = isCellEmpty(cell);
// Assert
Assert.assertEquals(expectedValue, actualValue);
}
In addition: Clear a cell properly
Just in case if someone wants to know, how to clear the content of a cell properly. There are two ways to archive that (I would recommend way 1).
// way 1
public static void clearCell(final XSSFCell cell) {
cell.setCellType(Cell.CELL_TYPE_BLANK);
}
// way 2
public static void clearCell(final XSSFCell cell) {
String nullString = null;
cell.setCellValue(nullString);
}
Why way 1? Explicit is better than implicit (thanks, Python)
Way 1: sets the cell type explicitly back to blank.
Way 2: sets the cell type implicitly back to blank due to a side effect when setting a cell value to a null String.
Useful sources
Official Documentation
CellTypes
XSSFCell.setCellValue(String)
Cell.setCellType(CellType)
Regards winklerrr

As of Apache POI 3.17 you will have to check if the cell is empty using enumerations:
import org.apache.poi.ss.usermodel.CellType;
if(cell == null || cell.getCellTypeEnum() == CellType.BLANK) { ... }

Cell cell = row.getCell(x, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
This trick helped me a lot, see if it's useful for you

This is the safest and most concise way I see as of POI 3.1.7 up to POI 4:
boolean isBlankCell = CellType.BLANK == cell.getCellTypeEnum();
boolean isEmptyStringCell = CellType.STRING == cell.getCellTypeEnum() && cell.getStringCellValue().trim().isEmpty();
if (isBlankCell || isEmptyStringCell) {
...
As of POI 4 getCellTypeEnum() will be deprecated if favor of getCellType() but the return type should stay the same.

First to avoid NullPointerException you have to add this
Row.MissingCellPolicy.CREATE_NULL_AS_BLANK
This will create a blank cell instead of giving you NPE then you can check to make sure nothing went wrong just like what #Gagravarr have said.
Cell cell = row.getCell(j, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
if (cell == null || cell.getCellTypeEnum() == CellType.BLANK)
// do what you want

Row.MissingCellPolicy.CREATE_NULL_AS_BLANK is work in my case.
total_colume = myRow.getLastCellNum();
int current_colume = 0;
HSSFCell ReadInCellValue;
while (current_colume <= total_colume) {
ReadInCellValue = myRow.getCell(current_colume, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);//if cell is empty, return black
if (ReadInCellValue.toString=="") Log.d("empty cell", "colume=" + String.valuOf(current_colume));
current_colume++;
}

There is one other option also .
row=(Row) sheet.getRow(i);
if (row == null || isEmptyRow(row)) {
return;
}
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext())
{}

.getCellType() != Cell.CELL_TYPE_BLANK

Cell.getCellType() is deprecated in the latest POI API. If you are using POI API version 3.17, use the below code:
if (Cell.getCellTypeEnum() == CellType.BLANK) {
//do your stuff here
}

You can also use switch case like
String columndata2 = "";
if (cell.getColumnIndex() == 1) {// To match column index
switch (cell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
columndata2 = "";
break;
case Cell.CELL_TYPE_NUMERIC:
columndata2 = "" + cell.getNumericCellValue();
break;
case Cell.CELL_TYPE_STRING:
columndata2 = cell.getStringCellValue();
break;
}
}
System.out.println("Cell Value "+ columndata2);

Try below code:
String empty = "-";
if (row.getCell(3) == null || row.getCell(3).getCellType() == Cell.CELL_TYPE_BLANK) {
upld.setValue(empty);
} else {
upld.setValue(row.getCell(3).getStringCellValue());
}

Related

Apache POI (.xlsx) - null values - I want some to be ignored and other to use (to check if the required field is filled, for example)

I tried a lot of stuff but didn't come up with the good plan it seems.
My mini application fails sometimes with null error. Sometimes I think that I 'touched' some cell and sometimes I don't know why it happens. But when I delete empty rows and columns (near my filled rows) - all is good, no more null.
And I don't want a client to delete empty cells it's stupid.
And I also want to use some null values (if they are in my semi/filled row), so I can perform a check and see if required cell is filled.
But I don't want null values around my filled rows (right side and bellow).
Anyway, if someone understood above, here is the code as well:
workbook.getSheetAt(11);
for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getLastRowNum(); i++) {
Row rows = sheet.getRow(i);
for (int c = 0; c < 8; c++) {
Cell cells = rows.getCell(c);
if ((c == 0 && cells == null) || (c == 1 && cells == null)) {
//if required cells are not filled throw error or blabla
}
}
}
aand picture:
null
Thank you!

POI Servlet Check Null no working

There are certain result that run in my program and it will be display in excel. Unfortunately the problem i facing was the cell can't set other value if there is null value detected. Error message i get is java null pointer.
Date invalid_dt=servPerfTracking.getInvalid_d();
cell=row.createCell(10);
if(cell.getCellType()==cell.CELL_TYPE_BLANK){
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue("Apple");
log.debug("invalid date is null");
}else if(cell.getCellType()==cell.CELL_TYPE_STRING){
cell=row.createCell(10);
cell.setCellValue(invalid_dt);
cell.setCellStyle(dataCellStyle);
log.debug("invalid date is not equal to null");
}
What you are actually doing
First, you are creating a new and empty cell. After that, you are checking the type of that cell.
By definition, the type of newly created cells is CELL_TYPE_BLANK.
What you should do
Use the method row.getCell(int columnNumber) to receive the actual cell of the current row for the specified column number.
Example
Date invalid_dt = servPerfTracking.getInvalid_d();
cell = row.getCell(10, Row.RETURN_NULL_AS_BLANK);
if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
cell.setCellValue("Apple");
log.debug("invalid date is null");
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
cell.setCellValue(invalid_dt);
cell.setCellStyle(dataCellStyle);
log.debug("invalid date is not equal to null");
}
Tip: You don't need to call cell.setCellType(Cell.CELL_TYPE_STRING) because it will be implicitly set by the method cell.setCellValue("Apple").
void setCellType(int cellType)
Set the cells type (numeric, formula or string).
If the cell currently contains a value, the value will be converted to match the new type, if possible.
Actually what i did for resolve it was:
String invalid_dt="";
if(servPerfTracking.getInvalid_d()!=null)
invalid_dt=servPerfTracking.getInvalid_d().toString();
cell = row.createCell(10);
cell.setCellValue(invalid_dt);
cell.setCellStyle(dataCellStyle);

Using Apache POI (java) to store excel cells in 2 dimensional array. Exception being returned despite me formatting all Excel cells as "text"

I am extremely new to using Apache POI (and still new to Java too, infact!) and have come across an exception that I cannot determine how to fix.
Obviously you cannot store 2 different datatypes in an array, so I selected every column with data and converted the cell format to "Text" in Excel.
I then try to store this data in an array with the following:
String cellData[][] = new String[rows][cols];
System.out.println(rows+" entries found with "+cols+" columns of data");
//iterate over every row and store cell data;
for(int i=0; i<rows; i++){
row = worksheet.getRow(i);
if(row != null){
for(int j=0;j<cols;j++){
cell = row.getCell(j);
if(cell != null){
try{
cellData[i][j] = cell.getStringCellValue();
}catch(IllegalStateException e){
System.out.println("Cell data is not a string(text)");
}
}
}
}
}
The output from this is countless rows of "Cell data is not a string(text)", where am I going wrong here? Forgive me for any oversights I am also new to Stackoverflow and want to become a valued member of the community here too :) Thanks for your advice!
EDIT: Added e.printStackTrace() as requested.
at exceltesting.ExcelTesting.main(ExcelTesting.java:80)
java.lang.IllegalStateException: Cannot get a text value from a numeric cell
at org.apache.poi.hssf.usermodel.HSSFCell.typeMismatch(HSSFCell.java:648)
at org.apache.poi.hssf.usermodel.HSSFCell.getRichStringCellValue(HSSFCell.java:725)
at org.apache.poi.hssf.usermodel.HSSFCell.getStringCellValue(HSSFCell.java:708)
Interestingly enough, when I change it from cell.getStringCellValue() to cell.getNumericCellValue() the IllegalStateException then changes to "Cannot get a numerical value from a text cell"... I think the excel document, despite converting the cells to text is not actually changing to string data and passing them as their inherent data type? Thanks again
It seems that some of the cells are of Numeric type and some of them are of String Type. You need to handle Numeric Cell Types and String Cell types separately. I have not checked on my end, but sure... the following will work.
Cell cell = row.getCell(j);
CellValue cellValue = evaluator.evaluate(cell);
switch (cellValue.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
cellData[i][j] = String.valueOf(cellValue.getNumberValue());
break;
case Cell.CELL_TYPE_STRING:
cellData[i][j] = cell.getStringCellValue();
break
}

handling empty columns in apache poi

I have a program reading excel sheet from a java program.
I am iterating over cells as below:
Iterator cells = row.cellIterator();
String temp;
StringBuilder sb;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
while (cells.hasNext()) {
Cell cell = (Cell) cells.next();
temp = null;
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
temp = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
temp = sdf.format(cell.getDateCellValue());
} else {
temp = df.format(new BigDecimal(cell.getNumericCellValue()));
}
break;
default:
}
if (temp == null || temp.equalsIgnoreCase("null")) {
sb.append("").append(";");
} else {
sb.append(temp).append(";");
}
}
As seen, I am trying to create a string builder containing values from excel row in semicolon separated way.
Issue is, if a column value is empty, I want it as an empty value in the string builder with two consecutive semicolons.
However, the call
Cell cell = (Cell) cells.next();
simply ignores the empty cells and jumps over to next non empty cell.
So the line
if (temp == null || temp.equalsIgnoreCase("null"))
is never met.
How to get a handle on empty column values as well in the iterator ?
This is virtually a duplicate of this question, and so my answer to that question basically applies exactly to you too.
The Cell Iterator only iterates over cells that are defined in the file. If the cell has never been used in Excel, it probably won't appear in the file (Excel isn't always consistent...), so POI won't see it
If you want to make sure you hit every cell, you should lookup by index instead, and either check for null cells (indicating the cell has never existed in the file), or set a MissingCellPolicy to control how you want null and blank cells to be treated
So, if you really do want to get every cell, do something like:
Row r = sheet.getRow(myRowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn=0; cn<lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
} else {
// Do something useful with the cell's contents
}
}
You can do this
int previous=0;
while(cell.hasNext())
{
Cell cell = (Cell) cells.next();
int current=cell.getColumnIndex();
int numberofsemicolons=previous-current;
for(numberofsemicolons)
{
sb.append("").append(";");
}
previous=current;
}
or you can do
int numberofcells=row.getFirstCellNum()-row.getLastCellNum();
for(i=0;i<=numberofcells;i++)
{
Cell cell = (Cell) cells.next();
int current=cell.getColumnIndex();
while(i<current)
{
sb.append("").append(";");
i++
}
}
Answer posted by #Gagravarr works perfectly for me but MissingCellPolicy is an enum now, so while getting the cell value instead of using
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
I have used
Cell c =r.getCell(cn,Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);

How to fix a StackOverflowError generated by a JTable event?

I get a StackOverflowError when I am trying to fill a cell with the multiplication of two other cells of the same row.
Here is the code :
tableModel.addTableModelListener(new TableModelListener(){
public void tableChanged(TableModelEvent e)
{
DefaultTableModel model = (DefaultTableModel)e.getSource();
//Object data = model.getValueAt(e.getFirstRow(), e.getColumn());
if (e.getColumn() == 0)
{
Object data = model.getValueAt(e.getFirstRow(), e.getColumn());
String stockSymbol = (String)data;
XMLService2 myService = new XMLService2(stockSymbol);
String stockName = XMLService2.getStockName();
model.setValueAt(stockName, e.getFirstRow(), e.getColumn() + 1);
}
if (model.getValueAt(e.getFirstRow(), 2) != null && model.getValueAt(e.getFirstRow(), 3) != null)
{
Double myDouble =(Integer)model.getValueAt(e.getFirstRow(), 2)*(Double)model.getValueAt(e.getFirstRow(), 3);
model.setValueAt(myDouble, e.getFirstRow(), 4);
}
}
});
The last line of this code that calls the setValueAt function is producing the StackOverflowError.
Thank you.
PS :
The table consists of 5 columns.
The type of the 3rd column is Integer.
The type of the 4th column is Double.
The type of the 5th column which gets the result of the multiplication of 3rd and 4th cell is Double.
The program is falling into an endless recursive loop (at least until the stack overflows) because the last model.setValueAt line fires another tableChanged event. Try changing the second conditional statement to
if (e.getColumn() != 4 && model.getValueAt(e.getFirstRow(), 2) != null && model.getValueAt(e.getFirstRow(), 3) != null)
This should prevent the event from re-firing when the last column is updated.
I think a better way is providing a custom TableModel to the grid, in which the getValueAt is overrided, so the operation you want is performed there (the col3*col5).
http://docs.oracle.com/javase/1.5.0/docs/api/javax/swing/table/TableModel.html

Categories