From f50adf36d183f2d29cf4110bcb539a9e3dc5dce1 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Fri, 12 Dec 2008 15:36:05 +0000 Subject: [PATCH] 1. fixed HSSFCell.setCellFormula to call HSSFFormulaParser.parse before any cell modifications, if it fails the cell must be left in the state prior to the invocation. 2. added @throws javadoc to HSSFRow.createCell and XSSFRow.createCell, see bug #10393 3. fixed incorrect condition type in CFRuleRecord if the rule is a formula git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@726049 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/CFRuleRecord.java | 3 +- .../apache/poi/hssf/usermodel/HSSFCell.java | 6 +- .../apache/poi/hssf/usermodel/HSSFRow.java | 4 + .../org/apache/poi/ss/usermodel/Row.java | 6 +- .../apache/poi/xssf/usermodel/XSSFRow.java | 6 +- .../poi/hssf/record/TestCFRuleRecord.java | 659 +++++++++--------- 6 files changed, 357 insertions(+), 327 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java index 13ef0956e7..986a0333bb 100644 --- a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java +++ b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java @@ -125,8 +125,6 @@ public final class CFRuleRecord extends StandardRecord { private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { this(conditionType, comparisonOperation); - field_1_condition_type = CONDITION_TYPE_CELL_VALUE_IS; - field_2_comparison_operator = comparisonOperation; field_17_formula1 = Formula.create(formula1); field_18_formula2 = Formula.create(formula2); } @@ -485,6 +483,7 @@ public final class CFRuleRecord extends StandardRecord { public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("[CFRULE]\n"); + buffer.append(" .condition_type ="+field_1_condition_type); buffer.append(" OPTION FLAGS=0x"+Integer.toHexString(getOptions())); if (false) { if (containsFontFormattingBlock()) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 4033556cb2..f97be8f8e4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -578,6 +578,7 @@ public class HSSFCell implements Cell { setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex); return; } + Ptg[] ptgs = HSSFFormulaParser.parse(formula, book); setCellType(CELL_TYPE_FORMULA, false, row, col, styleIndex); FormulaRecordAggregate agg = (FormulaRecordAggregate) record; FormulaRecord frec = agg.getFormulaRecord(); @@ -588,7 +589,6 @@ public class HSSFCell implements Cell { if (agg.getXFIndex() == (short)0) { agg.setXFIndex((short) 0x0f); } - Ptg[] ptgs = HSSFFormulaParser.parse(formula, book); agg.setParsedExpression(ptgs); } /** @@ -896,11 +896,11 @@ public class HSSFCell implements Cell { */ private void checkBounds(int cellNum) { if (cellNum > 255) { - throw new RuntimeException("You cannot have more than 255 columns "+ + throw new IllegalArgumentException("You cannot have more than 255 columns "+ "in a given row (IV). Because Excel can't handle it"); } else if (cellNum < 0) { - throw new RuntimeException("You cannot reference columns with an index of less then 0."); + throw new IllegalArgumentException("You cannot reference columns with an index of less then 0."); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java index 0ddccfb0ec..c6f9dca536 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -114,6 +114,8 @@ public final class HSSFRow implements Comparable, Row { * @param column - the column number this cell represents * * @return HSSFCell a high level representation of the created cell. + * @throws IllegalArgumentException if columnIndex < 0 or greater than 255, + * the maximum number of columns supported by the Excel binary format (.xls) */ public HSSFCell createCell(int column) { @@ -129,6 +131,8 @@ public final class HSSFRow implements Comparable, Row { * @param columnIndex - the column number this cell represents * * @return HSSFCell a high level representation of the created cell. + * @throws IllegalArgumentException if columnIndex < 0 or greater than 255, + * the maximum number of columns supported by the Excel binary format (.xls) */ public HSSFCell createCell(int columnIndex, int type) { diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java index 2cb7b8b6d5..f29a437c99 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Row.java @@ -33,7 +33,8 @@ public interface Row extends Iterable { * * @param column - the column number this cell represents * @return Cell a high level representation of the created cell. - * @throws IllegalArgumentException if columnIndex < 0 + * @throws IllegalArgumentException if columnIndex < 0 or greater than the maximum number of supported columns + * (255 for *.xls, 1048576 for *.xlsx) */ Cell createCell(int column); @@ -45,7 +46,8 @@ public interface Row extends Iterable { * * @param column - the column number this cell represents * @return Cell a high level representation of the created cell. - * @throws IllegalArgumentException if columnIndex < 0 + * @throws IllegalArgumentException if columnIndex < 0 or greate than a maximum number of supported columns + * (255 for *.xls, 1048576 for *.xlsx) */ Cell createCell(int column, int type); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index 748bc3df9d..d402eed4fc 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -134,7 +134,8 @@ public class XSSFRow implements Row, Comparable { *

* @param columnIndex - the column number this cell represents * @return Cell a high level representation of the created cell. - * @throws IllegalArgumentException if columnIndex < 0 + * @throws IllegalArgumentException if columnIndex < 0 or greater than 16384, + * the maximum number of columns supported by the SpreadsheetML format (.xlsx) */ public XSSFCell createCell(int columnIndex) { return createCell(columnIndex, Cell.CELL_TYPE_BLANK); @@ -146,7 +147,8 @@ public class XSSFRow implements Row, Comparable { * @param columnIndex - the column number this cell represents * @param type - the cell's data type * @return XSSFCell a high level representation of the created cell. - * @throws IllegalArgumentException if columnIndex < 0 or if the specified cell type is invalid + * @throws IllegalArgumentException if the specified cell type is invalid, columnIndex < 0 + * or greater than 16384, the maximum number of columns supported by the SpreadsheetML format (.xlsx) * @see Cell#CELL_TYPE_BLANK * @see Cell#CELL_TYPE_BOOLEAN * @see Cell#CELL_TYPE_ERROR diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java index 80de959809..1e54031f91 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java @@ -30,6 +30,7 @@ import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.util.LittleEndian; +import org.apache.poi.ss.formula.Formula; /** * Tests the serialization and deserialization of the TestCFRuleRecord @@ -39,322 +40,344 @@ import org.apache.poi.util.LittleEndian; */ public final class TestCFRuleRecord extends TestCase { - - public void testCreateCFRuleRecord () - { - HSSFWorkbook workbook = new HSSFWorkbook(); - CFRuleRecord record = CFRuleRecord.create(workbook, "7"); - testCFRuleRecord(record); - - // Serialize - byte [] serializedRecord = record.serialize(); - - // Strip header - byte [] recordData = new byte[serializedRecord.length-4]; - System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length); - - // Deserialize - record = new CFRuleRecord(TestcaseRecordInputStream.create(CFRuleRecord.sid, recordData)); - - // Serialize again - byte[] output = record.serialize(); - - // Compare - assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength - - for (int i = 0; i < recordData.length;i++) - { - assertEquals("CFRuleRecord doesn't match", recordData[i], output[i+4]); - } - } - - private void testCFRuleRecord(CFRuleRecord record) - { - FontFormatting fontFormatting = new FontFormatting(); - testFontFormattingAccessors(fontFormatting); - assertFalse(record.containsFontFormattingBlock()); - record.setFontFormatting(fontFormatting); - assertTrue(record.containsFontFormattingBlock()); - - BorderFormatting borderFormatting = new BorderFormatting(); - testBorderFormattingAccessors(borderFormatting); - assertFalse(record.containsBorderFormattingBlock()); - record.setBorderFormatting(borderFormatting); - assertTrue(record.containsBorderFormattingBlock()); - - assertFalse(record.isLeftBorderModified()); - record.setLeftBorderModified(true); - assertTrue(record.isLeftBorderModified()); - - assertFalse(record.isRightBorderModified()); - record.setRightBorderModified(true); - assertTrue(record.isRightBorderModified()); - - assertFalse(record.isTopBorderModified()); - record.setTopBorderModified(true); - assertTrue(record.isTopBorderModified()); - - assertFalse(record.isBottomBorderModified()); - record.setBottomBorderModified(true); - assertTrue(record.isBottomBorderModified()); - - assertFalse(record.isTopLeftBottomRightBorderModified()); - record.setTopLeftBottomRightBorderModified(true); - assertTrue(record.isTopLeftBottomRightBorderModified()); - - assertFalse(record.isBottomLeftTopRightBorderModified()); - record.setBottomLeftTopRightBorderModified(true); - assertTrue(record.isBottomLeftTopRightBorderModified()); - - - PatternFormatting patternFormatting = new PatternFormatting(); - testPatternFormattingAccessors(patternFormatting); - assertFalse(record.containsPatternFormattingBlock()); - record.setPatternFormatting(patternFormatting); - assertTrue(record.containsPatternFormattingBlock()); - - assertFalse(record.isPatternBackgroundColorModified()); - record.setPatternBackgroundColorModified(true); - assertTrue(record.isPatternBackgroundColorModified()); - - assertFalse(record.isPatternColorModified()); - record.setPatternColorModified(true); - assertTrue(record.isPatternColorModified()); - - assertFalse(record.isPatternStyleModified()); - record.setPatternStyleModified(true); - assertTrue(record.isPatternStyleModified()); - } - - private void testPatternFormattingAccessors(PatternFormatting patternFormatting) - { - patternFormatting.setFillBackgroundColor(HSSFColor.GREEN.index); - assertEquals(HSSFColor.GREEN.index,patternFormatting.getFillBackgroundColor()); - - patternFormatting.setFillForegroundColor(HSSFColor.INDIGO.index); - assertEquals(HSSFColor.INDIGO.index,patternFormatting.getFillForegroundColor()); - - patternFormatting.setFillPattern(PatternFormatting.DIAMONDS); - assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern()); - } - - private void testBorderFormattingAccessors(BorderFormatting borderFormatting) - { - borderFormatting.setBackwardDiagonalOn(false); - assertFalse(borderFormatting.isBackwardDiagonalOn()); - borderFormatting.setBackwardDiagonalOn(true); - assertTrue(borderFormatting.isBackwardDiagonalOn()); - - borderFormatting.setBorderBottom(BorderFormatting.BORDER_DOTTED); - assertEquals(BorderFormatting.BORDER_DOTTED, borderFormatting.getBorderBottom()); - - borderFormatting.setBorderDiagonal(BorderFormatting.BORDER_MEDIUM); - assertEquals(BorderFormatting.BORDER_MEDIUM, borderFormatting.getBorderDiagonal()); - - borderFormatting.setBorderLeft(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT); - assertEquals(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT, borderFormatting.getBorderLeft()); - - borderFormatting.setBorderRight(BorderFormatting.BORDER_MEDIUM_DASHED); - assertEquals(BorderFormatting.BORDER_MEDIUM_DASHED, borderFormatting.getBorderRight()); - - borderFormatting.setBorderTop(BorderFormatting.BORDER_HAIR); - assertEquals(BorderFormatting.BORDER_HAIR, borderFormatting.getBorderTop()); - - borderFormatting.setBottomBorderColor(HSSFColor.AQUA.index); - assertEquals(HSSFColor.AQUA.index, borderFormatting.getBottomBorderColor()); - - borderFormatting.setDiagonalBorderColor(HSSFColor.RED.index); - assertEquals(HSSFColor.RED.index, borderFormatting.getDiagonalBorderColor()); - - assertFalse(borderFormatting.isForwardDiagonalOn()); - borderFormatting.setForwardDiagonalOn(true); - assertTrue(borderFormatting.isForwardDiagonalOn()); - - borderFormatting.setLeftBorderColor(HSSFColor.BLACK.index); - assertEquals(HSSFColor.BLACK.index, borderFormatting.getLeftBorderColor()); - - borderFormatting.setRightBorderColor(HSSFColor.BLUE.index); - assertEquals(HSSFColor.BLUE.index, borderFormatting.getRightBorderColor()); - - borderFormatting.setTopBorderColor(HSSFColor.GOLD.index); - assertEquals(HSSFColor.GOLD.index, borderFormatting.getTopBorderColor()); - } - - - private void testFontFormattingAccessors(FontFormatting fontFormatting) - { - // Check for defaults - assertFalse(fontFormatting.isEscapementTypeModified()); - assertFalse(fontFormatting.isFontCancellationModified()); - assertFalse(fontFormatting.isFontOutlineModified()); - assertFalse(fontFormatting.isFontShadowModified()); - assertFalse(fontFormatting.isFontStyleModified()); - assertFalse(fontFormatting.isUnderlineTypeModified()); - assertFalse(fontFormatting.isFontWeightModified()); - - assertFalse(fontFormatting.isBold()); - assertFalse(fontFormatting.isItalic()); - assertFalse(fontFormatting.isOutlineOn()); - assertFalse(fontFormatting.isShadowOn()); - assertFalse(fontFormatting.isStruckout()); - - assertEquals(0, fontFormatting.getEscapementType()); - assertEquals(-1, fontFormatting.getFontColorIndex()); - assertEquals(-1, fontFormatting.getFontHeight()); - assertEquals(0, fontFormatting.getFontWeight()); - assertEquals(0, fontFormatting.getUnderlineType()); - - fontFormatting.setBold(true); - assertTrue(fontFormatting.isBold()); - fontFormatting.setBold(false); - assertFalse(fontFormatting.isBold()); - - fontFormatting.setEscapementType(FontFormatting.SS_SUB); - assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType()); - fontFormatting.setEscapementType(FontFormatting.SS_SUPER); - assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType()); - fontFormatting.setEscapementType(FontFormatting.SS_NONE); - assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType()); - - fontFormatting.setEscapementTypeModified(false); - assertFalse(fontFormatting.isEscapementTypeModified()); - fontFormatting.setEscapementTypeModified(true); - assertTrue(fontFormatting.isEscapementTypeModified()); - - fontFormatting.setFontWieghtModified(false); - assertFalse(fontFormatting.isFontWeightModified()); - fontFormatting.setFontWieghtModified(true); - assertTrue(fontFormatting.isFontWeightModified()); - - fontFormatting.setFontCancellationModified(false); - assertFalse(fontFormatting.isFontCancellationModified()); - fontFormatting.setFontCancellationModified(true); - assertTrue(fontFormatting.isFontCancellationModified()); - - fontFormatting.setFontColorIndex((short)10); - assertEquals(10,fontFormatting.getFontColorIndex()); - - fontFormatting.setFontHeight(100); - assertEquals(100,fontFormatting.getFontHeight()); - - fontFormatting.setFontOutlineModified(false); - assertFalse(fontFormatting.isFontOutlineModified()); - fontFormatting.setFontOutlineModified(true); - assertTrue(fontFormatting.isFontOutlineModified()); - - fontFormatting.setFontShadowModified(false); - assertFalse(fontFormatting.isFontShadowModified()); - fontFormatting.setFontShadowModified(true); - assertTrue(fontFormatting.isFontShadowModified()); - - fontFormatting.setFontStyleModified(false); - assertFalse(fontFormatting.isFontStyleModified()); - fontFormatting.setFontStyleModified(true); - assertTrue(fontFormatting.isFontStyleModified()); - - fontFormatting.setItalic(false); - assertFalse(fontFormatting.isItalic()); - fontFormatting.setItalic(true); - assertTrue(fontFormatting.isItalic()); - - fontFormatting.setOutline(false); - assertFalse(fontFormatting.isOutlineOn()); - fontFormatting.setOutline(true); - assertTrue(fontFormatting.isOutlineOn()); - - fontFormatting.setShadow(false); - assertFalse(fontFormatting.isShadowOn()); - fontFormatting.setShadow(true); - assertTrue(fontFormatting.isShadowOn()); - - fontFormatting.setStrikeout(false); - assertFalse(fontFormatting.isStruckout()); - fontFormatting.setStrikeout(true); - assertTrue(fontFormatting.isStruckout()); - - fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING); - assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType()); - - fontFormatting.setUnderlineTypeModified(false); - assertFalse(fontFormatting.isUnderlineTypeModified()); - fontFormatting.setUnderlineTypeModified(true); - assertTrue(fontFormatting.isUnderlineTypeModified()); - } - - public void testWrite() { - HSSFWorkbook workbook = new HSSFWorkbook(); - CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10"); - - PatternFormatting patternFormatting = new PatternFormatting(); - patternFormatting.setFillPattern(PatternFormatting.BRICKS); - rr.setPatternFormatting(patternFormatting); - - byte[] data = rr.serialize(); - assertEquals(26, data.length); - assertEquals(3, LittleEndian.getShort(data, 6)); - assertEquals(3, LittleEndian.getShort(data, 8)); - - int flags = LittleEndian.getInt(data, 10); - assertEquals("unused flags should be 111", 0x00380000, flags & 0x00380000); - assertEquals("undocumented flags should be 0000", 0, flags & 0x03C00000); // Otherwise Excel gets unhappy - // check all remaining flag bits (some are not well understood yet) - assertEquals(0x203FFFFF, flags); - } - - private static final byte[] DATA_REFN = { - // formula extracted from bugzilla 45234 att 22141 - 1, 3, - 9, // formula 1 length - 0, 0, 0, -1, -1, 63, 32, 2, -128, 0, 0, 0, 5, - // formula 1: "=B3=1" (formula is relative to B4) - 76, -1, -1, 0, -64, // tRefN(B1) - 30, 1, 0, - 11, - }; - - /** - * tRefN and tAreaN tokens must be preserved when re-serializing conditional format formulas - */ - public void testReserializeRefNTokens() { - - RecordInputStream is = TestcaseRecordInputStream.create(CFRuleRecord.sid, DATA_REFN); - CFRuleRecord rr = new CFRuleRecord(is); - Ptg[] ptgs = rr.getParsedExpression1(); - assertEquals(3, ptgs.length); - if (ptgs[0] instanceof RefPtg) { - throw new AssertionFailedError("Identified bug 45234"); - } - assertEquals(RefNPtg.class, ptgs[0].getClass()); - RefNPtg refNPtg = (RefNPtg) ptgs[0]; - assertTrue(refNPtg.isColRelative()); - assertTrue(refNPtg.isRowRelative()); - - byte[] data = rr.serialize(); - - if (!compareArrays(DATA_REFN, 0, data, 4, DATA_REFN.length)) { - fail("Did not re-serialize correctly"); - } - } - - private static boolean compareArrays(byte[] arrayA, int offsetA, byte[] arrayB, int offsetB, int length) { - - if (offsetA + length > arrayA.length) { - return false; - } - if (offsetB + length > arrayB.length) { - return false; - } - for (int i = 0; i < length; i++) { - if (arrayA[i+offsetA] != arrayB[i+offsetB]) { - return false; - } - } - return true; - } - - public static void main(String[] ignored_args) - { - System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord"); - junit.textui.TestRunner.run(TestCFRuleRecord.class); - } + public void testConstructors () + { + HSSFWorkbook workbook = new HSSFWorkbook(); + + CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7"); + assertEquals(CFRuleRecord.CONDITION_TYPE_FORMULA, rule1.getConditionType()); + assertEquals(ComparisonOperator.NO_COMPARISON, rule1.getComparisonOperation()); + assertNotNull(rule1.getParsedExpression1()); + assertSame(Ptg.EMPTY_PTG_ARRAY, rule1.getParsedExpression2()); + + CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5"); + assertEquals(CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS, rule2.getConditionType()); + assertEquals(ComparisonOperator.BETWEEN, rule2.getComparisonOperation()); + assertNotNull(rule2.getParsedExpression1()); + assertNotNull(rule2.getParsedExpression2()); + + CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.EQUAL, null, null); + assertEquals(CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS, rule3.getConditionType()); + assertEquals(ComparisonOperator.EQUAL, rule3.getComparisonOperation()); + assertSame(Ptg.EMPTY_PTG_ARRAY, rule3.getParsedExpression2()); + assertSame(Ptg.EMPTY_PTG_ARRAY, rule3.getParsedExpression2()); + } + + public void testCreateCFRuleRecord () + { + HSSFWorkbook workbook = new HSSFWorkbook(); + CFRuleRecord record = CFRuleRecord.create(workbook, "7"); + testCFRuleRecord(record); + + // Serialize + byte [] serializedRecord = record.serialize(); + + // Strip header + byte [] recordData = new byte[serializedRecord.length-4]; + System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length); + + // Deserialize + record = new CFRuleRecord(TestcaseRecordInputStream.create(CFRuleRecord.sid, recordData)); + + // Serialize again + byte[] output = record.serialize(); + + // Compare + assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength + + for (int i = 0; i < recordData.length;i++) + { + assertEquals("CFRuleRecord doesn't match", recordData[i], output[i+4]); + } + } + + private void testCFRuleRecord(CFRuleRecord record) + { + FontFormatting fontFormatting = new FontFormatting(); + testFontFormattingAccessors(fontFormatting); + assertFalse(record.containsFontFormattingBlock()); + record.setFontFormatting(fontFormatting); + assertTrue(record.containsFontFormattingBlock()); + + BorderFormatting borderFormatting = new BorderFormatting(); + testBorderFormattingAccessors(borderFormatting); + assertFalse(record.containsBorderFormattingBlock()); + record.setBorderFormatting(borderFormatting); + assertTrue(record.containsBorderFormattingBlock()); + + assertFalse(record.isLeftBorderModified()); + record.setLeftBorderModified(true); + assertTrue(record.isLeftBorderModified()); + + assertFalse(record.isRightBorderModified()); + record.setRightBorderModified(true); + assertTrue(record.isRightBorderModified()); + + assertFalse(record.isTopBorderModified()); + record.setTopBorderModified(true); + assertTrue(record.isTopBorderModified()); + + assertFalse(record.isBottomBorderModified()); + record.setBottomBorderModified(true); + assertTrue(record.isBottomBorderModified()); + + assertFalse(record.isTopLeftBottomRightBorderModified()); + record.setTopLeftBottomRightBorderModified(true); + assertTrue(record.isTopLeftBottomRightBorderModified()); + + assertFalse(record.isBottomLeftTopRightBorderModified()); + record.setBottomLeftTopRightBorderModified(true); + assertTrue(record.isBottomLeftTopRightBorderModified()); + + + PatternFormatting patternFormatting = new PatternFormatting(); + testPatternFormattingAccessors(patternFormatting); + assertFalse(record.containsPatternFormattingBlock()); + record.setPatternFormatting(patternFormatting); + assertTrue(record.containsPatternFormattingBlock()); + + assertFalse(record.isPatternBackgroundColorModified()); + record.setPatternBackgroundColorModified(true); + assertTrue(record.isPatternBackgroundColorModified()); + + assertFalse(record.isPatternColorModified()); + record.setPatternColorModified(true); + assertTrue(record.isPatternColorModified()); + + assertFalse(record.isPatternStyleModified()); + record.setPatternStyleModified(true); + assertTrue(record.isPatternStyleModified()); + } + + private void testPatternFormattingAccessors(PatternFormatting patternFormatting) + { + patternFormatting.setFillBackgroundColor(HSSFColor.GREEN.index); + assertEquals(HSSFColor.GREEN.index,patternFormatting.getFillBackgroundColor()); + + patternFormatting.setFillForegroundColor(HSSFColor.INDIGO.index); + assertEquals(HSSFColor.INDIGO.index,patternFormatting.getFillForegroundColor()); + + patternFormatting.setFillPattern(PatternFormatting.DIAMONDS); + assertEquals(PatternFormatting.DIAMONDS,patternFormatting.getFillPattern()); + } + + private void testBorderFormattingAccessors(BorderFormatting borderFormatting) + { + borderFormatting.setBackwardDiagonalOn(false); + assertFalse(borderFormatting.isBackwardDiagonalOn()); + borderFormatting.setBackwardDiagonalOn(true); + assertTrue(borderFormatting.isBackwardDiagonalOn()); + + borderFormatting.setBorderBottom(BorderFormatting.BORDER_DOTTED); + assertEquals(BorderFormatting.BORDER_DOTTED, borderFormatting.getBorderBottom()); + + borderFormatting.setBorderDiagonal(BorderFormatting.BORDER_MEDIUM); + assertEquals(BorderFormatting.BORDER_MEDIUM, borderFormatting.getBorderDiagonal()); + + borderFormatting.setBorderLeft(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT); + assertEquals(BorderFormatting.BORDER_MEDIUM_DASH_DOT_DOT, borderFormatting.getBorderLeft()); + + borderFormatting.setBorderRight(BorderFormatting.BORDER_MEDIUM_DASHED); + assertEquals(BorderFormatting.BORDER_MEDIUM_DASHED, borderFormatting.getBorderRight()); + + borderFormatting.setBorderTop(BorderFormatting.BORDER_HAIR); + assertEquals(BorderFormatting.BORDER_HAIR, borderFormatting.getBorderTop()); + + borderFormatting.setBottomBorderColor(HSSFColor.AQUA.index); + assertEquals(HSSFColor.AQUA.index, borderFormatting.getBottomBorderColor()); + + borderFormatting.setDiagonalBorderColor(HSSFColor.RED.index); + assertEquals(HSSFColor.RED.index, borderFormatting.getDiagonalBorderColor()); + + assertFalse(borderFormatting.isForwardDiagonalOn()); + borderFormatting.setForwardDiagonalOn(true); + assertTrue(borderFormatting.isForwardDiagonalOn()); + + borderFormatting.setLeftBorderColor(HSSFColor.BLACK.index); + assertEquals(HSSFColor.BLACK.index, borderFormatting.getLeftBorderColor()); + + borderFormatting.setRightBorderColor(HSSFColor.BLUE.index); + assertEquals(HSSFColor.BLUE.index, borderFormatting.getRightBorderColor()); + + borderFormatting.setTopBorderColor(HSSFColor.GOLD.index); + assertEquals(HSSFColor.GOLD.index, borderFormatting.getTopBorderColor()); + } + + + private void testFontFormattingAccessors(FontFormatting fontFormatting) + { + // Check for defaults + assertFalse(fontFormatting.isEscapementTypeModified()); + assertFalse(fontFormatting.isFontCancellationModified()); + assertFalse(fontFormatting.isFontOutlineModified()); + assertFalse(fontFormatting.isFontShadowModified()); + assertFalse(fontFormatting.isFontStyleModified()); + assertFalse(fontFormatting.isUnderlineTypeModified()); + assertFalse(fontFormatting.isFontWeightModified()); + + assertFalse(fontFormatting.isBold()); + assertFalse(fontFormatting.isItalic()); + assertFalse(fontFormatting.isOutlineOn()); + assertFalse(fontFormatting.isShadowOn()); + assertFalse(fontFormatting.isStruckout()); + + assertEquals(0, fontFormatting.getEscapementType()); + assertEquals(-1, fontFormatting.getFontColorIndex()); + assertEquals(-1, fontFormatting.getFontHeight()); + assertEquals(0, fontFormatting.getFontWeight()); + assertEquals(0, fontFormatting.getUnderlineType()); + + fontFormatting.setBold(true); + assertTrue(fontFormatting.isBold()); + fontFormatting.setBold(false); + assertFalse(fontFormatting.isBold()); + + fontFormatting.setEscapementType(FontFormatting.SS_SUB); + assertEquals(FontFormatting.SS_SUB, fontFormatting.getEscapementType()); + fontFormatting.setEscapementType(FontFormatting.SS_SUPER); + assertEquals(FontFormatting.SS_SUPER, fontFormatting.getEscapementType()); + fontFormatting.setEscapementType(FontFormatting.SS_NONE); + assertEquals(FontFormatting.SS_NONE, fontFormatting.getEscapementType()); + + fontFormatting.setEscapementTypeModified(false); + assertFalse(fontFormatting.isEscapementTypeModified()); + fontFormatting.setEscapementTypeModified(true); + assertTrue(fontFormatting.isEscapementTypeModified()); + + fontFormatting.setFontWieghtModified(false); + assertFalse(fontFormatting.isFontWeightModified()); + fontFormatting.setFontWieghtModified(true); + assertTrue(fontFormatting.isFontWeightModified()); + + fontFormatting.setFontCancellationModified(false); + assertFalse(fontFormatting.isFontCancellationModified()); + fontFormatting.setFontCancellationModified(true); + assertTrue(fontFormatting.isFontCancellationModified()); + + fontFormatting.setFontColorIndex((short)10); + assertEquals(10,fontFormatting.getFontColorIndex()); + + fontFormatting.setFontHeight(100); + assertEquals(100,fontFormatting.getFontHeight()); + + fontFormatting.setFontOutlineModified(false); + assertFalse(fontFormatting.isFontOutlineModified()); + fontFormatting.setFontOutlineModified(true); + assertTrue(fontFormatting.isFontOutlineModified()); + + fontFormatting.setFontShadowModified(false); + assertFalse(fontFormatting.isFontShadowModified()); + fontFormatting.setFontShadowModified(true); + assertTrue(fontFormatting.isFontShadowModified()); + + fontFormatting.setFontStyleModified(false); + assertFalse(fontFormatting.isFontStyleModified()); + fontFormatting.setFontStyleModified(true); + assertTrue(fontFormatting.isFontStyleModified()); + + fontFormatting.setItalic(false); + assertFalse(fontFormatting.isItalic()); + fontFormatting.setItalic(true); + assertTrue(fontFormatting.isItalic()); + + fontFormatting.setOutline(false); + assertFalse(fontFormatting.isOutlineOn()); + fontFormatting.setOutline(true); + assertTrue(fontFormatting.isOutlineOn()); + + fontFormatting.setShadow(false); + assertFalse(fontFormatting.isShadowOn()); + fontFormatting.setShadow(true); + assertTrue(fontFormatting.isShadowOn()); + + fontFormatting.setStrikeout(false); + assertFalse(fontFormatting.isStruckout()); + fontFormatting.setStrikeout(true); + assertTrue(fontFormatting.isStruckout()); + + fontFormatting.setUnderlineType(FontFormatting.U_DOUBLE_ACCOUNTING); + assertEquals(FontFormatting.U_DOUBLE_ACCOUNTING, fontFormatting.getUnderlineType()); + + fontFormatting.setUnderlineTypeModified(false); + assertFalse(fontFormatting.isUnderlineTypeModified()); + fontFormatting.setUnderlineTypeModified(true); + assertTrue(fontFormatting.isUnderlineTypeModified()); + } + + public void testWrite() { + HSSFWorkbook workbook = new HSSFWorkbook(); + CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10"); + + PatternFormatting patternFormatting = new PatternFormatting(); + patternFormatting.setFillPattern(PatternFormatting.BRICKS); + rr.setPatternFormatting(patternFormatting); + + byte[] data = rr.serialize(); + assertEquals(26, data.length); + assertEquals(3, LittleEndian.getShort(data, 6)); + assertEquals(3, LittleEndian.getShort(data, 8)); + + int flags = LittleEndian.getInt(data, 10); + assertEquals("unused flags should be 111", 0x00380000, flags & 0x00380000); + assertEquals("undocumented flags should be 0000", 0, flags & 0x03C00000); // Otherwise Excel gets unhappy + // check all remaining flag bits (some are not well understood yet) + assertEquals(0x203FFFFF, flags); + } + + private static final byte[] DATA_REFN = { + // formula extracted from bugzilla 45234 att 22141 + 1, 3, + 9, // formula 1 length + 0, 0, 0, -1, -1, 63, 32, 2, -128, 0, 0, 0, 5, + // formula 1: "=B3=1" (formula is relative to B4) + 76, -1, -1, 0, -64, // tRefN(B1) + 30, 1, 0, + 11, + }; + + /** + * tRefN and tAreaN tokens must be preserved when re-serializing conditional format formulas + */ + public void testReserializeRefNTokens() { + + RecordInputStream is = TestcaseRecordInputStream.create(CFRuleRecord.sid, DATA_REFN); + CFRuleRecord rr = new CFRuleRecord(is); + Ptg[] ptgs = rr.getParsedExpression1(); + assertEquals(3, ptgs.length); + if (ptgs[0] instanceof RefPtg) { + throw new AssertionFailedError("Identified bug 45234"); + } + assertEquals(RefNPtg.class, ptgs[0].getClass()); + RefNPtg refNPtg = (RefNPtg) ptgs[0]; + assertTrue(refNPtg.isColRelative()); + assertTrue(refNPtg.isRowRelative()); + + byte[] data = rr.serialize(); + + if (!compareArrays(DATA_REFN, 0, data, 4, DATA_REFN.length)) { + fail("Did not re-serialize correctly"); + } + } + + private static boolean compareArrays(byte[] arrayA, int offsetA, byte[] arrayB, int offsetB, int length) { + + if (offsetA + length > arrayA.length) { + return false; + } + if (offsetB + length > arrayB.length) { + return false; + } + for (int i = 0; i < length; i++) { + if (arrayA[i+offsetA] != arrayB[i+offsetB]) { + return false; + } + } + return true; + } + + public static void main(String[] ignored_args) + { + System.out.println("Testing org.apache.poi.hssf.record.CFRuleRecord"); + junit.textui.TestRunner.run(TestCFRuleRecord.class); + } } -- 2.39.5