I want to write data into excel(.xlsx file) using Apache poi. but getting some error while writing a data. I have followed this video " How to read/write data from Excel file using Apache POI API in Selenium || Latest POI Version", I m able to read data but while writing I m getting this error " Cannot invoke "org.apache.poi.xssf.usermodel.XSSFCell.getStringCellValue()" because the return value of "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" is null ", basically nullpointerexception.
enter code here
String resourceGroupNameElement = driver.findElement(By.xpath(FrameworkValidator_Constants.Constants.RESOURCE_GROUP_NAME_XPATH)).getText();
String expectedResult = reader.getCellData("RG",6,2);
if( resourceGroupNameElement== expectedResult) {
String status= "pass";
System.out.println(status);
}
else {
String status="fail";
System.out.println(status);
}
//reader.setCellData("RG", "STATUS/PASS/FAIL", 2, status);
System.out.println(status);
reader.setCellData("RG","ACTUAL RESULT" , 2, resourceGroupNameElement);
Assert.assertEquals(resourceGroupNameElement, expectedResult);
#######
It is showing error in this section
public String setCellData(String sheetName, String colName, int rowNum, String data) {
try {
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(fis);
if (rowNum <= 0)
return "";
int index = workbook.getSheetIndex(sheetName);
int colNum = -1;
if (index == -1)
return "";
sheet = workbook.getSheetAt(index);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++) {
// System.out.println(row.getCell(i).getStringCellValue().trim());
if (row.getCell(i).getStringCellValue().trim().equals(colName))
colNum = i;
}
if (colNum == -1)
return "";
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(data);
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
return "";
}
return "";
}
so can anybody tell me where I m going wrong.
Have a look at the HOWTO and examples.
You will notice that there are calls for creating a row or creating a cell. Unless you do so, the row/cell does not exist and your getCell() function will return null.
Changing for loop condition part i.e. i < row.getLastCellNum(); to i < row.getLastCellNum()-1; can resolve this issue.
getLastCellNum() returns index plus one and once the counter will reach to end value, getCell(i) can point to the null value as per your code.
Related
I want to read a set of usernames and password from an excel sheet. My user name is present in the First column but my password values are present in the 8th column. I don't want to read the 8th column values by giving the 8th column address. Instead i want to read the password values wherever I place it in the excel sheet. Is there any way to do this ?
FileInputStream fs = new FileInputStream(strReadFile);
Workbook wb = Workbook.getWorkbook(fs);
Sheet sh = wb.getSheet("Sheet1");
int rowCount=sh.getRows();
System.out.println("No of Rows:"+rowCount);
for(int row=1;row<rowCount;row++) {
String Username = sh.getCell(1,row).getContents();
driver.findElement(By.id("user_name")).sendKeys(Username);
String Password = sh.getCell(2,row).getContents();
driver.findElement(By.id("user_pass")).sendKeys(Password);
driver.findElement(By.id("login_button")).click();
}
There is no inbuilt method As per my understanding. Check below method column for your solution.
for(int row=1;row<rowCount;row++) {
String Username = sh.getCell(column("username column",sh),row).getContents();
driver.findElement(By.id("user_name")).sendKeys(Username);
String Password = sh.getCell(column("password column",sh),row).getContents();
driver.findElement(By.id("user_pass")).sendKeys(Password);
driver.findElement(By.id("login_button")).click();
}
public int column(String columnName, Sheet sheetAt) throws Exception{
Row row = sheetAt.getRow(0);
int col = -1;
for (int i=0; i<row.getLastCellNum(); i++) {
Cell cell = row.getCell(i);
if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
continue;
}
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
String text = cell.getStringCellValue();
if (columnName.equals(text)) {
col = i;
break;
}
}
}
if (col == -1) {
throw new Exception("None of the cells in the first row were Patch");
}
return col;
}
Abstract of the module which gets book name, sheet name and column name as arguments and expecting the module to return the desired row index.
public int getExcelData(String WBookName, String sheetName, String columnName) {
int colNum = -1;
int rowIndex = -1;
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/"+WBookName+".xls");
try {
excelWBook = new XSSFWorkbook(inputStream);
Log.info(WBookName+"Excel File loaded Successfully");
} catch (IOException e) {
Log.fatal("Unable to load"+WBookName+" Excel File");
e.printStackTrace();
}
excelWSheet = excelWBook.getSheet(sheetName);
row = excelWSheet.getRow(0);
for(int i=0; i<row.getLastCellNum();i++) {
if(row.getCell(i).getStringCellValue().trim().equals(columnName)){
colNum = i;
}
}
{
//code for getting last non-empty row for a columnName (Possible using Iterator?)
}
return rowIndex;
As Apache POI has the method Sheet#getLastRowNum(), I would use a for-loop going backwards from excelWSheet.getLastRowNum() to 0 and ask each row for a presence of a value.
The code would be something like (you should try it yourself, I am now just "programming in the browser") this:
for (int rowNum = excelWSheet.getLastRowNum(); rowNum >= 0; rowNum--) {
final Row row = excelWSheet.getRow(rowNum);
if (row != null && row.getCell(colNum) != null) {
rowIndex = rowNum;
break;
}
}
I'm here to ask for help in my java project in Netbeans.
I'm using Apache POI to import/export excel data. To make you understand what is the problem in my application, I'm showing you a print of the debug.
In the print, you can see 2 sheets. The first header "aiai" and the data from that sheet.
My problem is: How do i insert the data from "aiai2" which is the second sheet from my excel file, in its proper place, below the header "aiai2"
On other words, I want to separate the sheets vertically.
Below, I will show my code:
Workbook wb;
public String Importar(File archivo, JTable tablaD) {
String answer = "Unable to import";
DefaultTableModel modeloT = new DefaultTableModel();
tablaD.setModel(modeloT);
tablaD.getModel();
tablaD.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
try {
wb = WorkbookFactory.create(new FileInputStream(archivo));
int nsheets = wb.getNumberOfSheets();
for (int i = 0; i < nsheets; i++) {
Sheet sheet = wb.getSheetAt(i);
Iterator filaIterator = sheet.rowIterator();
int rownum = -1;
while (filaIterator.hasNext()) {
rownum++;
Row fila = (Row) filaIterator.next();
/*if (i > 0) {//se o nr da ficha atual for maior que 0, começa a escrever as linhas apartir da row 0 da tabela
modeloT.moveRow(modeloT.getRowCount() -1, modeloT.getRowCount() - 1, 0);
}*/
Iterator columnaIterator = fila.cellIterator();
Object[] listaColumna = new Object[1000];
int columnnum = -1;
while (columnaIterator.hasNext()) {
columnnum++;
Cell celda = (Cell) columnaIterator.next();
if (rownum == 0) {
modeloT.addColumn(celda.getStringCellValue());
} else {
if (celda != null) {
switch (celda.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
listaColumna[columnnum] = (int) Math.round(celda.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
listaColumna[columnnum] = celda.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN:
listaColumna[columnnum] = celda.getBooleanCellValue();
break;
default:
listaColumna[columnnum] = celda.getDateCellValue();
break;
}//end switch case
System.out.println("Column:" + columnnum + " Row:" + rownum + " value:" + celda + ".");
}
}
}//end while column Iterator
if (rownum != 0) {
modeloT.addRow(listaColumna);
}
}//end while row iterator
}//end for
answer = "Imported with success";
} catch (IOException | InvalidFormatException | EncryptedDocumentException e) {
System.err.println(e.getMessage());
}
return answer;
}
public String Exportar(File archivo, JTable tablaD) {
String answer = "Unable to export";
int numFila = tablaD.getRowCount(), numColumna = tablaD.getColumnCount();
if (archivo.getName().endsWith("xls")) {
wb = new HSSFWorkbook();
} else {
wb = new XSSFWorkbook();
}
Sheet hoja = wb.createSheet("Default");
try {
for (int i = -1; i < numFila; i++) {
Row fila = hoja.createRow(i + 1);
for (int j = 0; j < numColumna; j++) {
Cell celda = fila.createCell(j);
if (i == -1) {
celda.setCellValue(String.valueOf(tablaD.getColumnName(j)));
} else {
celda.setCellValue(String.valueOf(tablaD.getValueAt(i, j)));
}
wb.write(new FileOutputStream(archivo));
}
}
answer = "Exported with success";
} catch (Exception e) {
System.err.println(e.getMessage());
}
return answer;
}
As I understand your question, I assume you want to create a separate table for each sheet, one below other. In that case you need to create a new table everytime you read a new sheet. If you use only one table, you will get only one header.
Try this :
Create a new method Importar that takes a new table and a Sheet parameter
public String Importar(JTable tablaD, Sheet sheet) {
String answer = "Unable to import";
DefaultTableModel modeloT = new DefaultTableModel();
tablaD.setModel(modeloT);
tablaD.getModel();
tablaD.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
try {
Iterator filaIterator = sheet.rowIterator();
int rownum = -1;
....
....
So the calling method would be :
try {
Workbook wb = WorkbookFactory.create(new FileInputStream(archivo));
int nsheets = wb.getNumberOfSheets();
for (int i = 0; i < nsheets; i++) {
//You have to make sure your JTable gets rendered.
JTable tablaD = new JTable();
Importar( tablaD, wb.getSheetAt(i) );
}
} catch ( Exception e ) {
e.printStackTrace();
}
Important point is that your new table needs to get rendered or added to frame each time before you call Importar
I have data in the above format in an excel file , I want to edit it as follows:
I have used the following code :
public void editExcelTemplate() throws FileNotFoundException, IOException
{
InputStream ExcelFileToRead = new FileInputStream("file.xls");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFSheet sheet = wb.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
String cmp = "none";
for(int i=0;i<rows;i++)
{
Row row = sheet.getRow(i);
int col =row.getPhysicalNumberOfCells();
int colIndex = 1;
int v=0;
for(int j=0;j<col;j++)
{
String content = row.getCell(j).getStringCellValue();
if(!(content == cmp) && !(content.equals("none")))
{
if(!(cmp.equals("none")))
{
System.out.println("content: "+content);
System.out.println("cmp: "+cmp);
v= j;
System.out.println("row : "+i+"colst : "+(colIndex)+"colend : "+v);
if(!( v-colIndex == 0) && v>0)
{
System.out.println("row : "+i+"colst : "+(colIndex)+"colend : "+v);
sheet.addMergedRegion(new CellRangeAddress(i,i,colIndex-1,v-1));
System.out.println("merged");
}
}
}
if(!(content == cmp))
{
colIndex = v+1;
}
cmp = content;
}
}
FileOutputStream excelOutputStream = new FileOutputStream(
"file.xls");
wb.write(excelOutputStream);
excelOutputStream.close();
}
I endedup getting the following output :
Can anybody help me get an appropriate output ? The main purpose is to merge the cells with common data in the entire proces.
I want to remove the cell content but keeping its style but it's always remove the style and content. Here's my code:
private static void RefreshReport(String sheetName, String resultColumn) {
try {
InputStream inp = new FileInputStream(getExcelFile());
Workbook wb = WorkbookFactory.create(inp);
Sheet sheet = wb.getSheet(sheetName);
int colResult = getColumnResult(sheet, resultColumn);
int rowStart = getRowResult(sheet, resultColumn);
int rowEnd = Math.max(20, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
if (r != null) {
Cell cell = r.createCell(colResult);
if (cell.getCellType() != Cell.CELL_TYPE_BLANK) {
CellStyle cs = wb.createCellStyle();
cs = cell.getCellStyle();
r.removeCell(cell);
cell = r.createCell(colResult);
cell.setCellStyle(cs);
}
}
}
FileOutputStream fileOut = new FileOutputStream(getExcelFile());
wb.write(fileOut);
fileOut.close();
inp.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Any help would be great.
The reason that your method isn't working is that you are always calling createCell if the the row r is not null. This will overwrite any Cell that already exists, including contents and styling.
What you need to do is call getCell instead. This will retrieve the Cell at that column index, provided it exists, or null if it doesn't exist. Then if it exists, you can process the Cell as you are doing.
if (r != null) {
Cell cell = r.getCell(colResult);
if (cell != null && cell.getCellType() != CellType.BLANK) {
// rest of your code here
In an alternative to the delete/re-create method you have, you can just set the cell type to BLANK. This will set the contents to blank, but it will also preserve the cell style currently on that cell. There is no need to delete the cell and re-create it.
if (cell.getCellType() != CellType.BLANK) {
cell.setCellType(CellType.BLANK);
}
Related to the rgettman's comment.
But in POI 5.0, you should use cell.setBlank() instead, because cell.setCellType(CellType.BLANK) is deprecated.