POI: Append rows to existing workbook - apache-poi

Using XSSFWorkbook, is it possible to append rows to an existing sheet? I am doing multiple writes (which was a PITA to solve due to a bug) and while I can write out new sheets multiple times, it does not appear that I can append.
What I am currently doing is the following:
Read sheet to my workbook.
Load workbook.
Append rows to workbook in memory
Write out again.
4 Does not appear to work, just ignores it completely!
I am aware that SXSSFWorkbook exists, but attempting to convert my existing XSSFWorkbook into a streaming workbook creates corruption upon write.
Is it possible to solve this concundrum?
Update: Changed code based on suggestion, but getting stream closed error.
Code: (The physical rows returns correctly, but nothing gets written out)
private void writeToSheetMultipleTimes(SXSSFWorkbook wb,
ReportTemplateStructure appA, File wbFile)
{
Sheet sheet = wb.getSheetAt(0);
log.info("Attempting multi-write to sheet: " + sheet.getSheetName());
for(int i = 0; i < 10; i++)
{
Row row = sheet.getRow(i);
if (row == null) {
row = sheet.createRow(i);
}
Cell cell = row.getCell(0, Row.CREATE_NULL_AS_BLANK);
cell.setCellValue("Written value:" + i);
int numRows = sheet.getPhysicalNumberOfRows();
log.info("Current row count: " + numRows);
try{
XSSFWorkbook xssfBook = (XSSFWorkbook)writeOutAndReadBack(wb);
wb.dispose();
wb = new SXSSFWorkbook(xssfBook);
} catch (Exception e)
{
log.error("Unable to perform multiple write to same sheet", e);
}
}
}
public Workbook writeOutAndReadBack(Workbook wb) {
if(!(wb instanceof SXSSFWorkbook)) {
throw new IllegalArgumentException("Expected an instance of SXSSFWorkbook");
}
Workbook result;
try {
FileOutputStream baos = new FileOutputStream(streamingWorkBookFile);
wb.write(baos);
InputStream is = new FileInputStream(streamingWorkBookFile);
result = new XSSFWorkbook(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}

You appear to be always making changes to Sheet 0, but you're calling createRow every time. This won't go well if there's already something there, eg on your second pass! You either need to add a new Sheet every time, or check if the Row is there with a call to getRow(int) first and only create if it is null.
If we look at your code snippet:
Sheet sheet = wb.getSheetAt(0);
for(int i = 0; i < 10; i++)
{
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
That should either be something like:
Sheet sheet = wb.createSheet();
for(int i = 0; i < 10; i++)
{
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
Or you should check first and only create missing rows/cells, eg
Sheet sheet = wb.getSheetAt(0);
for(int i = 0; i < 10; i++)
{
Row row = sheet.getRow(i);
if (row == null) {
row = sheet.createRow(i);
}
Cell cell = row.getCell(0, Row.CREATE_NULL_AS_BLANK);

You can use getPhysicalNumberOfRows() Method in XSSFSheet class to get last updated row number. Now create a new row by incrementing this value to append new data.

Related

Datagrid gives null values using for loop in WPF

I have a dataGrid with more than 100 rows in it. I am extracting it to an existing Excel file. I can open the file and add values to the sheet. My problem is, the value becomes null as soon as it gets to the 14th row.
I tried reversing the order of the data in the datagrid just to be sure that it's not the value or data in the dataGrid that is causing the issue but I still get the same result. Only the first 13 rows are extracted to the Excel sheet. The for loop still goes to the rest of the loop but it seems to not get the values.
Here is my code:
var path = #"D:\Reports\Sample.xlsx";
var excel = new Excel.Application {Visible = true};
var wb = excel.Workbooks.Open(path);
var ws = (Excel.Worksheet)wb.Sheets["summary"];
for (var i = 0; i < Grid.Columns.Count; i++)
{
for (int j = 0; j < Grid.Items.Count; j++)
{
var b = Grid.Columns[i].GetCellContent(Grid.Items[j]) as TextBlock; =====> ON THE 14th ROW, the "b" variable becomes null all throught out the for-loop
var myRange = (Range)ws.Cells[j + 2, i + 1];
try
{
if (b != null) myRange.Value2 = b.Text;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(100);
}
}
This is the Excel file created. Values are not extracted any more after the 14th row.

How can I append the existing table?

As I'm working on an automated data-collector and writer, I am using POI (4.1) to append an existing Excel-File .xlsx
Everything is fine so far, until I realized that the Excel I'm writing to and reading from includes a "Table" from the automated data Import. That means the last Line where I have to append is the last line of the imported table but i want to append the table.
I heared sth about spreadsheets but I'm not concerend that this will solve my problem as I didn't understand it that well.
I tried to enlarge the Table in Excel to write to it but I found out, that the Last line of the table, wether it contains sth or not, is used as the last existing line.
/**This Method is is building the XSSFRow out of the String[] array. It works fine, as the Stream
* is just in another method*/
private void schreibeInWorkbook(String[] zuSchreiben)
{
XSSFSheet worksheet = workbook.getSheetAt(findSheet(zuSchreiben[1]));
int lastRow = worksheet.getLastRowNum();
XSSFRow row = worksheet.createRow(++lastRow);
int cellnum = 0;
for (Object obj : zuSchreiben)
{
try
{
obj = Double.parseDouble((String) obj);
}
catch (NumberFormatException e)
{
}
Cell cell = row.createCell(cellnum++);
if (obj instanceof String)
{
obj = ((String) obj).replaceAll("\"", "");
cell.setCellValue((String) obj);
}
else if (obj instanceof Double)
{
cell.setCellValue((Double) obj);
}
else if (obj instanceof Integer)
{
cell.setCellValue((Integer) obj);
}
}
int r = row.getRowNum();
Cell c2 = row.createCell(cellnum++);
c2.setCellFormula(formulaXYZ);
Cell c3 = row.createCell(cellnum++);
c3.setCellFormula(formulaXYZ);
}
I thought I could just expand the Excel Table by Hand and add it in there but it always appears in the next line right after the end of it although there are tons of empty lines.
This is what my JavaCode is adding to Excel

I want to write set of random numbers in an Excel sheet by iterating rows .I am able write random numbers and I am unable to store them in excel

I want to generate random numbers and parallel i want to write them in excel sheet in 1st column upto 15 rows. I tried with below script, but, it's not working.
I tried with below script, every time I want to store up to 15 numbers and those numbers should not be repeated.
I tried by using below methods, but I am not getting how can we iterate both of them. Random numbers and Excel cell.
public long Random_Number() {
Random rand = new Random();
long drand = (long)(rand.nextDouble()*1000000000L);
long correct = 0;
String numberString = Long.toString(drand);
if (numberString.length() == 8) {
System.out.println(drand+ "It's not a 9 digit");
}
else if (numberString.length() == 9) {
correct = drand;
System.out.println(correct);
}
return correct;
}
public void writeData_Int_SSN( int cellNum) {
try {
File src = new File("filename.xls");
Cell cell = null;
FileInputStream fis = new FileInputStream(src);
HSSFWorkbook wb = new HSSFWorkbook(fis);
HSSFSheet sh1 = wb.getSheetAt(0);
long gid = Random_Number();
String GroupID = Long.toString(gid);
System.out.println(GroupID);
int num = Integer.parseInt(GroupID);
for (int i = 1; i < 12; i++) {
System.out.println("Entering into excel sheet");
cell = sh1.getRow(i).getCell(cellNum);
System.out.println("Iterating cells");
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
System.out.println("We are entering numeric data");
int str1 = Integer.parseInt(cell.getStringCellValue());
System.out.println(str1);
cell.setCellValue(num);
}
}
FileOutputStream fout = new FileOutputStream(new File("filename.xls"));
wb.write(fout);
fout.close();
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}

I want to get some particular cell from excel using selenium webdriver

I am working with excel file with selenium webdriver. I can read the data from excel successfully but I want to get some particular Cell address and value from excel sheet using selenium webdirver.
Can anyone help on this?
Thanks in Advance.
Here is the Code.
String FilePath="D:\\ProUtility_Automation\\Transformation Logic.xls";
try {
Workbook wrk1 = Workbook.getWorkbook(new File(
FilePath));
Sheet sheet1 = wrk1.getSheet(0);
int totalNoOfRows = sheet1.getRows();
int totalNoOfCols = sheet1.getColumns();
//String a[][] = new String[1000][1000];
for (int row = 0; row < totalNoOfRows; row++) {
for (int col = 0; col < totalNoOfCols; col++) {
System.out.print(sheet1.getCell(col, row).getContents() + "\t");
}
System.out.println();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Here is the code for reading particular cell value from excel, please import the right POI jars in your project, so that this code works correctly
private static XSSFCell Cell;
private static XSSFRow Row;
public static String getCellData(int RowNum, int ColNum) throws Exception{
try{
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
String CellData = Cell.getStringCellValue();
return CellData;
}catch (Exception e){
return"";
}
}
If you want the 2nd row, 3rd column cell value simply pass the parameters getCellData(1,2)---------> excel rows and columns start from (0,0)

Modifying .xlsx file works instantly when tested in Eclipse, but when executed as a .jar file, it takes upwards of 20 seconds

I have the three methods that take the longest and then my run() method; the rest of the code takes a negligible amount of time. I'm just confused as to why it would run instantly in Eclipse but not be able to do the same when I run it from a .jar file.
It is around 120x slower when run from the .jar file. Is it my code or is there something else going on here?
public void modifyCell(String input, int rowNum, int column, Workbook wb) throws IOException {
Sheet sheet = wb.getSheet("Sheet1");
Row row = sheet.getRow(rowNum);
Cell cell = row.getCell(column);
cell = row.createCell(column);
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
cell.setCellStyle(cellStyle);
cell.setCellValue(input);
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
cell = row.getCell(column+1);
evaluator.evaluateFormulaCell(cell);
row = sheet.getRow(3);
cell = row.getCell(getFinalFormula(site));
evaluator.evaluateFormulaCell(cell);
evaluateTopFormulas(wb);
FileOutputStream fileOut = new FileOutputStream(workbook);
wb.write(fileOut);
fileOut.close();
}
public void evaluateTopFormulas(Workbook wb){
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
Sheet sheet = wb.getSheet("Sheet1");
Row row = sheet.getRow(1);
Cell cell = row.getCell(6);
evaluator.evaluateFormulaCell(cell);
row = sheet.getRow(2);
cell = row.getCell(6);
evaluator.evaluateFormulaCell(cell);
}
public int getRow(Workbook wb, int column){ // i also think this part is very poorly written
but I don't know how to go about it differently.
All I want is to get the next blank cell in a column after the 4th cell.
long startTime = System.nanoTime();
Sheet sheet1 = wb.getSheetAt(0);
int i = 4;
Row startRow = sheet1.getRow(i);
Cell cell = startRow.getCell(column);
Row row;
try {
while (!(cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK)){
row = sheet1.getRow(i++);
cell = row.getCell(column);
}
} catch (Exception e){
}
if (i == 4){
return i;
}
long estimatedTime = System.nanoTime() - startTime;
System.out.println(estimatedTime + " getRow");
return i-1;
}
public void run(){
try {
System.out.println("Adding to Invoice");
Workbook wb = openWorkbook();
int column = getColumn(site);
int row = getRow(wb, column);
modifyCell(input, row, column, wb);
System.out.println(input + " was added to " + workbook);
} catch (InvalidFormatException | IOException e) {
System.out.println(e);
}
}

Resources