从Excel文件中获取值并将其放入数据库

时间:2015-10-06 15:15:42

标签: java database excel apache-poi xlsm

我必须将Excel文件映射到数据库值。鉴于Excel文件有很多行我使用https://github.com/monitorjbl/excel-streaming-reader,否则,使用Apache POI,我会收到内存错误。 这是旧代码,不适用于大文件:

/**
 * Private method called from single and multiple file upload to retrieve the excel fields values
 * This method works if THE EXCEL FILE IS WITHOUT empty row!!
 * @param file
 * @return
 * @throws IOException
 */
private ExcelField[][] getExcelField(MultipartFile file) throws IOException{
    try{
        ArrayList<ArrayList<ExcelField>> valuesMatrix= new ArrayList<ArrayList<ExcelField>>();
        Workbook wb = WorkbookFactory.create(file.getInputStream());
        //Sheet to use
        Sheet firstSheet = wb.getSheetAt(0);
        //Assuming that the first row is without blank cell and it has the maximum number of columns.
        //numCol IS NECESSARY BECAUSE IF THERE IS A EMPTY CELL AT THE LAST POSITION OF THE ROW THE GETLASTCELLNUM RETURN 
        //THE NUMBER OF ROWS WITHOUT THE LAST
        int numCol=firstSheet.getRow(0).getLastCellNum();
        int numRow=firstSheet.getPhysicalNumberOfRows();
        for(int rw=0;rw<numRow;rw++) {
            Row row=firstSheet.getRow(rw);
            ArrayList<ExcelField> rowValues=new ArrayList<ExcelField>();
            for(int cn=0; cn<numCol; cn++) {
                Cell cell = row.getCell(cn, Row.CREATE_NULL_AS_BLANK);
                rowValues.add(getCellValue(cell));                  
                //Print into console the fields values
                //System.out.print(getCellValue(cell).getValue()!=null?getCellValue(cell).getValue().toString():" null"+" ");
            }
            valuesMatrix.add(rowValues);
            //System.out.println();
        }
        wb.close();         
        return convert2DimensionalArrayToMatrix(valuesMatrix);
    } catch (EncryptedDocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidFormatException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

在Excel文件中有公式,日期,双精度,合并单元格等。在这一刻我有问题,只有新方法,公式和日期,我经常收到str或其他类型的未知异常。

Caused by: java.lang.UnsupportedOperationException: Unsupported cell type 'str'
at com.monitorjbl.xlsx.impl.StreamingCell.getCellType(StreamingCell.java:106)
at com.mkyong.services.FileServicesImpl.getCellValue(FileServicesImpl.java:193)
at com.mkyong.services.FileServicesImpl.getExcelFieldSpeedImproved(FileServicesImpl.java:176)
at com.mkyong.services.FileServicesImpl.singleFileOpen(FileServicesImpl.java:86)

相反,日期返回null值。我并不关心公式,但我感兴趣的只是因为我必须将它存储在数据库中。这是我的代码:

@Override
public Response<ExcelField[][]> singleFileOpen(MultipartFile file) throws FileEmptyException, FileUploadException{
    if (!file.isEmpty()) {
        try {
            openedFile=file;
            //Retrieve the fields values
            //              ExcelField[][] valuesMatrix=getExcelField(openedFile);
            ExcelField[][] valuesMatrix=getExcelFieldSpeedImproved(openedFile);
            //              //return the Response with status ad excel fields
            return new Response<ExcelField[][]>(HttpStatus.OK.value(),valuesMatrix);
        } catch (Exception e) {
            throw new FileUploadException("You failed to read " + openedFile.getOriginalFilename(), e);
        }
    } else {
        throw new FileEmptyException("You failed to read" );
    }
}

和主要方法:

private ExcelField[][] getExcelFieldSpeedImproved(MultipartFile file) throws IOException{
    ArrayList<ArrayList<ExcelField>> valuesMatrix= new ArrayList<ArrayList<ExcelField>>();
    InputStream is = file.getInputStream();
    StreamingReader reader = StreamingReader.builder()
            .rowCacheSize(100)    // number of rows to keep in memory (defaults to 10)
            .bufferSize(4096)     // buffer size to use when reading InputStream to file (defaults to 1024)
            .sheetIndex(0)        // index of sheet to use (defaults to 0)
            .read(is);            // InputStream or File for XLSX file (required)
    for (Row r : reader) {
        ArrayList<ExcelField> rowValues=new ArrayList<ExcelField>();
        for (Cell c : r) {
            rowValues.add(getCellValue(c));
            System.out.print((String)getCellValue(c).getValue()+" ");
        }
        valuesMatrix.add(rowValues);
        System.out.println();

    }  
    return convert2DimensionalArrayToMatrix(valuesMatrix);
}

和类型选择:

/**
 * Retrieve the value in one excel field
 * @param cell
 * @return
 */
private ExcelField getCellValue(Cell cell) {

        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            return new ExcelField(ExcelTypeEnum.STRING,cell.getStringCellValue());
        case Cell.CELL_TYPE_BOOLEAN:
            return new ExcelField(ExcelTypeEnum.BOOLEAN,cell.getBooleanCellValue());
        case Cell.CELL_TYPE_NUMERIC:
            return new ExcelField(ExcelTypeEnum.NUMERIC,cell.getNumericCellValue());
        case Cell.CELL_TYPE_ERROR:
            return new ExcelField(ExcelTypeEnum.ERROR,cell.getErrorCellValue());
        case Cell.CELL_TYPE_FORMULA:
            return new ExcelField(ExcelTypeEnum.FORMULA,cell.getCachedFormulaResultType()); 
        default:
            return new ExcelField(ExcelTypeEnum.BLANK,null);
        }
}

检索Excel值的最佳方法是什么?

更新:使用此代码我解决旧方法和日期和公式:

    /**
 * Retrieve the value in one excel field
 * @param cell
 * @return
 */
private ExcelField getCellValue(int cellType, Cell cell) {
    switch (cellType) {
    case Cell.CELL_TYPE_STRING:
        return new ExcelField(ExcelTypeEnum.STRING,cell.getStringCellValue());
    case Cell.CELL_TYPE_BOOLEAN:
        return new ExcelField(ExcelTypeEnum.BOOLEAN,cell.getBooleanCellValue());
    case Cell.CELL_TYPE_NUMERIC:
        if (HSSFDateUtil.isCellDateFormatted(cell))
            //SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
            //System.out.print(dateFormat.format(cell.getDateCellValue()) + "\t\t");
                return new ExcelField(ExcelTypeEnum.NUMERIC,cell.getDateCellValue());
        return new ExcelField(ExcelTypeEnum.NUMERIC,cell.getNumericCellValue());
    case Cell.CELL_TYPE_ERROR:
        return new ExcelField(ExcelTypeEnum.ERROR,cell.getErrorCellValue());
    case Cell.CELL_TYPE_FORMULA:
            return getCellValue(cell.getCachedFormulaResultType(),cell);            
    case Cell.CELL_TYPE_BLANK:
        return new ExcelField(ExcelTypeEnum.BLANK,null);
    default:
        return new ExcelField(ExcelTypeEnum.BLANK,cell.getStringCellValue());
    }
}

0 个答案:

没有答案