From a139a17909c894baedaf0a37dcb8df59b4dffe42 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 20 Sep 2024 20:20:34 +0000 Subject: [PATCH] [github-692] D* functions are incompatible with the diamond operator. Thanks to Luk Spiewak. This closes #692 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1920817 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/formula/functions/DStarRunner.java | 76 ++++++++++++++---- .../ss/formula/functions/TestDAverage.java | 5 ++ .../poi/ss/formula/functions/TestDCount.java | 5 ++ .../poi/ss/formula/functions/TestDCountA.java | 5 ++ .../ss/formula/functions/TestDProduct.java | 5 ++ .../poi/ss/formula/functions/TestDStdev.java | 6 ++ .../poi/ss/formula/functions/TestDVar.java | 7 ++ test-data/spreadsheet/DStar.xls | Bin 33280 -> 35328 bytes 8 files changed, 92 insertions(+), 17 deletions(-) diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/DStarRunner.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/DStarRunner.java index 8007ad06e0..16b0b2c259 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/DStarRunner.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/DStarRunner.java @@ -175,7 +175,8 @@ public final class DStarRunner implements Function3Arg { largerEqualThan, smallerThan, smallerEqualThan, - equal + equal, + notEqual } /** @@ -295,7 +296,7 @@ public final class DStarRunner implements Function3Arg { } /** - * Test a value against a simple (< > <= >= = starts-with) condition string. + * Test a value against a simple (< > <= >= = <> starts-with) condition string. * * @param value The value to check. * @param condition The condition to check for. @@ -307,11 +308,19 @@ public final class DStarRunner implements Function3Arg { if(condition instanceof StringEval) { String conditionString = ((StringEval)condition).getStringValue(); - if(conditionString.startsWith("<")) { // It's a condition. String number = conditionString.substring(1); if(number.startsWith("=")) { number = number.substring(1); return testNumericCondition(value, operator.smallerEqualThan, number); + } else if (number.startsWith(">")) { + number = number.substring(1); + boolean itsANumber = isNumber(number); + if (itsANumber) { + return testNumericCondition(value, operator.notEqual, number); + } else { + return testStringCondition(value, operator.notEqual, number); + } } else { return testNumericCondition(value, operator.smallerThan, number); } @@ -330,23 +339,11 @@ public final class DStarRunner implements Function3Arg { return value instanceof BlankEval; } // Distinguish between string and number. - boolean itsANumber; - try { - Integer.parseInt(stringOrNumber); - itsANumber = true; - } catch (NumberFormatException e) { // It's not an int. - try { - Double.parseDouble(stringOrNumber); - itsANumber = true; - } catch (NumberFormatException e2) { // It's a string. - itsANumber = false; - } - } + boolean itsANumber = isNumber(stringOrNumber); if(itsANumber) { return testNumericCondition(value, operator.equal, stringOrNumber); } else { // It's a string. - String valueString = value instanceof BlankEval ? "" : OperandResolver.coerceValueToString(value); - return stringOrNumber.equalsIgnoreCase(valueString); + return testStringCondition(value, operator.equal, stringOrNumber); } } else { // It's a text starts-with condition. if(conditionString.isEmpty()) { @@ -418,6 +415,28 @@ public final class DStarRunner implements Function3Arg { return result <= 0; case equal: return result == 0; + case notEqual: + return result != 0; + } + return false; // Can not be reached. + } + + /** + * Test whether a value matches a text condition. + * @param valueEval Value to check. + * @param op Comparator to use. + * @param condition Value to check against. + * @return whether the condition holds. + */ + private static boolean testStringCondition( + ValueEval valueEval, operator op, String condition) { + + String valueString = valueEval instanceof BlankEval ? "" : OperandResolver.coerceValueToString(valueEval); + switch(op) { + case equal: + return valueString.equalsIgnoreCase(condition); + case notEqual: + return !valueString.equalsIgnoreCase(condition); } return false; // Can not be reached. } @@ -454,4 +473,27 @@ public final class DStarRunner implements Function3Arg { return e.getErrorEval(); } } + + /** + * Determines whether a given string represents a valid number. + * + * @param value The string to be checked if it represents a number. + * @return {@code true} if the string can be parsed as either an integer or + * a double; {@code false} otherwise. + */ + private static boolean isNumber(String value) { + boolean itsANumber; + try { + Integer.parseInt(value); + itsANumber = true; + } catch (NumberFormatException e) { // It's not an int. + try { + Double.parseDouble(value); + itsANumber = true; + } catch (NumberFormatException e2) { // It's a string. + itsANumber = false; + } + } + return itsANumber; + } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDAverage.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDAverage.java index 6e3028492d..a41630c4d4 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDAverage.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDAverage.java @@ -41,6 +41,8 @@ public class TestDAverage { HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DAVERAGE(A4:E10, \"Yield\", A1:B2)", 12); assertDouble(fe, cell, "DAVERAGE(A4:E10, 3, A4:E10)", 13); + assertDouble(fe, cell, "DAVERAGE(A4:E10, \"Profit\", A12:A13)", 92.6); + assertDouble(fe, cell, "DAVERAGE(A4:E10, \"Profit\", B12:C13)", 82.5); } } @@ -57,6 +59,9 @@ public class TestDAverage { addRow(sheet, 7, "Apple", 14, 15, 10, 75); addRow(sheet, 8, "Pear", 9, 8, 8, 76.8); addRow(sheet, 9, "Apple", 8, 9, 6, 45); + addRow(sheet, 10); + addRow(sheet, 11, "Tree", "Height", "Height"); + addRow(sheet, 12, "<>Apple", "<>12", "<>9"); return wb; } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCount.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCount.java index a75d1ca22c..ea4d79e5fe 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCount.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCount.java @@ -46,6 +46,8 @@ public class TestDCount { assertDouble(fe, cell, "DCOUNT(A5:E11, 2, A1:F3)", 4); assertDouble(fe, cell, "DCOUNT(A5:E11, 3, A1:F3)", 3); assertDouble(fe, cell, "DCOUNT(A5:E11, 5, A1:F3)", 3); + assertDouble(fe, cell, "DCOUNT(A5:E11, 5, A13:A14)", 2); + assertDouble(fe, cell, "DCOUNT(A5:E11, 5, B13:B14)", 3); } } @@ -63,6 +65,9 @@ public class TestDCount { addRow(sheet, 8, "Apple", 14, null, 10, 75); addRow(sheet, 9, "Pear", 9, 8, 8, "$77"); addRow(sheet, 10, "Apple", 12, 11, 6, 45); + addRow(sheet, 11); + addRow(sheet, 12, "Tree", "Height"); + addRow(sheet, 13, "<>Apple", "<>12"); return wb; } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCountA.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCountA.java index 85ee0ff510..8c531b733b 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCountA.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCountA.java @@ -45,6 +45,8 @@ public class TestDCountA { assertDouble(fe, cell, "DCOUNTA(A4:E10, \"Profit\", A1:F2)", 1); assertDouble(fe, cell, "DCOUNTA(A4:E10, \"Profit\", A1:F3)", 3); assertDouble(fe, cell, "DCOUNTA(A4:E10, \"Age\", A1:F3)", 2); + assertDouble(fe, cell, "DCOUNTA(A4:E10, \"Profit\", A12:A13)", 3); + assertDouble(fe, cell, "DCOUNTA(A4:E10, \"Age\", B12:B13)", 4); } } @@ -61,6 +63,9 @@ public class TestDCountA { addRow(sheet, 7, "Apple", 14, null, 10, 75); addRow(sheet, 8, "Pear", 9, 8, 8, "$77"); addRow(sheet, 9, "Apple", 8, 9, 6, 45); + addRow(sheet, 10); + addRow(sheet, 11, "Tree", "Height"); + addRow(sheet, 12, "<>Apple", "<>12"); return wb; } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDProduct.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDProduct.java index 80cef52f85..a654d84d65 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDProduct.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDProduct.java @@ -40,6 +40,8 @@ public class TestDProduct { HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DPRODUCT(A5:E11, \"Yield\", A1:F3)", 800, 0.0000000001); + assertDouble(fe, cell, "DPRODUCT(A5:E11, \"Yield\", A13:A14)", 720, 0.0000000001); + assertDouble(fe, cell, "DPRODUCT(A5:E11, \"Yield\", B13:C14)", 7560, 0.0000000001); } } @@ -72,6 +74,9 @@ public class TestDProduct { addRow(sheet, 8, "Apple", 14, 15, 10, 75); addRow(sheet, 9, "Pear", 9, 8, 8, 77); addRow(sheet, 10, "Apple", 8, 9, 6, 45); + addRow(sheet, 11); + addRow(sheet, 12, "Tree", "Height", "Height"); + addRow(sheet, 13, "<>Apple", "<>12", "<>9"); return wb; } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDStdev.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDStdev.java index df4eb99d5c..b19d06bb38 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDStdev.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDStdev.java @@ -40,6 +40,7 @@ public class TestDStdev { HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DSTDEV(A5:E11, \"Yield\", A1:A3)", 2.96647939483827, 0.0000000001); + assertDouble(fe, cell, "DSTDEV(A5:E11, \"Yield\", B12:C14)", 2.66458251889485, 0.0000000001); } } @@ -50,6 +51,8 @@ public class TestDStdev { HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DSTDEVP(A5:E11, \"Yield\", A1:A3)", 2.65329983228432, 0.0000000001); + assertDouble(fe, cell, "DSTDEVP(A5:E11, \"Yield\", A12:A13)", 0.816496580927726, 0.0000000001); + assertDouble(fe, cell, "DSTDEVP(A5:E11, \"Yield\", B12:C14)", 2.43241991988774, 0.0000000001); } } @@ -67,6 +70,9 @@ public class TestDStdev { addRow(sheet, 8, "Apple", 14, 15, 10, 75); addRow(sheet, 9, "Pear", 9, 8, 8, 77); addRow(sheet, 10, "Apple", 8, 9, 6, 45); + addRow(sheet, 11); + addRow(sheet, 11, "Tree", "Height", "Height"); + addRow(sheet, 12, "<>Apple", "<>12", "<>9"); return wb; } } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDVar.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDVar.java index 6c8a86bf28..46262eca04 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDVar.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDVar.java @@ -40,6 +40,8 @@ public class TestDVar { HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DVAR(A4:E10, \"Yield\", A1:A3)", 8.8, 0.0000000001); + assertDouble(fe, cell, "DVAR(A4:E10, \"Yield\", A12:A13)", 1.0, 0.0000000001); + assertDouble(fe, cell, "DVAR(A4:E10, \"Yield\", B12:C13)", 10.9166666667, 0.0000000001); } } @@ -50,6 +52,8 @@ public class TestDVar { HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(12); assertDouble(fe, cell, "DVARP(A4:E10, \"Yield\", A1:A3)", 7.04, 0.0000000001); + assertDouble(fe, cell, "DVARP(A4:E10, \"Yield\", A12:A13)", 0.666666666666667, 0.0000000001); + assertDouble(fe, cell, "DVARP(A4:E10, \"Yield\", B12:C13)", 8.1875, 0.0000000001); } } @@ -66,6 +70,9 @@ public class TestDVar { addRow(sheet, 7, "Apple", 14, 15, 10, 75); addRow(sheet, 8, "Pear", 9, 8, 8, 77); addRow(sheet, 9, "Apple", 8, 9, 6, 45); + addRow(sheet, 10); + addRow(sheet, 11, "Tree", "Height", "Height"); + addRow(sheet, 12, "<>Apple", "<>12", "<>9"); return wb; } } diff --git a/test-data/spreadsheet/DStar.xls b/test-data/spreadsheet/DStar.xls index 8a5a45d7ef399cd619b71220dfd5ac90f1e44f8b..e7c29bd63c5ba9010da487b31cfe6dfd2a302459 100644 GIT binary patch delta 9668 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 delta 7993 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 V7SDly3X7Jg4dJu^k>f`4`G2m*Ed&4n -- 2.39.5