I've the following code where fetching of data from excel sheet is done and then this data is added to list as below:
List<HashMap<String,String>> mydata = new ArrayList<>();
try
{
FileInputStream fs = new FileInputStream(filepath);
XSSFWorkbook workbook = new XSSFWorkbook(fs);
XSSFSheet sheet = workbook.getSheet(sheetName);
Row HeaderRow = sheet.getRow(0);
for(int i=1;i<sheet.getPhysicalNumberOfRows();i++)
{
Row currentRow = sheet.getRow(i);
HashMap<String,String> currentHash = new HashMap<String,String>();
for(int j=0;j<currentRow.getPhysicalNumberOfCells();j++)
{
Cell currentCell = currentRow.getCell(j);
switch (currentCell.getCellType())
{
case Cell.CELL_TYPE_STRING:
currentHash.put(HeaderRow.getCell(j).getStringCellValue(), currentCell.getStringCellValue());
break;
}
}
mydata.add(currentHash);
I've another class where we are making use Properties class and setting the property :
public List<HashMap<String,String>> datamap;
public static Properties prop;
public void read_Data_FromExcel(String arg1) throws Throwable {
datamap = DataHelper.data("C:/FINALORDER/ORDERING_Tools/ordering-tools/src/test/resources/Test451.xlsx","Sheet1");
prop=new Properties();
int index = Integer.parseInt(arg1)-2;
FileInputStream fs = new FileInputStream("C:\\FINALORDER\\ORDERING_Tools\\ordering-tools\\src\\test\\resources\\Test451.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(fs);
XSSFSheet sheet = workbook.getSheet("Sheet1");
Row HeaderRow = sheet.getRow(0);
for(int i=0;i<HeaderRow.getPhysicalNumberOfCells();i++) {
prop.setProperty(HeaderRow.getCell(i).toString(), datamap.get(index).get(HeaderRow.getCell(i).toString()));
Using the above code i m fetching the data from excel and then inputting that data into the fields present in the screen like below:
try {
String remark=ExcelSteps.prop.getProperty("Remark");
mosdpOrderSummaryEditPage.tbx_remarks.type(remark);
}catch(Exception e) {
}
The issue is if there are many fields like remark,name,address,id then i have to fetch them one by one using the above code as for remark which is sort of redundant work and increasing code unnecessarily , is there a way by which i can reduce the code or make any generic method.
You can create separate column and get those through
ExcelSteps.prop.getProperty("Here you should pass the column data");
By this code will automatically get remark,name,address,id field names dynamically.
:)
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 want to add value in the end of the column and but if i run the class it overrides the excel
JAVA , Apache POI:
// Blank workbook
XSSFWorkbook workbook = new XSSFWorkbook();
// Create a blank sheet
XSSFSheet sheet = workbook.createSheet("MyPolicies");
// Iterate over data and write to sheet
Set<Integer> keyset = data.keySet();
int rownum = 0;
for (Integer key : keyset) {
// this creates a new row in the sheet
Row row = sheet.createRow(rownum++);
Object[] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr) {
// this line creates a cell in the next column of that row
Cell cell = row.createCell(cellnum++);
if (obj instanceof String) {
cell.setCellValue((String) obj);
}
else if (obj instanceof Integer)
cell.setCellValue((Integer) obj);
}
}
try {
// this Writes the workbook
FileOutputStream out = new FileOutputStream(new File("extract.xlsx"));
workbook.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
The Excel overrides every time and new data alone is added.
Note : If both the ID's are same , we need to add the second map data in the same row
The reason why your document is replaced every time is that your workbook is blank. workbook.write(out) means you write everything in the workbook to a location (extract.xlsx), not that you write the data of your workbook into a file!
What you should be doing is open the workbook you're trying to edit:
FileInputStream xlsFile = new FileInputStream("extract.xls");
XSSFWorkbook workbook = new XSSFWorkbook(xlsFile);
... get the last row or column
XSSFSheet sheet = workbook.getSheetAt(0);
int lastRow = sheet.getLastRowNum();
... and write your data from there.
Then, as before, you can use workbook.write(out) to save your workbook.
I want to save the data in a single column row-wise, but at every time I save, a new cell is created and the data is not saved anymore in a single column.
Can you help me please ?
Thank you all.
System.setProperty("webdriver.chrome.driver", "/home/dev2/Downloads/newchromedriver/chromedriver");
WebDriver m = new ChromeDriver();
m.get("https://.130:2096/");
m.manage().window().maximize();
m.findElement(By.xpath(".//input[#id='user']")).sendKeys("talconnect.com.au");
m.findElement(By.xpath(".//input[#id='pass']")).sendKeys("$}+FdVI5$o!G");
m.findElement(By.xpath(".//button[#id='login_submit']")).click();
m.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
// m.manage().timeouts().implicitlyWait(2,TimeUnit.MINUTES);
m.switchTo().frame("mailFrame");
Thread.sleep(9000);
List<WebElement> xpath11 = m.findElements(By.xpath(".//tr[contains(#id, 'rcmrow')]"));
int count = xpath11.size();
System.out.println(count);
for (WebElement link : xpath11) {
String sd = link.getText();
File source = new File("/home/dev2/Desktop/readexcell.xlsx");
FileOutputStream input = new FileOutputStream(source);
XSSFWorkbook wb=new XSSFWorkbook();
XSSFSheet sheet=wb.createSheet("data");
int i;
for(i=0; i<=count; i++) {
XSSFRow excelRow = sheet.createRow(i);
XSSFCell excelCell = excelRow.createCell(i);
excelCell.setCellType(CellType.STRING);
excelCell.setCellValue(sd);
}
input.flush();
wb.write(input);
My requirement is to read the excel dynamically and store the contents in Map. The headers should be key and the respective column should be value so that when I pass the key, I can get the cell value.
My Excel sheet contains multiple rows and columns which can be changed dynamically. My intention is to write a common function in java to read an excel and store the contents in map. The Key should be column headers and the value should be respective cell value of the header. So while retrieving when I pass the header key, I should receive the respective cell value. My plan is to pass the row number and the key in a method so that it can retrieve the respective cell value related to the row as well as the key
static Map<String> excelMap = new LinkedHashMap<String>();
public static String readWriteExcel(String sheetName) throws EncryptedDocumentException, InvalidFormatException, IOException, JSONException
{
File file = new File("File Path");
FileInputStream inputStream = new FileInputStream( file );
Workbook workbook = WorkbookFactory.create( inputStream );
Sheet sheet = workbook.getSheet( sheetName );
int rowNumber =0;
int rowCount = sheet.getLastRowNum();
for(int i=1;i<=rowCount;i++){
Row row = sheet.getRow(0);
for(int j=0;j<row.getLastCellNum();j++) {
String key=row.getCell(j).getStringCellValue();
String value=sheet.getRow(rowNumber+1).getCell(j).getStringCellValue();
excelMap.put(key, value);
}
}
}
By looking at the code, i am assuming the issues: Multiple rows present in the sheet, but you are getting data of first row only.
Solution :
First of all, you need to store all rows data in a List of Map. where list index corresponds to the row number. Also You are not incrementing the rowNumber variable anywhere. Its always 0.
Why not directly use the variable i to get a particular row from sheet?
I think this should work.
static List<Map<String, String>> excelData = new ArrayList<HashMap<String, String>>();
public static String readWriteExcel(String sheetName) throws EncryptedDocumentException, InvalidFormatException, IOException, JSONException
{
File file = new File("File Path");
FileInputStream inputStream = new FileInputStream( file );
Workbook workbook = WorkbookFactory.create( inputStream );
Sheet sheet = workbook.getSheet( "sheetName" );
int rowCount = sheet.getLastRowNum();
for(int i=1;i<=rowCount;i++){
Row row = sheet.getRow(0);
Map<String,String> rowData = new HashMap<>();
for(int j=0;j<row.getLastCellNum();j++) {
String key=row.getCell(j).getStringCellValue();
String value=sheet.getRow(i).getCell(j).getStringCellValue();
rowData.put(key, value);
}
excelData.add(rowData);
}
}
Since you want to map multiple rows you have to store multiple rows.
One way is storing a map consisting column->list containing values for each row.
Another way is storing a map consisting column+row number->value.
Sample code for second method:
static Map<String, String> excelMap = new LinkedHashMap<String, String>();
...
// storing values
excelMap.put(key + "_" + i, value); // i is row index
...
// getting values
public static String getCellValue(String cellName, int rowIndex) {
return excelMap.get(cellName + "_" + rowIndex);
}
I have a workbook which contains several sheets where are there some data. At the end of the position, there will be a sheet which will not have the data for the very first time.
In this case, I have to update the data like this.
Test Suite Name: xxxxx
TestCase ID Request1 Request2 Request3
1234567890 PASS FAIL PASS
For that I have written the code like this but its not performing as expected.
public void readAndUpdateBlankExcelCells()
{
String xlPath = "D:\\working\\POC\\RunManager.xls"
try
{
log.info ("Entered into Blank Method")
FileInputStream inputStream = new FileInputStream(new File(xlPath))
HSSFWorkbook myBook = new HSSFWorkbook(inputStream)
HSSFSheet sheet = myBook.getSheet("TestSuiteSummary")
HSSFRow row;
HSSFCell cell;
Iterator itr = sheet.rowIterator()
while(itr.hasNext())
{
row = (HSSFRow) itr.next()
System.out.println("Entered while loop")
for (int idx = 0; idx < row.getLastCellNum(); idx++)
{
System.out.println("Entered for loop")
cell = row.getCell(idx, Row.CREATE_NULL_AS_BLANK)
cell.setCellValue("Test Suite Name: Sample Test Suite")
}
System.out.println()
}
}
catch(Exception ex)
{
System.out.println("In catch")
ex.printStackTrace()
}
}
If its updated properly which I had mentioned in the above next TestSuite details should update in the next row...it will go for each test suite.
Can anyone tell me your suggestions?
Thanks