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:
parent
72eaea0704
commit
f26db72b4b
@ -18,13 +18,10 @@
|
||||
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/>
|
||||
@ -223,43 +220,8 @@ public final class Offset implements Function {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,37 @@ public final class TestEqualEval extends TestCase {
|
||||
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
|
||||
|
@ -17,32 +17,41 @@
|
||||
|
||||
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);
|
||||
@ -62,25 +71,25 @@ public final class TestOffset extends TestCase {
|
||||
|
||||
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));
|
||||
@ -88,5 +97,4 @@ public final class TestOffset extends TestCase {
|
||||
assertTrue(lor.isOutOfBounds(0, 16383));
|
||||
assertFalse(lor.isOutOfBounds(0, 65535));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user