]> source.dussan.org Git - poi.git/commitdiff
Refactored OperandResolver coerce functions to convert BlankEval to 0.0
authorJosh Micich <josh@apache.org>
Mon, 8 Sep 2008 21:34:45 +0000 (21:34 +0000)
committerJosh Micich <josh@apache.org>
Mon, 8 Sep 2008 21:34:45 +0000 (21:34 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@693289 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/java/org/apache/poi/hssf/record/formula/atp/ParityFunction.java
src/java/org/apache/poi/hssf/record/formula/atp/YearFrac.java
src/java/org/apache/poi/hssf/record/formula/eval/OperandResolver.java
src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java
src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java
src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java
src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java
src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java
src/java/org/apache/poi/hssf/record/formula/functions/LookupUtils.java
src/java/org/apache/poi/hssf/record/formula/functions/Mid.java
src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
src/testcases/org/apache/poi/hssf/data/externalFunctionExample.xls
src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java

index dd9ecc2af33562c026df87a44b67c3dd15400b27..f7ea76a3674124394584618142256becf0a419ed 100644 (file)
@@ -61,9 +61,6 @@ final class ParityFunction implements FreeRefFunction {
        private static int evaluateArgParity(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
                ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
                
-               if (ve == BlankEval.INSTANCE) {
-                       return 0;
-               }
                double d = OperandResolver.coerceValueToDouble(ve);
                if (d < 0) {
                        d = -d;
index ac196723e20bec767335931d13307204069a5e38..005599d45fbc73358b25e9a4ab1728e966dd59d7 100644 (file)
@@ -97,9 +97,6 @@ final class YearFrac implements FreeRefFunction {
                        Calendar date = parseDate(strVal);
                        return HSSFDateUtil.getExcelDate(date, false);
                }
-               if (ve instanceof BlankEval) {
-                       return 0.0;
-               }
                return OperandResolver.coerceValueToDouble(ve);
        }
 
index 627b26998950850e3fd38eeb3e3b460a8300a793..87f45236bfac4a5086ff7206e55962c92842091f 100755 (executable)
@@ -171,7 +171,8 @@ public final class OperandResolver {
 
        /**
         * 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/>
         * The equivalent java code is:<br/>
@@ -181,6 +182,9 @@ public final class OperandResolver {
         * 
         */
        public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
+               if (ev == BlankEval.INSTANCE) {
+                       return 0;
+               }
                double d = coerceValueToDouble(ev);
                // Note - the standard java type conversion from double to int truncates toward zero.
                // 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.
-        * Note - <tt>BlankEval</tt> is not supported and must be handled by the caller. 
-        * @param ev must be a <tt>NumberEval</tt>, <tt>StringEval</tt> or <tt>BoolEval</tt>
+        * Note - <tt>BlankEval</tt> is converted to {@link NumberEval#ZERO}. 
+        * @param ev must be a {@link NumberEval}, {@link StringEval}, {@link BoolEval} or 
+        * {@link BlankEval}
         * @return actual, parsed or interpreted double value (respectively).
         * @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed
         * as a double (See <tt>parseDouble()</tt> for allowable formats).
-        * @throws RuntimeException if the supplied parameter is not <tt>NumberEval</tt>,
-        *  <tt>StringEval</tt> or <tt>BoolEval</tt>
+        * @throws RuntimeException if the supplied parameter is not {@link NumberEval}, 
+        * {@link StringEval}, {@link BoolEval} or {@link BlankEval}
         */
        public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
 
+               if (ev == BlankEval.INSTANCE) {
+                       return 0.0;
+               }
                if (ev instanceof NumericValueEval) {
                        // this also handles booleans
                        return ((NumericValueEval)ev).getNumberValue();
index d03e4474521a08753ae02bc8df58dc6228ae1c5f..d8a579c42dcbad32deaa6caba6f2a0c891f304a1 100755 (executable)
@@ -33,12 +33,9 @@ public final class PercentEval implements OperationEval {
                if (args.length != 1) {
                        return ErrorEval.VALUE_INVALID;
                }
-       double d0;
+               double d0;
                try {
                        ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
-                       if (ve instanceof BlankEval) {
-                               return NumberEval.ZERO;
-                       }
                        d0 = OperandResolver.coerceValueToDouble(ve);
                } catch (EvaluationException e) {
                        return e.getErrorEval();
@@ -50,7 +47,7 @@ public final class PercentEval implements OperationEval {
                return 1;
        }
        public final int getType() {
-       // TODO - remove
-        throw new RuntimeException("obsolete code should not be called");
-    }
+               // TODO - remove
+               throw new RuntimeException("obsolete code should not be called");
+       }
 }
index 665ba4b4601b251f313eae812448b353e197ffe0..0f2933faea074fc7638bbca72d0e7891bd25fc70 100644 (file)
@@ -23,18 +23,15 @@ package org.apache.poi.hssf.record.formula.eval;
 abstract class TwoOperandNumericOperation implements OperationEval {
 
        public final int getType() {
-       // TODO - remove
-        throw new RuntimeException("obsolete code should not be called");
-    }
-    protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
-       ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
-               if (ve instanceof BlankEval) {
-                       return 0.0;
-               }
-               return OperandResolver.coerceValueToDouble(ve);
-    }
-    
-    public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
+               // TODO - remove
+               throw new RuntimeException("obsolete code should not be called");
+       }
+       protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
+               ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
+               return OperandResolver.coerceValueToDouble(ve);
+       }
+       
+       public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
                double result;
                try {
                        double d0 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
@@ -46,8 +43,8 @@ abstract class TwoOperandNumericOperation implements OperationEval {
                } catch (EvaluationException e) {
                        return e.getErrorEval();
                }
-       return new NumberEval(result);
-    }
+               return new NumberEval(result);
+       }
        protected abstract double evaluate(double d0, double d1) throws EvaluationException;
        public final int getNumberOfOperands() {
                return 2;
index 8174429e01b2745684bdc778868c8a7a09e767bb..780334ae8d1cc5b24eecbbfd17e6876f56d83873 100644 (file)
@@ -33,12 +33,9 @@ public final class UnaryMinusEval implements OperationEval {
                if (args.length != 1) {
                        return ErrorEval.VALUE_INVALID;
                }
-       double d;
+               double d;
                try {
                        ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
-                       if (ve instanceof BlankEval) {
-                               return NumberEval.ZERO;
-                       }
                        d = OperandResolver.coerceValueToDouble(ve);
                } catch (EvaluationException e) {
                        return e.getErrorEval();
@@ -50,7 +47,7 @@ public final class UnaryMinusEval implements OperationEval {
                return 1;
        }
        public final int getType() {
-       // TODO - remove
-        throw new RuntimeException("obsolete code should not be called");
-    }
+               // TODO - remove
+               throw new RuntimeException("obsolete code should not be called");
+       }
 }
index 66c5f6801713abf4fada69572cf97b8db5668d97..831d342866d2c74f45066ede088d9bab1e13cfde 100644 (file)
@@ -24,21 +24,18 @@ package org.apache.poi.hssf.record.formula.eval;
  */
 public final class UnaryPlusEval implements OperationEval {
 
-    public static final OperationEval instance = new UnaryPlusEval();
-    
-    private UnaryPlusEval() {
-    }
+       public static final OperationEval instance = new UnaryPlusEval();
+       
+       private UnaryPlusEval() {
+       }
 
-    public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
-       if(args.length != 1) {
-               return ErrorEval.VALUE_INVALID;
-       }
-       double d;
+       public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
+               if(args.length != 1) {
+                       return ErrorEval.VALUE_INVALID;
+               }
+               double d;
                try {
                        ValueEval ve = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
-                       if(ve instanceof BlankEval) {
-                               return NumberEval.ZERO;
-                       }
                        if(ve instanceof StringEval) {
                                // Note - asymmetric with UnaryMinus
                                // -"hello" evaluates to #VALUE!
@@ -49,14 +46,14 @@ public final class UnaryPlusEval implements OperationEval {
                } catch (EvaluationException e) {
                        return e.getErrorEval();
                }
-       return new NumberEval(+d);      
-    }
+               return new NumberEval(+d);
+       }
 
-    public int getNumberOfOperands() {
-        return 1;
-    }
+       public int getNumberOfOperands() {
+               return 1;
+       }
 
-    public int getType() {
-        throw new RuntimeException("obsolete code should not be called");
-    }
+       public int getType() {
+               throw new RuntimeException("obsolete code should not be called");
+       }
 }
index 3df7c9c5d5c28e047fb2ad99b71d726e5269e5f6..b1ea02fdc072cc809df001a2e4e9447f1670273e 100644 (file)
@@ -21,7 +21,6 @@ import java.util.Calendar;
 import java.util.Date;
 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.Eval;
 import org.apache.poi.hssf.record.formula.eval.EvaluationException;
@@ -58,12 +57,7 @@ public final class CalendarFieldFunction implements Function {
                int val;
                try {
                        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) {
                        return e.getErrorEval();
                }
index ee67ef8ec59bfe69e5dda72caeb74cf0b046b7a2..613a3d144cb8cdb843ad2129213b9e05119a4748 100644 (file)
@@ -339,23 +339,19 @@ final class LookupUtils {
                        throw EvaluationException.invalidRef();
                }
                int oneBasedIndex;
-               if(veRowColIndexArg instanceof BlankEval) {
-                       oneBasedIndex = 0;
-               } else {
-                       if(veRowColIndexArg instanceof StringEval) {
-                               StringEval se = (StringEval) veRowColIndexArg;
-                               String strVal = se.getStringValue();
-                               Double dVal = OperandResolver.parseDouble(strVal);
-                               if(dVal == null) {
-                                       // String does not resolve to a number. Raise #REF! error.
-                                       throw EvaluationException.invalidRef();
-                                       // This includes text booleans "TRUE" and "FALSE".  They are not valid.
-                               }
-                               // else - numeric value parses OK
+               if(veRowColIndexArg instanceof StringEval) {
+                       StringEval se = (StringEval) veRowColIndexArg;
+                       String strVal = se.getStringValue();
+                       Double dVal = OperandResolver.parseDouble(strVal);
+                       if(dVal == null) {
+                               // String does not resolve to a number. Raise #REF! error.
+                               throw EvaluationException.invalidRef();
+                               // This includes text booleans "TRUE" and "FALSE".  They are not valid.
                        }
-                       // actual BoolEval values get interpreted as FALSE->0 and TRUE->1
-                       oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg);
+                       // else - numeric value parses OK
                }
+               // actual BoolEval values get interpreted as FALSE->0 and TRUE->1
+               oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg);
                if (oneBasedIndex < 1) {
                        // note this is asymmetric with the errors when the index is too large (#REF!)  
                        throw EvaluationException.invalidValue();
index 7f30aa4cec62a327e0ff3de83e5e978b2428db5a..b9d679d3d364a7aecf577a98e5d3fd7f03aff488 100644 (file)
@@ -17,7 +17,6 @@
 
 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.Eval;
 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 {
                ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
-               if (ev instanceof BlankEval) {
-                       // Note - for start_num arg, blank causes error(#VALUE!),
-                       // but for num_chars causes empty string to be returned.
-                       return 0;
-               }
-
+               // Note - for start_num arg, blank/zero causes error(#VALUE!),
+               // but for num_chars causes empty string to be returned.
                return OperandResolver.coerceValueToInt(ev);
        }
 }
\ No newline at end of file
index 68a12d834fed0d5ed7268b383a765729e8c9fa0e..e4c8e42dcbc4679e72ef4d458fe7686fc19333dd 100644 (file)
Binary files a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls and b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls differ
index fc81e60a18397f0a47b49bb77c3e32309d15662d..b8dabbf718f7a524de0d14a36c1615e5c9b6b99c 100755 (executable)
Binary files a/src/testcases/org/apache/poi/hssf/data/externalFunctionExample.xls and b/src/testcases/org/apache/poi/hssf/data/externalFunctionExample.xls differ
index b3a82c6de76321aa9584589dd68c5880b48b5abf..dbfc8269daeed765ba7b57389c78642f7a2c9142 100755 (executable)
@@ -77,8 +77,9 @@ public final class TestExternalFunctionFormulas extends TestCase {
                HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
                confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.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, 3, 0, fe, "IF(ISODD(3),1.2,1.6)", 1.2);
+               confirmCellEval(sheet, 2, 0, fe, "YEARFRAC(B3,C3,D3)", 0.0);
+               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,