Hopefully fix #45672 properly - improve handling by MissingRecordAwareHSSFListener of records that cover multiple cells (MulBlankRecord and MulRKRecord)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@832584 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2009-11-03 22:45:39 +00:00
parent 35c07feabe
commit 509c7bcb93
6 changed files with 103 additions and 3 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.6-beta1" date="2009-??-??"> <release version="3.6-beta1" date="2009-??-??">
<action dev="POI-DEVELOPERS" type="fix">45672 - improve handling by MissingRecordAwareHSSFListener of records that cover multiple cells (MulBlankRecord and MulRKRecord)</action>
<action dev="POI-DEVELOPERS" type="fix">48096 - relaxed validation check in RecalcIdRecord</action> <action dev="POI-DEVELOPERS" type="fix">48096 - relaxed validation check in RecalcIdRecord</action>
<action dev="POI-DEVELOPERS" type="fix">48085 - improved error checking in BlockAllocationTableReader to trap unreasonable field values</action> <action dev="POI-DEVELOPERS" type="fix">48085 - improved error checking in BlockAllocationTableReader to trap unreasonable field values</action>
<action dev="POI-DEVELOPERS" type="fix">47924 - fixed logic for matching cells and comments in HSSFCell.getCellComment()</action> <action dev="POI-DEVELOPERS" type="fix">47924 - fixed logic for matching cells and comments in HSSFCell.getCellComment()</action>

View File

@ -21,9 +21,14 @@ import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord; import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord; import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord;
import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface; import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.MulRKRecord;
import org.apache.poi.hssf.record.NoteRecord; import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.SharedFormulaRecord;
@ -62,7 +67,7 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener {
public void processRecord(Record record) { public void processRecord(Record record) {
int thisRow; int thisRow;
int thisColumn; int thisColumn;
CellValueRecordInterface[] expandedRecords = null;
if (record instanceof CellValueRecordInterface) { if (record instanceof CellValueRecordInterface) {
CellValueRecordInterface valueRec = (CellValueRecordInterface) record; CellValueRecordInterface valueRec = (CellValueRecordInterface) record;
@ -105,6 +110,19 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener {
// - so don't fire off the LastCellOfRowDummyRecord yet // - so don't fire off the LastCellOfRowDummyRecord yet
childListener.processRecord(record); childListener.processRecord(record);
return; return;
case MulBlankRecord.sid:
// These appear in the middle of the cell records, to
// specify that the next bunch are empty but styled
// Expand this out into multiple blank cells
MulBlankRecord mbr = (MulBlankRecord)record;
expandedRecords = RecordFactory.convertBlankRecords(mbr);
break;
case MulRKRecord.sid:
// This is multiple consecutive number cells in one record
// Exand this out into multiple regular number cells
MulRKRecord mrk = (MulRKRecord)record;
expandedRecords = RecordFactory.convertRKRecords(mrk);
break;
case NoteRecord.sid: case NoteRecord.sid:
NoteRecord nrec = (NoteRecord) record; NoteRecord nrec = (NoteRecord) record;
thisRow = nrec.getRow(); thisRow = nrec.getRow();
@ -112,6 +130,13 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener {
break; break;
} }
} }
// First part of expanded record handling
if(expandedRecords != null && expandedRecords.length > 0) {
thisRow = expandedRecords[0].getRow();
thisColumn = expandedRecords[0].getColumn();
}
// If we're on cells, and this cell isn't in the same // If we're on cells, and this cell isn't in the same
// row as the last one, then fire the // row as the last one, then fire the
// dummy end-of-row records // dummy end-of-row records
@ -148,14 +173,27 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener {
} }
} }
// Next part of expanded record handling
if(expandedRecords != null && expandedRecords.length > 0) {
thisColumn = expandedRecords[expandedRecords.length-1].getColumn();
}
// Update cell and row counts as needed // Update cell and row counts as needed
if(thisColumn != -1) { if(thisColumn != -1) {
lastCellColumn = thisColumn; lastCellColumn = thisColumn;
lastCellRow = thisRow; lastCellRow = thisRow;
} }
// Pass along the record(s)
if(expandedRecords != null && expandedRecords.length > 0) {
for(CellValueRecordInterface r : expandedRecords) {
childListener.processRecord((Record)r);
}
} else {
childListener.processRecord(record); childListener.processRecord(record);
} }
}
private void resetCounts() { private void resetCounts() {
lastRowRow = -1; lastRowRow = -1;

View File

@ -57,6 +57,13 @@ public final class MulBlankRecord extends StandardRecord {
return _firstCol; return _firstCol;
} }
/**
* @return ending column (last cell this holds in the row). Zero based
*/
public int getLastColumn() {
return _lastCol;
}
/** /**
* get the number of columns this contains (last-first +1) * get the number of columns this contains (last-first +1)
* @return number of columns (last - first +1) * @return number of columns (last - first +1)

View File

@ -281,7 +281,6 @@ public final class RecordFactory {
* Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s * Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s
*/ */
public static NumberRecord[] convertRKRecords(MulRKRecord mrk) { public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()]; NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
for (int k = 0; k < mrk.getNumColumns(); k++) { for (int k = 0; k < mrk.getNumColumns(); k++) {
NumberRecord nr = new NumberRecord(); NumberRecord nr = new NumberRecord();
@ -295,6 +294,22 @@ public final class RecordFactory {
return mulRecs; return mulRecs;
} }
/**
* Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s
*/
public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) {
BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()];
for (int k = 0; k < mbk.getNumColumns(); k++) {
BlankRecord br = new BlankRecord();
br.setColumn((short) (k + mbk.getFirstColumn()));
br.setRow(mbk.getRow());
br.setXFIndex(mbk.getXFAt(k));
mulRecs[k] = br;
}
return mulRecs;
}
/** /**
* @return an array of all the SIDS for all known records * @return an array of all the SIDS for all known records
*/ */

View File

@ -29,7 +29,9 @@ import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord; import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord; import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord;
import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.LabelSSTRecord; import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.SharedFormulaRecord;
@ -422,4 +424,41 @@ public final class TestMissingRecordAwareHSSFListener extends TestCase {
assertEquals(1, eorCount); assertEquals(1, eorCount);
assertEquals(1, sfrCount); assertEquals(1, sfrCount);
} }
/**
* MulBlank records hold multiple blank cells. Check we
* can handle them correctly.
*/
public void testMulBlankHandling() {
readRecords("45672.xls");
// Check that we don't have any MulBlankRecords, but do
// have lots of BlankRecords
Record[] rr = r;
int eorCount=0;
int mbrCount=0;
int brCount=0;
for (int i = 0; i < rr.length; i++) {
Record record = rr[i];
if (record instanceof MulBlankRecord) {
mbrCount++;
}
if (record instanceof BlankRecord) {
brCount++;
}
if (record instanceof LastCellOfRowDummyRecord) {
eorCount++;
}
}
if (mbrCount > 0) {
throw new AssertionFailedError("Identified bug 45672");
}
if (brCount < 20) {
throw new AssertionFailedError("Identified bug 45672");
}
if (eorCount != 2) {
throw new AssertionFailedError("Identified bug 45672");
}
assertEquals(2, eorCount);
}
} }

Binary file not shown.