如何使用Apache POI使用事件模型读取多个工作表?

时间:2015-10-09 07:29:54

标签: java excel apache-poi

我可以使用事件模型POI成功读取Excel文件(.xls)。我没有使用usermodel(org.apache.poi.ss.usermodel),而是使用Event API来处理xls和xlsx文件(以解决内存占用问题)。但是,在读取包含多个工作表的.xls文件时,只会读取第一个工作表。其他工作表被忽略。

我正在实现HSSFListener并覆盖xls文件的processRecord(记录记录)方法。

以下是我的代码部分:

/**
     * Main HSSFListener method for xls. It processes events and creates a RuntimeRecord to put into the DataPool.
     */
    public void processRecord(Record record) {
        int thisRow = -1;
        String thisStr = null;

        switch (record.getSid()) {
            case BoundSheetRecord.sid:
                boundSheetRecords.add(record);
                break;
            case BOFRecord.sid:
                BOFRecord br = (BOFRecord)record;
                if(br.getType() == BOFRecord.TYPE_WORKSHEET) {
                    // Works by ordering the BSRs by the location of their BOFRecords, and then knowing that we
                    // process BOFRecords in byte offset order
                    if(orderedBSRs == null) {
                        orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
                    }

                    // Check the existence of sheets
                    if(sheetIndex == 0) {
                        for(int i=0;i<excelSheetList.length;i++) {
                            boolean found = false;
                            if(this.getExcelSheetSpecification().equals(MSExcelAdapter.USE_WORKSHEET_NAME)) {
                                for(BoundSheetRecord rec : orderedBSRs) {
                                    int len = rec.getSheetname().length();
                                    if(len > 31)
                                        this.warning("processRecord()","The length of sheet: " + rec.getSheetname() + " has more than 31 characters. Please change the name of the sheet, save the file and try again.");
                                }
                            }

                            if(this.getExcelSheetSpecification().equals(MSExcelAdapter.USE_WORKSHEET_NUMBER)) {
                                int sheetNo = Integer.parseInt(excelSheetList[i]);
                                if(sheetNo > 0 && sheetNo <= orderedBSRs.length) {
                                    found = true;
                                }
                            } else {
                                for(int j=0;j<orderedBSRs.length;j++) {
                                    if(this.getExcelSheetSpecification().equals(MSExcelAdapter.USE_WORKSHEET_NAME)) {
                                        String sheetName = ((BoundSheetRecord) boundSheetRecords.get(j)).getSheetname();
                                        if(excelSheetList[i].equals(sheetName)) {
                                            found = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            if(!found)
                                this.error("processRecord()","Sheet: " + excelSheetList[i] + " does not exist.");
                        }
                    }

                    readCurrentSheet = true;
                    sheetIndex++;
                    System.out.println(sheetIndex);
                    if(this.getExcelSheetSpecification().equals(MSExcelAdapter.USE_WORKSHEET_NAME)) {
                        String sheetName = ((BoundSheetRecord) boundSheetRecords.get(sheetIndex-1)).getSheetname();
                        if(!canRead(sheetName)) {
                            readCurrentSheet = false;                       
                        }
                    } else {
                        if(!canRead(sheetIndex + "")) {
                            readCurrentSheet = false;
                        }
                    }
                }
                break;

            case SSTRecord.sid:
                sstRecord = (SSTRecord) record;
                break;

            case BlankRecord.sid:
                BlankRecord brec = (BlankRecord) record;

                thisRow = brec.getRow();
                thisStr = null;
                values.add(thisStr);
                columnCount++;
                break;

            case FormulaRecord.sid:
                FormulaRecord frec = (FormulaRecord) record;

                thisRow = frec.getRow();
                if(Double.isNaN( frec.getValue() )) {
                    // Formula result is a string
                    // This is stored in the next record
                    outputNextStringRecord = true;
                    nextRow = frec.getRow();
                } else {
                    thisStr = formatListener.formatNumberDateCell(frec);
                }
                break;  

            case StringRecord.sid:
                if(outputNextStringRecord) {
                    // String for formula
                    StringRecord srec = (StringRecord)record;
                    thisStr = srec.getString();
                    thisRow = nextRow;
                    outputNextStringRecord = false;
                }
                break;

            case LabelSSTRecord.sid:
                if(readCurrentSheet) {
                    LabelSSTRecord lsrec = (LabelSSTRecord) record;
                    thisRow = lsrec.getRow() + 1;
                    if(rowNumberList.contains(thisRow + "") ||
                            (rowNumberList.contains(END_OF_ROWS) && thisRow >= secondLastRow)) {
                        if(sstRecord == null) {
                            thisStr = "(No SST Record, can't identify string)";
                        } else {
                            thisStr = sstRecord.getString(lsrec.getSSTIndex()).toString();
                        }
                    }
                }
                break;

            case NumberRecord.sid:
                if(readCurrentSheet) {
                    NumberRecord numrec = (NumberRecord) record;
                    thisRow = numrec.getRow() + 1;
                    if(rowNumberList.contains(thisRow + "") ||
                                (rowNumberList.contains(END_OF_ROWS) && thisRow >= secondLastRow)) {
                        // No need to format.
                        // thisStr = formatListener.formatNumberDateCell(numrec); // Format
                        thisStr = String.valueOf(numrec.getValue()); 
                    }
                }
                break;
            default:
                break;
        }

        // Handle missing column
        if(record instanceof MissingCellDummyRecord) {
            thisStr = "";
        }

        // If we got something to print out, do so
        if(thisStr != null) {
            values.add(thisStr);
            columnCount++;
        }

        // Handle end of row
        if(record instanceof LastCellOfRowDummyRecord) {
            if(readCurrentSheet) {
                int currentRow = ((LastCellOfRowDummyRecord) record).getRow() + 1;
                if(rowsReadSet.add(String.valueOf(currentRow))) {
                    if(processTestData) {
                        try { 
                            int dpSize = this.getOutputDP().getSize();
                            if(dpSize < 1000 &&
                                    (rowNumberList.contains(currentRow + "") ||
                                            (rowNumberList.contains(END_OF_ROWS) && currentRow >= secondLastRow))) {
                                for(int i=columnCount; i<this.getConfigRecord().size(); i++) {
                                    values.add(null);  // Add empty string for missing columns
                                }   
                                RuntimeRecord resultRecord = this.createRuntimeRecord(values);
                                this.fireRecordCreatedEvent(resultRecord);
                                this.putNextRecord(resultRecord);   
                            }
                        } catch (Exception e) {
                            this.error("processRecord()",e.getMessage());
                            this.fireRecordCreationFailedEvent(e.getMessage(), e.getMessage());
                        }
                    } else {
                        try {

                            if(rowNumberList.contains(currentRow + "") || (rowNumberList.contains(END_OF_ROWS) && currentRow >= secondLastRow)) {
                                for(int i=columnCount; i<this.getConfigRecord().size(); i++) {
                                    values.add(null);  // Add empty string for missing columns
                                }
                                RuntimeRecord resultRecord = this.createRuntimeRecord(values);
                                this.fireRecordCreatedEvent(resultRecord);
                                this.putNextRecord(resultRecord);

                            }
                        } catch (Exception e) {
                            this.error("processRecord()",e.getMessage());
                            this.fireRecordCreationFailedEvent(e.getMessage(), e.getMessage());
                        }
                    }
                }
                values.removeAllElements();
                columnCount = 0;
            }
        }
    }

以下是注册侦听器的方法:

private void readxls() throws FileNotFoundException, IOException {
        POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(this.getFileName()));
        MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
        formatListener = new FormatTrackingHSSFListener(listener);

        HSSFEventFactory factory = new HSSFEventFactory();
        HSSFRequest request = new HSSFRequest();

        request.addListenerForAllRecords(formatListener);
        rowsReadSet.clear();
        factory.processWorkbookEvents(request, fs);
    }

当我通过添加一些断点进行调试时,我注意到它实际上将列值添加到我的values Vector中。但是,以下条件永远不会与第二张相匹配。

if(record instanceof LastCellOfRowDummyRecord) {
...
}

如何摆脱这个问题?我想阅读Excel文件(.xls)中的所有工作表。我正在使用Apache POI 3.11-20141221和JDK7。

0 个答案:

没有答案