package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
-import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* Implementation for Excel function OFFSET()<p/>
/**
* OFFSET's numeric arguments (2..5) have similar processing rules
*/
- private static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
-
- double d = evaluateDoubleArg(eval, srcCellRow, srcCellCol);
- return convertDoubleToInt(d);
- }
-
- /**
- * Fractional values are silently truncated by Excel.
- * Truncation is toward negative infinity.
- */
- /* package */ static int convertDoubleToInt(double d) {
- // Note - the standard java type conversion from double to int truncates toward zero.
- // but Math.floor() truncates toward negative infinity
- return (int)Math.floor(d);
- }
-
- private static double evaluateDoubleArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
+ static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcCellRow, srcCellCol);
-
- if (ve instanceof NumericValueEval) {
- return ((NumericValueEval) ve).getNumberValue();
- }
- if (ve instanceof StringEval) {
- StringEval se = (StringEval) ve;
- Double d = OperandResolver.parseDouble(se.getStringValue());
- if(d == null) {
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- return d.doubleValue();
- }
- if (ve instanceof BoolEval) {
- // in the context of OFFSET, booleans resolve to 0 and 1.
- if(((BoolEval) ve).getBooleanValue()) {
- return 1;
- }
- return 0;
- }
- throw new RuntimeException("Unexpected eval type (" + ve.getClass().getName() + ")");
+ return OperandResolver.coerceValueToInt(ve);
}
}
return be.getBooleanValue();
}
+ public void testBooleanCompares() {
+ confirmCompares(BoolEval.TRUE, new StringEval("TRUE"), +1);
+ confirmCompares(BoolEval.TRUE, new NumberEval(1.0), +1);
+ confirmCompares(BoolEval.TRUE, BoolEval.TRUE, 0);
+ confirmCompares(BoolEval.TRUE, BoolEval.FALSE, +1);
+
+ confirmCompares(BoolEval.FALSE, new StringEval("TRUE"), +1);
+ confirmCompares(BoolEval.FALSE, new StringEval("FALSE"), +1);
+ confirmCompares(BoolEval.FALSE, new NumberEval(0.0), +1);
+ confirmCompares(BoolEval.FALSE, BoolEval.FALSE, 0);
+ }
+ private static void confirmCompares(ValueEval a, ValueEval b, int expRes) {
+ confirm(a, b, expRes>0, EI.GreaterThan);
+ confirm(a, b, expRes>=0, EI.GreaterEqual);
+ confirm(a, b, expRes==0, EI.Equal);
+ confirm(a, b, expRes<=0, EI.LessEqual);
+ confirm(a, b, expRes<0, EI.LessThan);
+
+ confirm(b, a, expRes<0, EI.GreaterThan);
+ confirm(b, a, expRes<=0, EI.GreaterEqual);
+ confirm(b, a, expRes==0, EI.Equal);
+ confirm(b, a, expRes>=0, EI.LessEqual);
+ confirm(b, a, expRes>0, EI.LessThan);
+ }
+ private static void confirm(ValueEval a, ValueEval b, boolean expectedResult, Function cmpOp) {
+ ValueEval[] args = { a, b, };
+ ValueEval result = evaluate(cmpOp, args, 10, 20);
+ assertEquals(BoolEval.class, result.getClass());
+ assertEquals(expectedResult, ((BoolEval) result).getBooleanValue());
+ }
+
/**
* Bug 47198 involved a formula "-A1=0" where cell A1 was 0.0.
* Excel evaluates "-A1=0" to TRUE, not because it thinks -0.0==0.0
package org.apache.poi.hssf.record.formula.functions;
+import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
+import org.apache.poi.hssf.record.formula.eval.EvaluationException;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.Offset.LinearOffsetRange;
/**
* Tests for OFFSET function implementation
- *
+ *
* @author Josh Micich
*/
public final class TestOffset extends TestCase {
-
private static void confirmDoubleConvert(double doubleVal, int expected) {
- assertEquals(expected, Offset.convertDoubleToInt(doubleVal));
+ try {
+ assertEquals(expected, Offset.evaluateIntArg(new NumberEval(doubleVal), -1, -1));
+ } catch (EvaluationException e) {
+ throw new AssertionFailedError("Unexpected error '" + e.getErrorEval().toString() + "'.");
+ }
}
/**
* Excel's double to int conversion (for function 'OFFSET()') behaves more like Math.floor().
* Note - negative values are not symmetrical
+ * Fractional values are silently truncated.
+ * Truncation is toward negative infinity.
*/
public void testDoubleConversion() {
-
+
confirmDoubleConvert(100.09, 100);
confirmDoubleConvert(100.01, 100);
confirmDoubleConvert(100.00, 100);
confirmDoubleConvert(99.99, 99);
-
+
confirmDoubleConvert(+2.01, +2);
confirmDoubleConvert(+2.00, +2);
confirmDoubleConvert(+1.99, +1);
public void testLinearOffsetRange() {
LinearOffsetRange lor;
-
+
lor = new LinearOffsetRange(3, 2);
assertEquals(3, lor.getFirstIndex());
assertEquals(4, lor.getLastIndex());
lor = lor.normaliseAndTranslate(0); // expected no change
assertEquals(3, lor.getFirstIndex());
assertEquals(4, lor.getLastIndex());
-
+
lor = lor.normaliseAndTranslate(5);
assertEquals(8, lor.getFirstIndex());
assertEquals(9, lor.getLastIndex());
-
+
// negative length
-
+
lor = new LinearOffsetRange(6, -4).normaliseAndTranslate(0);
assertEquals(3, lor.getFirstIndex());
assertEquals(6, lor.getLastIndex());
-
-
+
+
// bounds checking
lor = new LinearOffsetRange(0, 100);
assertFalse(lor.isOutOfBounds(0, 16383));
assertTrue(lor.isOutOfBounds(0, 16383));
assertFalse(lor.isOutOfBounds(0, 65535));
}
-
}