aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Micich <josh@apache.org>2009-01-21 00:19:49 +0000
committerJosh Micich <josh@apache.org>2009-01-21 00:19:49 +0000
commitf890e59acef5d7f41140a9f30902a8b24db02910 (patch)
tree8ddd6485aec11caa56d6e25f52f441e909d18402
parenta8bcfddad42aa6f141ff6415fc80981a2db20131 (diff)
downloadpoi-f890e59acef5d7f41140a9f30902a8b24db02910.tar.gz
poi-f890e59acef5d7f41140a9f30902a8b24db02910.zip
Fix for bug 46547 - Allow for addition of conditional formatting when data validations are present. Avoid creation of and empty conditional formatting table while shifting formulas.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@736175 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/documentation/content/xdocs/changes.xml3
-rw-r--r--src/documentation/content/xdocs/status.xml3
-rw-r--r--src/java/org/apache/poi/hssf/model/RecordOrderer.java9
-rw-r--r--src/java/org/apache/poi/hssf/model/Sheet.java4
-rw-r--r--src/testcases/org/apache/poi/hssf/model/TestSheet.java1189
5 files changed, 632 insertions, 576 deletions
diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index dbac53ad9b..d1294862b9 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -37,7 +37,8 @@
<!-- Don't forget to update status.xml too! -->
<release version="3.5-beta5" date="2008-??-??">
- <action dev="POI-DEVELOPERS" type="fix">46548 - Print Settings Block fixes - continued PLS records and PSB in sheet sub-streams</action>
+ <action dev="POI-DEVELOPERS" type="fix">46547 - Allow addition of conditional formatting after data validation</action>
+ <action dev="POI-DEVELOPERS" type="fix">46548 - Page Settings Block fixes - continued PLS records and PSB in sheet sub-streams</action>
<action dev="POI-DEVELOPERS" type="add">46523 - added implementation for SUMIF function</action>
<action dev="POI-DEVELOPERS" type="add">Support for reading HSSF column styles</action>
<action dev="POI-DEVELOPERS" type="fix">Hook up POIXMLTextExtractor.getMetadataTextExtractor() to the already written POIXMLPropertiesTextExtractor</action>
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index 93ab10e196..6a00bac094 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -34,7 +34,8 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.5-beta5" date="2008-??-??">
- <action dev="POI-DEVELOPERS" type="fix">46548 - Print Settings Block fixes - continued PLS records and PSB in sheet sub-streams</action>
+ <action dev="POI-DEVELOPERS" type="fix">46547 - Allow addition of conditional formatting after data validation</action>
+ <action dev="POI-DEVELOPERS" type="fix">46548 - Page Settings Block fixes - continued PLS records and PSB in sheet sub-streams</action>
<action dev="POI-DEVELOPERS" type="add">46523 - added implementation for SUMIF function</action>
<action dev="POI-DEVELOPERS" type="add">Support for reading HSSF column styles</action>
<action dev="POI-DEVELOPERS" type="fix">Hook up POIXMLTextExtractor.getMetadataTextExtractor() to the already written POIXMLPropertiesTextExtractor</action>
diff --git a/src/java/org/apache/poi/hssf/model/RecordOrderer.java b/src/java/org/apache/poi/hssf/model/RecordOrderer.java
index c637ae7136..c0cb33f4db 100644
--- a/src/java/org/apache/poi/hssf/model/RecordOrderer.java
+++ b/src/java/org/apache/poi/hssf/model/RecordOrderer.java
@@ -91,7 +91,7 @@ final class RecordOrderer {
sheetRecords.add(index, newRecord);
}
- private static int findSheetInsertPos(List<RecordBase> records, Class recClass) {
+ private static int findSheetInsertPos(List<RecordBase> records, Class<? extends RecordBase> recClass) {
if (recClass == DataValidityTable.class) {
return findDataValidationTableInsertPos(records);
}
@@ -160,6 +160,10 @@ final class RecordOrderer {
if (rb instanceof MergedCellsTable) {
return i + 1;
}
+ if (rb instanceof DataValidityTable) {
+ continue;
+ }
+
Record rec = (Record) rb;
switch (rec.getSid()) {
case WindowTwoRecord.sid:
@@ -170,7 +174,10 @@ final class RecordOrderer {
// MergedCellsTable usually here
case UnknownRecord.LABELRANGES_015F:
case UnknownRecord.PHONETICPR_00EF:
+ // ConditionalFormattingTable goes here
return i + 1;
+ // HyperlinkTable (not aggregated by POI yet)
+ // DataValidityTable
}
}
throw new RuntimeException("Did not find Window2 record");
diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java
index 472fec9152..548d5ad781 100644
--- a/src/java/org/apache/poi/hssf/model/Sheet.java
+++ b/src/java/org/apache/poi/hssf/model/Sheet.java
@@ -504,7 +504,9 @@ public final class Sheet implements Model {
*/
public void updateFormulasAfterCellShift(FormulaShifter shifter, int externSheetIndex) {
getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
- getConditionalFormattingTable().updateFormulasAfterCellShift(shifter, externSheetIndex);
+ if (condFormatting != null) {
+ getConditionalFormattingTable().updateFormulasAfterCellShift(shifter, externSheetIndex);
+ }
// TODO - adjust data validations
}
diff --git a/src/testcases/org/apache/poi/hssf/model/TestSheet.java b/src/testcases/org/apache/poi/hssf/model/TestSheet.java
index 7a857d6ca5..c68a5f8772 100644
--- a/src/testcases/org/apache/poi/hssf/model/TestSheet.java
+++ b/src/testcases/org/apache/poi/hssf/model/TestSheet.java
@@ -36,12 +36,15 @@ import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
+import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
@@ -50,580 +53,622 @@ import org.apache.poi.hssf.usermodel.RecordInspector.RecordCollector;
import org.apache.poi.ss.util.CellRangeAddress;
/**
- * Unit test for the Sheet class.
+ * Unit test for the {@link Sheet} class.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class TestSheet extends TestCase {
- private static Sheet createSheet(List inRecs) {
- return Sheet.createSheet(new RecordStream(inRecs, 0));
- }
-
- private static Record[] getSheetRecords(Sheet s, int offset) {
- RecordCollector rc = new RecordCollector();
- s.visitContainedRecords(rc, offset);
- return rc.getRecords();
- }
-
- public void testCreateSheet() {
- // Check we're adding row and cell aggregates
- List<Record> records = new ArrayList<Record>();
- records.add(BOFRecord.createSheetBOF());
- records.add( new DimensionsRecord() );
- records.add(createWindow2Record());
- records.add(EOFRecord.instance);
- Sheet sheet = createSheet(records);
- Record[] outRecs = getSheetRecords(sheet, 0);
-
- int pos = 0;
- assertTrue(outRecs[pos++] instanceof BOFRecord );
- assertTrue(outRecs[pos++] instanceof IndexRecord );
- assertTrue(outRecs[pos++] instanceof DimensionsRecord );
- assertTrue(outRecs[pos++] instanceof WindowTwoRecord );
- assertTrue(outRecs[pos++] instanceof EOFRecord );
- }
-
- private static Record createWindow2Record() {
- WindowTwoRecord result = new WindowTwoRecord();
- result.setOptions(( short ) 0x6b6);
- result.setTopRow(( short ) 0);
- result.setLeftCol(( short ) 0);
- result.setHeaderColor(0x40);
- result.setPageBreakZoom(( short ) 0);
- result.setNormalZoom(( short ) 0);
- return result;
- }
-
- private static final class MergedCellListener implements RecordVisitor {
-
- private int _count;
- public MergedCellListener() {
- _count = 0;
- }
- public void visitRecord(Record r) {
- if (r instanceof MergeCellsRecord) {
- _count++;
- }
- }
- public int getCount() {
- return _count;
- }
- }
-
- public void testAddMergedRegion() {
- Sheet sheet = Sheet.createSheet();
- int regionsToAdd = 4096;
-
- //simple test that adds a load of regions
- for (int n = 0; n < regionsToAdd; n++)
- {
- int index = sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
- assertTrue("Merged region index expected to be " + n + " got " + index, index == n);
- }
-
- //test all the regions were indeed added
- assertTrue(sheet.getNumMergedRegions() == regionsToAdd);
-
- //test that the regions were spread out over the appropriate number of records
- MergedCellListener mcListener = new MergedCellListener();
- sheet.visitContainedRecords(mcListener, 0);
- int recordsAdded = mcListener.getCount();
- int recordsExpected = regionsToAdd/1027;
- if ((regionsToAdd % 1027) != 0)
- recordsExpected++;
- assertTrue("The " + regionsToAdd + " merged regions should have been spread out over "
- + recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
- // Check we can't add one with invalid date
- try {
- sheet.addMergedRegion(10, (short)10, 9, (short)12);
- fail("Expected an exception to occur");
- } catch(IllegalArgumentException e) {
- // occurs during successful test
- assertEquals("The 'to' row (9) must not be less than the 'from' row (10)", e.getMessage());
- }
- try {
- sheet.addMergedRegion(10, (short)10, 12, (short)9);
- fail("Expected an exception to occur");
- } catch(IllegalArgumentException e) {
- // occurs during successful test
- assertEquals("The 'to' col (9) must not be less than the 'from' col (10)", e.getMessage());
- }
- }
-
- public void testRemoveMergedRegion() {
- Sheet sheet = Sheet.createSheet();
- int regionsToAdd = 4096;
-
- for (int n = 0; n < regionsToAdd; n++) {
- sheet.addMergedRegion(n, 0, n, 1);
- }
-
- int nSheetRecords = sheet.getRecords().size();
-
- //remove a third from the beginning
- for (int n = 0; n < regionsToAdd/3; n++)
- {
- sheet.removeMergedRegion(0);
- //assert they have been deleted
- assertEquals("Num of regions", regionsToAdd - n - 1, sheet.getNumMergedRegions());
- }
-
- // merge records are removed from within the MergedCellsTable,
- // so the sheet record count should not change
- assertEquals("Sheet Records", nSheetRecords, sheet.getRecords().size());
- }
-
- /**
- * Bug: 22922 (Reported by Xuemin Guan)
- * <p>
- * Remove mergedregion fails when a sheet loses records after an initial CreateSheet
- * fills up the records.
- *
- */
- public void testMovingMergedRegion() {
- List<Record> records = new ArrayList<Record>();
-
- CellRangeAddress[] cras = {
- new CellRangeAddress(0, 1, 0, 2),
- };
- MergeCellsRecord merged = new MergeCellsRecord(cras, 0, cras.length);
- records.add(BOFRecord.createSheetBOF());
- records.add(new DimensionsRecord());
- records.add(new RowRecord(0));
- records.add(new RowRecord(1));
- records.add(new RowRecord(2));
- records.add(createWindow2Record());
- records.add(EOFRecord.instance);
- records.add(merged);
-
- Sheet sheet = createSheet(records);
- sheet.getRecords().remove(0); // TODO - what does this line do?
-
- //stub object to throw off list INDEX operations
- sheet.removeMergedRegion(0);
- assertEquals("Should be no more merged regions", 0, sheet.getNumMergedRegions());
- }
-
- public void testGetMergedRegionAt() {
- //TODO
- }
-
- public void testGetNumMergedRegions() {
- //TODO
- }
-
- /**
- * Makes sure all rows registered for this sheet are aggregated, they were being skipped
- *
- */
- public void testRowAggregation() {
- List<Record> records = new ArrayList<Record>();
-
- records.add(Sheet.createBOF());
- records.add(new DimensionsRecord());
- records.add(new RowRecord(0));
- records.add(new RowRecord(1));
- FormulaRecord formulaRecord = new FormulaRecord();
- formulaRecord.setCachedResultTypeString();
- records.add(formulaRecord);
- records.add(new StringRecord());
- records.add(new RowRecord(2));
- records.add(createWindow2Record());
- records.add(EOFRecord.instance);
-
- Sheet sheet = createSheet(records);
- assertNotNull("Row [2] was skipped", sheet.getRow(2));
- }
-
- /**
- * Make sure page break functionality works (in memory)
- *
- */
- public void testRowPageBreaks() {
- short colFrom = 0;
- short colTo = 255;
-
- Sheet worksheet = Sheet.createSheet();
- PageSettingsBlock sheet = worksheet.getPageSettings();
- sheet.setRowBreak(0, colFrom, colTo);
-
- assertTrue("no row break at 0", sheet.isRowBroken(0));
- assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
-
- sheet.setRowBreak(0, colFrom, colTo);
- sheet.setRowBreak(0, colFrom, colTo);
-
- assertTrue("no row break at 0", sheet.isRowBroken(0));
- assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
-
- sheet.setRowBreak(10, colFrom, colTo);
- sheet.setRowBreak(11, colFrom, colTo);
-
- assertTrue("no row break at 10", sheet.isRowBroken(10));
- assertTrue("no row break at 11", sheet.isRowBroken(11));
- assertEquals("3 row break available", 3, sheet.getNumRowBreaks());
-
-
- boolean is10 = false;
- boolean is0 = false;
- boolean is11 = false;
-
- int[] rowBreaks = sheet.getRowBreaks();
- for (int i = 0; i < rowBreaks.length; i++) {
- int main = rowBreaks[i];
- if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
- if (main == 0) is0 = true;
- if (main == 10) is10= true;
- if (main == 11) is11 = true;
- }
-
- assertTrue("one of the breaks didnt make it", is0 && is10 && is11);
-
- sheet.removeRowBreak(11);
- assertFalse("row should be removed", sheet.isRowBroken(11));
-
- sheet.removeRowBreak(0);
- assertFalse("row should be removed", sheet.isRowBroken(0));
-
- sheet.removeRowBreak(10);
- assertFalse("row should be removed", sheet.isRowBroken(10));
-
- assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
- }
-
- /**
- * Make sure column pag breaks works properly (in-memory)
- *
- */
- public void testColPageBreaks() {
- short rowFrom = 0;
- short rowTo = (short)65535;
-
- Sheet worksheet = Sheet.createSheet();
- PageSettingsBlock sheet = worksheet.getPageSettings();
- sheet.setColumnBreak((short)0, rowFrom, rowTo);
-
- assertTrue("no col break at 0", sheet.isColumnBroken(0));
- assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
-
- sheet.setColumnBreak((short)0, rowFrom, rowTo);
-
- assertTrue("no col break at 0", sheet.isColumnBroken(0));
- assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
-
- sheet.setColumnBreak((short)1, rowFrom, rowTo);
- sheet.setColumnBreak((short)10, rowFrom, rowTo);
- sheet.setColumnBreak((short)15, rowFrom, rowTo);
-
- assertTrue("no col break at 1", sheet.isColumnBroken(1));
- assertTrue("no col break at 10", sheet.isColumnBroken(10));
- assertTrue("no col break at 15", sheet.isColumnBroken(15));
- assertEquals("4 col break available", 4, sheet.getNumColumnBreaks());
-
- boolean is10 = false;
- boolean is0 = false;
- boolean is1 = false;
- boolean is15 = false;
-
- int[] colBreaks = sheet.getColumnBreaks();
- for (int i = 0; i < colBreaks.length; i++) {
- int main = colBreaks[i];
- if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
- if (main == 0) is0 = true;
- if (main == 1) is1 = true;
- if (main == 10) is10= true;
- if (main == 15) is15 = true;
- }
-
- assertTrue("one of the breaks didnt make it", is0 && is1 && is10 && is15);
-
- sheet.removeColumnBreak(15);
- assertFalse("column break should not be there", sheet.isColumnBroken(15));
-
- sheet.removeColumnBreak(0);
- assertFalse("column break should not be there", sheet.isColumnBroken(0));
-
- sheet.removeColumnBreak(1);
- assertFalse("column break should not be there", sheet.isColumnBroken(1));
-
- sheet.removeColumnBreak(10);
- assertFalse("column break should not be there", sheet.isColumnBroken(10));
-
- assertEquals("no more breaks", 0, sheet.getNumColumnBreaks());
- }
-
- /**
- * test newly added method Sheet.getXFIndexForColAt(..)
- * works as designed.
- */
- public void testXFIndexForColumn() {
- final short TEST_IDX = 10;
- final short DEFAULT_IDX = 0xF; // 15
- short xfindex = Short.MIN_VALUE;
- Sheet sheet = Sheet.createSheet();
-
- // without ColumnInfoRecord
- xfindex = sheet.getXFIndexForColAt((short) 0);
- assertEquals(DEFAULT_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 1);
- assertEquals(DEFAULT_IDX, xfindex);
-
- ColumnInfoRecord nci = new ColumnInfoRecord();
- sheet._columnInfos.insertColumn(nci);
-
- // single column ColumnInfoRecord
- nci.setFirstColumn((short) 2);
- nci.setLastColumn((short) 2);
- nci.setXFIndex(TEST_IDX);
- xfindex = sheet.getXFIndexForColAt((short) 0);
- assertEquals(DEFAULT_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 1);
- assertEquals(DEFAULT_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 2);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 3);
- assertEquals(DEFAULT_IDX, xfindex);
-
- // ten column ColumnInfoRecord
- nci.setFirstColumn((short) 2);
- nci.setLastColumn((short) 11);
- nci.setXFIndex(TEST_IDX);
- xfindex = sheet.getXFIndexForColAt((short) 1);
- assertEquals(DEFAULT_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 2);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 6);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 11);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 12);
- assertEquals(DEFAULT_IDX, xfindex);
-
- // single column ColumnInfoRecord starting at index 0
- nci.setFirstColumn((short) 0);
- nci.setLastColumn((short) 0);
- nci.setXFIndex(TEST_IDX);
- xfindex = sheet.getXFIndexForColAt((short) 0);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 1);
- assertEquals(DEFAULT_IDX, xfindex);
-
- // ten column ColumnInfoRecord starting at index 0
- nci.setFirstColumn((short) 0);
- nci.setLastColumn((short) 9);
- nci.setXFIndex(TEST_IDX);
- xfindex = sheet.getXFIndexForColAt((short) 0);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 7);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 9);
- assertEquals(TEST_IDX, xfindex);
- xfindex = sheet.getXFIndexForColAt((short) 10);
- assertEquals(DEFAULT_IDX, xfindex);
- }
-
- private static final class SizeCheckingRecordVisitor implements RecordVisitor {
-
- private int _totalSize;
- public SizeCheckingRecordVisitor() {
- _totalSize = 0;
- }
- public void visitRecord(Record r) {
-
- int estimatedSize=r.getRecordSize();
- byte[] buf = new byte[estimatedSize];
- int serializedSize = r.serialize(0, buf);
- if (estimatedSize != serializedSize) {
- throw new AssertionFailedError("serialized size mismatch for record ("
- + r.getClass().getName() + ")");
- }
- _totalSize += estimatedSize;
- }
- public int getTotalSize() {
- return _totalSize;
- }
- }
- /**
- * Prior to bug 45066, POI would get the estimated sheet size wrong
- * when an <tt>UncalcedRecord</tt> was present.<p/>
- */
- public void testUncalcSize_bug45066() {
-
- List<Record> records = new ArrayList<Record>();
- records.add(BOFRecord.createSheetBOF());
- records.add(new UncalcedRecord());
- records.add(new DimensionsRecord());
- records.add(createWindow2Record());
- records.add(EOFRecord.instance);
- Sheet sheet = createSheet(records);
-
- // The original bug was due to different logic for collecting records for sizing and
- // serialization. The code has since been refactored into a single method for visiting
- // all contained records. Now this test is much less interesting
- SizeCheckingRecordVisitor scrv = new SizeCheckingRecordVisitor();
- sheet.visitContainedRecords(scrv, 0);
- assertEquals(90, scrv.getTotalSize());
- }
-
- /**
- * Prior to bug 45145 <tt>RowRecordsAggregate</tt> and <tt>ValueRecordsAggregate</tt> could
- * sometimes occur in reverse order. This test reproduces one of those situations and makes
- * sure that RRA comes before VRA.<br/>
- *
- * The code here represents a normal POI use case where a spreadsheet is created from scratch.
- */
- public void testRowValueAggregatesOrder_bug45145() {
-
- Sheet sheet = Sheet.createSheet();
-
- RowRecord rr = new RowRecord(5);
- sheet.addRow(rr);
-
- CellValueRecordInterface cvr = new BlankRecord();
- cvr.setColumn((short)0);
- cvr.setRow(5);
- sheet.addValueRecord(5, cvr);
-
-
- int dbCellRecordPos = getDbCellRecordPos(sheet);
- if (dbCellRecordPos == 252) {
- // The overt symptom of the bug
- // DBCELL record pos is calculated wrong if VRA comes before RRA
- throw new AssertionFailedError("Identified bug 45145");
- }
-
- if (false) {
- // make sure that RRA and VRA are in the right place
- // (Aug 2008) since the VRA is now part of the RRA, there is much less chance that
- // they could get out of order. Still, one could write serialize the sheet here,
- // and read back with EventRecordFactory to make sure...
- }
- assertEquals(242, dbCellRecordPos);
- }
-
- /**
- * @return the value calculated for the position of the first DBCELL record for this sheet.
- * That value is found on the IndexRecord.
- */
- private static int getDbCellRecordPos(Sheet sheet) {
-
- MyIndexRecordListener myIndexListener = new MyIndexRecordListener();
- sheet.visitContainedRecords(myIndexListener, 0);
- IndexRecord indexRecord = myIndexListener.getIndexRecord();
- int dbCellRecordPos = indexRecord.getDbcellAt(0);
- return dbCellRecordPos;
- }
-
- private static final class MyIndexRecordListener implements RecordVisitor {
-
- private IndexRecord _indexRecord;
- public MyIndexRecordListener() {
- // no-arg constructor
- }
- public IndexRecord getIndexRecord() {
- return _indexRecord;
- }
- public void visitRecord(Record r) {
- if (r instanceof IndexRecord) {
- if (_indexRecord != null) {
- throw new RuntimeException("too many index records");
- }
- _indexRecord = (IndexRecord)r;
- }
- }
- }
-
- /**
- * Checks for bug introduced around r682282-r683880 that caused a second GUTS records
- * which in turn got the dimensions record out of alignment
- */
- public void testGutsRecord_bug45640() {
-
- Sheet sheet = Sheet.createSheet();
- sheet.addRow(new RowRecord(0));
- sheet.addRow(new RowRecord(1));
- sheet.groupRowRange( 0, 1, true );
- sheet.toString();
- List recs = sheet.getRecords();
- int count=0;
- for(int i=0; i< recs.size(); i++) {
- if (recs.get(i) instanceof GutsRecord) {
- count++;
- }
- }
- if (count == 2) {
- throw new AssertionFailedError("Identified bug 45640");
- }
- assertEquals(1, count);
- }
-
- public void testMisplacedMergedCellsRecords_bug45699() {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex45698-22488.xls");
-
- HSSFSheet sheet = wb.getSheetAt(0);
- HSSFRow row = sheet.getRow(3);
- HSSFCell cell = row.getCell(4);
- if (cell == null) {
- throw new AssertionFailedError("Identified bug 45699");
- }
- assertEquals("Informations", cell.getRichStringCellValue().getString());
- }
- /**
- * In 3.1, setting margins between creating first row and first cell caused an exception.
- */
- public void testSetMargins_bug45717() {
- HSSFWorkbook workbook = new HSSFWorkbook();
- HSSFSheet sheet = workbook.createSheet("Vorschauliste");
- HSSFRow row = sheet.createRow(0);
-
- sheet.setMargin(HSSFSheet.LeftMargin, 0.3);
- try {
- row.createCell(0);
- } catch (IllegalStateException e) {
- if (e.getMessage().equals("Cannot create value records before row records exist")) {
- throw new AssertionFailedError("Identified bug 45717");
- }
- throw e;
- }
- }
-
- /**
- * Some apps seem to write files with missing DIMENSION records.
- * Excel(2007) tolerates this, so POI should too.
- */
- public void testMissingDims() {
-
- int rowIx = 5;
- int colIx = 6;
- NumberRecord nr = new NumberRecord();
- nr.setRow(rowIx);
- nr.setColumn((short) colIx);
- nr.setValue(3.0);
-
- List<Record> inRecs = new ArrayList<Record>();
- inRecs.add(BOFRecord.createSheetBOF());
- inRecs.add(new RowRecord(rowIx));
- inRecs.add(nr);
- inRecs.add(createWindow2Record());
- inRecs.add(EOFRecord.instance);
- Sheet sheet;
- try {
- sheet = createSheet(inRecs);
- } catch (RuntimeException e) {
- if (e.getMessage().equals("DimensionsRecord was not found")) {
- throw new AssertionFailedError("Identified bug 46206");
- }
- throw e;
- }
-
- RecordCollector rv = new RecordCollector();
- sheet.visitContainedRecords(rv, rowIx);
- Record[] outRecs = rv.getRecords();
- assertEquals(8, outRecs.length);
- DimensionsRecord dims = (DimensionsRecord) outRecs[5];
- assertEquals(rowIx, dims.getFirstRow());
- assertEquals(rowIx, dims.getLastRow());
- assertEquals(colIx, dims.getFirstCol());
- assertEquals(colIx, dims.getLastCol());
- }
+ private static Sheet createSheet(List<Record> inRecs) {
+ return Sheet.createSheet(new RecordStream(inRecs, 0));
+ }
+
+ private static Record[] getSheetRecords(Sheet s, int offset) {
+ RecordCollector rc = new RecordCollector();
+ s.visitContainedRecords(rc, offset);
+ return rc.getRecords();
+ }
+
+ public void testCreateSheet() {
+ // Check we're adding row and cell aggregates
+ List<Record> records = new ArrayList<Record>();
+ records.add(BOFRecord.createSheetBOF());
+ records.add( new DimensionsRecord() );
+ records.add(createWindow2Record());
+ records.add(EOFRecord.instance);
+ Sheet sheet = createSheet(records);
+ Record[] outRecs = getSheetRecords(sheet, 0);
+
+ int pos = 0;
+ assertTrue(outRecs[pos++] instanceof BOFRecord );
+ assertTrue(outRecs[pos++] instanceof IndexRecord );
+ assertTrue(outRecs[pos++] instanceof DimensionsRecord );
+ assertTrue(outRecs[pos++] instanceof WindowTwoRecord );
+ assertTrue(outRecs[pos++] instanceof EOFRecord );
+ }
+
+ private static Record createWindow2Record() {
+ WindowTwoRecord result = new WindowTwoRecord();
+ result.setOptions(( short ) 0x6b6);
+ result.setTopRow(( short ) 0);
+ result.setLeftCol(( short ) 0);
+ result.setHeaderColor(0x40);
+ result.setPageBreakZoom(( short ) 0);
+ result.setNormalZoom(( short ) 0);
+ return result;
+ }
+
+ private static final class MergedCellListener implements RecordVisitor {
+
+ private int _count;
+ public MergedCellListener() {
+ _count = 0;
+ }
+ public void visitRecord(Record r) {
+ if (r instanceof MergeCellsRecord) {
+ _count++;
+ }
+ }
+ public int getCount() {
+ return _count;
+ }
+ }
+
+ public void testAddMergedRegion() {
+ Sheet sheet = Sheet.createSheet();
+ int regionsToAdd = 4096;
+
+ //simple test that adds a load of regions
+ for (int n = 0; n < regionsToAdd; n++)
+ {
+ int index = sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
+ assertTrue("Merged region index expected to be " + n + " got " + index, index == n);
+ }
+
+ //test all the regions were indeed added
+ assertTrue(sheet.getNumMergedRegions() == regionsToAdd);
+
+ //test that the regions were spread out over the appropriate number of records
+ MergedCellListener mcListener = new MergedCellListener();
+ sheet.visitContainedRecords(mcListener, 0);
+ int recordsAdded = mcListener.getCount();
+ int recordsExpected = regionsToAdd/1027;
+ if ((regionsToAdd % 1027) != 0)
+ recordsExpected++;
+ assertTrue("The " + regionsToAdd + " merged regions should have been spread out over "
+ + recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
+ // Check we can't add one with invalid date
+ try {
+ sheet.addMergedRegion(10, (short)10, 9, (short)12);
+ fail("Expected an exception to occur");
+ } catch(IllegalArgumentException e) {
+ // occurs during successful test
+ assertEquals("The 'to' row (9) must not be less than the 'from' row (10)", e.getMessage());
+ }
+ try {
+ sheet.addMergedRegion(10, (short)10, 12, (short)9);
+ fail("Expected an exception to occur");
+ } catch(IllegalArgumentException e) {
+ // occurs during successful test
+ assertEquals("The 'to' col (9) must not be less than the 'from' col (10)", e.getMessage());
+ }
+ }
+
+ public void testRemoveMergedRegion() {
+ Sheet sheet = Sheet.createSheet();
+ int regionsToAdd = 4096;
+
+ for (int n = 0; n < regionsToAdd; n++) {
+ sheet.addMergedRegion(n, 0, n, 1);
+ }
+
+ int nSheetRecords = sheet.getRecords().size();
+
+ //remove a third from the beginning
+ for (int n = 0; n < regionsToAdd/3; n++)
+ {
+ sheet.removeMergedRegion(0);
+ //assert they have been deleted
+ assertEquals("Num of regions", regionsToAdd - n - 1, sheet.getNumMergedRegions());
+ }
+
+ // merge records are removed from within the MergedCellsTable,
+ // so the sheet record count should not change
+ assertEquals("Sheet Records", nSheetRecords, sheet.getRecords().size());
+ }
+
+ /**
+ * Bug: 22922 (Reported by Xuemin Guan)
+ * <p>
+ * Remove mergedregion fails when a sheet loses records after an initial CreateSheet
+ * fills up the records.
+ *
+ */
+ public void testMovingMergedRegion() {
+ List<Record> records = new ArrayList<Record>();
+
+ CellRangeAddress[] cras = {
+ new CellRangeAddress(0, 1, 0, 2),
+ };
+ MergeCellsRecord merged = new MergeCellsRecord(cras, 0, cras.length);
+ records.add(BOFRecord.createSheetBOF());
+ records.add(new DimensionsRecord());
+ records.add(new RowRecord(0));
+ records.add(new RowRecord(1));
+ records.add(new RowRecord(2));
+ records.add(createWindow2Record());
+ records.add(EOFRecord.instance);
+ records.add(merged);
+
+ Sheet sheet = createSheet(records);
+ sheet.getRecords().remove(0); // TODO - what does this line do?
+
+ //stub object to throw off list INDEX operations
+ sheet.removeMergedRegion(0);
+ assertEquals("Should be no more merged regions", 0, sheet.getNumMergedRegions());
+ }
+
+ public void testGetMergedRegionAt() {
+ //TODO
+ }
+
+ public void testGetNumMergedRegions() {
+ //TODO
+ }
+
+ /**
+ * Makes sure all rows registered for this sheet are aggregated, they were being skipped
+ *
+ */
+ public void testRowAggregation() {
+ List<Record> records = new ArrayList<Record>();
+
+ records.add(Sheet.createBOF());
+ records.add(new DimensionsRecord());
+ records.add(new RowRecord(0));
+ records.add(new RowRecord(1));
+ FormulaRecord formulaRecord = new FormulaRecord();
+ formulaRecord.setCachedResultTypeString();
+ records.add(formulaRecord);
+ records.add(new StringRecord());
+ records.add(new RowRecord(2));
+ records.add(createWindow2Record());
+ records.add(EOFRecord.instance);
+
+ Sheet sheet = createSheet(records);
+ assertNotNull("Row [2] was skipped", sheet.getRow(2));
+ }
+
+ /**
+ * Make sure page break functionality works (in memory)
+ *
+ */
+ public void testRowPageBreaks() {
+ short colFrom = 0;
+ short colTo = 255;
+
+ Sheet worksheet = Sheet.createSheet();
+ PageSettingsBlock sheet = worksheet.getPageSettings();
+ sheet.setRowBreak(0, colFrom, colTo);
+
+ assertTrue("no row break at 0", sheet.isRowBroken(0));
+ assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
+
+ sheet.setRowBreak(0, colFrom, colTo);
+ sheet.setRowBreak(0, colFrom, colTo);
+
+ assertTrue("no row break at 0", sheet.isRowBroken(0));
+ assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
+
+ sheet.setRowBreak(10, colFrom, colTo);
+ sheet.setRowBreak(11, colFrom, colTo);
+
+ assertTrue("no row break at 10", sheet.isRowBroken(10));
+ assertTrue("no row break at 11", sheet.isRowBroken(11));
+ assertEquals("3 row break available", 3, sheet.getNumRowBreaks());
+
+
+ boolean is10 = false;
+ boolean is0 = false;
+ boolean is11 = false;
+
+ int[] rowBreaks = sheet.getRowBreaks();
+ for (int i = 0; i < rowBreaks.length; i++) {
+ int main = rowBreaks[i];
+ if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
+ if (main == 0) is0 = true;
+ if (main == 10) is10= true;
+ if (main == 11) is11 = true;
+ }
+
+ assertTrue("one of the breaks didnt make it", is0 && is10 && is11);
+
+ sheet.removeRowBreak(11);
+ assertFalse("row should be removed", sheet.isRowBroken(11));
+
+ sheet.removeRowBreak(0);
+ assertFalse("row should be removed", sheet.isRowBroken(0));
+
+ sheet.removeRowBreak(10);
+ assertFalse("row should be removed", sheet.isRowBroken(10));
+
+ assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
+ }
+
+ /**
+ * Make sure column pag breaks works properly (in-memory)
+ *
+ */
+ public void testColPageBreaks() {
+ short rowFrom = 0;
+ short rowTo = (short)65535;
+
+ Sheet worksheet = Sheet.createSheet();
+ PageSettingsBlock sheet = worksheet.getPageSettings();
+ sheet.setColumnBreak((short)0, rowFrom, rowTo);
+
+ assertTrue("no col break at 0", sheet.isColumnBroken(0));
+ assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
+
+ sheet.setColumnBreak((short)0, rowFrom, rowTo);
+
+ assertTrue("no col break at 0", sheet.isColumnBroken(0));
+ assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
+
+ sheet.setColumnBreak((short)1, rowFrom, rowTo);
+ sheet.setColumnBreak((short)10, rowFrom, rowTo);
+ sheet.setColumnBreak((short)15, rowFrom, rowTo);
+
+ assertTrue("no col break at 1", sheet.isColumnBroken(1));
+ assertTrue("no col break at 10", sheet.isColumnBroken(10));
+ assertTrue("no col break at 15", sheet.isColumnBroken(15));
+ assertEquals("4 col break available", 4, sheet.getNumColumnBreaks());
+
+ boolean is10 = false;
+ boolean is0 = false;
+ boolean is1 = false;
+ boolean is15 = false;
+
+ int[] colBreaks = sheet.getColumnBreaks();
+ for (int i = 0; i < colBreaks.length; i++) {
+ int main = colBreaks[i];
+ if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
+ if (main == 0) is0 = true;
+ if (main == 1) is1 = true;
+ if (main == 10) is10= true;
+ if (main == 15) is15 = true;
+ }
+
+ assertTrue("one of the breaks didnt make it", is0 && is1 && is10 && is15);
+
+ sheet.removeColumnBreak(15);
+ assertFalse("column break should not be there", sheet.isColumnBroken(15));
+
+ sheet.removeColumnBreak(0);
+ assertFalse("column break should not be there", sheet.isColumnBroken(0));
+
+ sheet.removeColumnBreak(1);
+ assertFalse("column break should not be there", sheet.isColumnBroken(1));
+
+ sheet.removeColumnBreak(10);
+ assertFalse("column break should not be there", sheet.isColumnBroken(10));
+
+ assertEquals("no more breaks", 0, sheet.getNumColumnBreaks());
+ }
+
+ /**
+ * test newly added method Sheet.getXFIndexForColAt(..)
+ * works as designed.
+ */
+ public void testXFIndexForColumn() {
+ final short TEST_IDX = 10;
+ final short DEFAULT_IDX = 0xF; // 15
+ short xfindex = Short.MIN_VALUE;
+ Sheet sheet = Sheet.createSheet();
+
+ // without ColumnInfoRecord
+ xfindex = sheet.getXFIndexForColAt((short) 0);
+ assertEquals(DEFAULT_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 1);
+ assertEquals(DEFAULT_IDX, xfindex);
+
+ ColumnInfoRecord nci = new ColumnInfoRecord();
+ sheet._columnInfos.insertColumn(nci);
+
+ // single column ColumnInfoRecord
+ nci.setFirstColumn((short) 2);
+ nci.setLastColumn((short) 2);
+ nci.setXFIndex(TEST_IDX);
+ xfindex = sheet.getXFIndexForColAt((short) 0);
+ assertEquals(DEFAULT_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 1);
+ assertEquals(DEFAULT_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 2);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 3);
+ assertEquals(DEFAULT_IDX, xfindex);
+
+ // ten column ColumnInfoRecord
+ nci.setFirstColumn((short) 2);
+ nci.setLastColumn((short) 11);
+ nci.setXFIndex(TEST_IDX);
+ xfindex = sheet.getXFIndexForColAt((short) 1);
+ assertEquals(DEFAULT_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 2);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 6);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 11);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 12);
+ assertEquals(DEFAULT_IDX, xfindex);
+
+ // single column ColumnInfoRecord starting at index 0
+ nci.setFirstColumn((short) 0);
+ nci.setLastColumn((short) 0);
+ nci.setXFIndex(TEST_IDX);
+ xfindex = sheet.getXFIndexForColAt((short) 0);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 1);
+ assertEquals(DEFAULT_IDX, xfindex);
+
+ // ten column ColumnInfoRecord starting at index 0
+ nci.setFirstColumn((short) 0);
+ nci.setLastColumn((short) 9);
+ nci.setXFIndex(TEST_IDX);
+ xfindex = sheet.getXFIndexForColAt((short) 0);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 7);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 9);
+ assertEquals(TEST_IDX, xfindex);
+ xfindex = sheet.getXFIndexForColAt((short) 10);
+ assertEquals(DEFAULT_IDX, xfindex);
+ }
+
+ private static final class SizeCheckingRecordVisitor implements RecordVisitor {
+
+ private int _totalSize;
+ public SizeCheckingRecordVisitor() {
+ _totalSize = 0;
+ }
+ public void visitRecord(Record r) {
+
+ int estimatedSize=r.getRecordSize();
+ byte[] buf = new byte[estimatedSize];
+ int serializedSize = r.serialize(0, buf);
+ if (estimatedSize != serializedSize) {
+ throw new AssertionFailedError("serialized size mismatch for record ("
+ + r.getClass().getName() + ")");
+ }
+ _totalSize += estimatedSize;
+ }
+ public int getTotalSize() {
+ return _totalSize;
+ }
+ }
+ /**
+ * Prior to bug 45066, POI would get the estimated sheet size wrong
+ * when an <tt>UncalcedRecord</tt> was present.<p/>
+ */
+ public void testUncalcSize_bug45066() {
+
+ List<Record> records = new ArrayList<Record>();
+ records.add(BOFRecord.createSheetBOF());
+ records.add(new UncalcedRecord());
+ records.add(new DimensionsRecord());
+ records.add(createWindow2Record());
+ records.add(EOFRecord.instance);
+ Sheet sheet = createSheet(records);
+
+ // The original bug was due to different logic for collecting records for sizing and
+ // serialization. The code has since been refactored into a single method for visiting
+ // all contained records. Now this test is much less interesting
+ SizeCheckingRecordVisitor scrv = new SizeCheckingRecordVisitor();
+ sheet.visitContainedRecords(scrv, 0);
+ assertEquals(90, scrv.getTotalSize());
+ }
+
+ /**
+ * Prior to bug 45145 <tt>RowRecordsAggregate</tt> and <tt>ValueRecordsAggregate</tt> could
+ * sometimes occur in reverse order. This test reproduces one of those situations and makes
+ * sure that RRA comes before VRA.<br/>
+ *
+ * The code here represents a normal POI use case where a spreadsheet is created from scratch.
+ */
+ public void testRowValueAggregatesOrder_bug45145() {
+
+ Sheet sheet = Sheet.createSheet();
+
+ RowRecord rr = new RowRecord(5);
+ sheet.addRow(rr);
+
+ CellValueRecordInterface cvr = new BlankRecord();
+ cvr.setColumn((short)0);
+ cvr.setRow(5);
+ sheet.addValueRecord(5, cvr);
+
+
+ int dbCellRecordPos = getDbCellRecordPos(sheet);
+ if (dbCellRecordPos == 252) {
+ // The overt symptom of the bug
+ // DBCELL record pos is calculated wrong if VRA comes before RRA
+ throw new AssertionFailedError("Identified bug 45145");
+ }
+
+ if (false) {
+ // make sure that RRA and VRA are in the right place
+ // (Aug 2008) since the VRA is now part of the RRA, there is much less chance that
+ // they could get out of order. Still, one could write serialize the sheet here,
+ // and read back with EventRecordFactory to make sure...
+ }
+ assertEquals(242, dbCellRecordPos);
+ }
+
+ /**
+ * @return the value calculated for the position of the first DBCELL record for this sheet.
+ * That value is found on the IndexRecord.
+ */
+ private static int getDbCellRecordPos(Sheet sheet) {
+
+ MyIndexRecordListener myIndexListener = new MyIndexRecordListener();
+ sheet.visitContainedRecords(myIndexListener, 0);
+ IndexRecord indexRecord = myIndexListener.getIndexRecord();
+ int dbCellRecordPos = indexRecord.getDbcellAt(0);
+ return dbCellRecordPos;
+ }
+
+ private static final class MyIndexRecordListener implements RecordVisitor {
+
+ private IndexRecord _indexRecord;
+ public MyIndexRecordListener() {
+ // no-arg constructor
+ }
+ public IndexRecord getIndexRecord() {
+ return _indexRecord;
+ }
+ public void visitRecord(Record r) {
+ if (r instanceof IndexRecord) {
+ if (_indexRecord != null) {
+ throw new RuntimeException("too many index records");
+ }
+ _indexRecord = (IndexRecord)r;
+ }
+ }
+ }
+
+ /**
+ * Checks for bug introduced around r682282-r683880 that caused a second GUTS records
+ * which in turn got the dimensions record out of alignment
+ */
+ public void testGutsRecord_bug45640() {
+
+ Sheet sheet = Sheet.createSheet();
+ sheet.addRow(new RowRecord(0));
+ sheet.addRow(new RowRecord(1));
+ sheet.groupRowRange( 0, 1, true );
+ sheet.toString();
+ List<RecordBase> recs = sheet.getRecords();
+ int count=0;
+ for(int i=0; i< recs.size(); i++) {
+ if (recs.get(i) instanceof GutsRecord) {
+ count++;
+ }
+ }
+ if (count == 2) {
+ throw new AssertionFailedError("Identified bug 45640");
+ }
+ assertEquals(1, count);
+ }
+
+ public void testMisplacedMergedCellsRecords_bug45699() {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex45698-22488.xls");
+
+ HSSFSheet sheet = wb.getSheetAt(0);
+ HSSFRow row = sheet.getRow(3);
+ HSSFCell cell = row.getCell(4);
+ if (cell == null) {
+ throw new AssertionFailedError("Identified bug 45699");
+ }
+ assertEquals("Informations", cell.getRichStringCellValue().getString());
+ }
+ /**
+ * In 3.1, setting margins between creating first row and first cell caused an exception.
+ */
+ public void testSetMargins_bug45717() {
+ HSSFWorkbook workbook = new HSSFWorkbook();
+ HSSFSheet sheet = workbook.createSheet("Vorschauliste");
+ HSSFRow row = sheet.createRow(0);
+
+ sheet.setMargin(HSSFSheet.LeftMargin, 0.3);
+ try {
+ row.createCell(0);
+ } catch (IllegalStateException e) {
+ if (e.getMessage().equals("Cannot create value records before row records exist")) {
+ throw new AssertionFailedError("Identified bug 45717");
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Some apps seem to write files with missing DIMENSION records.
+ * Excel(2007) tolerates this, so POI should too.
+ */
+ public void testMissingDims() {
+
+ int rowIx = 5;
+ int colIx = 6;
+ NumberRecord nr = new NumberRecord();
+ nr.setRow(rowIx);
+ nr.setColumn((short) colIx);
+ nr.setValue(3.0);
+
+ List<Record> inRecs = new ArrayList<Record>();
+ inRecs.add(BOFRecord.createSheetBOF());
+ inRecs.add(new RowRecord(rowIx));
+ inRecs.add(nr);
+ inRecs.add(createWindow2Record());
+ inRecs.add(EOFRecord.instance);
+ Sheet sheet;
+ try {
+ sheet = createSheet(inRecs);
+ } catch (RuntimeException e) {
+ if (e.getMessage().equals("DimensionsRecord was not found")) {
+ throw new AssertionFailedError("Identified bug 46206");
+ }
+ throw e;
+ }
+
+ RecordCollector rv = new RecordCollector();
+ sheet.visitContainedRecords(rv, rowIx);
+ Record[] outRecs = rv.getRecords();
+ assertEquals(8, outRecs.length);
+ DimensionsRecord dims = (DimensionsRecord) outRecs[5];
+ assertEquals(rowIx, dims.getFirstRow());
+ assertEquals(rowIx, dims.getLastRow());
+ assertEquals(colIx, dims.getFirstCol());
+ assertEquals(colIx, dims.getLastCol());
+ }
+
+ /**
+ * Prior to the fix for bug 46547, shifting formulas would have the side-effect
+ * of creating a {@link ConditionalFormattingTable}. There was no impairment to
+ * functionality since empty record aggregates are equivalent to missing record
+ * aggregates. However, since this unnecessary creation helped expose bug 46547b,
+ * and since there is a slight performance hit the fix was made to avoid it.
+ */
+ public void testShiftFormulasAddCondFormat_bug46547() {
+ // Create a sheet with data validity (similar to bugzilla attachment id=23131).
+ Sheet sheet = Sheet.createSheet();
+
+ List<RecordBase> sheetRecs = sheet.getRecords();
+ assertEquals(22, sheetRecs.size());
+
+ FormulaShifter shifter = FormulaShifter.createForRowShift(0, 0, 0, 1);
+ sheet.updateFormulasAfterCellShift(shifter, 0);
+ if (sheetRecs.size() == 23 && sheetRecs.get(21) instanceof ConditionalFormattingTable) {
+ throw new AssertionFailedError("Identified bug 46547a");
+ }
+ assertEquals(22, sheetRecs.size());
+
+ }
+ /**
+ * Bug 46547 happened when attempting to add conditional formatting to a sheet
+ * which already had data validity constraints.
+ */
+ public void testAddCondFormatAfterDataValidation_bug46547() {
+ // Create a sheet with data validity (similar to bugzilla attachment id=23131).
+ Sheet sheet = Sheet.createSheet();
+ sheet.getOrCreateDataValidityTable();
+
+ ConditionalFormattingTable cft;
+ // attempt to add conditional formatting
+ try {
+
+ cft = sheet.getConditionalFormattingTable(); // lazy getter
+ } catch (ClassCastException e) {
+ throw new AssertionFailedError("Identified bug 46547b");
+ }
+ assertNotNull(cft);
+ }
}