Reading Excel with JXL, cell count per row changing between rows - java

I attempted to find a solution already, but nothing has come up that matches my problem. I'm using JXL to read an excel spreadsheet and convert each row into a specified object. Each cell within a row corresponds to a property of the object I'm creating. My spreadsheet has 41 columns and after reading 375 rows, the number of cells per row changes from 41 to 32. I can't figure out why.
Here's the code where I'm looping through rows and retrieving the cells:
w = Workbook.getWorkbook(inputWorkbook);
// Get the first sheet
Sheet sheet = w.getSheet(0);
// Loop over first 10 column and lines
for (int row=1; row < sheet.getRows();row++)
{
EventData event = new EventData();
// we skip first row bc that should be header info
//now iterate through columns in row
try
{
Cell[] cell = sheet.getRow(row);
event.Name = cell[0].getContents();
event.Location = cell[1].getContents();
The rest of the code continues to grab the contents of each cell and assign them accordingly. But when attempting to access cell[32] on row 376, I get an out of bounds exception.

Could it not just be that everything after cell[32] on that row is empty and thus cell[32] (and up) in the array are not created at all?
Am now just starting with jxl and I think that's what I'm seeing

Instead of accessing the cell data as:
Cell[] cell = sheet.getRow(row);
event.Name = cell[0].getContents();
event.Location = cell[1].getContents();
Try to access the data as:
sheet.getCell(column, row);
Complete code would be:
w = Workbook.getWorkbook(inputWorkbook);
// Get the first sheet
Sheet sheet = w.getSheet(0);
// Loop over first 10 column and lines
for (int row=1; row < sheet.getRows();row++)
{
EventData event = new EventData();
// we skip first row bc that should be header info
//now iterate through columns in row
try
{
event.Name = sheet.getCell(0, row).getContents();
event.Location = sheet.getCell(1, row).getContents();
}
}

Related

How to loop over values of a certain column in an excel sheet to get the index of a value using java apache poi

I am still new to Java trying only to loop over an excel column.
The Excel sheet:
I want to have in HashMap or Array so that I can compare these dates later on with another column.
My Code is giving me yet a string as you see in the screenshot:
How can I change this String to a another Data structure to access the "index" of the values. Something like dates.get(0) --> So 01-Jul-2018. I would change the time format later.
The Code section:
XSSFWorkbook workbook = new XSSFWorkbook(fsIP);
XSSFSheet sheet = workbook.getSheetAt(0);
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (row != null) {
Cell cell = row.getCell(0); // getColumn(0)
if (cell != null) {
System.out.print(cell);
}
}
}
What would you like to know further from me?
I would be thankful for every help!

Java Apache POI Unable to Get Code Working Correctly

Edit - thanks for responses. Have made changes and as suggested found the problem was a NOW on empty rows.
I am writing a program that loads various excel sheets and provides an output based on certain criteria. See code below. My problem is that the code does not write or save to the DISPLAY sheet. I realise the code below is not particularly neat but have copy pasted to check if I can get anything to save. If I comment out everything within the loop and try to write to the cell at the end before I save, it works and shows in the sheet. If I don't comment out the data formatter part it doesn't work even when trying to write to cell just before the part where I am saving output file. I am guessing the problem is caused by the data formatter, but I can't work out why.
public void checkForChanges() {
try {
FileInputStream fsIP = new FileInputStream("Change.xls");
HSSFWorkbook fWorkbook = new HSSFWorkbook(fsIP);
HSSFSheet recipeSheet = fWorkbook.getSheet("RECIPE STEPS");
HSSFSheet fromSheet = fWorkbook.getSheet("FROM FORMAT");
HSSFSheet toSheet = fWorkbook.getSheet("TO FORMAT");
HSSFSheet displaySheet = fWorkbook.getSheet("DISPLAY");
for (int i = 0; i < 30; i++) {
DataFormatter recipeFormatter = new DataFormatter();
HSSFRow recipeRow = recipeSheet.getRow(i);
HSSFCell recipeCellsColumnA = recipeRow.getCell(0);
String recipeCellValueColumnA = recipeFormatter.formatCellValue(recipeCellsColumnA);
System.out.println(recipeCellValueColumnA);
HSSFCell recipeCellsColumnB = recipeRow.getCell(1);
String recipeCellValueColumnB = recipeFormatter.formatCellValue(recipeCellsColumnB);
System.out.println(recipeCellValueColumnB);
DataFormatter fromFormatter = new DataFormatter();
HSSFRow fromRow = fromSheet.getRow(i);
HSSFCell fromCells = fromRow.getCell(0);
String fromCellValue = fromFormatter.formatCellValue(fromCells);
System.out.println(fromCellValue);
DataFormatter toFormatter = new DataFormatter();
HSSFRow toRow = toSheet.getRow(i);
HSSFCell toCells = toRow.getCell(0);
String toCellValue = toFormatter.formatCellValue(toCells);
System.out.println(toCellValue);
if (recipeCellValueColumnB.equals("YES") && !fromCellValue.equals(toCellValue)) {
System.out.println("PUT VALUE FROM 'TO FORMAT' COLUMN A ROW I INTO 'DISPLAY' SHEET CELL COLUMN B ROW I");
System.out.println("PUT VALUE FROM 'RECIPE STEPS' COLUMN A ROW I INTO 'DISPLAY' SHEET CELL COLUMN A ROW I");
Row row = displaySheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("TEST");
} else if (recipeCellValueColumnB.equals("YES") && fromCellValue.equals(toCellValue)) {
System.out.println("SET CELL IN 'DISPLAY' SHEET COLUMN A ROW I TO '' ");
System.out.println("SET CELL IN 'DISPLAY' SHEET COLUMN B ROW I TO '' ");
Row row = displaySheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("TEST");
} else if (recipeCellValueColumnB.equals("NO")) {
System.out.println("PUT VALUE FROM 'TO FORMAT' COLUMN A ROW I INTO 'DISPLAY' SHEET CELL COLUMN B ROW I");
System.out.println("PUT VALUE FROM 'RECIPE STEPS' COLUMN A ROW I INTO 'DISPLAY' SHEET CELL COLUMN A ROW I");
Row row = displaySheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("TEST");
}else if (recipeCellValueColumnA.equals("Step Name") && recipeCellValueColumnB.equals("Always Compare?")) {
System.out.println("SET CELL IN DISPLAY COLUMN A ROW I TO 'REQUIRED STEPS'");
System.out.println("PUT VALUE FROM 'TO FORMAT' COLUMN A ROW I INTO 'DISPLAY' SHEET CELL COLUMN B ROW I");
Row row = displaySheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("TEST");
}
}
FileOutputStream output_file = new FileOutputStream(new File("Change.xls"));
BufferedOutputStream bos = new BufferedOutputStream(output_file);
fWorkbook.write(output_file);
fWorkbook.close();
bos.close();
output_file.close();
}catch(Exception e){
}
}
Sorry for any poor explanation, it's late and I'm tired and frustrated!
Thanks
The problem with your code is this:
catch(Exception e)
{
}
This is saying "don't tell me about any exceptions". This is exception squashing ... and it is horrible, and lazy, and just plain wrong.
Somewhere in your code there is probably something that is either throwing an exception directly, or causing POI (or something) to throw an exception. That's a bug. But your horrible exception squashing is throwing away the evidence that will allow you to identify and then fix the bug.
I am guessing the problem is caused by the data formatter, but I can't work out why.
It could be many things ... including something daft like an NPE or a passing an out-of-range index of an incorrect filename.
Solution:
Get rid of the try catch, and allow the exceptions to propagate to the caller.
In the caller (or further up the stack) handle unexpected exceptions by printing or logging a stacktrace and causing the application to fail.
Run the modified program.
When it fails (at it probably will), read the exception message and stacktrace and work out what the underlying problem is; i.e the problam that your horrible exception squashing is hiding.
Then remember to NEVER squash all exceptions like that, in Java or in any other programming language.
(It is sometimes OK to squash a specific exception in a specific context ... but only after carefully analyzing the code to ensure that that you won't squash other (unexpected) exceptions at the same time.)

Results address of empty cell in Excel sheet using XSSF

I am reading an Excel sheet using POI's XSSF . The Excel sheet has thousands of rows of user information like user name, address, age, department etc.
I can read and write the Excel sheet successfully but i want to locate empty/null cell's address and want to print it as result in another sheet
example result what i want is:
Empty cell : C5
Empty cell : E7
Empty cell : H8
Thanks and appreciate for discussions and replies.
You need to check for both Null and Blank cells. Null cells are ones that have never been used, Blank ones are ones that have been used or styled in some way that Excel has decided to keep them around in the file
The easiest way to control this fetching is with a MissingCellPolicy. Your code can then be something like:
Row r = getRow(); // Logic here to get the row of interest
// Iterate over all cells in the row, up to at least the 10th column
int lastColumn = Math.max(r.getLastCellNum(), 10);
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
// eg...
System.out.println("There is data in cell " + (new CellReference(c)).formatAsString());
}
}
You can find more on this in the POI docs on iterating over rows and cells
As far as I unterstood your question right, this should do the trick:
XSSFCell cell = (XSSFCell) row.getCell( index );
if( cell == null )
{
cell = (XSSFCell) row.createCell( index );
}
if( cell.getStringCellValue().trim().isEmpty() )
{
String cellRef = CellReference.convertNumToColString( cell.getColumnIndex() );
System.err.println( "Empty cell found: " + cellRef
+ Integer.toString( row.getRowNum() ) );
}

Excel formula not updating on row delete from java application using Apache POI

I'm using Apache POI in my application to write data to an excel file. I've an excel file template and a few formulas are also there in it. In my application, i use the excel template, write into it ,then delete unused rows and calculate formulas in the end. I'm using SUM formula in the file. The problem is when rows are deleted, the SUM formula is not updating,due to which error values are coming up in excel.
Example : the formula being used is : for cell B215 : SUM(B15:B214). in the application,after writing to the file i delete unused rows. now I've data till 70th row in the file.All other rows have been deleted. So my formula should get updated to : SUM(B15:B69) for cell B70. But in the file it's still showing the formula as SUM(B15:B214). Hence the value of that cell is "VALUE#
Code snippet :
File file = new File(path)
InputStream is = new FileInputStream(file)
POIFSFileSystem fs = new POIFSFileSystem(is)
HSSFWorkbook wb = new HSSFWorkbook(fs)
HSSFSheet excelSheet
int[] indexArray = populateSheet(excelSheet)
//indexArray is array with 3 values as startrow, lastrow, and first empty row.
removeBlankRows(excelSheet,indexArray)
//evaluate formula
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator()
for(HSSFRow r : excelSheet) {
for(HSSFCell c : r) {
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
String formula = c.getCellFormula();
evaluator.evaluateFormulaCell(c)
}
}
}
private void removeBlankRows(HSSFSheet sheet, int[] shiftInfo){
for(int i = shiftInfo[2]; i <= shiftInfo[1]; ++i) {
sheet.removeRow(sheet.getRow(i))
}
//Shift up the rows
def startRow = shiftInfo[1]+1
def endRow = sheet.getLastRowNum()
def rowCount = -1* (shiftInfo[1] - shiftInfo[2] + 1)
sheet.shiftRows(startRow, endRow, rowCount)
}
This is an Excel bug. I've dealt with this in the past by doing the following:
Label the sum cell BSUM
We need a stable range that won't be affected by inserts/deletes.
Add a formula to a safe (one that won't get deleted) cell, for this example D15: ="B15:B"&ROW(BSUM)-1
This will produce a stable range.
Use INDIRECT in the BSUM cell like so:
=SUM(INDIRECT(D15))

Apache POI blank values

I am using Apache POI to import data from excel file to database.(newbie to APACHE POI)
In which I am allowing user to select columns from excel sheet and Map those columns to the Database columns. After mapping the columns, when I try to insert the records from Excel to Database then:
If Columns with NO blank values in them are Mapped then Proper data is inserted into the database
If columns are Mapped with BLANK values in them, then if a Excel Cell has blank value then previous value of that column is assigned.
Source Code:
FileInputStream file = new FileInputStream(new File("C:/Temp.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(file); //Get the workbook instance for XLS file
HSSFSheet sheet = workbook.getSheetAt(0); //Get first sheet from the workbook
Iterator<Row> rowIterator = sheet.iterator(); //Iterate through each rows from first sheet
while (rowIterator.hasNext())
{
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
Iterator<Cell> iterator = hssfRow.cellIterator();
int current = 0, next = 1;
while (iterator.hasNext())
{
HSSFCell hssfCell = (HSSFCell) iterator.next();
current = hssfCell.getColumnIndex();
for(int i=0;i<arrIndex.length;i++) //arrayIndex is array of Excel cell Indexes selected by the user
{
if(arrIndex[i] == hssfCell.getColumnIndex())
{
if(current<next)
{
//System.out.println("Condition Satisfied");
}
else
{
System.out.println( "pstmt.setString("+next+",null);");
pstmt.setString(next,null);
next = next + 1;
}
System.out.println( "pstmt.setString("+next+","+((Object)hssfCell).toString()+");");
pstmt.setString(next,((Object)hssfCell).toString());
next = next + 1;
}
}
}
pstmt.addBatch();
}
I have look for similar questions on SO, but still not able to solve the issue.. So any help will be appreciated.
Thanks in advance..
You've made a very common mistake, which has been covered in rather a lot of past StackOverflow questions
As the Apache POI documentation on cell iterating says
In some cases, when iterating, you need full control over how missing or blank cells are treated, and you need to ensure you visit every cell and not just those defined in the file. (The CellIterator will only return the cells defined in the file, which is largely those with values or stylings, but it depends on Excel).
It sounds like you are in that situation, where you need to care about hitting every row/cell, and not just grabbing all the available cells without worrying about the gaps
You'll want to change you code to look somewhat like the example in the POI docs:
// Decide which rows to process
int rowStart = Math.min(15, sheet.getFirstRowNum());
int rowEnd = Math.max(1400, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
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
// Mark it as blank in the database if needed
} else {
// Do something useful with the cell's contents
}
}
}

Categories