-1

I am using Apache poi to extract Mysql data to an Excel file. The code is running correctly but when I am trying to open the excel file it is showing error.

package com.telkomsel.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.telkomsel.configuirator.Configurator;
import com.telkomsel.dbconnection.DBConnection;
import com.telkomsel.service.TelkomselEntities;

public class TelkomselExcel {

    DBConnection db = new DBConnection();
    static Configurator configurator = null;
    Connection conn = null;
    static Statement statement = null;
    static ResultSet resultSet = null;

    public static HashMap<Integer, TelkomselEntities> getTelkomselData(Statement statement) {

        configurator = new Configurator();
        String Query = configurator.getProperty("sql_query1");

        HashMap<Integer, TelkomselEntities> all = null;
        TelkomselEntities smsModel = null;

        try {
            all = new HashMap<Integer, TelkomselEntities>();
            resultSet = statement.executeQuery(Query);
            while (resultSet.next()) {

                int hour = resultSet.getInt("hour(timestamp)");
                String count = resultSet.getString("count(1)");

                smsModel = new TelkomselEntities(hour, count, count, count);
                all.put(hour, smsModel);
            }

            smsModel = new TelkomselEntities();

            FileInputStream fis = new FileInputStream(new File("Tracker.xlsx"));

            XSSFWorkbook workbook = new XSSFWorkbook(fis);

            XSSFSheet worksheet = workbook.getSheetAt(0);

            XSSFRow row = null;
            XSSFCell cell;
            int i = 1;

            for (Integer l : all.keySet()) {
                TelkomselEntities us = all.get(l);

                row = worksheet.createRow(i);

                cell = row.createCell(2);
                cell.setCellValue(us.getHour());
                cell = row.createCell(3);
                cell.setCellValue(us.getCharge_Count());

                i++;
            

            }
            fis.close();
            FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),true);
            
            
            
            System.out.println("SUCCESS");
            
            workbook.write(output_file);
            workbook.close();
            output_file.flush();

            output_file.close();
            

        } catch (Exception e) {

            System.out.println(e);
        }
        return all;

    }

}

I think file output stream is creating problem as it converts data into byte codes. i tried every thing but doesn't work. my excel file is not working

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Arundhati
  • 1
  • 3
  • 1
    Can you please report the error your excel file is reporting on opening? – VinceLomba Jan 30 '21 at 19:20
  • We found a problem with some content in tracker.xlsv. do you want to recovet as much as we can?? – Arundhati Jan 30 '21 at 19:26
  • This error im getting while opening file – Arundhati Jan 30 '21 at 19:27
  • Are you sure that the exel file you're using is created as an .xlsx file and not as an .xls file (even if it's called "Tracker.xlsx")? – VinceLomba Jan 30 '21 at 19:29
  • yes its xlsx i also checked its property file – Arundhati Jan 30 '21 at 19:30
  • is there any issue in code?? plz help me sir this is driving me crazy – Arundhati Jan 30 '21 at 19:33
  • the error is in `new FileOutputStream(...,true)` which is appending content on the already existing file. I would remove that `, true` and go with the default of truncating/overriding the file. Actually I would rather write in a different file, especially under Windows. Apart of that, you may of course override the content of cells, opposed to what @VinceLomba says ... there's no such rule. – kiwiwings Feb 01 '21 at 01:41

1 Answers1

1

As you supposed, the problem hides inside the line:

FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),true);

When creating a new XSSFWorkbook Java Object from an existing excel (which you want to update), that XSSFWorkbook is initially created based on your excel file content, then it is totally independent from it.The proof of this is that all changes to the XSSFWorkbook Java Object ARE NOT going to affect the original excel file at all. Apache Poi works that way!

This is the reason why once you're done editing your XSSFWorkbook you have to save it as a new excel file (using a FileOutputStream) overriding the original one (in a sense, you're now updating your excel file with all your changes).

But as the docs says, you're telling FileOutputStream not to override the original excel file with the new and updated one but to append the second to the first one, upsi dupsi! You're creating a single file which contains both all the bytes of the original old file and all the bytes of the new updated one!

To solve the problem, just use instead:

FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),false);

or

FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"));

and you're done!

Edit: learn Apache Poi before using Apache Poi

It seems that you're using FileOutputStream wrong because you don't know how Apache Poi works and how to use it. You might want to study a little bit about it before using it, the web is full of examples and tutorials! Here they are some examples provided by Apache Poi itself, you might want to have a look at them.

As I said before, the XSSFWorkbook is initialized with all the content of your original excel file. So if you start filling your XSSFSheet from the second line (that's what you're actually doing with your code) you are literally asking to your XSSFWorkbook to override existing data with new one.

You have to improve your code, searching for already existing data in rows and cells and not overriding it if you don't want to.

Rows and cells of each XSSFSheet of your XSSFWorkbook are numbered using 0-based indexes (that's the reason why your code, which starts filling rows from index 1, is filling rows starting from the second one).

With the method XSSFSheet#getRow(int rownum) you can retreive any row from the current XSSFSheet indicating its 0-based index. If this method returns null, then the row you're asking for has never been used and you have to create it using the method XSSFSheet#createRow(int rownum). If it doesn't, then the row you're asking for has already been used and contains some data in some of its cells.

With the method XSSFRow#getCell(int cellnum) you can retrieve any cell from the current XSSFRow indicating its 0-based index. If this method returns null, then the cell you're asking for has never been used and you have to create it using the method XSSFRow#createCell(int cellnum, CellType celltype). If it doesn't, then the cell you're asking for has already been used and contains some data in it.

You can retrieve the CellType of an existing XSSFCell with the method XSSFCell#getCellType().

You can retreive the content of an existing XSSFCell (on the basis of its CellType) using such methods as XSSFCell#getStringCellValue(), XSSFCell#getNumericCellValue() or XSSFCell#getBooleanCellValue().

Other useful methods are XSSFSheet#getLastRowNum() and XSSFRow#getLastCellNum(). The first one returns the index of the last already used row inside your sheet, the second one returns the index of the first not used cell inside your row.

Here it is an example for you (filling 42 rows of your sheet after the last existing one):

public static void main(String[] args) throws EncryptedDocumentException, FileNotFoundException, IOException {
    
        // Step 1: load your excel file as a Workbook
    
        String excelFilePath = "D:\\Desktop\\textExcel.xlsx";
        XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(new FileInputStream(excelFilePath));
        
        // Step 2: modify your Workbook as you prefer
        
        XSSFSheet sheet = workbook.getSheetAt(0);
        int firstUnusedRowIndex = sheet.getLastRowNum() + 1;
        for (int rowIndex = firstUnusedRowIndex ; rowIndex < firstUnusedRowIndex + 42 ; rowIndex++) {
            sheet.createRow(rowIndex).createCell(0, CellType.STRING).setCellValue("New Row n°" + (rowIndex - firstUnusedRowIndex + 1));
        }
        
        // Step 3: update the original excel file
        
        FileOutputStream outputStream = new FileOutputStream(excelFilePath);
        workbook.write(outputStream);
        workbook.close();
        outputStream.close();
}
VinceLomba
  • 398
  • 2
  • 8
  • 18
  • FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx")); thanku for your answer but i have already used this line of code and it deletes my already existing data in the file ie tracker.xlsx – Arundhati Jan 30 '21 at 20:26
  • It should not and it does not for me. Mabye you should check your code, cause mabye you're explicitly telling to the XSSFWorkbook to override existing cells. You must be sure to NOT write new data into existing cells (overriding them). If you need some examples, ask for them and I'll update my answer tomorrow! – VinceLomba Jan 30 '21 at 20:42
  • Where can i use this example that you have mentioned in my code. Could you plz elaborate – Arundhati Jan 30 '21 at 20:51
  • Answer updated with explanation and example. Please, make SURE to mark my answer as the accepted one IF it answers your original question ("unable to open excel file") – VinceLomba Jan 31 '21 at 15:10
  • i understand your statements but how can i stop my code from over riding existing data and if you are giving me an exapme then where shouls i use your example in my code to improve my code – Arundhati Feb 01 '21 at 03:20
  • the probklem is still there – Arundhati Feb 01 '21 at 04:05
  • the data is overlapping – Arundhati Feb 01 '21 at 04:05
  • I already gave you an example about how to add new rows AFTER the last existing one WITHOUT overlapping data. Just copy my example in a new Java Main method and run it to understand how it works. Please, read carefully ALL my answer. I cannot help you more without knowing better what you're trying to achieve and without knowing what is actually overlapping.. – VinceLomba Feb 01 '21 at 06:56
  • Glad I could help you! – VinceLomba Feb 01 '21 at 10:06