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.
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 have a list of variables in an excel file which I use as input for an online app and generate a result. That occurs successfully however when I try to save the output in that same file by adding a new column and cells, the original content of the file would be deleted. I only want to add the info to the same document but the only option I found by googling is to create another file.
just to clarify:Variables for input
and instead of just adding the info this happens Changed document.
How can I fix it without adding more parameter and re-adding the info?
#Keyword
public void demoKey(String name) throws IOException{
FileInputStream fis = new FileInputStream("C://Users/i2srsm/Desktop/New Microsoft Excel Worksheet.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(fis);
XSSFSheet sheet = workbook.getSheet("Data for full set");
int columnNumber = sheet.getRow(0).getLastCellNum();
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
sheet.createRow(firstRow).createCell(columnNumber).setCellValue('Proposta');
for (int rn=(firstRow); rn<=lastRow; rn++){
Cell cell = sheet.createRow(rn).createCell(columnNumber+1)
cell.setCellType(cell.CELL_TYPE_STRING);
cell.setCellValue(name);
FileOutputStream fos = new FileOutputStream("C://Users/i2srsm/Desktop/New Microsoft Excel Worksheet.xlsx");
workbook.write(fos);
fos.close();
}
}
}
don't use a sheet.createRow(row index) for update the existing excel file. this one create a new row. if you want to update the existing row in a sheet, firstly get related existing row and then create a new cell.
for get existing row
Row row = sheet.getRow(row index);
for create a new cell in above existing row
Cell cell = row.createCell(cell index);
try with this
sheet.getRow(firstRow).createCell(columnNumber).setCellValue("Proposta");
for (int i=(firstRow+1); i<=lastRow; i++){
Row row = sheet.getRow(i);
Cell cell = row.createCell(columnNumber);
cell.setCellType(cell.CELL_TYPE_STRING);
cell.setCellValue(name);
}
FileOutputStream fos = new FileOutputStream("C:/Users/LifeStyle/Documents/output.xlsx");
workbook.write(fos);
fos.close();
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.
:)
I am trying to write my test results/data to excel at runtime for which I have written the below code. I am not getting any error while compiling this code however the results are not getting written in this. Can someone help me out with the problem?
public void WritetoExcel(String filepath, String OrderID) throws IOException
{
FileInputStream ExcelFile = new FileInputStream(filepath);
System.out.println(filepath);
ExcelWBook = new XSSFWorkbook(ExcelFile);
System.out.println("WorkBook Sucessfully");
ExcelWSheet = ExcelWBook.getSheetAt(0);
System.out.println("Sheet Sucessfully");
Iterator<Row> rowIterator= ExcelWSheet.iterator();
int RowNum =0;
while (rowIterator.hasNext())
{
Row row=rowIterator.next();
RowNum++;
}
try
{
Row = ExcelWSheet.createRow(RowNum);
Iterator<Cell> cellIterator=Row.iterator();
Cell = Row.getCell(0);
if (Cell==null)
{
Cell=Row.createCell(0);
Cell.setCellValue(OrderID);
}
else
{
Cell.setCellValue(OrderID);
}
FileOutputStream fileOut = new FileOutputStream(filepath);
ExcelWBook.write(fileOut);
fileOut.flush();
fileOut.close();
}
catch (Exception e )
{
throw (e);
}
}
I was going to make this a comment, but it is too long.
There are a few comments I can make about your code.
First, it seems you are iterating through and counting rows that exist in the sheet. Then you are creating a new row at that index. Since a spreadsheet could have missing rows, this will only work for a very specific type of spreadsheet. That is, one which has no missing rows, and you always want to add the next row in the next empty spot. Instead of:
Iterator<Row> rowIterator= ExcelWSheet.iterator();
int RowNum =0;
while (rowIterator.hasNext())
{
Row row=rowIterator.next();
RowNum++;
}
try
{
Row = ExcelWSheet.createRow(RowNum);
You can just as easily use:
int rowNum = ExcelWSheet.getLastRowNum() + 1;
Row row = ExcelWSheet.createRow(rowNum);
Then you write orderId in the first column of that row. Instead of:
Iterator<Cell> cellIterator=Row.iterator();
Cell = Row.getCell(0);
if (Cell==null)
{
Cell = Row.createCell(0);
Cell.setCellValue(OrderID);
}
else
{
Cell.setCellValue(OrderID);
}
You could just use:
Cell cell = row.createCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK);
cell.setCellValue(OrderID);
In addition, for this you don't even need the iterators, but when you really need to iterate through the rows and cells of a spreadsheet it is better to use the for each syntax like this:
for (Row row : sheet) {
for (Cell cell : row) {
// do something with the cell
}
}
My scenario is to get text from "Status" column and based on text comparison ,I want to highlight that particular cell.Below is my code-
private static void colorSheet(String xlsxFileAddress)
{
try
{
FileInputStream file = new FileInputStream(new File(xlsxFileAddress));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFFormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
XSSFSheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type after eveluating formulae
//If it is formula cell, it will be evaluated otherwise no change will happen
switch (evaluator.evaluateInCell(cell).getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "tt");
break;
case Cell.CELL_TYPE_STRING:
{
System.out.print(cell.getStringCellValue() + "tt");
ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.EQUAL,"Extra Rows in new table");
org.apache.poi.ss.usermodel.PatternFormatting fill2 = rule2.createPatternFormatting();
fill2.setFillBackgroundColor(IndexedColors.BLUE.index);
fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A2:A7")
};
sheetCF.addConditionalFormatting(regions, rule2);
break;
}
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
I want that whichever cell has a text "Extra Rows in new table" should be highlighted in blue but my code is not working.please suggest needful.
Okay, the problem is that you're reading the file and changing its content in the process memory, but you never write the changes back into the file.
Try replacing:
file.close();
with:
file.close();
FileOutputStream writeFile = new FileOutputStream(new File(xlsxFileAddress));
workbook.write(writeFile);
writeFile.close();
It can be because of
ConditionalFormattingRule "Equal" will work only when it is given like ComparisonOperator.EQUAL, "\"" + "Extra Rows in new table" + "\"" instead of (ComparisonOperator.EQUAL,"Extra Rows in new table");
Add this after your file.close() in order to write back to the file.
FileOutputStream writeFile = new FileOutputStream(new
File(xlsxFileAddress));
workbook.write(writeFile);
writeFile.close();