I am trying to fetching data from excel sheet(.xlsx) file. when I use to print fetched data using
System.out.println(sheet.getRow(i).getCell(c).getStringCellValue()); I see the all the rows from excel sheet is fetched. But when I add this data in jtable it misses last three rows and shows following error:
Cannot invoke "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" because the return value of "org.apache.poi.xssf.usermodel.XSSFSheet.getRow(int)" is null
enter code here
JFileChooser fileChooser = new JFileChooser("D:");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
selectedFile = fileChooser.getSelectedFile();
FileName = selectedFile.getName();
String FilePath = selectedFile.getPath();
System.out.println(FileName);
System.out.println(FilePath);
File excelfile = new File(FileName);
try{
FileInputStream fis = new FileInputStream(selectedFile);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
int totalrows = sheet.getPhysicalNumberOfRows();
for (int i = 0; i <=totalrows; )
{
dmodel.addRow(new Object[]{"" });
System.out.println(sheet.getRow(i).getCell(0).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(0).getStringCellValue();
jTable1.setValueAt(name , i, 0); // this line does not work
i++ ;
}
JOptionPane.showMessageDialog(null, "All rows are fetched Successfully" );
}catch(Exception fx)
{
System.out.println(fx.getMessage());
// System.out.println(fx.getCause());
}
System.out.println(sheet.getRow(r).getCell(c).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(c).getStringCellValue();
jTable1.setValueAt(name , i, 0); // this line does not work
Don't know if this will solve your problem, but the above code is not how you use System.out.println(...) to debug your logic.
To verify the data you use:
//System.out.println(sheet.getRow(r).getCell(c).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(c).getStringCellValue();
System.out.println( name );
jTable1.setValueAt(name , i, 0); // this line does not work
Don't attempt to read the data twice. By assigning the data to a variable you are debugging the data in the variable. Don't repeat the nested methods multiple times.
Maybe the class expects you to only read the data once, so the second read gives the null value. The simple change above will prevent this.
Related
I am working with a large excel file ( larger than 40 Mb , more than 100k rows and 50 columns ). I am successfully reading it using POI ( 3.10.1 version ) event stream and then doing some calculation and storing result into a List.
Now I have to append this List as a column in the same file. In this part I am facing issue.
I have tried to achieve this by using the below code
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
Workbook workbook = new XSSFWorkbook(excelFile);
Sheet datatypeSheet = workbook.getSheetAt(0); // Get first sheet
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
workbook.write(fos);
fos.close();
It is working fine with smaller files But the issue is that I am getting Out of memory for the larger files. Now I tried to modify this and use SXSSF in place of XSFF to get over the memory issue (See below code). But while testing even for smaller files I am getting output file same as the input file.
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
XSSFWorkbook xwb = new XSSFWorkbook(inputStream);
inputStream.close();
SXSSFWorkbook wb = new SXSSFWorkbook(xwb,100);
wb.setCompressTempFiles(true);
SXSSFSheet sh = (SXSSFSheet) wb.getSheetAt(0);
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
wb.write(fos);
fos.close();
Using a db is not suitable in my use case and i want to avoid using a temporary data structure to hold data for writing due to memory constraint.
Is there a way to write in output workbook while streaming ? Here is the code that I am using to read using POI Streaming API
private class ExcelData implements SheetContentsHandler {
LinkedHashMap<Strin, String> rowMap;
public void startRow(int rowNum) {
}
public void endRow(int rowNum) {
// Process the row
// Handle write to output workbook ??
}
public void cell(String cellReference, String formattedValue,
XSSFComment comment) {
// Save current row in rowMap ( column name => cell value )
}
public void headerFooter(String text, boolean isHeader, String tagName)
{
}
}
It is not possible to add column to existing workbook using POI SXSSF. It only allows addition of new rows.
The only solution is to read the existing workbook and write to a new workbook with the added column.
To achieve this we can store the rows in a data structure or database in the endrow() method and then use the persisted data to write a new workbook.
I am trying to edit an xls file through apache POI, but while calling workbook.write(fileOutpuStream), I am getting the following error :
ERROR [2018-01-16 20:33:50,817] java.lang.ArrayIndexOutOfBoundsException: 1
at org.apache.poi.xssf.usermodel.XSSFTable.setCellReferences(XSSFTable.java:294)
at org.apache.poi.xssf.usermodel.XSSFTable.getStartCellReference(XSSFTable.java:266)
at org.apache.poi.xssf.usermodel.XSSFTable.updateHeaders(XSSFTable.java:347)
at org.apache.poi.xssf.usermodel.XSSFTable.writeTo(XSSFTable.java:93)
at org.apache.poi.xssf.usermodel.XSSFTable.commit(XSSFTable.java:104)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:414)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:419)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:419)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:242)
Some lines of my code are :
Workbook workbook = new XSSFWorkbook(fileInputStream)
Sheet firstSheet = workbook.getSheetAt(0);
/* iterate through rows and columns, write at the last column (fixed number) */
fileInputSream.close()
FileOutputStream fileOut = new FileOutputStream(localFile);
workbook.write(fileOut);
fileOut.close()
A similar code was working for me earlier, so I have no idea what is wrong with this. I'm literally stuck on this.
EDIT:
I got to part pointed by jontro.
It is indeed finding only the start reference of my sheet.
I have an excel like :
id | name | result
1 | first |
2 | second |
I am iterating through the rows, and creating users in my system, if created successfully, I write true (false) in the result column. Since xlsx is created through google spreadsheets, I do not have an end row so if I find empty name, I break out of the row iterator. Then execute the part of my code below the comments, written above.
EDIT 2:
InputStream is = new FileInputStream(localFile);
try (Workbook workbook = new XSSFWorkbook(is)) {
Sheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = firstSheet.iterator();
while (iterator.hasNext()) {
Row row = iterator.next();
Data data = new Data(row.cellIterator());
//do something with data
data.getCell().setCellValue("processed");
}
FileOutputStream fileOut = new FileOutputStream(localFile);
workbook.write(fileOut); //fails here
fileOut.close();
} catch (Exception e) {//print
}
public class Data {
Data (Iterator<Cell> iterator) {
Cell cell = iterator.next();
this.var1 = cell.getStringCellValue();
cell = iterator.next();
this.var2 = cell.getStringValue();
....
this.cell = iterator.next(); //this is for saying processed
}
I am starting to agree with Axel's comment that this has to do with google spreadsheet creation of Table objects. I have a similar code, where there is a different class Data, and that worked! I double verified everything and nothing was different.
By looking at the code in the trunk of XSSFTable.java we can see the following code
private void setCellReferences() {
String ref = ctTable.getRef();
if (ref != null) {
String[] boundaries = ref.split(":", 2);
String from = boundaries[0];
String to = boundaries[1];
startCellReference = new CellReference(from);
endCellReference = new CellReference(to);
}
}
The ArrayIndexOutOfBoundsException is thrown on the following line String to = boundaries[1];
The cell reference is expected to be in the form A1:B3 or similar. Since you do not post your loop it's hard to say exactly what is causing this error. Check that you are not creating incomplete cell ranges
I have fetched the value from the textbox and stored in a string. Now i want to write this value stored in string into the column named as 'Username' in the excel file.
E.G: Fetched the Username from the textbox as 'Test1' and want to write this in the column 'Username' of the Excel. I am using POI to write excel file using Selenium.
hi please implement the logic like below
public static void writeExcel(String filePath,String fileName,String sheetName,String[] dataToWrite) throws IOException{
//Create a object of File class to open xlsx file
File file = new File(filePath+"\\"+fileName);
//Create an object of FileInputStream class to read excel file
FileInputStream inputStream = new FileInputStream(file);
Workbook Workbook = null;
//Find the file extension by spliting file name in substing and getting only extension name
String fileExtensionName = fileName.substring(fileName.indexOf("."));
//Check condition if the file is xlsx file
if(fileExtensionName.equals(".xlsx")){
//If it is xlsx file then create object of XSSFWorkbook class
Workbook = new XSSFWorkbook(inputStream);
}
//Check condition if the file is xls file
else if(fileExtensionName.equals(".xls")){
//If it is xls file then create object of XSSFWorkbook class
Workbook = new HSSFWorkbook(inputStream);
}
//Read excel sheet by sheet name
Sheet sheet = Workbook.getSheet(sheetName);
//Get the current count of rows in excel file
int rowCount = sheet.getLastRowNum()-sheet.getFirstRowNum();
//Get the first row from the sheet
Row row = sheet.getRow(0);
//Create a new row and append it at last of sheet
Row newRow = sheet.createRow(rowCount+1);
//Create a loop over the cell of newly created Row
for(int j = 0; j < row.getLastCellNum(); j++){
//Fill data in row
Cell cell = newRow.createCell(j);
cell.setCellValue(dataToWrite[j]);
}
//Close input stream
inputStream.close();
//Create an object of FileOutputStream class to create write data in excel file
FileOutputStream outputStream = new FileOutputStream(file);
//write data in the excel file
Workbook.write(outputStream);
//close output stream
outputStream.close();
}
Now call the above in main method like below
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
String valueToWrite = "test 1";
//Create an object of current class
WriteExcelFile objExcelFile = new WriteExcelFile();
//Write the file using file name , sheet name and the data to be filled
objExcelFile.writeExcel(System.getProperty("user.dir")+"\\src\\excelExportAndFileIO","ExportExcel.xlsx","ExcelDemo",valueToWrite);
}
You need to know column number of "Username" column in the excel sheet. Once you know that then it will be easy to write value of String that you captured from webpage. You can take below approach -
File excelFile = new File("C:\\path\\of\\excel\\file\\excel.xlsx");
String cellNo = 3; //column number of "UserName" column
String rowNo = 1; // row number
String userName = "Test1"; // username fetched from textbox
FileInputStream fis = new FileInputStream(excelFile);
XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(fis);
XSSFSheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(rowNo);
row.createCell(cellNo).setCellValue(userName);
fis.close();
FileOutputStream fos = new FileOutputStream(excelFile);
workbook.write(fos);
fos.close();
This is very simple approach just for this purpose and is not generalized one for any other task.
You can take a look at simple script that reads from a excel sheet and writes back to same excel sheet using Apache POI, here.
Regards,
Punkaaj
I have created program which match console output with excel cell data and prints "TRUE" - "FALSE" based on data matching. Issue is my data is matching here 100% then also it is printing "FALSE" in excel , WHY?
Code is given below :
//CODE TO REMOVE UNNECESSARY WARNING
System.setProperty("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.Jdk14Logger");
//CALL FIREFOX DRIVER TO OPEN IT
WebDriver driver = new FirefoxDriver();
//GETTING PAGE , OPEN IT IN BROWSER AND GET PAGE TITLE TO PRINT IT
driver.get("http://en.wikipedia.org/wiki/Software_testing");
String title = driver.getTitle();
System.out.println(title);
//EXCEL FILE READING
FileInputStream input = new FileInputStream("D:\\sel.xls");
int count=0;
HSSFWorkbook wb = new HSSFWorkbook(input);
HSSFSheet sh = wb.getSheet("sheet1");
HSSFRow row = sh.getRow(count);
String data = row.getCell(1).toString();
System.out.println(data);
//CONDITION TO MATCH CONSOLE OUTPUT WITH EXCEL CELL DATA VALUE
if(title==data)
{
FileOutputStream webdata = new FileOutputStream ("D:\\sel.xls");
row.createCell(10).setCellValue("TRUE");
wb.write(webdata);
}
else
{
FileOutputStream webdata = new FileOutputStream ("D:\\sel.xls");
row.createCell(11).setCellValue("FALSE");
wb.write(webdata);
}
driver.close();
wb.close();
input.close();
}
}
title and data are two different objects, means holding two different references. Your == symbol will match references and not exact value. Use equals() instead.
Use
if(title.equals(data))
instead of
if(title==data)
I have a script that reads a row in an excel sheet, fills an array list with the contents of each cell in that row, and writes it to a text file. I want to be able to write it to a pdf file (using iText) so that I can include an image in the file as well. The problem is I keep getting an error stating that the document has been closed and "Elements cannot be added" to the document. Here is the relevant code:
public File processFile(File excelWorkbook) throws FileNotFoundException, IOException, DocumentException{
System.out.println("Processing file...");
FileInputStream fileInputStream = new FileInputStream(excelWorkbook);
HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
HSSFSheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = firstSheet.iterator();
System.out.println("Please choose output file name.");
String fName = this.chooseFileName();
try{
for(int cntr=1; cntr<=firstSheet.getPhysicalNumberOfRows(); cntr++){
ArrayList<String> values = new ArrayList<String>();
Row currentRow = firstSheet.getRow(cntr);
for(int cntr2 = 0; cntr2<currentRow.getLastCellNum(); cntr2++){
Cell currentCell = currentRow.getCell(cntr2, Row.RETURN_NULL_AND_BLANK);
if(currentCell==null){
//cell doesn't have anything in there
values.add("-not in excel file-");
continue;
}else{
switch(currentCell.getCellType()){
case Cell.CELL_TYPE_STRING:
values.add(currentCell.getStringCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
double num = currentCell.getNumericCellValue();
String numString = String.valueOf(num);
values.add(numString);
break;
}
}
}
//libF = writeArrayListToFile(values, fName);
writePDF(values, fName);//the method that writes to pdf
}
}catch (NullPointerException e){
System.out.println("Cell is null.");
//e.printStackTrace();
}
fileInputStream.close();
return libF;
}
Here is the writePDF(ArrayList al, String fName) method:
public void writePDF(ArrayList<String> al, String filepath) throws FileNotFoundException, DocumentException{
PdfWriter.getInstance(document, new FileOutputStream(filepath));
document.open();
document.add(new Paragraph("Library"));
for(String i: al){
document.add(new Phrase(i+"\n"));
}
document.close();
}
Why am I not able to write to this file continuously? If I write to a text file, I can close it and open it again easily, so I can get all the information from the excel spreadsheet into a text file. The same does not seem to apply to a pdf file. It is unable to open and close easily. Can someone tell me how I should modify my code? All I want is for the script to read the Row in the excel sheet, add the Cell contents to the array list, and add the array list immediately after that to the pdf document. It just needs to do this for every row. This works for a text file but not for a pdf.
you are writing every row into a pdf document
your writePDF function has a field:
document
which isn't initialized around file opening (instead i think it's initialized in construction time)
initialize the document the same time you open the output file