0

I'm working on a project in Spring using SpringMVC. I'm importing data from (.xls) files .

the problem is that:

  • I'm reading this value "945854955" as a String but saved in DB as "9.45854955E8"

  • this value "26929" saved as "26929.0"

  • this value "21/05/1987" saved as "31918.0"

/read Code

    // import ...
    @RequestMapping(value="/read")
    public String Read(Model model,@RequestParam CommonsMultipartFile[] fileUpload)
    throws IOException, EncryptedDocumentException, InvalidFormatException {

    List<String> liste = new ArrayList();
    Employe employe = new Employe();
    String modelnom = null;

    liste = extraire(modelnom); //See the second code

    for (int m=0, i=29;i<liste.size();i=i+29) {
        if(i % 29 == 0) {
            m++;
        }
            employe.setNomEmploye(liste.get(29*m+1));
            //...
            employe.setDateNaissance((String)liste.get(29*m+8).toString());  // here i had the date problem
            employe.setDateEntree((String)liste.get(29*m+9).toString());     // here i had the date problem
            employe.setDateSortie((String)liste.get(29*m+10).toString());    // here i had the date problem
            // ...
            employe.setNumCpteBanc(liste.get(29*m+17)); // here i had the first & second case problem
            employe.setNumCIMR(liste.get(29*m+19));     // here i had the first & second case problem
            employe.setNumMUT(liste.get(29*m+20));      // here i had the first & second case problem
            employe.setNumCNSS(liste.get(29*m+21));     // here i had the first & second case problem

            boolean bool=true;
            List<Employe> employes = dbE.getAll();// liste des employes

            for (int n=0;n<employes.size();n++) {
                if (employes.get(n).getMatriculeMY() ==  (int)mat ) {
                    bool= false;
                }
            }
            if (bool) {

                dbE.create(employe);
            }
    }
     return "redirect";
    }

extraire code

private List<String> extraire (String nomFichier) throws IOException {
    List<String> liste = new ArrayList();
    FileInputStream fis = new FileInputStream(new File(nomFichier));
    HSSFWorkbook  workbook = new HSSFWorkbook(fis);
    HSSFSheet spreadsheet = workbook.getSheetAt(0);
    Iterator < Row > rowIterator = null;
// recup une ligne
    rowIterator = spreadsheet.iterator();
    while (rowIterator.hasNext()) {
        int i = 0;
        row =  (HSSFRow) rowIterator.next();
        Iterator < Cell > cellIterator = row.cellIterator();
        while ( cellIterator.hasNext()) {
            Cell cell = cellIterator.next();
            i++;
            /**
             * Pour verifier si une ligne est vide. (for verifing if the line is empty)
             */
            if (i % 29 == 0 || i == 1) {
                while ( cellIterator.hasNext() && cell.getCellType() == Cell.CELL_TYPE_BLANK) {
                    cell = cellIterator.next();
                }
            }

            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_NUMERIC:
                    String cellule = String.valueOf(cell.getNumericCellValue());
                    liste.add(cellule);
                    break;
                case Cell.CELL_TYPE_STRING:
                    liste.add(cell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_BLANK:
                     cellule = " ";
                             liste.add(cellule);
                             break;
            }
        }
    }
        fis.close();
        return liste;
}
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
yb3prod
  • 564
  • 2
  • 10
  • 22
  • 1
    Add intermediate layer as a mapper between incompatible types ? – John Aug 25 '15 at 14:43
  • i didn't understand how can i do it, can you explain more or give me PLZ an example – yb3prod Aug 25 '15 at 15:28
  • @John i found the solution for date problem but not for the 2 first cases, **PLZ can you help?** – yb3prod Aug 26 '15 at 08:48
  • 1
    Sorry i haven't been working with .xls files in java and therefore do not have direct solution. Only thing i could suggest is as in answer bellow to write some middle layer which handles conversions. – John Aug 26 '15 at 08:51
  • Did you try using [DataFormatter](http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DataFormatter.html) to do your Cell -> String conversion? – Gagravarr Sep 01 '15 at 11:11

1 Answers1

1

Excel's tries to data type cells and sometimes when you explicitly specify the data type Excel may try and cast the cell. You can try to right click on the cell and select 'Format Cell', then select 'Text' as the type (Category). However, at parse time it may still get hosed up.

Your quickest solution might be to save the file as a CSV and use that. You can still edit it in Excel. Although you will need to do some validation to ensure Excel isn't trying to do the above conversions on CSV save as. There are a lot of good Java CSV parsers out there OpenCSV, Super CSV.

The most time consuming, but probably the most correct way, if you want to continue to use Excel, is build a middle ware layer that parses the row and correctly identifies and formats the cell values. Apache POI and HSSF & XSSF can be used. Be warned that to handle xls and xlsx requires two different sets of libraries and often enough abstraction to handle both. See https://poi.apache.org/spreadsheet/

As an Example:

protected String getCellValue(final Cell cell){
    if (null == cell) { return null; }
    // For Excel binaries 97 and below, The method of setting the cell type to CELL_TYPE_STRING converts the
    // Formatted to date to a short. To correct this we check that the cell type is numeric and the check that it is
    // date formatted. If we don't check that it is Numeric first an IllegalAccessorException is thrown.
    if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC && isCellDateFormated(cell) {
        // isCellDateFormated is seperate util function to look at the cell value in order to determine if the date is formatted as a double.
        // is a date format.
        return // do date format procedure.
    }
    cell.setTypeCell(Cell.CELL_TYPE_STRING);
    return cell.toString();
}

Hope this helps.

============Update==================

Instead of calling methods like "getNumericCellValue()" try setting the cell type to String and using toString like the example above. Here is my test code. Note the xls file has one row and 4 cells in csv: "abba,1,211,q123,11.22"

public void testExtract() throws Exception{
    InputStream is = new FileInputStream("/path/to/project/Test/src/test/java/excelTest.xls");
    HSSFWorkbook wb = new HSSFWorkbook(is);
    HSSFSheet sheet = wb.getSheetAt(0);
    Iterator<Row> rowIter = sheet.iterator();
    while (rowIter.hasNext()){
        HSSFRow row = (HSSFRow) rowIter.next();
        Iterator<Cell> cellIter = row.cellIterator();
        while (cellIter.hasNext()){
            Cell cell = cellIter.next();
            System.out.println("Raw to string: " + cell.toString());

            // Check for data format here. If you set a date cell to string and to string the response the output is funky.
            cell.setCellType(Cell.CELL_TYPE_STRING);
            System.out.println("Formatted to string: " + cell.toString());
        }
    }
    is.close();
}

Output is

Raw to string: abba
Formatted to string: abba
Raw to string: 1.0
Formatted to string: 1
Raw to string: 211.0
Formatted to string: 211
Raw to string: q1123
Formatted to string: q1123
Raw to string: 11.22
Formatted to string: 11.22
Ryboflavin
  • 789
  • 5
  • 8
  • when i changed the Cell Format from date to text it works good but for the first two cases i have the same problem + i'm working just on importing (.xls) files using Apache POI – yb3prod Aug 26 '15 at 08:24
  • @yb3prod Can you post the code that does the conversion for the first two cases? What types are the first two cases being loading in as in JAVA (i.e. Longs, int, String)? What are the types of the database columns that the values are being persisted too? Are you using any ORM? Try to put a debug statement after the Excel parsing but before the database persistence. It would be useful to know, for sure, when the value changes. My guess is when you're parsing the value from Excel, but I want to be sure before I recommend anything else. – Ryboflavin Aug 27 '15 at 11:50
  • the type of the first two cases in Java -> String , and in DB -> varchar, i'm using hibernate as ORM – yb3prod Aug 27 '15 at 13:35
  • @yb3prod Added another example. You should use the toString method after setting the cell type to String. You can then use the Integer.parseInt(); – Ryboflavin Aug 31 '15 at 17:20
  • Why not just use [DataFormatter](http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DataFormatter.html), which handles all the conversion from Cell to String with formatting for you? – Gagravarr Sep 01 '15 at 11:10