How to check if excel file is blank? - java

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 !

Related

Print the Empty cell Adjacent cell value in Excel Sheet using Java

I have an Excel sheet I need to print the adjacent cell value when I am seeing the empty cell in java.
I had written the code to print the values in the Excel sheet and I too find the empty cell but I don't how to print the adjacent cell value on seeing the empty cell
public class empty {
public static void main(String args[]) throws Exception {
InputStream ExcelFileToRead = new FileInputStream("C:\\Users\\GOMATHI\\Desktop\\data1.xls");
HSSFWorkbook wb = new HSSFWorkbook(ExcelFileToRead);
HSSFSheet sheet = wb.getSheetAt(0);
HSSFRow row;
HSSFCell cell;
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext()) {
cell = (HSSFCell) cells.next();
if (cell == null || cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
// logic goes here. I don't know.
System.out.println(no);
}
System.out.println(cell.toString());
}
}
// System.out.println();
}
}
Input: Excel File
Id Value
01 200
02 201
03 203
04
05 205
Output:
The Value at 4th cell Value is empty so I need to print its corresponding ID.
04
First, I think your test if (cell == null || cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) is half useless because cell should never be null.
Assuming this, you can get the cell of the previous column with row.getCell(cell.getColumnIndex() - 1)

Reading multiple columns for a row from excel, in java?

I want to read excel spreadsheet(.xlxs) having testcases preconditions column/expected result column and so on. How do i read multiple columns for specific row. Everyrow(first Column)is a testcase name.
I am able to read one row and two columns, but unsure how to read multiple columns for same row . I also don't want to hardcode column#,row# while reading it. Any suggestions?
Map<String,String> arrayExcelData = new Hashtable<String,String>();
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
Cell methodNameCol = row.getCell(0);
Cell expectedResults = row.getCell(1);
if (expectedResults != null && methodNameCol !=null)
{
arrayExcelData.put(methodNameCol.getStringCellValue(),expectedResults.getStringCellValue());
}
workbook.close();
}
The Row class provides methods that return the index of the first and last cell (aka column) in that Row instance. Use these indexes to iterate over the columns:
Row row = rowIterator.next();
short firstCellNumber = row.getFirstCellNum();
short lastCellNumber = row.getLastCellNum();
for(short cellNumber = firstCellNumber; cellNumber < lastCellNumber; cellNumber++) {
Cell dataCell = row.getCell(cellNumber);
//Do something with the dataCell here
}

why apache poi reading less number of cell in a row of excel

I am trying to fetch the cell using named range.But After trying the below code,not able to get consistent cell in a row of the sheet that's getting null exception while using r.getCell().
String cname = "TestName";
Workbook wb = getMyWorkbook(); // retrieve workbook
// retrieve the named range
int namedCellIdx = wb.getNameIndex(cellName);
Name aNamedCell = wb.getNameAt(namedCellIdx);
// retrieve the cell at the named range and test its contents
AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula());
CellReference[] crefs = aref.getAllReferencedCells();
for (int i = 0; i < crefs.length; i++) {
Sheet s = wb.getSheet(crefs[i].getSheetName());
Row r = sheet.getRow(crefs[i].getRow());
Cell c = r.getCell(crefs[i].getCol());
// extract the cell contents based on cell type etc.
}
For the sake of memory consuming, totally empty rows are not stored on the sheet. Also totally empty cells are not stored in rows of the sheet.
Sheet.getRow returns null if the row is not defined on the sheet. Also Row.getCell returns null if the cell is undefined in that row.
So we always need check:
...
Row r = sheet.getRow(crefs[i].getRow());
if (r == null) {
//row is empty
} else {
Cell c = r.getCell(crefs[i].getCol());
if (c == null) {
//cell is empty
} else {
//do something with c
}
}
...

Retrieve values from excel using poi

I am trying to get the column values for a specific row in a excel using poi methods.
I am able to get the values but the problem is I want the values only from second column.
public static ArrayList<String> GetBusinessComponentList() throws IOException{
String Tcname = "TC02_AggregateAutoByPassRO_CT";
ArrayList<String> arrayListBusinessFlow ;
arrayListBusinessFlow = new ArrayList<String>();
FileInputStream fileInput = new FileInputStream(oFile);
wb = new HSSFWorkbook(fileInput);
sheet = wb.getSheet("Business Flow");
int rownr = findRow(sheet, Tcname);
row = sheet.getRow(rownr);
for (Cell cell : row) {
String arr = cell.getStringCellValue();
arrayListBusinessFlow.add(arr);
}
return arrayListBusinessFlow;
}
private static int findRow(HSSFSheet sheet, String cellContent){
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
if (cell.getRichStringCellValue().getString().trim().equals(cellContent)) {
return row.getRowNum();
}
}
}
}
return 0;
}
}
OUTPUT:
[TC02_AggregateAutoByPassRO_CT,
StrategicUINewBusiness.Login,
StrategicUINewBusiness.CustomerSearch,
StrategicUINewBusiness.NamedInsured,
StrategicUINewBusiness.InsuranceScoreByPass,
StrategicUINewBusiness.VehiclePage,
StrategicUINewBusiness.DriverPage,
StrategicUINewBusiness.ViolationPage,
StrategicUINewBusiness.UnderwritingPage,
StrategicUINewBusiness.CoveragePage,
StrategicUINewBusiness.Portfolio,
StrategicUINewBusiness.BillingPage,
StrategicUINewBusiness.FinalSalePage,
StrategicUINewBusiness.PolicyConfirmation, , , ]
But I do not want my test case name when I am getting.
Please help me what changes i needed to do. thanks!
Currently, the code you're using to iterate over cells only returns cells with content or styling, and skips totally empty ones. You need to change to one of the other ways of iterating over cells, so you can control it to read from the second column onwards.
If you look at the Apache POI Documentation on iterating over rows and cells, you'll see a lot more details on the two main ways to iterate.
For your case, you'll want something like:
// We want to read from the 2nd column onwards, zero based
int firstColumn = 1;
// Always fetch at least 4 columns
int MY_MINIMUM_COLUMN_COUNT = 5;
// Work out the last column to go to
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
// To format cells into strings
DataFormatter df = new DataFormatter();
// Iterate over the cells
for (int cn = firstColumn; 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
// eg get the cells value as a string
String cellAsString = df.formatCellValue(c);
}
}
Use Cell cell=row.getCell(1); and also you can use sheet.getLastRowNum() to get the number last row on the sheet.
for (int i=0;i<=row.getLastCellNum();i++) {
if (i!=1){
//your stuff
}
}

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