Refactored OperandResolver coerce functions to convert BlankEval to 0.0

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@693289 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-09-08 21:34:45 +00:00
parent f722d1e209
commit 906bceb891
13 changed files with 66 additions and 90 deletions

View File

@ -61,9 +61,6 @@ final class ParityFunction implements FreeRefFunction {
private static int evaluateArgParity(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { private static int evaluateArgParity(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
if (ve == BlankEval.INSTANCE) {
return 0;
}
double d = OperandResolver.coerceValueToDouble(ve); double d = OperandResolver.coerceValueToDouble(ve);
if (d < 0) { if (d < 0) {
d = -d; d = -d;

View File

@ -97,9 +97,6 @@ final class YearFrac implements FreeRefFunction {
Calendar date = parseDate(strVal); Calendar date = parseDate(strVal);
return HSSFDateUtil.getExcelDate(date, false); return HSSFDateUtil.getExcelDate(date, false);
} }
if (ve instanceof BlankEval) {
return 0.0;
}
return OperandResolver.coerceValueToDouble(ve); return OperandResolver.coerceValueToDouble(ve);
} }

View File

@ -171,7 +171,8 @@ public final class OperandResolver {
/** /**
* Applies some conversion rules if the supplied value is not already an integer.<br/> * Applies some conversion rules if the supplied value is not already an integer.<br/>
* Value is first coerced to a <tt>double</tt> ( See <tt>coerceValueToDouble()</tt> ).<p/> * Value is first coerced to a <tt>double</tt> ( See <tt>coerceValueToDouble()</tt> ).
* Note - <tt>BlankEval</tt> is converted to <code>0</code>.<p/>
* *
* Excel typically converts doubles to integers by truncating toward negative infinity.<br/> * Excel typically converts doubles to integers by truncating toward negative infinity.<br/>
* The equivalent java code is:<br/> * The equivalent java code is:<br/>
@ -181,6 +182,9 @@ public final class OperandResolver {
* *
*/ */
public static int coerceValueToInt(ValueEval ev) throws EvaluationException { public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
if (ev == BlankEval.INSTANCE) {
return 0;
}
double d = coerceValueToDouble(ev); double d = coerceValueToDouble(ev);
// Note - the standard java type conversion from double to int truncates toward zero. // Note - the standard java type conversion from double to int truncates toward zero.
// but Math.floor() truncates toward negative infinity // but Math.floor() truncates toward negative infinity
@ -189,16 +193,20 @@ public final class OperandResolver {
/** /**
* Applies some conversion rules if the supplied value is not already a number. * Applies some conversion rules if the supplied value is not already a number.
* Note - <tt>BlankEval</tt> is not supported and must be handled by the caller. * Note - <tt>BlankEval</tt> is converted to {@link NumberEval#ZERO}.
* @param ev must be a <tt>NumberEval</tt>, <tt>StringEval</tt> or <tt>BoolEval</tt> * @param ev must be a {@link NumberEval}, {@link StringEval}, {@link BoolEval} or
* {@link BlankEval}
* @return actual, parsed or interpreted double value (respectively). * @return actual, parsed or interpreted double value (respectively).
* @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed * @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed
* as a double (See <tt>parseDouble()</tt> for allowable formats). * as a double (See <tt>parseDouble()</tt> for allowable formats).
* @throws RuntimeException if the supplied parameter is not <tt>NumberEval</tt>, * @throws RuntimeException if the supplied parameter is not {@link NumberEval},
* <tt>StringEval</tt> or <tt>BoolEval</tt> * {@link StringEval}, {@link BoolEval} or {@link BlankEval}
*/ */
public static double coerceValueToDouble(ValueEval ev) throws EvaluationException { public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
if (ev == BlankEval.INSTANCE) {
return 0.0;
}
if (ev instanceof NumericValueEval) { if (ev instanceof NumericValueEval) {
// this also handles booleans // this also handles booleans
return ((NumericValueEval)ev).getNumberValue(); return ((NumericValueEval)ev).getNumberValue();

View File

@ -36,9 +36,6 @@ public final class PercentEval implements OperationEval {
double d0; double d0;
try { try {
ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol); ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
if (ve instanceof BlankEval) {
return NumberEval.ZERO;
}
d0 = OperandResolver.coerceValueToDouble(ve); d0 = OperandResolver.coerceValueToDouble(ve);
} catch (EvaluationException e) { } catch (EvaluationException e) {
return e.getErrorEval(); return e.getErrorEval();

View File

@ -28,9 +28,6 @@ abstract class TwoOperandNumericOperation implements OperationEval {
} }
protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
if (ve instanceof BlankEval) {
return 0.0;
}
return OperandResolver.coerceValueToDouble(ve); return OperandResolver.coerceValueToDouble(ve);
} }

View File

@ -36,9 +36,6 @@ public final class UnaryMinusEval implements OperationEval {
double d; double d;
try { try {
ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol); ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
if (ve instanceof BlankEval) {
return NumberEval.ZERO;
}
d = OperandResolver.coerceValueToDouble(ve); d = OperandResolver.coerceValueToDouble(ve);
} catch (EvaluationException e) { } catch (EvaluationException e) {
return e.getErrorEval(); return e.getErrorEval();

View File

@ -36,9 +36,6 @@ public final class UnaryPlusEval implements OperationEval {
double d; double d;
try { try {
ValueEval ve = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
if(ve instanceof BlankEval) {
return NumberEval.ZERO;
}
if(ve instanceof StringEval) { if(ve instanceof StringEval) {
// Note - asymmetric with UnaryMinus // Note - asymmetric with UnaryMinus
// -"hello" evaluates to #VALUE! // -"hello" evaluates to #VALUE!

View File

@ -21,7 +21,6 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
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.Eval; import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
@ -58,12 +57,7 @@ public final class CalendarFieldFunction implements Function {
int val; int val;
try { try {
ValueEval ve = OperandResolver.getSingleValue(operands[0], srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(operands[0], srcCellRow, srcCellCol);
if (ve == BlankEval.INSTANCE) {
val = 0;
} else {
val = OperandResolver.coerceValueToInt(ve); val = OperandResolver.coerceValueToInt(ve);
}
} catch (EvaluationException e) { } catch (EvaluationException e) {
return e.getErrorEval(); return e.getErrorEval();
} }

View File

@ -339,9 +339,6 @@ final class LookupUtils {
throw EvaluationException.invalidRef(); throw EvaluationException.invalidRef();
} }
int oneBasedIndex; int oneBasedIndex;
if(veRowColIndexArg instanceof BlankEval) {
oneBasedIndex = 0;
} else {
if(veRowColIndexArg instanceof StringEval) { if(veRowColIndexArg instanceof StringEval) {
StringEval se = (StringEval) veRowColIndexArg; StringEval se = (StringEval) veRowColIndexArg;
String strVal = se.getStringValue(); String strVal = se.getStringValue();
@ -355,7 +352,6 @@ final class LookupUtils {
} }
// actual BoolEval values get interpreted as FALSE->0 and TRUE->1 // actual BoolEval values get interpreted as FALSE->0 and TRUE->1
oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg); oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg);
}
if (oneBasedIndex < 1) { if (oneBasedIndex < 1) {
// note this is asymmetric with the errors when the index is too large (#REF!) // note this is asymmetric with the errors when the index is too large (#REF!)
throw EvaluationException.invalidValue(); throw EvaluationException.invalidValue();

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
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.Eval; import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
@ -81,12 +80,8 @@ public class Mid implements Function {
private static int evaluateNumberArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { private static int evaluateNumberArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
if (ev instanceof BlankEval) { // Note - for start_num arg, blank/zero causes error(#VALUE!),
// Note - for start_num arg, blank causes error(#VALUE!),
// but for num_chars causes empty string to be returned. // but for num_chars causes empty string to be returned.
return 0;
}
return OperandResolver.coerceValueToInt(ev); return OperandResolver.coerceValueToInt(ev);
} }
} }

View File

@ -77,8 +77,9 @@ public final class TestExternalFunctionFormulas extends TestCase {
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb); HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.0); confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.0);
confirmCellEval(sheet, 1, 0, fe, "YEARFRAC(B2,C2)", 0.0); confirmCellEval(sheet, 1, 0, fe, "YEARFRAC(B2,C2)", 0.0);
confirmCellEval(sheet, 2, 0, fe, "IF(ISEVEN(3),1.2,1.6)", 1.6); confirmCellEval(sheet, 2, 0, fe, "YEARFRAC(B3,C3,D3)", 0.0);
confirmCellEval(sheet, 3, 0, fe, "IF(ISODD(3),1.2,1.6)", 1.2); confirmCellEval(sheet, 3, 0, fe, "IF(ISEVEN(3),1.2,1.6)", 1.6);
confirmCellEval(sheet, 4, 0, fe, "IF(ISODD(3),1.2,1.6)", 1.2);
} }
private static void confirmCellEval(HSSFSheet sheet, int rowIx, int colIx, private static void confirmCellEval(HSSFSheet sheet, int rowIx, int colIx,