]> source.dussan.org Git - poi.git/commitdiff
Bug 62904: Support array arguments in IF and logical IS*** functions
authorYegor Kozlov <yegor@apache.org>
Mon, 7 Jan 2019 14:34:19 +0000 (14:34 +0000)
committerYegor Kozlov <yegor@apache.org>
Mon, 7 Jan 2019 14:34:19 +0000 (14:34 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1850646 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
src/java/org/apache/poi/ss/formula/eval/RelationalOperationEval.java
src/java/org/apache/poi/ss/formula/eval/TwoOperandNumericOperation.java
src/java/org/apache/poi/ss/formula/eval/UnaryMinusEval.java
src/java/org/apache/poi/ss/formula/eval/UnaryPlusEval.java
src/java/org/apache/poi/ss/formula/functions/ArrayFunction.java
src/java/org/apache/poi/ss/formula/functions/IfFunc.java
src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java
src/testcases/org/apache/poi/ss/formula/functions/TestIFFunctionFromSpreadsheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunctionsFromSpreadsheet.java [new file with mode: 0644]
test-data/spreadsheet/IfFunctionTestCaseData.xls [new file with mode: 0644]
test-data/spreadsheet/LogicalFunctionsTestCaseData.xls [new file with mode: 0644]

index 60befcaab3ff2f754562d92b38dd52edf7708e1e..65676a61fde8a5d5571e5bfaba19be7684ce6d11 100644 (file)
@@ -56,6 +56,7 @@ import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
 import org.apache.poi.ss.formula.functions.ArrayFunction;
 import org.apache.poi.ss.formula.functions.Function;
 import org.apache.poi.ss.formula.functions.Indirect;
+import org.apache.poi.ss.util.CellRangeAddress;
 
 /**
  * This class creates <tt>OperationEval</tt> instances to help evaluate <tt>OperationPtg</tt>
@@ -138,8 +139,16 @@ final class OperationEvaluatorFactory {
                        EvaluationSheet evalSheet = ec.getWorkbook().getSheet(ec.getSheetIndex());
                        EvaluationCell evalCell = evalSheet.getCell(ec.getRowIndex(), ec.getColumnIndex());
 
-                   if (evalCell != null && (evalCell.isPartOfArrayFormulaGroup() || ec.isArraymode()) && result instanceof ArrayFunction)
-                       return ((ArrayFunction) result).evaluateArray(args, ec.getRowIndex(), ec.getColumnIndex());
+                   if (evalCell != null && result instanceof ArrayFunction) {
+                               ArrayFunction func = (ArrayFunction) result;
+                               if(evalCell.isPartOfArrayFormulaGroup()){
+                                       // array arguments must be evaluated relative to the function defining range
+                                       CellRangeAddress ca = evalCell.getArrayFormulaRange();
+                                       return func.evaluateArray(args, ca.getFirstRow(), ca.getFirstColumn());
+                               } else if (ec.isArraymode()){
+                                       return func.evaluateArray(args, ec.getRowIndex(), ec.getColumnIndex());
+                               }
+                       }
                                
                        return  result.evaluate(args, ec.getRowIndex(), ec.getColumnIndex());
                } else if (udfFunc != null){
index 594dfb45412f6770fddeae1b396b3ad83d5cb610..e91c0e109528eb53cf34df818b18470a9264a211 100644 (file)
@@ -453,15 +453,24 @@ public final class WorkbookEvaluator {
                         // nothing to skip - true param follows
                     } else {
                         int dist = attrPtg.getData();
+                        Ptg currPtg = ptgs[i+1];
                         i+= countTokensToBeSkipped(ptgs, i, dist);
                         Ptg nextPtg = ptgs[i+1];
-                        if (ptgs[i] instanceof AttrPtg && nextPtg instanceof FuncVarPtg && 
-                                // in order to verify that there is no third param, we need to check 
+
+                        if (ptgs[i] instanceof AttrPtg && nextPtg instanceof FuncVarPtg &&
+                                // in order to verify that there is no third param, we need to check
                                 // if we really have the IF next or some other FuncVarPtg as third param, e.g. ROW()/COLUMN()!
                                 ((FuncVarPtg)nextPtg).getFunctionIndex() == FunctionMetadataRegistry.FUNCTION_INDEX_IF) {
                             // this is an if statement without a false param (as opposed to MissingArgPtg as the false param)
-                            i++;
-                            stack.push(BoolEval.FALSE);
+                            //i++;
+                            stack.push(arg0);
+                            if(currPtg instanceof AreaPtg){
+                                // IF in array mode. See Bug 62904
+                                ValueEval currEval = getEvalForPtg(currPtg, ec);
+                                stack.push(currEval);
+                            } else {
+                                stack.push(BoolEval.FALSE);
+                            }
                         }
                     }
                     continue;
@@ -759,7 +768,7 @@ public final class WorkbookEvaluator {
             return evaluateNameFormula(nameRecord.getNameDefinition(), ec);
         }
 
-        throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
+        throw new RuntimeException("Don't now how to evaluate name '" + nameRecord.getNameText() + "'");
     }
     
     /**
index 0b0cc87c8f925f5d880d65b7bfbfda49e0a39ae0..f83a54de474621fce93a32a6477c8876337c8458 100644 (file)
@@ -17,7 +17,6 @@
 
 package org.apache.poi.ss.formula.eval;
 
-import org.apache.poi.ss.formula.CacheAreaEval;
 import org.apache.poi.ss.formula.functions.ArrayFunction;
 import org.apache.poi.ss.formula.functions.Fixed2ArgFunction;
 import org.apache.poi.ss.formula.functions.Function;
@@ -74,84 +73,16 @@ public abstract class RelationalOperationEval extends Fixed2ArgFunction implemen
                return BoolEval.valueOf(result);
        }
 
+       @Override
        public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
                ValueEval arg0 = args[0];
                ValueEval arg1 = args[1];
+               return evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex, (vA, vB) -> {
+                       int cmpResult = doCompare(vA, vB);
+                       boolean result = convertComparisonResult(cmpResult);
+                       return BoolEval.valueOf(result);
+               });
 
-               int w1, w2, h1, h2;
-               int a1FirstCol = 0, a1FirstRow = 0;
-               if (arg0 instanceof AreaEval) {
-                       AreaEval ae = (AreaEval)arg0;
-                       w1 = ae.getWidth();
-                       h1 = ae.getHeight();
-                       a1FirstCol = ae.getFirstColumn();
-                       a1FirstRow = ae.getFirstRow();
-               } else if (arg0 instanceof RefEval){
-                       RefEval ref = (RefEval)arg0;
-                       w1 = 1;
-                       h1 = 1;
-                       a1FirstCol = ref.getColumn();
-                       a1FirstRow = ref.getRow();
-               } else {
-                       w1 = 1;
-                       h1 = 1;
-               }
-               int a2FirstCol = 0, a2FirstRow = 0;
-               if (arg1 instanceof AreaEval) {
-                       AreaEval ae = (AreaEval)arg1;
-                       w2 = ae.getWidth();
-                       h2 = ae.getHeight();
-                       a2FirstCol = ae.getFirstColumn();
-                       a2FirstRow = ae.getFirstRow();
-               } else if (arg1 instanceof RefEval){
-                       RefEval ref = (RefEval)arg1;
-                       w2 = 1;
-                       h2 = 1;
-                       a2FirstCol = ref.getColumn();
-                       a2FirstRow = ref.getRow();
-               } else {
-                       w2 = 1;
-                       h2 = 1;
-               }
-
-               int width = Math.max(w1, w2);
-               int height = Math.max(h1, h2);
-
-               ValueEval[] vals = new ValueEval[height * width];
-
-               int idx = 0;
-               for(int i = 0; i < height; i++){
-                       for(int j = 0; j < width; j++){
-                               ValueEval vA;
-                               try {
-                                       vA = OperandResolver.getSingleValue(arg0, a1FirstRow + i, a1FirstCol + j);
-                               } catch (EvaluationException e) {
-                                       vA = e.getErrorEval();
-                               }
-                               ValueEval vB;
-                               try {
-                                       vB = OperandResolver.getSingleValue(arg1, a2FirstRow + i, a2FirstCol + j);
-                               } catch (EvaluationException e) {
-                                       vB = e.getErrorEval();
-                               }
-                               if(vA instanceof ErrorEval){
-                                       vals[idx++] = vA;
-                               } else if (vB instanceof ErrorEval) {
-                                       vals[idx++] = vB;
-                               } else {
-                                       int cmpResult = doCompare(vA, vB);
-                                       boolean result = convertComparisonResult(cmpResult);
-                                       vals[idx++] = BoolEval.valueOf(result);
-                               }
-
-                       }
-               }
-
-               if (vals.length == 1) {
-                       return vals[0];
-               }
-
-               return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals);
        }
 
        private static int doCompare(ValueEval va, ValueEval vb) {
index 7bec3599b66d2d68b36d78fabf02cefb68326046..8d15ebea9355e3ee3b0a70cea76ae1a03d66c64c 100644 (file)
@@ -37,7 +37,20 @@ public abstract class TwoOperandNumericOperation extends Fixed2ArgFunction imple
            if (args.length != 2) {
                return ErrorEval.VALUE_INVALID;
            }
-           return new ArrayEval().evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]);
+           //return new ArrayEval().evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]);
+
+               return evaluateTwoArrayArgs(args[0], args[1], srcRowIndex, srcColumnIndex,
+                               (vA, vB) -> {
+                                       try {
+                                               double d0 = OperandResolver.coerceValueToDouble(vA);
+                                               double d1 = OperandResolver.coerceValueToDouble(vB);
+                                               double result = evaluate(d0, d1);
+                                               return new NumberEval(result);
+                                       } catch (EvaluationException e){
+                                               return e.getErrorEval();
+                                       }
+                               });
+
        }
        
        public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
index 02d6d5e12c11f17705af19011a41c696764fea2f..ac1ee34118090bd86e53628b94ff1abff785a77c 100644 (file)
 
 package org.apache.poi.ss.formula.eval;
 
+import org.apache.poi.ss.formula.functions.ArrayFunction;
 import org.apache.poi.ss.formula.functions.Fixed1ArgFunction;
 import org.apache.poi.ss.formula.functions.Function;
 
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  */
-public final class UnaryMinusEval extends Fixed1ArgFunction {
+public final class UnaryMinusEval extends Fixed1ArgFunction  implements ArrayFunction {
 
        public static final Function instance = new UnaryMinusEval();
 
@@ -44,4 +45,12 @@ public final class UnaryMinusEval extends Fixed1ArgFunction {
                }
                return new NumberEval(-d);
        }
+
+       @Override
+       public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex){
+               return evaluateOneArrayArg(args, srcRowIndex, srcColumnIndex, (valA) ->
+                               evaluate(srcRowIndex, srcColumnIndex, valA)
+               );
+       }
+
 }
index 9b10f2b10c0ed935f720d0269025c21225376a7b..d5cb586a85f57d632843d132329e6060d0eb0bb9 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.ss.formula.eval;
 
+import org.apache.poi.ss.formula.functions.ArrayFunction;
 import org.apache.poi.ss.formula.functions.Fixed1ArgFunction;
 import org.apache.poi.ss.formula.functions.Function;
 
@@ -24,7 +25,7 @@ import org.apache.poi.ss.formula.functions.Function;
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  */
-public final class UnaryPlusEval extends Fixed1ArgFunction {
+public final class UnaryPlusEval extends Fixed1ArgFunction  implements ArrayFunction {
 
        public static final Function instance = new UnaryPlusEval();
 
@@ -48,4 +49,12 @@ public final class UnaryPlusEval extends Fixed1ArgFunction {
                }
                return new NumberEval(+d);
        }
+
+       @Override
+       public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex){
+               return evaluateOneArrayArg(args, srcRowIndex, srcColumnIndex, (valA) ->
+                               evaluate(srcRowIndex, srcColumnIndex, valA)
+               );
+       }
+
 }
index 3e864e5b9bea7a01f97f764ede1ff6fc99e2e62a..088d7b34fdcf603ae17c1272cc8614c44273aca2 100644 (file)
 
 package org.apache.poi.ss.formula.functions;
 
-import org.apache.poi.ss.formula.eval.BlankEval;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.MissingArgEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.CacheAreaEval;
+import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.formula.eval.*;
+
+import java.util.function.BiFunction;
 
 /**
  * @author Robert Hulbert
@@ -41,4 +42,153 @@ public interface ArrayFunction {
      */
 
     ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex);
+
+    /**
+     * Evaluate an array function with two arguments.
+     *
+     * @param arg0 the first function argument. Empty values are represented with
+     *        {@link BlankEval} or {@link MissingArgEval}, never <code>null</code>
+     * @param arg1 the first function argument. Empty values are represented with
+     *      @link BlankEval} or {@link MissingArgEval}, never <code>null</code>
+     *
+     * @param srcRowIndex row index of the cell containing the formula under evaluation
+     * @param srcColumnIndex column index of the cell containing the formula under evaluation
+     * @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>.
+     * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when
+     * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link
+     * ErrorEval#NUM_ERROR}.
+     */
+    default ValueEval evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex,
+                                           BiFunction<ValueEval, ValueEval, ValueEval> evalFunc) {
+        int w1, w2, h1, h2;
+        int a1FirstCol = 0, a1FirstRow = 0;
+        if (arg0 instanceof AreaEval) {
+            AreaEval ae = (AreaEval)arg0;
+            w1 = ae.getWidth();
+            h1 = ae.getHeight();
+            a1FirstCol = ae.getFirstColumn();
+            a1FirstRow = ae.getFirstRow();
+        } else if (arg0 instanceof RefEval){
+            RefEval ref = (RefEval)arg0;
+            w1 = 1;
+            h1 = 1;
+            a1FirstCol = ref.getColumn();
+            a1FirstRow = ref.getRow();
+        } else {
+            w1 = 1;
+            h1 = 1;
+        }
+        int a2FirstCol = 0, a2FirstRow = 0;
+        if (arg1 instanceof AreaEval) {
+            AreaEval ae = (AreaEval)arg1;
+            w2 = ae.getWidth();
+            h2 = ae.getHeight();
+            a2FirstCol = ae.getFirstColumn();
+            a2FirstRow = ae.getFirstRow();
+        } else if (arg1 instanceof RefEval){
+            RefEval ref = (RefEval)arg1;
+            w2 = 1;
+            h2 = 1;
+            a2FirstCol = ref.getColumn();
+            a2FirstRow = ref.getRow();
+        } else {
+            w2 = 1;
+            h2 = 1;
+        }
+
+        int width = Math.max(w1, w2);
+        int height = Math.max(h1, h2);
+
+        ValueEval[] vals = new ValueEval[height * width];
+
+        int idx = 0;
+        for(int i = 0; i < height; i++){
+            for(int j = 0; j < width; j++){
+                ValueEval vA;
+                try {
+                    vA = OperandResolver.getSingleValue(arg0, a1FirstRow + i, a1FirstCol + j);
+                } catch (FormulaParseException e) {
+                    vA = ErrorEval.NAME_INVALID;
+                } catch (EvaluationException e) {
+                    vA = e.getErrorEval();
+                }
+                ValueEval vB;
+                try {
+                    vB = OperandResolver.getSingleValue(arg1, a2FirstRow + i, a2FirstCol + j);
+                } catch (FormulaParseException e) {
+                    vB = ErrorEval.NAME_INVALID;
+                } catch (EvaluationException e) {
+                    vB = e.getErrorEval();
+                }
+                if(vA instanceof ErrorEval){
+                    vals[idx++] = vA;
+                } else if (vB instanceof ErrorEval) {
+                    vals[idx++] = vB;
+                } else {
+                    vals[idx++] = evalFunc.apply(vA, vB);
+                }
+
+            }
+        }
+
+        if (vals.length == 1) {
+            return vals[0];
+        }
+
+        return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals);
+    }
+
+    default ValueEval evaluateOneArrayArg(ValueEval[] args, int srcRowIndex, int srcColumnIndex,
+                                          java.util.function.Function<ValueEval, ValueEval> evalFunc){
+        ValueEval arg0 = args[0];
+
+        int w1, w2, h1, h2;
+        int a1FirstCol = 0, a1FirstRow = 0;
+        if (arg0 instanceof AreaEval) {
+            AreaEval ae = (AreaEval)arg0;
+            w1 = ae.getWidth();
+            h1 = ae.getHeight();
+            a1FirstCol = ae.getFirstColumn();
+            a1FirstRow = ae.getFirstRow();
+        } else if (arg0 instanceof RefEval){
+            RefEval ref = (RefEval)arg0;
+            w1 = 1;
+            h1 = 1;
+            a1FirstCol = ref.getColumn();
+            a1FirstRow = ref.getRow();
+        } else {
+            w1 = 1;
+            h1 = 1;
+        }
+        w2 = 1;
+        h2 = 1;
+
+        int width = Math.max(w1, w2);
+        int height = Math.max(h1, h2);
+
+        ValueEval[] vals = new ValueEval[height * width];
+
+        int idx = 0;
+        for(int i = 0; i < height; i++){
+            for(int j = 0; j < width; j++){
+                ValueEval vA;
+                try {
+                    vA = OperandResolver.getSingleValue(arg0, a1FirstRow + i, a1FirstCol + j);
+                } catch (FormulaParseException e) {
+                    vA = ErrorEval.NAME_INVALID;
+                } catch (EvaluationException e) {
+                    vA = e.getErrorEval();
+                }
+                vals[idx++] = evalFunc.apply(vA);
+            }
+        }
+
+        if (vals.length == 1) {
+            return vals[0];
+        }
+
+        return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals);
+
+    }
+
 }
index d410350b7c9770a924dc89bbecd5eabb5f964394..effff27815e295c2a6ce7ddee6d4e6965a8a8e24 100644 (file)
 
 package org.apache.poi.ss.formula.functions;
 
-import org.apache.poi.ss.formula.eval.BlankEval;
-import org.apache.poi.ss.formula.eval.BoolEval;
-import org.apache.poi.ss.formula.eval.EvaluationException;
-import org.apache.poi.ss.formula.eval.MissingArgEval;
-import org.apache.poi.ss.formula.eval.OperandResolver;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 import org.apache.poi.ss.formula.ptg.Ptg;
 import org.apache.poi.ss.formula.ptg.RefPtg;
 
@@ -36,8 +31,9 @@ import org.apache.poi.ss.formula.ptg.RefPtg;
  * See bug numbers #55324 and #55747 for the full details on this.
  * TODO Fix this...
  */
-public final class IfFunc extends Var2or3ArgFunction {
+public final class IfFunc extends Var2or3ArgFunction implements ArrayFunction {
 
+    @Override
        public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
                boolean b;
                try {
@@ -54,6 +50,7 @@ public final class IfFunc extends Var2or3ArgFunction {
                return BoolEval.FALSE;
        }
 
+    @Override
        public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
                        ValueEval arg2) {
                boolean b;
@@ -83,4 +80,29 @@ public final class IfFunc extends Var2or3ArgFunction {
                }
                return b.booleanValue();
        }
+
+
+       @Override
+       public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+               ValueEval arg0 = args[0];
+               ValueEval arg1 = args[1];
+               return evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex,
+                (vA, vB) -> {
+                                       Boolean b;
+                                       try {
+                                               b = OperandResolver.coerceValueToBoolean(vA, false);
+                                       } catch (EvaluationException e) {
+                                               return e.getErrorEval();
+                                       }
+                                       if (b != null && b) {
+                                               if (vB == MissingArgEval.instance) {
+                                                       return BlankEval.instance;
+                                               }
+                                               return vB;
+                                       }
+                                       return BoolEval.FALSE;
+                               }
+        );
+       }
+
 }
index a3fe304746f04014375471017bd543c7044e70c7..5cb7d25505a8c029c8fd4729bdb8ab7edc2657b5 100644 (file)
@@ -23,7 +23,7 @@ import org.apache.poi.ss.formula.eval.*;
  * Implementation of the various ISxxx Logical Functions, which
  *  take a single expression argument, and return True or False.
  */
-public abstract class LogicalFunction extends Fixed1ArgFunction {
+public abstract class LogicalFunction extends Fixed1ArgFunction implements ArrayFunction{
 
     @SuppressWarnings("unused")
     public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
@@ -41,6 +41,14 @@ public abstract class LogicalFunction extends Fixed1ArgFunction {
                return BoolEval.valueOf(evaluate(ve));
 
        }
+
+       @Override
+       public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex){
+               return evaluateOneArrayArg(args, srcRowIndex, srcColumnIndex, (valA) ->
+                               BoolEval.valueOf(evaluate(valA))
+               );
+       }
+
        /**
         * @param arg any {@link ValueEval}, potentially {@link BlankEval} or {@link ErrorEval}.
         */
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIFFunctionFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIFFunctionFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..cbdbfa5
--- /dev/null
@@ -0,0 +1,32 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.formula.functions;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Collection;
+
+/**
+ * Tests IF() as loaded from a test data spreadsheet.<p>
+ */
+public class TestIFFunctionFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
+    @Parameters(name="{0}")
+    public static Collection<Object[]> data() throws Exception {
+        return data(TestIFFunctionFromSpreadsheet.class, "IfFunctionTestCaseData.xls");
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunctionsFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..6432eb2
--- /dev/null
@@ -0,0 +1,32 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.formula.functions;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Collection;
+
+/**
+ * Tests for logical ISxxx functions as loaded from a test data spreadsheet.<p>
+ */
+public class TestLogicalFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
+    @Parameters(name="{0}")
+    public static Collection<Object[]> data() throws Exception {
+        return data(TestLogicalFunctionsFromSpreadsheet.class, "LogicalFunctionsTestCaseData.xls");
+    }
+}
diff --git a/test-data/spreadsheet/IfFunctionTestCaseData.xls b/test-data/spreadsheet/IfFunctionTestCaseData.xls
new file mode 100644 (file)
index 0000000..1d289d7
Binary files /dev/null and b/test-data/spreadsheet/IfFunctionTestCaseData.xls differ
diff --git a/test-data/spreadsheet/LogicalFunctionsTestCaseData.xls b/test-data/spreadsheet/LogicalFunctionsTestCaseData.xls
new file mode 100644 (file)
index 0000000..df62cde
Binary files /dev/null and b/test-data/spreadsheet/LogicalFunctionsTestCaseData.xls differ