git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@832584 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_6
@@ -34,6 +34,7 @@ | |||
<changes> | |||
<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">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> |
@@ -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.MissingRowDummyRecord; | |||
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.MulBlankRecord; | |||
import org.apache.poi.hssf.record.MulRKRecord; | |||
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.RecordFactory; | |||
import org.apache.poi.hssf.record.RowRecord; | |||
import org.apache.poi.hssf.record.SharedFormulaRecord; | |||
@@ -62,7 +67,7 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener { | |||
public void processRecord(Record record) { | |||
int thisRow; | |||
int thisColumn; | |||
CellValueRecordInterface[] expandedRecords = null; | |||
if (record instanceof CellValueRecordInterface) { | |||
CellValueRecordInterface valueRec = (CellValueRecordInterface) record; | |||
@@ -105,6 +110,19 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener { | |||
// - so don't fire off the LastCellOfRowDummyRecord yet | |||
childListener.processRecord(record); | |||
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: | |||
NoteRecord nrec = (NoteRecord) record; | |||
thisRow = nrec.getRow(); | |||
@@ -112,6 +130,13 @@ public final class MissingRecordAwareHSSFListener implements HSSFListener { | |||
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 | |||
// row as the last one, then fire the | |||
// dummy end-of-row records | |||
@@ -148,13 +173,26 @@ 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 | |||
if(thisColumn != -1) { | |||
lastCellColumn = thisColumn; | |||
lastCellRow = thisRow; | |||
} | |||
childListener.processRecord(record); | |||
// Pass along the record(s) | |||
if(expandedRecords != null && expandedRecords.length > 0) { | |||
for(CellValueRecordInterface r : expandedRecords) { | |||
childListener.processRecord((Record)r); | |||
} | |||
} else { | |||
childListener.processRecord(record); | |||
} | |||
} | |||
private void resetCounts() { |
@@ -56,6 +56,13 @@ public final class MulBlankRecord extends StandardRecord { | |||
public int getFirstColumn() { | |||
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) |
@@ -281,7 +281,6 @@ public final class RecordFactory { | |||
* Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s | |||
*/ | |||
public static NumberRecord[] convertRKRecords(MulRKRecord mrk) { | |||
NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()]; | |||
for (int k = 0; k < mrk.getNumColumns(); k++) { | |||
NumberRecord nr = new NumberRecord(); | |||
@@ -295,6 +294,22 @@ public final class RecordFactory { | |||
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 | |||
*/ |
@@ -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.MissingRowDummyRecord; | |||
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.MulBlankRecord; | |||
import org.apache.poi.hssf.record.Record; | |||
import org.apache.poi.hssf.record.RowRecord; | |||
import org.apache.poi.hssf.record.SharedFormulaRecord; | |||
@@ -422,4 +424,41 @@ public final class TestMissingRecordAwareHSSFListener extends TestCase { | |||
assertEquals(1, eorCount); | |||
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); | |||
} | |||
} |