Fix for bug 46647 - COUNTIF NE operator and other special cases involving type conversion

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@740088 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-02-02 19:42:57 +00:00
parent d3ac17f5f2
commit 4057cb7cf0
4 changed files with 77 additions and 8 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.5-beta5" date="2008-??-??"> <release version="3.5-beta5" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46647 - Fixed COUNTIF NE operator and other special cases involving type conversion</action>
<action dev="POI-DEVELOPERS" type="add">46635 - Added a method to remove slides</action> <action dev="POI-DEVELOPERS" type="add">46635 - Added a method to remove slides</action>
<action dev="POI-DEVELOPERS" type="fix">46520 - Fixed HSSFFont.applyFont() to properly apply font to overlapping regions</action> <action dev="POI-DEVELOPERS" type="fix">46520 - Fixed HSSFFont.applyFont() to properly apply font to overlapping regions</action>
<action dev="POI-DEVELOPERS" type="fix">46545 - Fixed ObjRecord to ignore excessive padding written by previous POI versions</action> <action dev="POI-DEVELOPERS" type="fix">46545 - Fixed ObjRecord to ignore excessive padding written by previous POI versions</action>

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.5-beta5" date="2008-??-??"> <release version="3.5-beta5" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46647 - Fixed COUNTIF NE operator and other special cases involving type conversion</action>
<action dev="POI-DEVELOPERS" type="add">46635 - Added a method to remove slides</action> <action dev="POI-DEVELOPERS" type="add">46635 - Added a method to remove slides</action>
<action dev="POI-DEVELOPERS" type="fix">46520 - Fixed HSSFFont.applyFont() to properly apply font to overlapping regions</action> <action dev="POI-DEVELOPERS" type="fix">46520 - Fixed HSSFFont.applyFont() to properly apply font to overlapping regions</action>
<action dev="POI-DEVELOPERS" type="fix">46545 - Fixed ObjRecord to ignore excessive padding written by previous POI versions</action> <action dev="POI-DEVELOPERS" type="fix">46545 - Fixed ObjRecord to ignore excessive padding written by previous POI versions</action>

View File

@ -128,7 +128,7 @@ public final class Countif implements Function {
case NONE: case NONE:
case EQ: case EQ:
return cmpResult == 0; return cmpResult == 0;
case NE: return cmpResult == 0; case NE: return cmpResult != 0;
case LT: return cmpResult < 0; case LT: return cmpResult < 0;
case LE: return cmpResult <= 0; case LE: return cmpResult <= 0;
case GT: return cmpResult > 0; case GT: return cmpResult > 0;
@ -160,14 +160,27 @@ public final class Countif implements Function {
double testValue; double testValue;
if(x instanceof StringEval) { if(x instanceof StringEval) {
// if the target(x) is a string, but parses as a number // if the target(x) is a string, but parses as a number
// it may still count as a match // it may still count as a match, only for the equality operator
switch (_operator.getCode()) {
case CmpOp.EQ:
case CmpOp.NONE:
break;
case CmpOp.NE:
// Always matches (inconsistent with above two cases).
// for example '<>123' matches '123', '4', 'abc', etc
return true;
default:
// never matches (also inconsistent with above three cases).
// for example '>5' does not match '6',
return false;
}
StringEval se = (StringEval)x; StringEval se = (StringEval)x;
Double val = OperandResolver.parseDouble(se.getStringValue()); Double val = OperandResolver.parseDouble(se.getStringValue());
if(val == null) { if(val == null) {
// x is text that is not a number // x is text that is not a number
return false; return false;
} }
testValue = val.doubleValue(); return _value == val.doubleValue();
} else if((x instanceof NumberEval)) { } else if((x instanceof NumberEval)) {
NumberEval ne = (NumberEval) x; NumberEval ne = (NumberEval) x;
testValue = ne.getNumberValue(); testValue = ne.getNumberValue();
@ -249,6 +262,7 @@ public final class Countif implements Function {
_pattern = getWildCardPattern(value); _pattern = getWildCardPattern(value);
break; break;
default: default:
// pattern matching is never used for < > <= =>
_pattern = null; _pattern = null;
} }
} }

View File

@ -108,11 +108,64 @@ public final class TestCountFuncs extends TestCase {
// note - same results when criteria is a string that parses as the number with the same value // note - same results when criteria is a string that parses as the number with the same value
confirmCountIf(3, range, new StringEval("2.00")); confirmCountIf(3, range, new StringEval("2.00"));
if (false) { // not supported yet: // when criteria is an expression (starting with a comparison operator)
// when criteria is an expression (starting with a comparison operator) confirmCountIf(2, range, new StringEval(">1"));
confirmCountIf(4, range, new StringEval(">1")); // when criteria is an expression (starting with a comparison operator)
} confirmCountIf(2, range, new StringEval(">0.5"));
} }
public void testCriteriaPredicateNe_Bug46647() {
I_MatchPredicate mp = Countif.createCriteriaPredicate(new StringEval("<>aa"), 0, 0);
StringEval seA = new StringEval("aa"); // this should not match the criteria '<>aa'
StringEval seB = new StringEval("bb"); // this should match
if (mp.matches(seA) && !mp.matches(seB)) {
throw new AssertionFailedError("Identified bug 46647");
}
assertFalse(mp.matches(seA));
assertTrue(mp.matches(seB));
// general tests for not-equal (<>) operator
AreaEval range;
ValueEval[] values;
values = new ValueEval[] {
new StringEval("aa"),
new StringEval("def"),
new StringEval("aa"),
new StringEval("ghi"),
new StringEval("aa"),
new StringEval("aa"),
};
range = EvalFactory.createAreaEval("A1:A6", values);
confirmCountIf(2, range, new StringEval("<>aa"));
values = new ValueEval[] {
new StringEval("ab"),
new StringEval("aabb"),
new StringEval("aa"), // match
new StringEval("abb"),
new StringEval("aab"),
new StringEval("ba"), // match
};
range = EvalFactory.createAreaEval("A1:A6", values);
confirmCountIf(2, range, new StringEval("<>a*b"));
values = new ValueEval[] {
new NumberEval(222),
new NumberEval(222),
new NumberEval(111),
new StringEval("aa"),
new StringEval("111"),
};
range = EvalFactory.createAreaEval("A1:A5", values);
confirmCountIf(4, range, new StringEval("<>111"));
}
/** /**
* special case where the criteria argument is a cell reference * special case where the criteria argument is a cell reference
*/ */
@ -219,7 +272,7 @@ public final class TestCountFuncs extends TestCase {
confirmPredicate(true, mp, 4); confirmPredicate(true, mp, 4);
confirmPredicate(true, mp, 5); confirmPredicate(true, mp, 5);
confirmPredicate(false, mp, 6); confirmPredicate(false, mp, 6);
confirmPredicate(true, mp, "4.9"); confirmPredicate(false, mp, "4.9");
confirmPredicate(false, mp, "4.9t"); confirmPredicate(false, mp, "4.9t");
confirmPredicate(false, mp, "5.1"); confirmPredicate(false, mp, "5.1");
confirmPredicate(false, mp, NULL); confirmPredicate(false, mp, NULL);