poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cen...@apache.org
Subject svn commit: r1795963 - in /poi/trunk: src/java/org/apache/poi/ss/formula/ src/java/org/apache/poi/ss/formula/eval/ src/java/org/apache/poi/ss/formula/functions/ src/ooxml/testcases/org/apache/poi/xssf/usermodel/ src/testcases/org/apache/poi/ss/formula/...
Date Tue, 23 May 2017 21:13:02 GMT
Author: centic
Date: Tue May 23 21:13:02 2017
New Revision: 1795963

URL: http://svn.apache.org/viewvc?rev=1795963&view=rev
Log:
Bug 61063: Add a RefListEval to handle UnionPtg and implement it for Rank(), may be missing
for other functions where ArrayEval is currently handled

Added:
    poi/trunk/src/java/org/apache/poi/ss/formula/eval/RefListEval.java
    poi/trunk/test-data/spreadsheet/61063.xlsx
Modified:
    poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
    poi/trunk/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java
    poi/trunk/src/java/org/apache/poi/ss/formula/functions/Rank.java
    poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java Tue May 23 21:13:02
2017
@@ -28,19 +28,7 @@ import java.util.TreeSet;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
 import org.apache.poi.ss.formula.atp.AnalysisToolPak;
-import org.apache.poi.ss.formula.eval.BlankEval;
-import org.apache.poi.ss.formula.eval.BoolEval;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.EvaluationException;
-import org.apache.poi.ss.formula.eval.ExternalNameEval;
-import org.apache.poi.ss.formula.eval.FunctionEval;
-import org.apache.poi.ss.formula.eval.FunctionNameEval;
-import org.apache.poi.ss.formula.eval.MissingArgEval;
-import org.apache.poi.ss.formula.eval.NotImplementedException;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.formula.eval.OperandResolver;
-import org.apache.poi.ss.formula.eval.StringEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
 import org.apache.poi.ss.formula.functions.Choose;
 import org.apache.poi.ss.formula.functions.FreeRefFunction;
@@ -84,12 +72,12 @@ public final class WorkbookEvaluator {
     private final IStabilityClassifier _stabilityClassifier;
     private final AggregatingUDFFinder _udfFinder;
 
-    private boolean _ignoreMissingWorkbooks = false;
+    private boolean _ignoreMissingWorkbooks;
 
     /**
      * whether print detailed messages about the next formula evaluation
      */
-    private boolean dbgEvaluationOutputForNextEval = false;
+    private boolean dbgEvaluationOutputForNextEval;
 
     // special logger for formula evaluation output (because of possibly very large output)
     private final POILogger EVAL_LOG = POILogFactory.getLogger("POI.FormulaEval");
@@ -415,11 +403,10 @@ public final class WorkbookEvaluator {
 
         Stack<ValueEval> stack = new Stack<ValueEval>();
         for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
-
             // since we don't know how to handle these yet :(
             Ptg ptg = ptgs[i];
             if (dbgEvaluationOutputIndent > 0) {
-                EVAL_LOG.log(POILogger.INFO, dbgIndentStr + "  * ptg " + i + ": " + ptg);
+                EVAL_LOG.log(POILogger.INFO, dbgIndentStr + "  * ptg " + i + ": " + ptg +
", stack: " + stack);
             }
             if (ptg instanceof AttrPtg) {
                 AttrPtg attrPtg = (AttrPtg) ptg;
@@ -504,13 +491,17 @@ public final class WorkbookEvaluator {
                 continue;
             }
 
+            if (ptg instanceof UnionPtg) {
+                ValueEval v2 = stack.pop();
+                ValueEval v1 = stack.pop();
+                stack.push(new RefListEval(v1, v2));
+                continue;
+            }
+
             ValueEval opResult;
             if (ptg instanceof OperationPtg) {
                 OperationPtg optg = (OperationPtg) ptg;
 
-                if (optg instanceof UnionPtg) { continue; }
-
-
                 int numops = optg.getNumberOfOperands();
                 ValueEval[] ops = new ValueEval[numops];
 

Added: poi/trunk/src/java/org/apache/poi/ss/formula/eval/RefListEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/eval/RefListEval.java?rev=1795963&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/eval/RefListEval.java (added)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/eval/RefListEval.java Tue May 23 21:13:02
2017
@@ -0,0 +1,46 @@
+/* ====================================================================
+   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.eval;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handling of a list of values, e.g. the 2nd argument in RANK(A1,(B1,B2,B3),1)
+ */
+public class RefListEval implements ValueEval {
+    private final List<ValueEval> list = new ArrayList<ValueEval>();
+
+    public RefListEval(ValueEval v1, ValueEval v2) {
+        add(v1);
+        add(v2);
+    }
+
+    private void add(ValueEval v) {
+        // flatten multiple nested RefListEval
+        if(v instanceof RefListEval) {
+            list.addAll(((RefListEval)v).list);
+        } else {
+            list.add(v);
+        }
+    }
+
+    public List<ValueEval> getList() {
+        return list;
+    }
+}

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java Tue May 23
21:13:02 2017
@@ -17,16 +17,7 @@
 
 package org.apache.poi.ss.formula.functions;
 
-import org.apache.poi.ss.formula.eval.AreaEval;
-import org.apache.poi.ss.formula.eval.BlankEval;
-import org.apache.poi.ss.formula.eval.BoolEval;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.EvaluationException;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.formula.eval.OperandResolver;
-import org.apache.poi.ss.formula.eval.RefEval;
-import org.apache.poi.ss.formula.eval.StringEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 
 /**
  * Implementation of the various ISxxx Logical Functions, which
@@ -131,7 +122,7 @@ public abstract class LogicalFunction ex
 	public static final Function ISREF = new Fixed1ArgFunction() {
 
 		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
-			if (arg0 instanceof RefEval || arg0 instanceof AreaEval) {
+			if (arg0 instanceof RefEval || arg0 instanceof AreaEval || arg0 instanceof RefListEval)
{
 				return BoolEval.TRUE;
 			}
 			return BoolEval.FALSE;

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/functions/Rank.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/functions/Rank.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/functions/Rank.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/functions/Rank.java Tue May 23 21:13:02 2017
@@ -19,13 +19,7 @@
 
 package org.apache.poi.ss.formula.functions;
 
-import org.apache.poi.ss.formula.eval.AreaEval;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.EvaluationException;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.formula.eval.OperandResolver;
-import org.apache.poi.ss.formula.eval.RefEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 
 
 /**
@@ -45,51 +39,56 @@ import org.apache.poi.ss.formula.eval.Va
 public class Rank extends Var2or3ArgFunction {
 
 	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval
arg1) {
-
-		AreaEval aeRange;
-		double result;
 		try {
 			ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
-			result = OperandResolver.coerceValueToDouble(ve);
+			double result = OperandResolver.coerceValueToDouble(ve);
 			if (Double.isNaN(result) || Double.isInfinite(result)) {
 				throw new EvaluationException(ErrorEval.NUM_ERROR);
 			}
-			aeRange = convertRangeArg(arg1);
+
+			if(arg1 instanceof RefListEval) {
+			    return eval(result, ((RefListEval)arg1), true);
+            }
+
+			final AreaEval aeRange = convertRangeArg(arg1);
+
+			return eval(result, aeRange, true);
 		} catch (EvaluationException e) {
 			return e.getErrorEval();
 		}
-		return eval(srcRowIndex, srcColumnIndex, result, aeRange, true);
 	}
 
 	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval
arg1, ValueEval arg2) {
-
-		AreaEval aeRange;
-		double result;
-		boolean order=false;
 		try {
 			ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
-			result = OperandResolver.coerceValueToDouble(ve);
+			final double result = OperandResolver.coerceValueToDouble(ve);
 			if (Double.isNaN(result) || Double.isInfinite(result)) {
 				throw new EvaluationException(ErrorEval.NUM_ERROR);
 			}
-			aeRange = convertRangeArg(arg1);
-			
-			ve = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
-			int order_value = OperandResolver.coerceValueToInt(ve);
-			if(order_value==0){
-				order=true;
-			}else if(order_value==1){
-				order=false;
-			}else throw new EvaluationException(ErrorEval.NUM_ERROR);
-			
+
+            ve = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
+            int order_value = OperandResolver.coerceValueToInt(ve);
+            final boolean order;
+            if(order_value==0) {
+                order = true;
+            } else if(order_value==1) {
+                order = false;
+            } else {
+                throw new EvaluationException(ErrorEval.NUM_ERROR);
+            }
+
+            if(arg1 instanceof RefListEval) {
+                return eval(result, ((RefListEval)arg1), order);
+            }
+
+            final AreaEval aeRange = convertRangeArg(arg1);
+			return eval(result, aeRange, order);
 		} catch (EvaluationException e) {
 			return e.getErrorEval();
 		}
-		return eval(srcRowIndex, srcColumnIndex, result, aeRange, order);
 	}
 
-	private static ValueEval eval(int srcRowIndex, int srcColumnIndex, double arg0, AreaEval
aeRange, boolean descending_order) {
-		
+	private static ValueEval eval(double arg0, AreaEval aeRange, boolean descending_order) {
 		int rank = 1;
 		int height=aeRange.getHeight();
 		int width= aeRange.getWidth();
@@ -105,9 +104,30 @@ public class Rank extends Var2or3ArgFunc
 		}
 		return new NumberEval(rank);
 	}
-	
-	private static Double getValue(AreaEval aeRange, int relRowIndex, int relColIndex) {
 
+	private static ValueEval eval(double arg0, RefListEval aeRange, boolean descending_order)
{
+		int rank = 1;
+		for(ValueEval ve : aeRange.getList()) {
+            if (ve instanceof RefEval) {
+                ve = ((RefEval) ve).getInnerValueEval(((RefEval) ve).getFirstSheetIndex());
+            }
+
+            final Double value;
+            if (ve instanceof NumberEval) {
+                value = ((NumberEval)ve).getNumberValue();
+            } else {
+                continue;
+            }
+
+            if(descending_order && value>arg0 || !descending_order &&
value<arg0){
+                rank++;
+            }
+        }
+
+		return new NumberEval(rank);
+	}
+
+	private static Double getValue(AreaEval aeRange, int relRowIndex, int relColIndex) {
 		ValueEval addend = aeRange.getRelativeValue(relRowIndex, relColIndex);
 		if (addend instanceof NumberEval) {
 			return ((NumberEval)addend).getNumberValue();

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java Tue May
23 21:13:02 2017
@@ -3188,4 +3188,23 @@ public final class TestXSSFBugs extends
 
         wb.close();
     }
+
+    @Test
+    public void bug61063() throws Exception {
+        Workbook wb = XSSFTestDataSamples.openSampleWorkbook("61063.xlsx");
+
+        FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
+        Sheet s = wb.getSheetAt(0);
+
+        Row r = s.getRow(3);
+        Cell c = r.getCell(0);
+        assertEquals(CellType.FORMULA, c.getCellTypeEnum());
+        System.out.println(c.getCellFormula());
+        eval.setDebugEvaluationOutputForNextEval(true);
+        CellValue cv = eval.evaluate(c);
+        assertNotNull(cv);
+        assertEquals("Had: " + cv, 2.0, cv.getNumberValue(), 0.00001);
+
+        wb.close();
+    }
 }
\ No newline at end of file

Modified: poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java Tue May 23
21:13:02 2017
@@ -36,13 +36,7 @@ import org.apache.poi.ss.formula.eval.Er
 import org.apache.poi.ss.formula.eval.MissingArgEval;
 import org.apache.poi.ss.formula.eval.NumberEval;
 import org.apache.poi.ss.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.ptg.AreaErrPtg;
-import org.apache.poi.ss.formula.ptg.AttrPtg;
-import org.apache.poi.ss.formula.ptg.DeletedArea3DPtg;
-import org.apache.poi.ss.formula.ptg.DeletedRef3DPtg;
-import org.apache.poi.ss.formula.ptg.IntPtg;
-import org.apache.poi.ss.formula.ptg.Ptg;
-import org.apache.poi.ss.formula.ptg.RefErrorPtg;
+import org.apache.poi.ss.formula.ptg.*;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.ss.usermodel.CellValue;
@@ -112,7 +106,6 @@ public class TestWorkbookEvaluator {
      */
     @Test
     public void testMemFunc() {
-
         Ptg[] ptgs = {
             new IntPtg(42),
             AttrPtg.SUM,
@@ -122,7 +115,6 @@ public class TestWorkbookEvaluator {
         assertEquals(42, ((NumberEval)result).getNumberValue(), 0.0);
     }
 
-
     @Test
     public void testEvaluateMultipleWorkbooks() {
         HSSFWorkbook wbA = HSSFTestDataSamples.openSampleWorkbook("multibookFormulaA.xls");
@@ -227,7 +219,6 @@ public class TestWorkbookEvaluator {
     /**
      * Functions like IF, INDIRECT, INDEX, OFFSET etc can return AreaEvals which
      * should be dereferenced by the evaluator
-     * @throws IOException 
      */
     @Test
     public void testResultOutsideRange() throws IOException {
@@ -262,7 +253,6 @@ public class TestWorkbookEvaluator {
 
     /**
      * formulas with defined names.
-     * @throws IOException 
      */
     @Test
     public void testNamesInFormulas() throws IOException {
@@ -406,7 +396,7 @@ public class TestWorkbookEvaluator {
             final String formula, final CellType cellType, final String expectedFormula,
final double expectedValue) {
         testIFEqualsFormulaEvaluation_evaluate(formula, cellType, expectedFormula, expectedValue);
         testIFEqualsFormulaEvaluation_evaluateFormulaCell(formula, cellType, expectedFormula,
expectedValue);
-        testIFEqualsFormulaEvaluation_evaluateInCell(formula, cellType, expectedFormula,
expectedValue);
+        testIFEqualsFormulaEvaluation_evaluateInCell(formula, cellType, expectedValue);
         testIFEqualsFormulaEvaluation_evaluateAll(formula, cellType, expectedFormula, expectedValue);
         testIFEqualsFormulaEvaluation_evaluateAllFormulaCells(formula, cellType, expectedFormula,
expectedValue);
     }
@@ -552,7 +542,7 @@ public class TestWorkbookEvaluator {
     }
     
     private void testIFEqualsFormulaEvaluation_evaluateInCell(
-            String formula, CellType cellType, String expectedFormula, double expectedResult)
{
+            String formula, CellType cellType, double expectedResult) {
         Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
         Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
         
@@ -564,7 +554,9 @@ public class TestWorkbookEvaluator {
         try {
             D1.getCellFormula();
             fail("cell formula should be overwritten with formula result");
-        } catch (final IllegalStateException expected) { }
+        } catch (final IllegalStateException expected) {
+            // expected here
+        }
         assertEquals(CellType.NUMERIC, D1.getCellTypeEnum());
         assertEquals(expectedResult, D1.getNumericCellValue(), EPSILON);
         

Modified: poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java?rev=1795963&r1=1795962&r2=1795963&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestTFunc.java Tue May 23
21:13:02 2017
@@ -19,13 +19,7 @@ package org.apache.poi.ss.formula.functi
 
 import junit.framework.TestCase;
 
-import org.apache.poi.ss.formula.eval.AreaEval;
-import org.apache.poi.ss.formula.eval.BlankEval;
-import org.apache.poi.ss.formula.eval.BoolEval;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.formula.eval.StringEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 
 /**
  * Test cases for Excel function T()
@@ -43,6 +37,7 @@ public final class TestTFunc extends Tes
 		assertNotNull("result may never be null", result);
 		return result;
 	}
+
 	/**
 	 * Simulates call: T(A1)
 	 * where cell A1 has the specified innerValue
@@ -60,7 +55,6 @@ public final class TestTFunc extends Tes
 	}
 
 	public void testTextValues() {
-
 		confirmText("abc");
 		confirmText("");
 		confirmText(" ");
@@ -121,8 +115,7 @@ public final class TestTFunc extends Tes
 		};
 		AreaEval ae = EvalFactory.createAreaEval("C10:D11", areaValues);
 
-		ValueEval ve;
-		ve = invokeT(ae);
+		ValueEval ve = invokeT(ae);
 		confirmString(ve, "abc");
 
 		areaValues[0] = new NumberEval(5.0);

Added: poi/trunk/test-data/spreadsheet/61063.xlsx
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/61063.xlsx?rev=1795963&view=auto
==============================================================================
Binary files poi/trunk/test-data/spreadsheet/61063.xlsx (added) and poi/trunk/test-data/spreadsheet/61063.xlsx
Tue May 23 21:13:02 2017 differ



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message