--- a/src/java/org/apache/poi/hssf/model/RecordOrderer.java +++ a/src/java/org/apache/poi/hssf/model/RecordOrderer.java @@ -159,6 +159,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: @@ -169,7 +173,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"); --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ a/src/java/org/apache/poi/hssf/model/Sheet.java @@ -435,7 +435,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 } --- a/src/testcases/org/apache/poi/hssf/model/TestSheet.java +++ a/src/testcases/org/apache/poi/hssf/model/TestSheet.java @@ -35,15 +35,18 @@ import org.apache.poi.hssf.record.GutsRecord; import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.MergeCellsRecord; 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.ColumnInfoRecordsAggregate; +import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.hssf.record.aggregates.MergedCellsTable; import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; 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; @@ -582,4 +585,47 @@ public final class TestSheet extends TestCase { throw e; } } + + /** + * 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 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); + } + }