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;
|
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() + ")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user