aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Stadler <centic@apache.org>2015-10-14 14:31:04 +0000
committerDominik Stadler <centic@apache.org>2015-10-14 14:31:04 +0000
commitb4c0a91af85c5d0a4bd63105e7ed7d8daefeb2d4 (patch)
tree353210855f9aad6c83a53154663a12e47c0a9467
parentf678783d466471a6472914038b4e83518879abcb (diff)
downloadpoi-b4c0a91af85c5d0a4bd63105e7ed7d8daefeb2d4.tar.gz
poi-b4c0a91af85c5d0a4bd63105e7ed7d8daefeb2d4.zip
Bug 58341: fix some edge cases in the DStar function
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1708606 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/poi/ss/formula/functions/DStarRunner.java142
-rw-r--r--test-data/spreadsheet/DGet.xlsbin39936 -> 51712 bytes
2 files changed, 97 insertions, 45 deletions
diff --git a/src/java/org/apache/poi/ss/formula/functions/DStarRunner.java b/src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
index c5fffbda3a..2fa27c84ae 100644
--- a/src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
+++ b/src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
@@ -24,6 +24,7 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NotImplementedException;
import org.apache.poi.ss.formula.eval.NumericValueEval;
import org.apache.poi.ss.formula.eval.RefEval;
+import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.StringValueEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.util.NumberComparer;
@@ -234,23 +235,26 @@ public final class DStarRunner implements Function3Arg {
targetHeader = solveReference(targetHeader);
- if(!(targetHeader instanceof StringValueEval))
- columnCondition = false;
- else if (getColumnForName(targetHeader, db) == -1)
+ if(!(targetHeader instanceof StringValueEval)) {
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
+
+ if (getColumnForName(targetHeader, db) == -1)
// No column found, it's again a special column that accepts formulas.
columnCondition = false;
if(columnCondition == true) { // normal column condition
// Should not throw, checked above.
- ValueEval target = db.getValue(
+ ValueEval value = db.getValue(
row, getColumnForName(targetHeader, db));
- // Must be a string.
- String conditionString = getStringFromValueEval(condition);
- if(!testNormalCondition(target, conditionString)) {
+ if(!testNormalCondition(value, condition)) {
matches = false;
break;
}
} else { // It's a special formula condition.
+ if(getStringFromValueEval(condition).isEmpty()) {
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
throw new NotImplementedException(
"D* function with formula conditions");
}
@@ -270,50 +274,83 @@ public final class DStarRunner implements Function3Arg {
* @return Whether the condition holds.
* @throws EvaluationException If comparison operator and operands don't match.
*/
- private static boolean testNormalCondition(ValueEval value, String condition)
+ private static boolean testNormalCondition(ValueEval value, ValueEval condition)
throws EvaluationException {
- if(condition.startsWith("<")) { // It's a </<= condition.
- String number = condition.substring(1);
- if(number.startsWith("=")) {
- number = number.substring(1);
- return testNumericCondition(value, operator.smallerEqualThan, number);
- } else {
- return testNumericCondition(value, operator.smallerThan, number);
+ 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 {
+ return testNumericCondition(value, operator.smallerThan, number);
+ }
}
- }
- else if(condition.startsWith(">")) { // It's a >/>= condition.
- String number = condition.substring(1);
- if(number.startsWith("=")) {
- number = number.substring(1);
- return testNumericCondition(value, operator.largerEqualThan, number);
- } else {
- return testNumericCondition(value, operator.largerThan, number);
+ else if(conditionString.startsWith(">")) { // It's a >/>= condition.
+ String number = conditionString.substring(1);
+ if(number.startsWith("=")) {
+ number = number.substring(1);
+ return testNumericCondition(value, operator.largerEqualThan, number);
+ } else {
+ return testNumericCondition(value, operator.largerThan, number);
+ }
}
- }
- else if(condition.startsWith("=")) { // It's a = condition.
- String stringOrNumber = condition.substring(1);
- // Distinguish between string and number.
- boolean itsANumber = false;
- try {
- Integer.parseInt(stringOrNumber);
- itsANumber = true;
- } catch (NumberFormatException e) { // It's not an int.
+ else if(conditionString.startsWith("=")) { // It's a = condition.
+ String stringOrNumber = conditionString.substring(1);
+
+ if(stringOrNumber.isEmpty()) {
+ return value instanceof BlankEval;
+ }
+ // Distinguish between string and number.
+ boolean itsANumber = false;
try {
- Double.parseDouble(stringOrNumber);
+ Integer.parseInt(stringOrNumber);
itsANumber = true;
- } catch (NumberFormatException e2) { // It's a string.
- itsANumber = false;
+ } catch (NumberFormatException e) { // It's not an int.
+ try {
+ Double.parseDouble(stringOrNumber);
+ itsANumber = true;
+ } catch (NumberFormatException e2) { // It's a string.
+ itsANumber = false;
+ }
+ }
+ if(itsANumber) {
+ return testNumericCondition(value, operator.equal, stringOrNumber);
+ } else { // It's a string.
+ String valueString = value instanceof BlankEval ? "" : getStringFromValueEval(value);
+ return stringOrNumber.equals(valueString);
+ }
+ } else { // It's a text starts-with condition.
+ if(conditionString.isEmpty()) {
+ return value instanceof StringEval;
+ }
+ else {
+ String valueString = value instanceof BlankEval ? "" : getStringFromValueEval(value);
+ return valueString.startsWith(conditionString);
}
}
- if(itsANumber) {
- return testNumericCondition(value, operator.equal, stringOrNumber);
- } else { // It's a string.
- String valueString = getStringFromValueEval(value);
- return stringOrNumber.equals(valueString);
+ }
+ else if(condition instanceof NumericValueEval) {
+ double conditionNumber = ((NumericValueEval)condition).getNumberValue();
+ Double valueNumber = getNumerFromValueEval(value);
+ if(valueNumber == null) {
+ return false;
+ }
+
+ return conditionNumber == valueNumber;
+ }
+ else if(condition instanceof ErrorEval) {
+ if(value instanceof ErrorEval) {
+ return ((ErrorEval)condition).getErrorCode() == ((ErrorEval)value).getErrorCode();
+ }
+ else {
+ return false;
}
- } else { // It's a text starts-with condition.
- String valueString = getStringFromValueEval(value);
- return valueString.startsWith(condition);
+ }
+ else {
+ return false;
}
}
@@ -361,6 +398,23 @@ public final class DStarRunner implements Function3Arg {
}
return false; // Can not be reached.
}
+
+ private static Double getNumerFromValueEval(ValueEval value) {
+ if(value instanceof NumericValueEval) {
+ return ((NumericValueEval)value).getNumberValue();
+ }
+ else if(value instanceof StringValueEval) {
+ String stringValue = ((StringValueEval)value).getStringValue();
+ try {
+ return Double.parseDouble(stringValue);
+ } catch (NumberFormatException e2) {
+ return null;
+ }
+ }
+ else {
+ return null;
+ }
+ }
/**
* Takes a ValueEval and tries to retrieve a String value from it.
@@ -373,8 +427,6 @@ public final class DStarRunner implements Function3Arg {
private static String getStringFromValueEval(ValueEval value)
throws EvaluationException {
value = solveReference(value);
- if(value instanceof BlankEval)
- return "";
if(!(value instanceof StringValueEval))
throw new EvaluationException(ErrorEval.VALUE_INVALID);
return ((StringValueEval)value).getStringValue();
diff --git a/test-data/spreadsheet/DGet.xls b/test-data/spreadsheet/DGet.xls
index e576d73a03..860158611e 100644
--- a/test-data/spreadsheet/DGet.xls
+++ b/test-data/spreadsheet/DGet.xls
Binary files differ