[gnumeric] SUMIF: fix problem with empty cells.



commit 082f7b3dd6398ed73a6ebe9f6f4cd6eccbe2ec61
Author: Morten Welinder <terra gnome org>
Date:   Thu Dec 3 10:17:46 2009 -0500

    SUMIF: fix problem with empty cells.

 ChangeLog                   |    5 ++++
 NEWS                        |    1 +
 plugins/fn-math/ChangeLog   |    5 ++++
 plugins/fn-math/functions.c |   45 ++++++++++++++++++++++---------------------
 src/value.c                 |    9 ++++++-
 5 files changed, 41 insertions(+), 24 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d51ca6b..e1ac146 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-12-03  Morten Welinder  <terra gnome org>
+
+	* src/value.c (parse_criteria): For matching, if we match the
+	empty string, make sure we look in empty cells.  Fixes #603671.
+
 2009-12-02  Morten Welinder  <terra gnome org>
 
 	* src/ssconvert.c (run_solver): Optionally run solver.  (For
diff --git a/NEWS b/NEWS
index a340675..4027ca4 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Morten:
 	* Elminate use of "float".
 	* Fix selection problem.  [#601107]
 	* Automate solver testing.
+	* Fix SUMIF problem.  [#603671]
 
 --------------------------------------------------------------------------
 Gnumeric 1.9.16
diff --git a/plugins/fn-math/ChangeLog b/plugins/fn-math/ChangeLog
index 969e60e..2fd7efd 100644
--- a/plugins/fn-math/ChangeLog
+++ b/plugins/fn-math/ChangeLog
@@ -1,3 +1,8 @@
+2009-12-03  Morten Welinder  <terra gnome org>
+
+	* functions.c (cb_averageif, cb_sumif, cb_countif): Handle empty
+	cells.  Part of #603671.
+
 2009-11-29  Morten Welinder <terra gnome org>
 
 	* Release 1.9.16
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index 6047fe2..ae46e78 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -472,13 +472,13 @@ cb_countif (GnmCellIter const *iter, CountIfClosure *res)
 	GnmCell *cell = iter->cell;
 	GnmValue *v;
 
-	if (!cell)
-		return NULL;
-
-	gnm_cell_eval (cell);
-	v = cell->value;
+	if (cell) {
+		gnm_cell_eval (cell);
+		v = cell->value;
+	} else
+		v = NULL;
 
-	if (!VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
+	if (!VALUE_IS_EMPTY (v) && !VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
 		return NULL;
 
 	if (!res->crit->fun (v, res->crit))
@@ -511,7 +511,6 @@ gnumeric_countif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
 	res.count = 0;
 	res.crit = parse_criteria (argv[1], date_conv);
-#warning "2006/May/31  Why do we not filter non-existent as a flag, rather than checking for NULL in cb_countif"
 	problem = sheet_foreach_cell_in_range
 		(sheet, res.crit->iter_flags,
 		 r->cell.a.col, r->cell.a.row, r->cell.b.col, r->cell.b.row,
@@ -548,13 +547,14 @@ cb_sumif (GnmCellIter const *iter, SumIfClosure *res)
 {
 	GnmCell *cell = iter->cell;
 	GnmValue *v;
-	if (!cell)
-		return NULL;
 
-	gnm_cell_eval (cell);
-	v = cell->value;
+	if (cell) {
+		gnm_cell_eval (cell);
+		v = cell->value;
+	} else
+		v = NULL;
 
-	if (!VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
+	if (!VALUE_IS_EMPTY (v) && !VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
 		return NULL;
 
 	if (!res->crit->fun (v, res->crit))
@@ -575,8 +575,9 @@ cb_sumif (GnmCellIter const *iter, SumIfClosure *res)
 			return NULL;
 	}
 
-	/* FIXME: Check bools.  */
-	res->sum += value_get_as_float (v);
+	/* FIXME: Check bools and strings.  */
+	if (v)
+		res->sum += value_get_as_float (v);
 
 	return NULL;
 }
@@ -622,7 +623,6 @@ gnumeric_sumif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 
 	res.sum = 0.;
 	res.crit = parse_criteria (argv[1], date_conv);
-#warning "2006/May/31  Why do we not filter non-existent as a flag, rather than checking for NULL in cb_sumif"
 	problem = sheet_foreach_cell_in_range
 		(start_sheet, res.crit->iter_flags,
 		 rs.start.col, rs.start.row, rs.end.col, rs.end.row,
@@ -659,13 +659,14 @@ cb_averageif (GnmCellIter const *iter, AverageIfClosure *res)
 {
 	GnmCell *cell = iter->cell;
 	GnmValue *v;
-	if (!cell)
-		return NULL;
 
-	gnm_cell_eval (cell);
-	v = cell->value;
+	if (cell) {
+		gnm_cell_eval (cell);
+		v = cell->value;
+	} else
+		v = NULL;
 
-	if (!VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
+	if (!VALUE_IS_EMPTY (v) && !VALUE_IS_NUMBER (v) && !VALUE_IS_STRING (v))
 		return NULL;
 
 	if (!res->crit->fun (v, res->crit))
@@ -687,7 +688,8 @@ cb_averageif (GnmCellIter const *iter, AverageIfClosure *res)
 	}
 
 	/* FIXME: Check bools.  */
-	res->sum += value_get_as_float (v);
+	if (v)
+		res->sum += value_get_as_float (v);
 	res->count++;
 
 	return NULL;
@@ -735,7 +737,6 @@ gnumeric_averageif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 	res.sum = 0.;
 	res.count = 0;
 	res.crit = parse_criteria (argv[1], date_conv);
-#warning "2006/May/31  Why do we not filter non-existent as a flag, rather than checking for NULL in cb_averageif"
 	problem = sheet_foreach_cell_in_range
 		(start_sheet, res.crit->iter_flags,
 		 rs.start.col, rs.start.row, rs.end.col, rs.end.row,
diff --git a/src/value.c b/src/value.c
index 53cf7dd..8b8810f 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1482,10 +1482,12 @@ criteria_test_greater_or_equal (GnmValue const *x, GnmCriteria *crit)
 static gboolean
 criteria_test_match (GnmValue const *x, GnmCriteria *crit)
 {
+	const char *xs;
 	if (!crit->has_rx)
 		return FALSE;
 
-	return go_regexec (&crit->rx, value_peek_string (x), 0, NULL, 0) == GO_REG_OK;
+	xs = x ? value_peek_string (x) : "";
+	return go_regexec (&crit->rx, xs, 0, NULL, 0) == GO_REG_OK;
 }
 
 /*
@@ -1609,7 +1611,7 @@ parse_criteria (GnmValue const *crit_val, GODateConventions const *date_conv)
 	} else if (strncmp (criteria, "<>", 2) == 0) {
 		res->fun = criteria_test_unequal;
 		len = 2;
-		res->iter_flags = CELL_ITER_ALL;
+		res->iter_flags &= ~CELL_ITER_IGNORE_BLANK;
 	} else if (*criteria == '<') {
 		res->fun = criteria_test_less;
 		len = 1;
@@ -1622,6 +1624,9 @@ parse_criteria (GnmValue const *crit_val, GODateConventions const *date_conv)
 	} else {
 		res->fun = criteria_test_match;
 		res->has_rx = (gnm_regcomp_XL (&res->rx, criteria, 0, TRUE) == GO_REG_OK);
+		if (res->fun (NULL, res))
+			res->iter_flags &= ~CELL_ITER_IGNORE_BLANK;
+
 		len = 0;
 	}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]