Reading from excel files using JAVA poi and ignoring empty cells - java

I was trying to read data from an excel sheet that contains empty cells consider the following code:
File src = new File(path to your file);
FileInputStream fis = new FileInputStream(src);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet1 = wb.getSheet("Sheet1");
int rowCount = sheet1.getLastRowNum();
System.out.println("total number of rows is: " + rowCount);
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
System.out.println(data);
}
However, my code also reads the empty cells and displays the value as 0 (The cells have numeric value). How do I make my script read-only cells that are filled and display them while ignoring the ones that are empty?
Thank you in advance

Just update the for loop with an if condition which will check for the value which is getting retrieved from the Cell. PFB the updated for loop.
For Apache POI version 4.x you can try below-
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
Cell cell = sheet1.getRow(i).getCell(1);
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
if(c.getCellType() == CellType.Blank)
{
continue;
}
else{
System.out.println(data);
}
}
For Apache POI version 3.x you can try below-
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
Cell cell = sheet1.getRow(i).getCell(1);
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
if(cell.getCellType() == Cell.CELL_TYPE_BLANK)
{
continue;
}
else{
System.out.println(data);
}
}

Related

POI XSSF overwriting specific cells in excel file

I am trying to write out to an existing excel file. I don't want to create new rows or cells, I just want to write out the value from my array into the value at row x column y. Every time I have tried this so far I can only get it to work if I create a new row. Please help!!!
Integer columns = DataImport.columns_in_sheet[0];
Integer rowNum = learnerRow + 2;
try {
FileInputStream inp = new FileInputStream("D:/location/update.xlsx");
XSSFWorkbook wb = null;
wb = (XSSFWorkbook) WorkbookFactory.create(inp);
XSSFSheet sheet = wb.getSheetAt(0);
XSSFRow row = sheet.getRow(18);//places the start row
XSSFCell cell = null;//places the start column
cell = row.getCell(0);
//#########################################################################################
//#########################################################################################
for (int j = 0; j < exportData.length; j++) {
//sheet.createRow(rowNum+j);
//row = sheet.getRow(rowNum+j);
//row = sheet.getRow(rowNum+j);
for (int i=0; i < columns;i++){
cell.setCellType(CellType.STRING);
cell.setCellValue(exportData[j][i]);
}
}
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("D:/location/update.xlsx");
wb.write(fileOut);
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
this code throws a null pointer because of row being null, I can only seem to get rid of the error by creating new rows. I am using XSSF formatting.
The logic of your code snippet is not clear. It looks not logically to me.
But to avoid NPE while using rows and cells from present sheets, one always needs check whether the row or cell was present already or needs to be new created. This is necessary because for not present rows Sheet.getRow will return null. Also Row.getCell will return null for not present cells.
So we can do:
Sheet sheet = ...
Row row = sheet.getRow(rowIdx); if (row == null) row = sheet.createRow(rowIdx);
Cell cell = row.getCell(cellIdx); if (cell == null) cell = row.createCell(cellIdx);
Now row either is a row which was already present or it is a new created row. And cell either is a cell which was already present or it is a new created cell. Neither row nor cell will be null. And at first present rows/cells will be got before they were new created if not present. So present rows and cells will not be destroyed.
The same is needed in loops:
Sheet sheet = ...
Row row;
Cell cell;
for (int rowIdx = 0; rowIdx < 10; rowIdx++) {
row = sheet.getRow(rowIdx); if (row == null) row = sheet.createRow(rowIdx);
for (int cellIdx = 0; cellIdx < 10; cellIdx++) {
cell = row.getCell(cellIdx); if (cell == null) cell = row.createCell(cellIdx);
// do something with cell
}
}

How to have excel formula refresh when new data inserted with Java through Apache POI

I am inserting a list of numbers into a column in Excel (column A) with Java. the following column has a list of average numbers (Column B). Column C has a list of formulas like this: =IF(B1 < 1,0,((A1)-B1)/B1).
In my program, I want to have the formulas in column C re-evaluate after I've input the new data so then I can extract the new cell value into Java. I'm checking to see if any new result in column C is -1.0.
I've tried to use FormulaEvaluator before extracting column C values but I still get the old values. I've also tried writing and closing the workbook and opening it again but that also hasn't worked.
//Pull the values stored procedure
ResultSet rs = dbutils.sqlserverdbvaliation(query, db);
System.out.println("Returned the Result Set");
//Get number of rows in result row to set array size
rs.last();
arraySize = rs.getRow();
rs.beforeFirst();
//Store values from resultSet into an array
int[] dlArray = new int[arraySize];
while(rs.next()) {
//Activity Process Count is name of ResultSet Column
dlArray[count] = rs.getInt("ActivityProcessCount");
count++;
}
//Create workbook
InputStream inp = new FileInputStream("C:\\TestWorkbook.xlsx");
Workbook wb = WorkbookFactory.create(inp);
org.apache.poi.ss.usermodel.Sheet sheet = wb.getSheetAt(1);
FormulaEvaluator evaluator =
wb.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateAll();
System.out.println(Arrays.toString(dlArray));
//Write the values from the array to the spreadsheet
int excelCount = 1;
for (int i = 0; i < arraySize ; i++) {
Row row = sheet.getRow(excelCount);
Cell cell = row.getCell(2);
cell.setCellValue(dlArray[i]);
evaluator.evaluateAll();
excelCount++;
}
FileOutputStream fos = new FileOutputStream("C:\\TestWorkbook.xlsx");
evaluator.evaluateAll();
wb.write(fos);
wb.close();
InputStream inp2 = new FileInputStream("C:\\TestWorkbook.xlsx");
Workbook wb2 = WorkbookFactory.create(inp2);
org.apache.poi.ss.usermodel.Sheet sheet2 = wb2.getSheetAt(1);
excelCount = 1;
for (int i = 0; i < arraySize ; i++) {
Row row = sheet2.getRow(excelCount);
Cell cell = row.getCell(4);
if (cell.getNumericCellValue() == -1.0) {
ExcelUtils.setCellStyle(excelPath, sheetName, excelCount, 5,
YELLOW);
}
else {
ExcelUtils.setCellStyle(excelPath, sheetName, excelCount, 5,
GREEN);
}
excelCount++;
}

Inserting data from arraylist in chunks in excel file using apache poi

I have the arraylist of data in the following format :
ArrayList> listResultData. Now collection contains around 11k+ rows to be inserted in the excel.
When i insert these 11490 rows in excel it took 6 hrs to insert the records, that means its very bad performance issue. Is there anyway to insert the data in excel in chunks for 1000 rows at a time (means there should be something like executeBatch() in sql for inserting records). A row contains 4-5 columns also.
Following is the code i have been using :
public boolean setArrayListData(String sheetName, ArrayList<ArrayList<String>> listResultData) {
try {
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(fis);
int index = workbook.getSheetIndex(sheetName);
if (index == -1)
return false;
sheet = workbook.getSheetAt(index);
int colNum = 0;
int rowNum = this.getRowCount(sheetName);
rowNum++;
for (ArrayList<String> al : listResultData) {
for (String s : al) {
sheet.autoSizeColumn(colNum);
row = sheet.getRow(rowNum - 1);
if (row == null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(colNum);
if (cell == null)
cell = row.createCell(colNum);
// cell style
// CellStyle cs = workbook.createCellStyle();
// cs.setWrapText(true);
// cell.setCellStyle(cs);
cell.setCellValue(s);
//System.out.print("Cell Value :: "+s);
colNum++;
}
rowNum++;
colNum = 0;
//System.out.println("");
}
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
workbook.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
Please suggest !!
Instead of XSSF you may want to try SXSSF the streaming extension of XSSF. In contrast to xssf where you have access to all rows in the document which can lead to performance or heap space issue sxssf allows you to define a sliding window and limits the access to rows in that window. You can specify the window size at construction time of your workbook using new SXSSFWorkbook(int windowSize) . As you then create your rows and the number of rows exceed the specified window size, the row with the lowest index is flushed and is no longer in memory.
Find further infos at SXSSF (Streaming Usermodel API)
Example:
// keep 100 rows in memory, exceeding rows will be flushed to disk
SXSSFWorkbook wb = new SXSSFWorkbook(100);
Sheet sh = wb.createSheet();
for(int rownum = 0; rownum < 1000; rownum++){
//When the row count reaches 101, the row with rownum=0 is flushed to disk and removed from memory,
//when rownum reaches 102 then the row with rownum=1 is flushed, etc.
Row row = sh.createRow(rownum);
for(int cellnum = 0; cellnum < 10; cellnum++){
Cell cell = row.createCell(cellnum);
String address = new CellReference(cell).formatAsString();
cell.setCellValue(address);
}
}

POI Appending .0 while reading numeric data from excel

I am using POI HSSF to read excel data and I am using JUnit to check the data against database proc RefCursor.
The Junit test fails as the numeric data from the Refcursor for example 100 are compared against the data in the excel sheet 100 but it fails as the POI reads it as 100.0.
InputStream fileInputStream = Testdb.class.getClassLoader().getResourceAsStream(fileName);
//retrieve number of columns and rows
int numRows=0, numCols=0, i, j, minColIndex=0, maxColIndex=0;
POIFSFileSystem fsFileSystem = new POIFSFileSystem(fileInputStream);
HSSFWorkbook workBook = new HSSFWorkbook(fsFileSystem);
HSSFSheet hssfSheet = workBook.getSheetAt(0);
Iterator rowIterator = hssfSheet.rowIterator();
while (rowIterator.hasNext())
{
numRows++;
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
Iterator iterator = hssfRow.cellIterator();
List cellTempList = new ArrayList();
if (numRows == 1)
{
minColIndex = hssfRow.getFirstCellNum();
maxColIndex = hssfRow.getLastCellNum();
numCols = maxColIndex;
}
for(int colIndex = minColIndex; colIndex < maxColIndex; colIndex++)
{
HSSFCell hssfCell = hssfRow.getCell(colIndex);
cellTempList.add(hssfCell);
}
cellDataList.add(cellTempList);
}
String expected[][] = new String[numRows][numCols];
String[] tableColumns = new String[numCols];
System.out.println("Rows : " + numRows + "Columns : " + numCols);
System.out.println("Min Col Index : " +minColIndex + "Max Col Index : " + maxColIndex);
for (i=0; i<numRows; i++)
{
List cellTempList = (List) cellDataList.get(i);
for (j=0; j < numCols; j++)
{
HSSFCell hssfCell = (HSSFCell) cellTempList.get(j);
if (i == 0)
{
tableColumns[j] = hssfCell.toString();
System.out.print(tableColumns[j] + "\t");
}
else
{
if(hssfCell != null)
{
expected[i-1][j] = hssfCell.toString();
}
else
{
expected[i-1][j] = null;
}
System.out.print(expected[i-1][j] + "\t");
}
}
System.out.println();
}
This is a generic framework program which I am building so the framework should be intelligent enough to disregard the ".0".
Any inputs on how to resolve this?
This is virtually identical to a number of other questions here, such as returning decimal instead of string (POI jar)
The answer is the same as the one I gave here:
POI is giving you the exact value that Excel has stored in the File. Generally, if you write a number in an Excel cell, Excel will store that as a number with formatting. POI provides support to do that formatting for you if you want it (most people don't - they want the numbers as numbers so they can use them)
The class you're looking for is DataFormatter. Your code would be something like
DataFormatter fmt = new DataFormatter();
for (Row r : sheet) {
for (Cell c : r) {
CellReference cr = new CellRefence(c);
System.out.println("Cell " + cr.formatAsString() + " is " +
fmt.formatCellValue(c) );
}
}
Hi my solution was just to put the symbol:
'
in front of every number. Then the number is processed as text.
After you do that you would see little green triangle and warning:
For me this is not a problem, because it works.

I need to iterate to the end of a column in Java on an Excel Sheet with Apache POI

I am iterating down a column of values until it hits a blank. I need to gather the entire column and store it, and no other values. I've attempted to check for blank, null, 0, "", and CELL_TYPE_BLANK (int = 3), and I cannot get it to avoid a null pointer exception. Code snippet and error are below. What can I do? This is not the entire method or program, just the relevant piece.
String s = list[i];
//find the directory from the list array to locate the file
InputStream input = new FileInputStream(s);
//create a new workbook object to hold the excel file
Workbook wb = new XSSFWorkbook(input);
//create an arbitrary starting location
int column = 2; //absolutely the correct number
int rownum = 10;
//get the value from the first sheet
org.apache.poi.ss.usermodel.Sheet insheet = wb.getSheetAt(0);
//of the second columm
Row row = insheet.getRow(rownum);
//in the 11th row (arbitrary number used to reduce iterations and skip whitespace)
Cell cell = row.getCell(column);
System.out.println("Skimming sheet: " + insheet.getSheetName());
//iterate until the very end of the column is found
System.out.println("Cell value B" + (rownum-1) + ": " + cell);
//3 denotes CELL_TYPE_BLANK
while (cell.getCellType() != 3 ) {
//go to the next location
//update to the next cell
System.out.println("Cell value B" + rownum + ": " + cell);
row = insheet.getRow(rownum);
if(row.getCell(column).getCellType() != 3){
cell = row.getCell(column); //error occurs here, line 241
}
rownum++;
}
Exception in thread "main" java.lang.NullPointerException
at FileTest.skim(FileTest.java:241)
at FileTest.main(FileTest.java:121)
You're gettint the error because the row you're trying to access is null, not the cell. You want to take a look in the Apache POI Iterator example.
//taken from the example
Sheet sheet = wb.getsheetat(0);
for (Iterator<Row> rit = sheet.rowiterator(); rit.hasnext(); ) {
Row row = rit.next();
//now, based in your needs
Cell cell = row.getCell(column);
//do what you need with the row-column
}
Iterate rows in a for loop up to last row, that will prevent running in to that exception:
for(int i =0 ; i< insheet.getLastRowNum(); i++){
//do stuff
}

Categories

Resources