[gnumeric] Conditional formats: handle starts-with for xls



commit 161a1003574801acd1c40b27d0bdc4b4d4e1cb5c
Author: Morten Welinder <terra gnome org>
Date:   Wed Mar 12 21:26:19 2014 -0400

    Conditional formats: handle starts-with for xls

 samples/cond-format-tests.gnumeric |  Bin 2254 -> 2355 bytes
 src/style-conditions.c             |   55 ++++++++++++++++++++++++++++++++---
 2 files changed, 50 insertions(+), 5 deletions(-)
---
diff --git a/samples/cond-format-tests.gnumeric b/samples/cond-format-tests.gnumeric
index fa935e4..7308171 100644
Binary files a/samples/cond-format-tests.gnumeric and b/samples/cond-format-tests.gnumeric differ
diff --git a/src/style-conditions.c b/src/style-conditions.c
index 31c83ad..cfb5236 100644
--- a/src/style-conditions.c
+++ b/src/style-conditions.c
@@ -295,8 +295,33 @@ gnm_style_cond_get_alternate_expr (GnmStyleCond const *cond)
                          gnm_expr_new_cellref (&self)));
                break;
 
-       case GNM_STYLE_COND_BEGINS_WITH_STR:
        case GNM_STYLE_COND_NOT_BEGINS_WITH_STR:
+               negate = TRUE; /* ...and fall through */
+       case GNM_STYLE_COND_BEGINS_WITH_STR: {
+               GnmExprTop const *sexpr = gnm_style_cond_get_expr (cond, 0);
+               if (!sexpr)
+                       return NULL;
+
+               /*
+                * We can do much better if sexpr is a constant.  We are
+                * constrained by using only Excel functions and not
+                * evaluating the needle more than once.  The expression
+                * used here works, but FIND is more expensive that it
+                * ought to be.
+                */
+               expr = gnm_expr_new_binary
+                       (gnm_expr_new_funcall2
+                        (gnm_func_lookup_or_add_placeholder ("IFERROR"),
+                         gnm_expr_new_funcall2
+                         (gnm_func_lookup_or_add_placeholder ("FIND"),
+                          gnm_expr_copy (sexpr->expr),
+                          gnm_expr_new_cellref (&self)),
+                         gnm_expr_new_constant (value_new_int (2))),
+                        GNM_EXPR_OP_EQUAL,
+                        gnm_expr_new_constant (value_new_int (1)));
+               break;
+       }
+
        case GNM_STYLE_COND_ENDS_WITH_STR:
        case GNM_STYLE_COND_NOT_ENDS_WITH_STR:
                /* we ought to do the above */
@@ -342,6 +367,7 @@ gnm_style_cond_canonicalize (GnmStyleCond *cond)
        GnmValue const *v;
        gboolean negate = FALSE;
        GnmFunc const *iserror;
+       GnmFunc const *iferror;
        GnmFunc const *find;
        GnmStyleCondOp newop = GNM_STYLE_COND_CUSTOM;
 
@@ -364,6 +390,7 @@ gnm_style_cond_canonicalize (GnmStyleCond *cond)
        }
 
        iserror = gnm_func_lookup_or_add_placeholder ("ISERROR");
+       iferror = gnm_func_lookup_or_add_placeholder ("IFERROR");
        find = gnm_func_lookup_or_add_placeholder ("FIND");
 
        if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
@@ -377,19 +404,37 @@ gnm_style_cond_canonicalize (GnmStyleCond *cond)
                   (expr2 = expr->func.argv[0]) &&
                   GNM_EXPR_GET_OPER (expr2) == GNM_EXPR_OP_FUNCALL &&
                   expr2->func.argc == 2 && expr2->func.func == find &&
-                  (v = gnm_expr_get_constant (expr2->func.argv[0])) &&
-                  VALUE_IS_STRING (v) &&
                   isself (expr2->func.argv[1])) {
-               if (strcmp (value_peek_string (v), " ") == 0)
+               GnmValue const *v =
+                       gnm_expr_get_constant (expr2->func.argv[0]);
+
+               if (v && VALUE_IS_STRING (v) &&
+                   strcmp (value_peek_string (v), " ") == 0)
                        newop = negate
                                ? GNM_STYLE_COND_CONTAINS_BLANKS
                                : GNM_STYLE_COND_NOT_CONTAINS_BLANKS;
                else {
-                       texpr = gnm_expr_top_new_constant (value_dup (v));
+                       texpr = gnm_expr_top_new (gnm_expr_copy (expr2->func.argv[0]));
                        newop = negate
                                ? GNM_STYLE_COND_CONTAINS_STR
                                : GNM_STYLE_COND_NOT_CONTAINS_STR;
                }
+       } else if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_EQUAL &&
+                  (v = gnm_expr_get_constant (expr->binary.value_b)) &&
+                  VALUE_IS_FLOAT (v) && value_get_as_float (v) == 1 &&
+                  (expr2 = expr->binary.value_a) &&
+                  GNM_EXPR_GET_OPER (expr2) == GNM_EXPR_OP_FUNCALL &&
+                  expr2->func.argc == 2 && expr2->func.func == iferror &&
+                  (v = gnm_expr_get_constant (expr2->func.argv[1])) &&
+                  VALUE_IS_FLOAT (v) && value_get_as_float (v) != 1 &&
+                  (expr2 = expr2->func.argv[0]) &&
+                  GNM_EXPR_GET_OPER (expr2) == GNM_EXPR_OP_FUNCALL &&
+                  expr2->func.argc == 2 && expr2->func.func == find &&
+                  isself (expr2->func.argv[1])) {
+               texpr = gnm_expr_top_new (gnm_expr_copy (expr2->func.argv[0]));
+               newop = negate
+                       ? GNM_STYLE_COND_NOT_BEGINS_WITH_STR
+                       : GNM_STYLE_COND_BEGINS_WITH_STR;
        }
 
        if (newop != GNM_STYLE_COND_CUSTOM) {


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