[gnumeric] Conditional formats: improve xls import.



commit bbe34632e5b499431c94420f123c227dba22c619
Author: Morten Welinder <terra gnome org>
Date:   Wed Mar 12 19:25:34 2014 -0400

    Conditional formats: improve xls import.

 ChangeLog                     |    1 +
 plugins/excel/ChangeLog       |    3 +
 plugins/excel/ms-excel-read.c |    3 +
 src/style-conditions.c        |   87 +++++++++++++++++++++++++++++++++++++++++
 src/style-conditions.h        |    2 +
 5 files changed, 96 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4533822..4af6a4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@
 
        * src/style-conditions.c (gnm_style_cond_get_alternate_expr): New
        function.
+       (gnm_style_cond_canonicalize): New function.
 
        * src/ssconvert.c (convert): only print "Using exporter ..." if
        --verbose is given, and print it to stderr.
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index c0fba41..b61a1f0 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -4,6 +4,9 @@
        gnm_style_cond_get_alternate_expr for conditions not available in
        xls.
 
+       * ms-excel-read.c (excel_read_CF): Undo the alternate expression
+       stuff.
+
 2014-03-10  Morten Welinder  <terra gnome org>
 
        * xlsx-read.c (xlsx_CT_vertAlign): Read super/subscript.
diff --git a/plugins/excel/ms-excel-read.c b/plugins/excel/ms-excel-read.c
index 55e0f70..5f004cf 100644
--- a/plugins/excel/ms-excel-read.c
+++ b/plugins/excel/ms-excel-read.c
@@ -5204,6 +5204,9 @@ excel_read_CF (BiffQuery *q, ExcelReadSheet *esheet, GnmStyleConditions *sc)
                gnm_expr_top_unref (texpr);
        }
 
+       /* Reverse the alternate-expression treatment on save.  */
+       gnm_style_cond_canonicalize (cond);
+
        /* UNDOCUMENTED : the format of the conditional format
         * is unspecified.
         *
diff --git a/src/style-conditions.c b/src/style-conditions.c
index c0aaeeb..285cf35 100644
--- a/src/style-conditions.c
+++ b/src/style-conditions.c
@@ -26,6 +26,7 @@
 #include "mstyle.h"
 #include "gnm-style-impl.h"
 #include "expr.h"
+#include "expr-impl.h"
 #include "cell.h"
 #include "value.h"
 #include "sheet.h"
@@ -290,6 +291,92 @@ gnm_style_cond_get_alternate_expr (GnmStyleCond const *cond)
        return gnm_expr_top_new (expr);
 }
 
+static gboolean
+isself (GnmExpr const *expr)
+{
+       GnmCellRef const *cr;
+
+       if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CELLREF)
+               return FALSE;
+       cr = &expr->cellref.ref;
+
+       return (cr->sheet == NULL &&
+               cr->col == 0 && cr->row == 0 &&
+               cr->col_relative && cr->row_relative);
+}
+
+static gboolean
+issinglespace (GnmExpr const *expr)
+{
+       GnmValue const *v = gnm_expr_get_constant (expr);
+       return (v &&
+               VALUE_IS_STRING (v) &&
+               strcmp (value_peek_string (v), " ") == 0);
+}
+
+/**
+ * gnm_style_cond_canonicalize:
+ * @cond: condition
+ *
+ * Turns a custom condition into a more specific one, i.e., reverses the
+ * effect of using gnm_style_cond_get_alternate_expr.  Leaves the condition
+ * alone if it is not recognized.
+ **/
+void
+gnm_style_cond_canonicalize (GnmStyleCond *cond)
+{
+       GnmExpr const *expr, *expr2;
+       GnmExprTop const *texpr;
+       gboolean negate = FALSE;
+       GnmFunc const *iserror;
+       GnmFunc const *find;
+       GnmStyleCondOp newop = GNM_STYLE_COND_CUSTOM;
+
+       g_return_if_fail (cond != NULL);
+
+       if (cond->op != GNM_STYLE_COND_CUSTOM)
+               return;
+
+       texpr = gnm_style_cond_get_expr (cond, 0);
+       if (!texpr)
+               return;
+       expr = texpr->expr;
+
+       if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
+           expr->func.argc == 1 &&
+           expr->func.func == gnm_func_lookup_or_add_placeholder ("NOT")) {
+               negate = TRUE;
+               expr = expr->func.argv[0];
+       }
+
+       iserror = gnm_func_lookup_or_add_placeholder ("ISERROR");
+       find = gnm_func_lookup_or_add_placeholder ("FIND");
+
+       if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
+           expr->func.argc == 1 && expr->func.func == iserror &&
+           isself (expr->func.argv[0])) {
+               newop = negate
+                       ? GNM_STYLE_COND_NOT_CONTAINS_ERR
+                       : GNM_STYLE_COND_CONTAINS_ERR;
+       } else if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
+                  expr->func.argc == 1 && expr->func.func == iserror &&
+                  (expr2 = expr->func.argv[0]) &&
+                  GNM_EXPR_GET_OPER (expr2) == GNM_EXPR_OP_FUNCALL &&
+                  expr2->func.argc == 2 && expr2->func.func == find &&
+                  issinglespace (expr2->func.argv[0]) &&
+                  isself (expr2->func.argv[1])) {
+               newop = negate
+                       ? GNM_STYLE_COND_CONTAINS_BLANKS
+                       : GNM_STYLE_COND_NOT_CONTAINS_BLANKS;
+       }
+
+       if (newop != GNM_STYLE_COND_CUSTOM) {
+               gnm_style_cond_set_expr (cond, NULL, 0);
+               cond->op = newop;
+       }
+}
+
+
 static void
 gnm_style_conditions_finalize (GObject *obj)
 {
diff --git a/src/style-conditions.h b/src/style-conditions.h
index e4790ae..4229496 100644
--- a/src/style-conditions.h
+++ b/src/style-conditions.h
@@ -57,7 +57,9 @@ GnmExprTop const *gnm_style_cond_get_expr (GnmStyleCond const *cond,
 void          gnm_style_cond_set_expr (GnmStyleCond *cond,
                                       GnmExprTop const *texpr,
                                       unsigned idx);
+
 GnmExprTop const *gnm_style_cond_get_alternate_expr (GnmStyleCond const *cond);
+void gnm_style_cond_canonicalize (GnmStyleCond *cond);
 
 Sheet      *gnm_style_cond_get_sheet (GnmStyleCond const *cond);
 void        gnm_style_cond_set_sheet (GnmStyleCond *cond, Sheet *sheet);


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