[gnumeric] DCOUNT/DCOUNTA: Allow missing field argument.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] DCOUNT/DCOUNTA: Allow missing field argument.
- Date: Thu, 9 Jun 2016 18:34:28 +0000 (UTC)
commit 19044f4bef1007b84b4b43f5f5b679e544afb30e
Author: Morten Welinder <terra gnome org>
Date: Thu Jun 9 14:34:04 2016 -0400
DCOUNT/DCOUNTA: Allow missing field argument.
NEWS | 1 +
plugins/fn-database/ChangeLog | 11 +++++++
plugins/fn-database/functions.c | 58 ++++++++++++++++++++++++++++-----------
src/value.c | 2 +-
4 files changed, 55 insertions(+), 17 deletions(-)
---
diff --git a/NEWS b/NEWS
index 5de164c..4de3fc1 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.12.30
Morten:
* Improve format guessing for csv and txt files.
+ * Fix DCOUNT and DCOUNTA with missing field. [#767290]
--------------------------------------------------------------------------
Gnumeric 1.12.29
diff --git a/plugins/fn-database/ChangeLog b/plugins/fn-database/ChangeLog
index a976e70..ce22faa 100644
--- a/plugins/fn-database/ChangeLog
+++ b/plugins/fn-database/ChangeLog
@@ -1,3 +1,14 @@
+2016-06-09 Morten Welinder <terra gnome org>
+
+ * functions.c (database_find_values): Accept also
+ COLLECT_IGNORE_ERRORS.
+ (gnumeric_dcount): Use database_value_range_function; ignore
+ errors.
+ (gnumeric_dcounta): Use database_value_range_function.
+ (database_value_range_function): Add flag to control whether a
+ missing field is allowed. Clear all flags in that case.
+ (find_cells_that_match): Handle missing field. Poorly.
+
2016-05-06 Morten Welinder <terra gnome org>
* Release 1.12.29
diff --git a/plugins/fn-database/functions.c b/plugins/fn-database/functions.c
index 308951e..f14bb5b 100644
--- a/plugins/fn-database/functions.c
+++ b/plugins/fn-database/functions.c
@@ -102,19 +102,23 @@ find_cells_that_match (Sheet *sheet, GnmValue const *database,
int row, first_row, last_row;
gboolean add_flag;
GnmCell *cell;
+ int fake_col;
cells = NULL;
/* TODO : Why ignore the first row ? What if there is no header ? */
first_row = database->v_range.cell.a.row + 1;
last_row = database->v_range.cell.b.row;
+ fake_col = database->v_range.cell.a.col;
for (row = first_row; row <= last_row; row++) {
- cell = sheet_cell_get (sheet, col, row);
+ cell = (col == -1)
+ ? sheet_cell_fetch (sheet, fake_col, row)
+ : sheet_cell_get (sheet, col, row);
if (cell != NULL)
gnm_cell_eval (cell);
- if (gnm_cell_is_empty (cell))
+ if (col != -1 && gnm_cell_is_empty (cell))
continue;
add_flag = TRUE;
@@ -161,14 +165,17 @@ database_find_values (Sheet *sheet, GnmValue const *database,
GnmValue **res2 = NULL;
void *res;
- if (flags & ~(COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS | COLLECT_IGNORE_BLANKS)) {
+ if (flags & ~(COLLECT_IGNORE_STRINGS |
+ COLLECT_IGNORE_BOOLS |
+ COLLECT_IGNORE_BLANKS |
+ COLLECT_IGNORE_ERRORS)) {
g_warning ("unsupported flags in database_find_values %x", flags);
}
/* FIXME: expand and sanitise this call later. */
cells = find_cells_that_match (sheet, database, col, criterias);
-
cellcount = g_slist_length (cells);
+
/* Allocate memory -- one extra to make sure we don't get NULL. */
if (floats)
res = res1 = g_new (gnm_float, cellcount + 1);
@@ -184,6 +191,8 @@ database_find_values (Sheet *sheet, GnmValue const *database,
continue;
if ((flags & COLLECT_IGNORE_BLANKS) && VALUE_IS_EMPTY (value))
continue;
+ if ((flags & COLLECT_IGNORE_ERRORS) && VALUE_IS_ERROR (value))
+ continue;
if (floats)
res1[count++] = value_get_as_float (value);
else
@@ -270,7 +279,8 @@ database_value_range_function (GnmFuncEvalInfo *ei,
value_range_function_t func,
CollectFlags flags,
GnmStdError zero_count_error,
- GnmStdError func_error)
+ GnmStdError func_error,
+ gboolean allow_missing_field)
{
int fieldno;
GSList *criterias = NULL;
@@ -285,9 +295,14 @@ database_value_range_function (GnmFuncEvalInfo *ei,
!VALUE_IS_CELLRANGE (database))
return value_new_error_NUM (ei->pos);
- fieldno = find_column_of_field (ei->pos, database, field);
- if (fieldno < 0)
- return value_new_error_NUM (ei->pos);
+ if (allow_missing_field && VALUE_IS_EMPTY (field)) {
+ flags = 0;
+ fieldno = -1;
+ } else {
+ fieldno = find_column_of_field (ei->pos, database, field);
+ if (fieldno < 0)
+ return value_new_error_NUM (ei->pos);
+ }
criterias = parse_database_criteria (ei->pos, database, criteria);
if (criterias == NULL)
@@ -374,20 +389,29 @@ static GnmFuncHelp const help_dcount[] = {
{ GNM_FUNC_HELP_END }
};
+static int
+range_count (G_GNUC_UNUSED GnmValue **xs, int n, GnmValue **res)
+{
+ *res = value_new_int (n);
+ return 0;
+}
+
static GnmValue *
gnumeric_dcount (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
- return database_float_range_function (ei,
+ return database_value_range_function (ei,
argv[0],
argv[1],
argv[2],
- gnm_range_count,
+ range_count,
COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BOOLS |
- COLLECT_IGNORE_BLANKS,
+ COLLECT_IGNORE_BLANKS |
+ COLLECT_IGNORE_ERRORS,
GNM_ERROR_UNKNOWN,
- GNM_ERROR_NUM);
+ GNM_ERROR_NUM,
+ TRUE);
}
/***************************************************************************/
@@ -412,14 +436,15 @@ static GnmFuncHelp const help_dcounta[] = {
static GnmValue *
gnumeric_dcounta (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
- return database_float_range_function (ei,
+ return database_value_range_function (ei,
argv[0],
argv[1],
argv[2],
- gnm_range_count,
+ range_count,
COLLECT_IGNORE_BLANKS,
GNM_ERROR_UNKNOWN,
- GNM_ERROR_NUM);
+ GNM_ERROR_NUM,
+ TRUE);
}
/***************************************************************************/
@@ -462,7 +487,8 @@ gnumeric_dget (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
range_first,
COLLECT_IGNORE_BLANKS,
GNM_ERROR_VALUE,
- GNM_ERROR_NUM);
+ GNM_ERROR_NUM,
+ FALSE);
}
static GnmFuncHelp const help_dmax[] = {
diff --git a/src/value.c b/src/value.c
index 88de916..7cd7c65 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1676,7 +1676,7 @@ find_column_of_field (GnmEvalPos const *ep,
int begin_col, end_col, row, n, column;
int offset;
- // I'm not certain we shoul demand this, but the code clearly wants
+ // I'm not certain we should demand this, but the code clearly wants
// it.
if (!VALUE_IS_CELLRANGE (database))
return -1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]