I have a problem with getting data from this function when I call it twice. The function returns an arrayList of all rows fetched from an excel sheet. When I call the function the first time I get the correct amount of rows (all rows except the headline row and the row with exit). The second time I call the function I get 0.
It seems that something happens with file or the sheets created the second time, here is the code:
private static List<String[]> getDataFromXLS(String excelPath) {
FileInputStream fis;
Workbook workbook; Sheet sheet; XSSFRow row;
Iterator<Row> rows;
XSSFCell cell;
List<String[]> allExcelRows = new ArrayList<String[]>();
String[] xlsRow;
columnNames = new LinkedHashMap<Integer, String>();
paramNames = new LinkedHashMap<String, Integer>();
int totalColumnCount = 0;
int rowNumber = 1;
try {
fis = new FileInputStream(new File(excelPath));
workbook = WorkbookFactory.create(fis);
sheet = workbook.getSheet("TestData");
rows = sheet.rowIterator();
while (rows.hasNext()) {
row = ((XSSFRow) rows.next());
if (rowNumber == 1) {
//based on amount of parameters on first xls row
totalColumnCount = row.getLastCellNum();
}
xlsRow = new String[totalColumnCount];
//check which column is TestType
//iterate through all the columns
for (int columnNumber=0; columnNumber<totalColumnCount; columnNumber++) {
cell = row.getCell(columnNumber, Row.CREATE_NULL_AS_BLANK);
if (getCellValue(cell).trim().toLowerCase().trim().equals("testtype") ){
testTypeColumnIndex = columnNumber; //this is Testtype index
break;
}
}
if (rowNumber != 1) {
for(int columnNumber=0; columnNumber<totalColumnCount; columnNumber++) {
cell = row.getCell(columnNumber, Row.CREATE_NULL_AS_BLANK);
//read only rows before exit
if (columnNumber == testTypeColumnIndex && getCellValue(cell).trim().toLowerCase().trim().equals("exit") ){
reachedExit = true;
break;
}
xlsRow[columnNumber] = getCellValue(cell).trim();
}
//reached exit?
if (reachedExit) {
break;
}
allExcelRows.add(xlsRow);
} else {
//save column names into map
for(int columnNumber=0; columnNumber<totalColumnCount; columnNumber++) {
cell = row.getCell(columnNumber, Row.CREATE_NULL_AS_BLANK);
columnNames.put(columnNumber, getCellValue(cell).trim());
paramNames.put(getCellValue(cell).trim(), columnNumber);
}
}
rowNumber++;
}
} catch (Exception e) {
e.printStackTrace();
}
fis.close();
return allExcelRows;
}
Am taking a bit of a guess here but I think the problem is that the reachedExit class level boolean is not reset at the start of the method. Hence when you call it the second time this code block executes:
//reached exit?
if (reachedExit) {
break;
}
....meaning that nothing gets added to allExcelRows
Related
I made poi excel read, upload and save into DB but when I check my DB, excel parsing db without first row. I tried to change code but it doesn't work so I put the my original code. please help!
public static List<Product> excelToExcelEntity(InputStream inputStream) {
try {
Workbook wb = new XSSFWorkbook(inputStream);
Sheet sheet = wb.getSheet(SHEET);
Iterator<Row> rows = sheet.iterator();
List<Product> entities = new ArrayList<Product>();
int rowNumber = 0;
while (rows.hasNext()) {
Row currentRow = rows.next();
if (rowNumber == 0) {
rowNumber++;
continue;
}
Iterator<Cell> cellsInRow = currentRow.iterator();
Product excelEntity = new Product();
DataFormatter formatter = new DataFormatter();
int cellIdx = 0;
while (cellsInRow.hasNext()) {
Cell currentCell = cellsInRow.next();
switch:
---
break;}
cellIdx++;
}
entities.add(excelEntity);
}
wb.close();
return entities;
if (rowNumber == 0) {
rowNumber++;
continue;
}
remove/comment above block code, in here continue will skip further execution and goes back to next element from the list, in your case it's skipping first row.
I'm trying to write data in excel while running my tests and in Excel Test Class I have written a code to check if specific row under column is empty then write data else increment the row by 1 and then check same and write data.
From another class I'm calling ExcelTest:
ExcelTest sfName = new ExcelTest("C:\\Users\\abc\\eclipse-workspace\\dgc\\src\\com\\dg\\base\\utility\\TestData.xlsx");
sfName.setCellData("Sheet1","SingleFactor Campaign",SFCampName);
ExcelTest Class
public class ExcelTest
{
public FileInputStream fis = null;
public FileOutputStream fos = null;
public XSSFWorkbook workbook = null;
public XSSFSheet sheet = null;
public XSSFRow row = null;
public XSSFCell cell = null;
String xlFilePath;
boolean isEmptyStringCell;
public ExcelTest(String xlFilePath) throws Exception
{
this.xlFilePath = xlFilePath;
fis = new FileInputStream(xlFilePath);
workbook = new XSSFWorkbook(fis);
fis.close();
}
public void setCellData(String sheetName, String colName, int rowNum, String value)
{
try
{
int col_Num = -1;
sheet = workbook.getSheet(sheetName);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++)
{
if(row.getCell(i).getStringCellValue().trim().equals(colName))
{
col_Num = i;
}
}
sheet.autoSizeColumn(col_Num);
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
/*row = sheet.getRow(rowNum - 1);
if(row==null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(col_Num);
if(cell == null)
cell = row.createCell(col_Num);
cell.setCellValue(value);*/
System.out.println("The cell value is "+cell.getStringCellValue());
fos = new FileOutputStream(xlFilePath);
workbook.write(fos);
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
If we remove the block comment(mentioned above in code and add then comment to this code listed below then it will just write data in cell whichever is provided while calling the function.
In below code I'm starting a loop till max 7 rows and then checking if the cell contains data then increment or write data and once it writes then exit the loop.
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
Expected: It should write data in a row which has no cell data.
Actual: It doesn't write anything.
I've found solution for the above question and only need to change few code and now it is working as expected:
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
//it will check if cell contains no value then create cell and set value
if(cell == null)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
}
I am using JAVA 8 and Apache POI 3.17. I have an Excel file and i want to keep only few lines and delete the others. But my Excel have 40K rows and deleting them one by one is quite long (nearly 30 min :/ )
So i try to change my way of doing it. Now i think it's better to only take rows that i need in the excel source and copy to another new one. But what i have tried so far is not efficient.
I have all my rows and want to keep in a List. But this not working and create me a blank excel :
public void createExcelFileFromLog (Path logRejetFilePath, Path fichierInterdits) throws IOException {
Map<Integer, Integer> mapLigneColonne = getRowAndColumnInError(logRejetFilePath);
Workbook sourceWorkbook = WorkbookFactory.create(new File(fichierInterdits.toAbsolutePath().toString()));
Sheet sourceSheet = sourceWorkbook.getSheetAt(0);
List<Row> listLignes = new ArrayList<Row>();
// get Rows from source Excel
for (Map.Entry<Integer, Integer> entry : mapLigneColonne.entrySet()) {
listLignes.add(sourceSheet.getRow(entry.getKey()-1));
}
// The new Excel
Workbook workbookToWrite = new XSSFWorkbook();
Sheet sheetToWrite = workbookToWrite.createSheet("Interdits en erreur");
// Copy Rows
Integer i = 0;
for (Row row : listLignes) {
copyRow(sheetToWrite, row, i);
i++;
}
FileOutputStream fos = new FileOutputStream(config.getDossierTemporaire() + "Interdits_en_erreur.xlsx");
workbookToWrite.write(fos);
workbookToWrite.close();
sourceWorkbook.close();
}
private static void copyRow(Sheet newSheet, Row sourceRow, int newRowNum) {
Row newRow = newSheet.createRow(newRowNum);
newRow = sourceRow;
}
EDIT : Change the method of copyRow it's better but the date have weird format and blank cells from the original row are gone.
private static void copyRow(Sheet newSheet, Row sourceRow, int newRowNum) {
Row newRow = newSheet.createRow(newRowNum);
Integer i = 0;
for (Cell cell : sourceRow) {
if(cell.getCellTypeEnum() == CellType.NUMERIC) {
newRow.createCell(i).setCellValue(cell.getDateCellValue());
} else {
newRow.createCell(i).setCellValue(cell.getStringCellValue());
}
i++;
}
}
EDIT 2 : To keep blank cell
private static void copyRow(Sheet newSheet, Row sourceRow, Integer newRowNum, Integer cellToColor) {
Row newRow = newSheet.createRow(newRowNum);
//Integer i = 0;
int lastColumn = Math.max(sourceRow.getLastCellNum(), 0);
for(int i = 0; i < lastColumn; i++) {
Cell oldCell = sourceRow.getCell(i, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
if(oldCell == null) {
newRow.createCell(i).setCellValue("");
} else if (oldCell.getCellTypeEnum() == CellType.NUMERIC) {
newRow.createCell(i).setCellValue(oldCell.getDateCellValue());
} else {
newRow.createCell(i).setCellValue(oldCell.getStringCellValue());
}
}
}
I have to check the strings of two xlsx files if they are equal must return the name, but it always returns null, someone can help me?
try
{
FileInputStream fisCod = new FileInputStream(pathC);
XSSFWorkbook wb = new XSSFWorkbook (fisCod);
XSSFSheet sheet = wb.getSheetAt(0);
int lastRow = sheet.getLastRowNum();
for(int i=0; i<lastRow; i++)
{
Row row = sheet.getRow(i);
Cell cell = row.getCell(jobCod);
String tmp = cell.getRichStringCellValue().getString().toLowerCase();
if (tmp.equals(jobName)) //jobName is a String
{
return tmp;
}
else
{
return null;
}
}
fisCod.close();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
The first mismatch in the above code will cause null to be returned without checking subsequent row values. More than likely, this is the scenario you are describing.
Check all cell values before resorting to returning null when the attempted match fails.
for (int i = 0; i < lastRow; i++) {
Row row = sheet.getRow(i);
Cell cell = row.getCell(jobCod);
String tmp = cell.getRichStringCellValue().getString().toLowerCase();
if (tmp.equals(jobName)) {
return tmp;
}
}
return null; // now return null
I am making a program where I am reading data from excel files and store them in tables. I have made the program using Apache POI and works fine. But when files have blank cells as the one here I have some problems. The program skip the blanks and read the next data. Could anyone help me how I would do it? I know that there are several posts for this issue but I have not found something useful for me.
The code for reading the data from excel file is the below. As you can see I have 3 types of data. How i would give the option for BLANK CELL?
// Create an ArrayList to store the data read from excel sheet.
List sheetData = new ArrayList();
FileInputStream fis = null;
try {
// Create a FileInputStream that will be use to read the
// excel file.
fis = new FileInputStream(strfullPath);
// Create an excel workbook from the file system
HSSFWorkbook workbook = new HSSFWorkbook(fis);
// Get the first sheet on the workbook.
HSSFSheet sheet = workbook.getSheetAt(0);
// store the data read on an ArrayList so that we can printed the
// content of the excel to the console.
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
List data = new ArrayList();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
data.add(cell);
}
sheetData.add(data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
fis.close();
}
}
showExcelData(sheetData);
}
private static void showExcelData(List sheetData) {
// LinkedHashMap<String, String> tableFields = new LinkedHashMap();
for (int i = 0; i < sheetData.size(); i++) {
List list = (List) sheetData.get(i);
for (int j = 0; j < list.size(); j++) {
Cell cell = (Cell) list.get(j);
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
System.out.print(cell.getNumericCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
System.out.print(cell.getRichStringCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
System.out.print(cell.getBooleanCellValue());
} else if (cell.getCellType()== Cell.CELL_TYPE_BLANK ){
System.out.print(cell.toString());
}
if (j < list.size() - 1) {
System.out.print(", ");
}
}
System.out.println("");
}
}
}
Also I have read about workbook.setMissingCellPolicy(HSSFRow.RETURN_NULL_AND_BLANK);. Could this help me with my problem?
int maxNumOfCells = sheet.getRow(0).getLastCellNum(); // The the maximum number of columns
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
List data = new ArrayList();
for( int cellCounter = 0
; cellCounter < maxNumOfCells
; cellCounter ++){ // Loop through cells
HSSFCell cell;
if( row.getCell(cellCounter ) == null ){
cell = row.createCell(cellCounter);
} else {
cell = row.getCell(cellCounter);
}
data.add(cell);
}
sheetData.add(data);
YOUR METHOD:
public static void showExcelData(List sheetData) {
// LinkedHashMap<String, String> tableFields = new LinkedHashMap();
for (int i = 0; i < sheetData.size(); i++) {
List list = (List) sheetData.get(i);
for (int j = 0; j < list.size(); j++) {
Cell cell = (Cell) list.get(j);
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
System.out.print(cell.getNumericCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
System.out.print(cell.getRichStringCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
System.out.print(cell.getBooleanCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
System.out.print("THIS IS BLANK");
}
if (j < list.size() - 1) {
System.out.print(", ");
}
}
System.out.println("");
}
}
Explanation:
int maxNumOfCells = sheet.getRow(0).getLastCellNum(); - This line will make sure that you were able to get the number of columns. Using the Row's method .getLastCellNum() on the next rows will result to unexpected number. Example on your on row 3 of your spreadsheet, the method will return 2 since the next value is null.
for( int cellCounter = 0
; cellCounter < maxNumOfCells
; cellCounter ++){ // Loop through cells
HSSFCell cell;
if( row.getCell(cellCounter ) == null ){
cell = row.createCell(cellCounter);
} else {
cell = row.getCell(cellCounter);
}
data.add(cell);
}
Looping through the cells. From cell 0 (Base 0) to the last cell number. If the cell was found null, basically, it would create the cell with a blank value. Lastly, adding the cell to your List.
Another solution if you don't know the size of your spreadsheet is to loop through row and column and compare the index of row and column with the previous one you parsed. If the increment is more than one you will create the missing intermediate cells.