I have some java code that opens an excel sheet, adds auto filter to a group of columns, then saves and closes. The problem is that when a user opens the file and trys to sort smallest to largest or largest to smallest excel will freeze then crash. But if you first filter then you can sort with out issue and it does not freeze and crash.
private static void AddFilter()
{
//Adds filter to the rows in Column 2
try
{
FileInputStream fileIn = new FileInputStream("C:\\Users\\gria\\Desktop\\Fleet Manager Summary.xls");
HSSFWorkbook report = new HSSFWorkbook(fileIn);
Sheet sheet = report.getSheetAt(0);
sheet.setAutoFilter(CellRangeAddress.valueOf("A5:P5"));
FileOutputStream fileOut = new FileOutputStream("C:\\Users\\gria\\Desktop\\Fleet Manager SummaryT.xls");
report.write(fileOut);
fileOut.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Thank you,
UPDATE:
After some experimenting I have updated the info and code since the original question was asked to better explain the problem.
Try changing
XSSFFormulaEvaluator.evaluateAllFormulaCells(report);
to
HSSFFormulaEvaluator.evaluateAllFormulaCells(report);
XSSFFormulaEvaluator.evaluateAllFormulaCells() works for XSSfWorkbook, but not for the HSSFWorkbook.
Documentation
Also,
you can edit your commented code to:
for(int i = 5; i < sheet.getLastRowNum(); i++)
{
Cell cell = sheet.getRow(i).getCell(6);
//I don't know if you have data in all of the cells,
//So I suggest you to evaluate null
if(cell != null && !cell.getStringCellValue().isEmpty())
{
cell.setCellValue(Double.valueOf(cell.getStringCellValue()).doubleValue());
}
}
Related
In my below script, an Excel is created but failed to write the data to the sheet. Could anybody sort this out.
FileOutputStream fo = new FileOutputStream("D:\\Output.xls");
WritableWorkbook wb = Workbook.createWorkbook(fo);
WritableSheet ws = wb.createSheet("Sheet1",0);
String OutText = driver.findElement(By.xpath("gbqfqdss")).getText();
int y=0;
Label label1 = new Label(0,y,OutText);
ws.addCell(label1);
Thread.sleep(1000);
//System.out.print(OutText);
wb.write();
y++;
Thread.sleep(1000);
driver.findElement(By.id("gbqfq")).clear();
Thread.sleep(1000);
}
wb.close();
driver.quit();
With the same code, working fine in my lappy.
How you are confirming that it is not writing to excel sheet?
Mostly the cause should be "OutText" string value which is coming from getText() is null/blank value.
Try to print the value of string first & see.
Try the examples in the following link-:
http://howtodoinjava.com/2013/06/19/readingwriting-excel-files-in-java-poi-tutorial/
I am using POI to read,edit and write excel files.
My process flow is like write an excel, read it and again write it.
Then if I try to edit the file using normal desktop excel application while my Java app is still running, the excel cannot be saved, it says some process is holding the excel,
I am properly closing all file handles.
Please help and tell me how to fix this issue.
SXSSFWorkbook wb = new SXSSFWorkbook(WINDOW_SIZE);
Sheet sheet = getCurrentSheet();//stores the current sheet in a instance variable
for (int rowNum = 0; rowNum < data.size(); rowNum++) {
if (rowNum > RECORDS_PER_SHEET) {
if (rowNum % (RECORDS_PER_SHEET * numberOfSheets) == 1) {
numberOfSheets++;
setCurrentSheet(wb.getXSSFWorkbook().createSheet());
sheet = getCurrentSheet();
}
}
final Row row = sheet.createRow(effectiveRowCnt);
for (int columnCount = 0; columnCount < data.get(rowNum).size(); columnCount++) {
final Object value = data.get(rowNum).get(columnCount);
final Cell cell = row.createCell(columnCount);
//This method creates the row and cell at the given loc and adds value
createContent(value, cell, effectiveRowCnt, columnCount, false, false);
}
}
public void closeFile(boolean toOpen) {
FileOutputStream out = null;
try {
out = new FileOutputStream(getFileName());
wb.write(out);
}
finally {
try {
if (out != null) {
out.close();
out = null;
if(toOpen){
// Open the file for user with default program
final Desktop dt = Desktop.getDesktop();
dt.open(new File(getFileName()));
}
}
}
}
}
The code looks correct. After out.close();, there shouldn't be any locks left.
Things that could still happen:
You have another Java process (for example hanging in a debugger). Your new process tries to write the file, fails (because of process 1) and in the finally, it tries to open Excel which sees the same problem. Make sure you log all exceptions that happen in wb.write(out);
Note: The code above looks correct in this respect, since it only starts Excel when out != null and that should only be the case when Java could open the file.
Maybe the file wasn't written completely (i.e. there was an exception during write()). Excel tries to open the corrupt file and gives you the wrong error message.
Use a tool like Process Explorer to find out which process keeps a lock on a file.
I tried all the options. After looking thoroughly, it seems the problem is the Event User model.
I am using the below code for reading the data:
final OPCPackage pkg = OPCPackage.open(getFileName());
final XSSFReader r = new XSSFReader(pkg);
final SharedStringsTable sst = r.getSharedStringsTable();
final XMLReader parser = fetchSheetParser(sst);
final Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
final InputStream sheet = sheets.next();
final InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
I assume the excel is for some reason held by this process for some time. If I remove this code and use the below code:
final File file = new File(getFileName());
final FileInputStream fis = new FileInputStream(file);
final XSSFWorkbook xWb = new XSSFWorkbook(fis);
The process works fine an the excel does not remain locked.
I figured it out actually.
A very simple line was required but some some reason it was not explained in the New Halloween Document (http://poi.apache.org/spreadsheet/how-to.html#sxssf)
I checked the Busy Developer's Guide and got the solution.
I needed to add
pkg.close(); //To close the OPCPackage
This added my code works fine with any number of reads and writes on the same excel file.
I am using Apache POI to create new XSSFWorkbook from an existing one, after updating some values. Suppose I have two worksheets (Lets say: worksheet A & B) in my existing workbook. Worksheet B has some cell reference from Worksheet A. IF i modify those cell values of worksheet A and save them as a new workbook, corresponding cell values of worksheet B should be updated too. But it doesn't. How can i update them programmatically? . Thank you.
My code:
public void createExcel(ClientData cd) throws FileNotFoundException, IOException, InvalidFormatException{
// create a new file
double[] dataHolder1= cd.getFinalData1(), param1 = cd.getRecord1Param();
double[] dataHolder2 = cd.getFinalData2(), param2 = cd.getRecord2Param();
double[] ncv = cd.getNcv();
String[] pname = cd.getName();
Workbook workbook = new XSSFWorkbook(OPCPackage.open(new FileInputStream("template/mncv.xlsx"))); // or sample.xls
//CreationHelper createHelper = workbook.getCreationHelper();
Sheet s=workbook.getSheetAt(0);
int counter = dataHolder1.length + param1.length +param2.length+dataHolder2.length;//+ param1.length + param2.length;
// r = s.getRow(0);
// r.getCell(0).setCellValue("Param1");
// r.getCell(1).setCellValue("Record1");
// r.getCell(2).setCellValue("Param2");
// r.getCell(3).setCellValue("Record2");
int i;
for(i=0;i<counter;i++){
if(i<param1.length){
for(int j=0;j<param1.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(param1[j]);
i++;
}
}else if(i<dataHolder1.length+param1.length && i>=param1.length){
for(int j=0;j<dataHolder1.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(dataHolder1[j]);
i++;
}
}else if(i<dataHolder1.length+param1.length+param2.length && i>=dataHolder1.length+param1.length){
for(int j=0;j<param2.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(param2[j]);
i++;
}
}else{
for(int j=0;j<dataHolder2.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(dataHolder2[j]);
i++;
}
}
// if(i<=param1.length){
// r.getCell(0).setCellValue(param1[i-1]);
// r.getCell(2).setCellValue(param2[i-1]);
//
// }
// r.getCell(0).setCellValue(param1[i]);
//r.getCell(3).setCellValue(dataHolder2[i-1]);
i--;
}
for(int k=0;k<ncv.length;k++){
r = s.getRow(i);
r.getCell(0).setCellValue(ncv[k]);
i++;
}
s = workbook.getSheetAt(1);
s.getRow(2).getCell(5).setCellValue(pname[0]+" "+pname[1]+" "+pname[2]);
s.getRow(3).getCell(5).setCellValue(cd.getAge());
s.getRow(4).getCell(5).setCellValue(cd.getGender());
try (FileOutputStream out = new FileOutputStream("workbook.xlsx")) {
//WorkbookEvaluator we = new WorkbookEvaluator(workbook);
workbook.write(out);
out.close();
XSSFFormulaEvaluator.evaluateAllFormulaCells((XSSFWorkbook) workbook);
}catch(Exception e){
System.out.println(e);
}
The Excel file format caches the result of formula evaluation, to make opening the file quicker. This means that when you're done making changes to your file, you'll need to evaluate all of the formula cells to updated their cached value. (Otherwise, when you load the file in Excel, for almost all cases it'll still show the old value until you go into that cell)
Luckily, Apache POI provides code to do that, see the Formula Evaluation documentation for details. (You can choose to only recalculate certain formulas, if you know just those cells have changed, or do everything)
For any cell, say "B5", at runtime,
cell.getReference();
will give you cell reference (like in example... it will return you "B5")
cell.getReference().toString().charAt(0);
will give you the Column Reference (will give you "B" if the current cell is B5). Now
cell.getRowIndex();
OR
cell.getReference().toString().charAt(1);
will give you Row Index. Now you have the reference of the target cell. just replace these character with the references you have already created. This will update the cell references.
The following solution worked for me
wb.setForceFormulaRecalculation(true);
// replace "wb" with your HSSFWorkbook/XSSFWorkbook object
So I am pulling data from select cells from sheets in an excel file and then trying to write it to another file. The data is being carried over fine inside the vatAdata array and from what I can tell its being written to the cell in the for loop because it prints out each cell after inserting into (just for debugging purposes). But when I open the file later only the last cell has data in it and all other cells are null. Any idea what is causing this issue?
for(int i=0;i<vatAdata.length;i++){
Cell cellInsert=sheet.createRow(rowIndex).createCell(colIndex+i);
cellInsert.setCellType(vatAtype[i]);
// System.out.println(cellInsert.);
if(vatAtype[i]==0){
cellInsert.setCellValue(Double.parseDouble(vatAdata[i]));
System.out.println(cellInsert.getNumericCellValue()+" written");
}
else{
cellInsert.setCellValue(vatAdata[i]);
System.out.println(cellInsert.getStringCellValue()+" written");
}
}
FileOutputStream out=new FileOutputStream("/home/chris/Documents/test.xlsx");
wb.write(out);
out.close();
cellInsert=sheet.createRow(rowIndex).createCell(colIndex+i);
you need save the new Row value to a variable to reuse it.
row = sheet.createRow(rowIndex);
cellInsert = row.createCell(colIndex+i);
How to delete contents of an Excel sheet in an Excel workbook, using Java SE and Apache POI?
As mentioned in previous comments
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
this code throwing ConcurrentModificationException to me. So, I have modified the code and it's working fine. Here is the code:
Sheet sheet = wb.getSheetAt(0);
Iterator<Row> rowIte = sheet.iterator();
while(rowIte.hasNext()){
rowIte.next();
rowIte.remove();
}
I've found that removeSheetAt/createSheet isn't really an acceptable answer, because you can't put the new sheet into the correct position in the workbook without running into a bug in WorkSheet.setSheetOrder
This code snippet
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
in my world throws a ConcurrentModificationException
I had to resort to
for (int index = crnt.getLastRowNum(); index >= crnt.getFirstRowNum(); index--) {
crnt.removeRow( crnt.getRow(index));
}
Depending on what contents you want to delete you may remove a single cell or row.
Too erase the complete sheet iterate over all rows and delete it.
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
I know this is an old thread but I think I found the best solution
What I did was just create a new workbook of the same type and save it over the file that I wanted to delete.
Heres the code
private void clearOldFile(){
FileOutputStream out = null;
try{
oldFile = new XSSFWorkbook();
Sheet sheet = oldFile.createSheet("temp data");
out = new FileOutputStream(AbsolutePathForTempExcelFile);
oldFile.write(out);
out.close();
} catch(Exception e){
e.printStackTrace();
}
}
You probably want to use HSSFWorkbook.removeSheetAt(index).
I guess it is an old thread but I also get ConcurrentModificationException. Based on VoiceOfUnreason I found this to work:
while (xlsSheet.getPhysicalNumberOfRows() > 0) {
xlsSheet.removeRow(xlsSheet.getRow(xlsSheet.getLastRowNum()));
}
if (xlsSheet.getDrawingPatriarch() != null) {
xlsSheet.getDrawingPatriarch().clear();
}
I also got concurrent modification exception, also using the more "modern" way of doing it :
sheet.forEach(r->sheet.remove(r));
The iterator based solution from #Thirupathi S apparently worked, but for reasons I don't exactly know it was creating xslx files that were not readable by Apple's Numbers and OSX preview (and probably other softwares too).
I suspect this has something to do with the iterator not removing something: the code of the removeRow method is way more complex than the simple iterator remove operation.
Using old plain for-loop with reversed index worked like a charm :
for (int i = sheet.getLastRowNum(); i >= 0; i--) {
sheet.removeRow(sheet.getRow(i));
}
This solution works fine with me. And also consider special cases, e.g. the sheet is blank, or the spaces between the firstRow and lastRow are present.
public void cleanSheet(Sheet sheet) {
int numberOfRows = sheet.getPhysicalNumberOfRows();
if(numberOfRows > 0) {
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
if(sheet.getRow(i) != null) {
sheet.removeRow( sheet.getRow(i));
} else {
System.out.println("Info: clean sheet='" + sheet.getSheetName() + "' ... skip line: " + i);
}
}
} else {
System.out.println("Info: clean sheet='" + sheet.getSheetName() + "' ... is empty");
}
}
My reason for not deleting and recreating sheet: Keep references to sheet-scoped names working.
for(int i = sheet.getLastRowNum(); i >= 0; i--)
{
Row row = sheet.getRow(i);
if(row != null)
{
sheet.removeRow(row);
}
}
The other iterator methods appeared to work but Excel then refused to open the file.
This one worked for me:
int rownum;
while ((rownum=sheet.getLastRowNum()) > 0) sheet.removeRow(sheet.getRow(rownum));