apache poi indexoutofbound exception - java

Excel File (test1.xlsx)
Name Gender Age Resign Date
Ali M 20
Abu M 25
Siti F 30
Code
public class ReadExcel {
public static ArrayList<String> record;
public static void main(String[] args) throws FileNotFoundException, IOException {
//---Read file---
FileInputStream in = new FileInputStream("test1.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(in);
XSSFSheet spreadsheet = workbook.getSheetAt(0);
XSSFRow row;
Cell cell;
Iterator<Row> rowIterator = spreadsheet.iterator();
while(rowIterator.hasNext()){
record = new ArrayList<String>();
row = (XSSFRow)rowIterator.next();
if(row.getRowNum()==0) {
continue;
}
for(int k = 0; k < row.getLastCellNum();k++){
cell = row.getCell(k, Row.CREATE_NULL_AS_BLANK);
}
Iterator<Cell> cellIterator = row.cellIterator();
while(cellIterator.hasNext()){
cell = cellIterator.next();
cell.setCellType(Cell.CELL_TYPE_STRING);
switch(cell.getCellType()){
case Cell.CELL_TYPE_STRING:
record.add(cell.getStringCellValue());
System.out.print(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
Double value = cell.getNumericCellValue();
Long longValue = value.longValue();
record.add(Double.toString(cell.getNumericCellValue()));
System.out.print(cell.getNumericCellValue());
break;
}
}
System.out.println();
String name = record.get(0);
String gender = record.get(1);
String age = record.get(2);
String dateLeave = record.get(3); //[ERROR]
System.out.println(name + gender + age + dateLeave);
}
}
}
However, from my above program, I get this exception:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at ibguobform.ReadExcel.main(ReadExcel.java:66)
Java Result: 1
What is the errors that I made?

Your code is trying to reference the fourth element of a collection that has only three elements:
record.get(3)
Since there's only three elements, trying to reference the fourth one produces an error.
Why are there only three elements?
Well, look at the data:
Ali M 20
Abu M 25
Siti F 30
Three elements per line.
What appears to be happening is the code is dynamically checking for the last "element":
for(int k = 0; k < row.getLastCellNum(); k++){
cell = row.getCell(k, Row.CREATE_NULL_AS_BLANK);
}
It would seem that row.getLastCellNum() is telling the code that there are only three cells. (Because, well, there are only three cells with data in them.) If the fourth cell is valid even when there's no data, explicitly note that in the code by always using four elements:
for(int k = 0; k < 4; k++){
cell = row.getCell(k, Row.CREATE_NULL_AS_BLANK);
}

Related

Error when editing an excel file with Java (ConcurrentModificationException)

I'm trying to modify the last cell of the rows in an excel workbook that in any cell match another value.
In the first iteration it works fine, but in the second loop I get this java.util.ConcurrentModificationException error in the for (Cell cell : row) { line.
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.TreeMap$PrivateEntryIterator.nextEntry(TreeMap.java:1486)
at java.base/java.util.TreeMap$ValueIterator.next(TreeMap.java:1531)
at Package.Fotos.initial(Fotos.java:266)
at Package.Fotos.main(Fotos.java:360)
Does anyone know what I'm doing wrong? This is the code I'm using based on this answer.
...
for (int i = 0; i < cuentafilas; i++) {
List<WebElement> columnas = filas.get(i).findElements(By.tagName("img"));
int cuentacolumnas = columnas.size();
for (int k = 0; k < cuentacolumnas; k++) {
String c = columnas.get(k).getAttribute("src");
if (c.contains("jpg")) {
String filtroValor = id;
Workbook libro = WorkbookFactory.create(new FileInputStream("D:\\archivos\\entrada.xlsx"));
DataFormatter formatter = new DataFormatter();
Sheet hoja = libro.getSheetAt(0);
for (Row row : hoja) {
for (Cell cell : row) {
CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
String text = formatter.formatCellValue(cell);
if (filtroValor.equals(text)) {
Row fila = hoja.getRow(row.getRowNum());
int ultimaCelda = fila.getLastCellNum();
Cell celda = fila.createCell(ultimaCelda);
celda.setCellValue(c);
OutputStream os = new FileOutputStream("D:\\archivos\\entrada.xlsx");
libro.write(os);
}
}
}
}
}
}
...
Thanks.
The error lies in
Cell celda = fila.createCell(ultimaCelda);
where you create a new cell in the row.
You can't add a cell, while iterating over the list of all cells.
Try creating a copy of the list you are wanting to edit and iterate
over that one instead, so the other one becomes editable
the java.util.ConcurrentModificationException appears,
when editing a list, that you are currently iterating over.

Arraylist and Iteration

I have an Excel File with Values in the Ranges C17:C40, D17:D40 and E17:E40.
Now I read with Apache Poi the first Range with a for each loop. My Problem is I want to include a Code something like this:
If C17 is empty go to the next range (in this case D17) and check if D17 ist empty. If not read every Cell from the List and put it into a new Array list.
I hope some of you understand me. Here is my code:
public static ArrayList<String> list = new ArrayList<>();
public static ArrayList<String> ForEachLoop() throws EncryptedDocumentException, FileNotFoundException, IOException {
Workbook readWorkbook = WorkbookFactory.create(new FileInputStream(FileChooser.FileChoose()) );
Sheet sheet = readWorkbook.getSheetAt(4);
DataFormatter dataFormatter = new DataFormatter();
String cellValue = null;
for (int i = 16; i < 40; i++) { //Statt 20 soll hier 40
Row row = sheet.getRow(i);
if(row == null) {
continue;
}
for (int j = 2; j < 4; j++) {
Cell cell = row.getCell(j);
list.add(dataFormatter.formatCellValue(cell));
if(cell == null) {
continue;
}
// cellValue = dataFormatter.formatCellValue(cell);
// System.out.print(cellValue + "\n");
}
}
return list;
}

Write sheet data from workbook n number of times

I am reading data from excel workbook with multiple sheets.
I am able to read data from multiple sheets, but i am trying to print particular sheet data "n" number of times.
For Example : My workbook contains 10 sheets numbered from 1-10, and i want to print "sheet 1" data 3 times, "Sheet 2" data 3 times..
Similarly, i will be printing every sheet data "n" number of times.
Variables: name-contains sheet names,occurances-contains number of times sheet data to be printed.
String[] name = { "a", "b", "c" };
int[] occurances = { 2, 3, 4 };
int c1 = 0;
int c2 = 0;
Excel file Reading code :
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
Sheet datatypeSheet = workbook.getSheetAt(i);
Iterator<Row> iterator = datatypeSheet.iterator();
if (datatypeSheet.getSheetName().equals(name[c1])) {
c1++;
for (int d = 0; d < occurances[c2]; d++) {
c2++;
while (iterator.hasNext()) {
Row currentRow = iterator.next();
Iterator<Cell> cellIterator = currentRow.iterator();
while (cellIterator.hasNext()) {
Cell currentCell = cellIterator.next();
if (currentCell.getCellTypeEnum() == CellType.STRING) {
System.out.print(currentCell
.getStringCellValue() + "--");
}
}
System.out.println();
}
}
}
}
I tried, but am getting all sheet data printed for 1 time.
Please HELP!
There are a couple of problems with your code. Best way to understand why your code is not working is debugging (either through IDE or through logging).
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
// if your sheets are not in 'a', 'b', 'c' order this code
// will not work. think why
Sheet datatypeSheet = workbook.getSheetAt(i);
if (datatypeSheet.getSheetName().equals(name[c1])) {
c1++;
// you need this variable to be fixed for your loop
int occurancesForSheet = occurances[c2++];
for (int d = 0; d < occurancesForSheet; d++) {
// you need a new iterator each time
Iterator<Row> iterator = datatypeSheet.iterator();
while (iterator.hasNext()) {
Row currentRow = iterator.next();
Iterator<Cell> cellIterator = currentRow.iterator();
while (cellIterator.hasNext()) {
Cell currentCell = cellIterator.next();
if (currentCell.getCellTypeEnum() == CellType.STRING) {
System.out.print(currentCell
.getStringCellValue() + "--");
}
}
System.out.println();
}
}
}
}

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.

How to get an Excel Blank Cell Value in Apache POI?

I have a huge excel file with tons of columns which looks like this :-
Column1 Column2 Column3 Column4 Column5
abc def ghi
mno pqr
......
This is the code that I wrote to print these values:
try {
FileInputStream inputStr = new FileInputStream(fileName);
XSSFWorkbook xssfWork = new XSSFWorkbook(inputStr) ;
XSSFSheet sheet1 = xssfWork.getSheetAt(0);
Iterator rowItr = sheet1.rowIterator();
while ( rowItr.hasNext() ) {
XSSFRow row = (XSSFRow) rowItr.next();
System.out.println("ROW:-->");
Iterator cellItr = row.cellIterator();
while ( cellItr.hasNext() ) {
XSSFCell cell = (XSSFCell) cellItr.next();
System.out.println("CELL:-->"+cell.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
The output generated by this code is :-
ROW:-->
CELL:-->Column1
CELL:-->Column2
CELL:-->Column3
CELL:-->Column4
CELL:-->Column5
ROW:-->
CELL:-->abc
CELL:-->def
CELL:-->ghi
ROW:-->
CELL:-->mno
CELL:-->pqr
So, If we look at the output above we can note that the cells where I left blank values was not picked up by the POI library , is there a way in which I can get these values as null. or a way to recognize that the values presented skipped blank cells?
Thanks.
If you want to get all cells, no matter if they exist or not, then the iterator isn't for you. Instead, you need to manually fetch the appropriate cells, likely with a missing cell policy
for(Row row : sheet) {
for(int cn=0; cn<row.getLastCellNum(); cn++) {
// If the cell is missing from the file, generate a blank one
// (Works by specifying a MissingCellPolicy)
Cell cell = row.getCell(cn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// Print the cell for debugging
System.out.println("CELL: " + cn + " --> " + cell.toString());
}
}
There's more details on all of this in the Apache POI documentation on iterating over cells
I have been frustrated by this same problem. Here is what I found with poi-3.7-20101029 and poi-3.8.
RowIterator and CellIterator do not support iterating over NULL cells or rows -- only physically defined cells (which can be BLANK).
The solution that returns what I expect requires using the 0-based Row.getCell([int], Row.CREATE_NULL_AS_BLANK), much like Chavira's answer alludes to (assuming 8 cell rows). Or you can use the Cell.columnIndex value while iterating to check for jumping numbers...
Annoyingly, after creating blank cells using method #1, the iterators will return the now created BLANK cells. I consider it a bug that MissingCellPolicy is ignored by CellIterator.
The reason is quite simple: Excel files can contain as many rows and as many columns as possibles, so returning all available blank rows and columns will render the cells huge and memory intensive.
Assuming you have a 10x10 sheet, in Excel, it's not "exactly" 10x10 since you can add 11x10 very easily with blank cell, so should POI return the 11th column?
One way to do what you're requesting is to use HSSFCell.getColumnIndex().
Example:
//Assuming your have a 2 dimensional array.
String[][] values = ......;// It is assigned
POIFSFileSystem fileSystem = new POIFSFileSystem(new FileInputStream(fileName));
HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
//Going through every worksheet.
for (int sheetPos = 0; sheetPos < workbook.getNumberOfSheets(); sheetPos++) {
HSSFSheet sheet = workbook.getSheetAt(sheetPos);
int rowPos = 0;
Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
String value = "";
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_NUMERIC:
value = BigDecimal.valueOf(cell.getNumericCellValue()).toPlainString();
break;
case HSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_BLANK:
value = "";
break;
case HSSFCell.CELL_TYPE_FORMULA:
value = cell.getCellFormula();
break;
default:
break;
}
values[rowPos][cell.getColumnIndex()] = value;
}
rowPos++;
}
}
Below is what worked for me. The "row.CREATE_NULL_AS_BLANK" did not appear to be valid but that could be lack of NPOI knowledge.
HSSFCell dataCell= (HSSFCell)row.GetCell(column, NPOI.SS.UserModel.MissingCellPolicy.CREATE_NULL_AS_BLANK);
for(org.apache.poi.ss.usermodel.Row tmp : hssfSheet){
for(int i = 0; i<8;i++){
System.out.println(tmp.getCell(i));
}
}
This worked for me....
int rowNumber;
int previousCell;
int currentCell;
int currentRowNumber;
HSSFCell cell;
while (rows.hasNext()) {
previousCell = -1;
currentCell = 0;
while (cellIterator.hasNext()) {
cell = (HSSFCell) cellIterator.next();
currentCell = cell.getColumnIndex();
if (previousCell == currentCell-1) {
//...
}
else {
System.out.println("Blank cell found");
}
previousCell = currentCell;
}
}
List cellDataList = new ArrayList();
int lineNumber = 0;
while (rowIterator.hasNext()) {
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
//System.out.println("Befor If");
lineNumber++;
if(lineNumber==1){continue;}
//System.out.println("Out side if ");
Iterator<Cell> iterator = hssfRow.cellIterator();
List<Cell> cellTempList = new ArrayList();
int current = 0, next = 1;
while (iterator.hasNext()) {
Cell hssfCell = iterator.next();
current = hssfCell.getColumnIndex();
if(current<next){
System.out.println("Condition Satisfied");
}
else{
int loop = current-next;
System.out.println("inside else Loop value : "+(loop));
for(int k=0;k<loop+1;k++){
System.out.println("Adding nulls");
cellTempList.add(null);
next = next + 1;
}
}
cellTempList.add(hssfCell);
next = next + 1;
System.out.println("At End next value is : "+next);
}
cellDataList.add(cellTempList);
}
public String[] rowToString(Row row)
{
Iterator<Cell> cells = row.cellIterator() ;
String[] data = new String[row.getLastCellNum()] ;
int previousCell = 0 ;
Cell cell = cells.next() ;
int currentCell = cell.getColumnIndex();
while (true)
{
if (previousCell == currentCell) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
data[previousCell] = cell.getNumericCellValue()+"" ;
break;
case Cell.CELL_TYPE_STRING:
data[previousCell] = cell.getStringCellValue() ;
break;
/* // there could be other cases here.
case Cell.CELL_TYPE_FORMULA:
data[previousCell] =eval.evaluateFormulaCell(cell);
break;
case Cell.CELL_TYPE_BOOLEAN:
data[previousCell] = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK:
data[previousCell] = "";
break;
case Cell.CELL_TYPE_ERROR:
data[previousCell] = "ERROR";
break;
*/
}
if(cells.hasNext()){
cell = cells.next() ;
currentCell = cell.getColumnIndex();
} else {
break ;
}
} else {
data[previousCell] = "";
}
previousCell++ ;
}
return data ;
}
for (Row row: sheet){
// This will return null if cell is empty / blank
Cell cell = row.getCell(columnNumber);
}

Categories

Resources