Refactored some code in OFFSET implementation. Added test cases showing comparisons with BoolEval.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@888555 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-12-08 20:08:59 +00:00
parent 72eaea0704
commit f26db72b4b
3 changed files with 53 additions and 52 deletions

View File

@ -18,13 +18,10 @@
package org.apache.poi.hssf.record.formula.functions; 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.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.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; 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.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval; 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; import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* Implementation for Excel function OFFSET()<p/> * Implementation for Excel function OFFSET()<p/>
@ -223,43 +220,8 @@ public final class Offset implements Function {
/** /**
* OFFSET's numeric arguments (2..5) have similar processing rules * OFFSET's numeric arguments (2..5) have similar processing rules
*/ */
private static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException { 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 {
ValueEval ve = OperandResolver.getSingleValue(eval, srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(eval, srcCellRow, srcCellCol);
return OperandResolver.coerceValueToInt(ve);
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() + ")");
} }
} }

View File

@ -95,6 +95,37 @@ public final class TestEqualEval extends TestCase {
return be.getBooleanValue(); 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. * 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 * Excel evaluates "-A1=0" to TRUE, not because it thinks -0.0==0.0

View File

@ -17,8 +17,12 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; 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; import org.apache.poi.hssf.record.formula.functions.Offset.LinearOffsetRange;
/** /**
@ -28,13 +32,18 @@ import org.apache.poi.hssf.record.formula.functions.Offset.LinearOffsetRange;
*/ */
public final class TestOffset extends TestCase { public final class TestOffset extends TestCase {
private static void confirmDoubleConvert(double doubleVal, int expected) { 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(). * Excel's double to int conversion (for function 'OFFSET()') behaves more like Math.floor().
* Note - negative values are not symmetrical * Note - negative values are not symmetrical
* Fractional values are silently truncated.
* Truncation is toward negative infinity.
*/ */
public void testDoubleConversion() { public void testDoubleConversion() {
@ -88,5 +97,4 @@ public final class TestOffset extends TestCase {
assertTrue(lor.isOutOfBounds(0, 16383)); assertTrue(lor.isOutOfBounds(0, 16383));
assertFalse(lor.isOutOfBounds(0, 65535)); assertFalse(lor.isOutOfBounds(0, 65535));
} }
} }