Bug 55982

Summary: ClassCastException from BOFRecord to TabIdRecord
Product: POI Reporter: Matthieu <bachelier.matthieu>
Component: HSSFAssignee: POI Developers List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 3.10-dev   
Target Milestone: ---   
Hardware: PC   
OS: All   
Attachments: Excel file which produces the exception
[PATCH] First patch for Apache Software Foundation

Description Matthieu 2014-01-09 14:04:18 UTC
Created attachment 31188 [details]
Excel file which produces the exception

This exception happens when trying to clone the Second sheet in the Workbook. I can modify it (inserting contents, saving) but if I want to clone and prepend this "empty" sheet, a ClassCastException is thrown.

java.lang.ClassCastException: org.apache.poi.hssf.record.BOFRecord cannot be cast to org.apache.poi.hssf.record.TabIdRecord
	at org.apache.poi.hssf.model.InternalWorkbook.fixTabIdRecord(InternalWorkbook.java:732)
	at org.apache.poi.hssf.model.InternalWorkbook.checkSheets(InternalWorkbook.java:687)
	at org.apache.poi.hssf.model.InternalWorkbook.setSheetName(InternalWorkbook.java:524)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.cloneSheet(HSSFWorkbook.java:717)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.cloneSheet(HSSFWorkbook.java:85)
Comment 1 Matthieu 2014-01-09 16:16:22 UTC
Created attachment 31189 [details]
[PATCH] First patch for Apache Software Foundation
Comment 2 Nick Burch 2014-01-09 16:20:57 UTC
Any chance you could produce a diff of the changes, rather than the whole changed file? The former makes it much easier to identify what has changed than the latter
Comment 3 Matthieu 2014-01-09 16:44:46 UTC
Sure, I change the method fixTabIdRecord() :

    /**
     * Make the tabid record look like the current situation.
     */
    private void fixTabIdRecord() {
        Record r = records.get(records.getTabpos());
        if (r instanceof TabIdRecord) {
        	TabIdRecord tir = ( TabIdRecord ) r;
        	int sz = tir.getRecordSize();
            short[]     tia = new short[ boundsheets.size() ];

            for (short k = 0; k < tia.length; k++) {
                tia[ k ] = k;
            }
            tir.setTabIdArray(tia);
            // No need to return int because it's not used in this class
            // return tir.getRecordSize() - sz;
        } else if (r instanceof BOFRecord) {
        	// so what ?
        	BOFRecord bof = null; 
        }
    }
Comment 4 Dominik Stadler 2016-01-30 09:32:20 UTC
Hm, this still does not look like a full solution, the assignment in the else is quite useless. And what happens for even other Record-types, should we at least log out or throw an exception?
Comment 5 Dominik Stadler 2016-02-25 14:55:45 UTC
Unfortunately the patch attached here needs more work, therefore I am removing the "PatchAvailable" marker.

FYI, when running our large regression test suite against 1 mio files this exception pops among the top failures besides invalid file formats, see http://people.apache.org/~centic/poi_regression/reportsAll/ for some details.

When verifying 1051003 files, this exception is found 10674 times, i.e. roughly 1% fails with this exception.
Comment 6 Dominik Stadler 2016-04-03 18:40:17 UTC
As this is responsible for a large part of failing documents in our large CommonCrawl regression test-suite and thus is likely to affect some people, I have now put in a fix which tries to handle this similar to what LibreOffice/Excel seem to do in these cases.

See r1737602 for the actual changes.