[gnumeric] Funcs: add SWITCH function.



commit 2b743e3aedba9f07d60132667e6dfd991a95df6b
Author: Morten Welinder <terra gnome org>
Date:   Fri Aug 5 15:08:28 2016 -0400

    Funcs: add SWITCH function.
    
    This isn't well tested.  There are probably issues with strictness,
    range arguments, array formulas, equality.  For starters.

 NEWS                                  |    1 +
 doc/C/func.defs                       |   14 ++++++-
 doc/C/functions.xml                   |   38 ++++++++++++++++++-
 plugins/fn-logical/functions.c        |   66 ++++++++++++++++++++++++++++++++-
 plugins/fn-logical/plugin.xml.in      |    1 +
 plugins/openoffice/openoffice-read.c  |    1 +
 plugins/openoffice/openoffice-write.c |    1 +
 7 files changed, 118 insertions(+), 4 deletions(-)
---
diff --git a/NEWS b/NEWS
index cd6fd52..617081f 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ Morten:
        * New function CONCAT.
        * New function TEXTJOIN.
        * New function IFS.
+       * New function SWITCH.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.31
diff --git a/doc/C/func.defs b/doc/C/func.defs
index 3aaff6c..0eb3542 100644
--- a/doc/C/func.defs
+++ b/doc/C/func.defs
@@ -2928,7 +2928,7 @@ The depreciation coefficient used is:
 @{value1}: value if @{condition1} is true
 @{cond2}: condition
 @{value2}: value if @{condition2} is true
-@DESCRIPTION=This function returns the after the first true contional.  If no conditional is true, #VALUE! 
is returned.
+@DESCRIPTION=This function returns the value after the first true contional.  If no conditional is true, 
#VALUE! is returned.
 @SEEALSO=IF
 
 @CATEGORY=Logic
@@ -2953,6 +2953,18 @@ The depreciation coefficient used is:
 @SEEALSO=AND,XOR,NOT,IF
 
 @CATEGORY=Logic
+@FUNCTION=SWITCH
+@SHORTDESC=multi-branch selector
+@SYNTAX=SWITCH(ref,choice1,value1,choice2,value2,…)
+@ARGUMENTDESCRIPTION=@{ref}: value
+@{choice1}: first choice value
+@{value1}: first result value
+@{choice2}: second choice value
+@{value2}: second result value
+@DESCRIPTION=This function compares the reference value, @{ref}, against the choice values, @{choice1} etc., 
and returns the corresponding result value when it finds a match.  The choices may be followed by a default 
value to use.  If there are no choices that match and no default value, #NA! is return.
+@SEEALSO=IF,IFS
+
+@CATEGORY=Logic
 @FUNCTION=TRUE
 @SHORTDESC=the value TRUE
 @SYNTAX=TRUE()
diff --git a/doc/C/functions.xml b/doc/C/functions.xml
index dbfc7e5..f38ef22 100644
--- a/doc/C/functions.xml
+++ b/doc/C/functions.xml
@@ -9324,7 +9324,7 @@
       </refsect1>
       <refsect1>
         <title>Description</title>
-        <para>This function returns the after the first true contional.  If no conditional is true, #VALUE! 
is returned.</para>
+        <para>This function returns the value after the first true contional.  If no conditional is true, 
#VALUE! is returned.</para>
       </refsect1>
       <refsect1>
         <title>See also</title>
@@ -9416,6 +9416,42 @@
       </para>
       </refsect1>
     </refentry>
+    <refentry id="gnumeric-function-SWITCH">
+      <refmeta>
+        <refentrytitle>
+          <function>SWITCH</function>
+        </refentrytitle>
+      </refmeta>
+      <refnamediv>
+        <refname>
+          <function>SWITCH</function>
+        </refname>
+        <refpurpose>
+        multi-branch selector
+      </refpurpose>
+      </refnamediv>
+      <refsynopsisdiv>
+        
<synopsis><function>SWITCH</function>(<parameter>ref</parameter>,<parameter>choice1</parameter>,<parameter>value1</parameter>,<parameter>choice2</parameter>,<parameter>value2</parameter>,<parameter/>…)</synopsis>
+      </refsynopsisdiv>
+      <refsect1>
+        <title>Arguments</title>
+        <para><parameter>ref</parameter>: value</para>
+        <para><parameter>choice1</parameter>: first choice value</para>
+        <para><parameter>value1</parameter>: first result value</para>
+        <para><parameter>choice2</parameter>: second choice value</para>
+        <para><parameter>value2</parameter>: second result value</para>
+      </refsect1>
+      <refsect1>
+        <title>Description</title>
+        <para>This function compares the reference value, <parameter>ref</parameter>, against the choice 
values, <parameter>choice1</parameter> etc., and returns the corresponding result value when it finds a 
match.  The choices may be followed by a default value to use.  If there are no choices that match and no 
default value, #NA! is return.</para>
+      </refsect1>
+      <refsect1>
+        <title>See also</title>
+        <para><link linkend="gnumeric-function-IF"><function>IF</function></link>,
+        <link linkend="gnumeric-function-IFS"><function>IFS</function></link>.
+      </para>
+      </refsect1>
+    </refentry>
     <refentry id="gnumeric-function-TRUE">
       <refmeta>
         <refentrytitle>
diff --git a/plugins/fn-logical/functions.c b/plugins/fn-logical/functions.c
index 1f2abe8..32badc1 100644
--- a/plugins/fn-logical/functions.c
+++ b/plugins/fn-logical/functions.c
@@ -270,7 +270,7 @@ static GnmFuncHelp const help_ifs[] = {
        { GNM_FUNC_HELP_ARG, F_("value1:value if @{condition1} is true") },
        { GNM_FUNC_HELP_ARG, F_("cond2:condition") },
        { GNM_FUNC_HELP_ARG, F_("value2:value if @{condition2} is true") },
-       { GNM_FUNC_HELP_DESCRIPTION, F_("This function returns the after the first true contional.  If no 
conditional is true, #VALUE! is returned.") },
+       { GNM_FUNC_HELP_DESCRIPTION, F_("This function returns the value after the first true contional.  If 
no conditional is true, #VALUE! is returned.") },
         { GNM_FUNC_HELP_EXAMPLES, "=IFS(false,1/0,true,42)" },
        { GNM_FUNC_HELP_SEEALSO, "IF" },
        { GNM_FUNC_HELP_END }
@@ -279,7 +279,7 @@ static GnmFuncHelp const help_ifs[] = {
 static GnmValue *
 gnumeric_ifs (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 {
-       int a = 0;
+       int a;
 
        for (a = 0; a + 1 <= argc; a += 2) {
                GnmValue *v;
@@ -308,6 +308,65 @@ gnumeric_ifs (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
 /***************************************************************************/
 
+static GnmFuncHelp const help_switch[] = {
+       { GNM_FUNC_HELP_NAME, F_("SWITCH:multi-branch selector") },
+       { GNM_FUNC_HELP_ARG, F_("ref:value") },
+       { GNM_FUNC_HELP_ARG, F_("choice1:first choice value") },
+       { GNM_FUNC_HELP_ARG, F_("value1:first result value") },
+       { GNM_FUNC_HELP_ARG, F_("choice2:second choice value") },
+       { GNM_FUNC_HELP_ARG, F_("value2:second result value") },
+       { GNM_FUNC_HELP_DESCRIPTION, F_("This function compares the reference value, @{ref}, against the 
choice values, @{choice1} etc., and returns the corresponding result value when it finds a match.  The 
choices may be followed by a default value to use.  If there are no choices that match and no default value, 
#NA! is return.") },
+        { GNM_FUNC_HELP_EXAMPLES, "=SWITCH(WEEKDAY(TODAY()),0,\"Sunday\",1,\"Saturday\",\"not weekend\")" },
+       { GNM_FUNC_HELP_SEEALSO, "IF,IFS" },
+       { GNM_FUNC_HELP_END }
+};
+
+static GnmValue *
+gnumeric_switch (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
+{
+       int a;
+       GnmValue *res = NULL;
+       GnmValue *ref;
+
+       if (argc < 1)
+               return value_new_error_VALUE (ei->pos);
+
+       ref = gnm_expr_eval (argv[0], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+       if (VALUE_IS_ERROR (ref))
+               return ref;
+
+       for (a = 1; !res && a + 1 <= argc; a += 2) {
+               GnmValue *v;
+
+               v = gnm_expr_eval (argv[a], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+               // Strict in case arguments
+               if (VALUE_IS_ERROR (v)) {
+                       res = v;
+                       break;
+               }
+
+               // Docs are unclear on what kind of equality
+               if (value_equal (v, ref))
+                       res = gnm_expr_eval (argv[a + 1], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+
+               value_release (v);
+       }
+
+       if (res == NULL) {
+               // No match
+               if (a < argc)
+                       res = gnm_expr_eval (argv[a], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+               else
+                       res = value_new_error_NA (ei->pos);
+       }
+
+       value_release (ref);
+
+       return res;
+}
+
+/***************************************************************************/
+
 static GnmFuncHelp const help_true[] = {
        { GNM_FUNC_HELP_NAME, F_("TRUE:the value TRUE") },
        { GNM_FUNC_HELP_DESCRIPTION, F_("TRUE returns the value TRUE.") },
@@ -367,6 +426,9 @@ GnmFuncDescriptor const logical_functions[] = {
        { "ifs", NULL,  help_ifs,
          NULL, gnumeric_ifs, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
+       { "switch", NULL,  help_switch,
+         NULL, gnumeric_switch, NULL, NULL,
+         GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
        { "true", "", help_true, gnumeric_true,
          NULL, NULL, NULL,
          GNM_FUNC_SIMPLE + GNM_FUNC_AUTO_UNITLESS,
diff --git a/plugins/fn-logical/plugin.xml.in b/plugins/fn-logical/plugin.xml.in
index 623afcb..b552616 100644
--- a/plugins/fn-logical/plugin.xml.in
+++ b/plugins/fn-logical/plugin.xml.in
@@ -18,6 +18,7 @@
                                <function name="iferror"/>
                                <function name="ifna"/>
                                <function name="ifs"/>
+                               <function name="switch"/>
                                <function name="true"/>
                                <function name="false"/>
                        </functions>
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 050ed34..bc73b13 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -12949,6 +12949,7 @@ oo_func_map_in (GnmConventions const *convs, Workbook *scope,
                { "RANK.AVG","RANK.AVG" },
                { "STDEV.S","STDEV" },
                { "STDEV.P","STDEVP" },
+               { "SWITCH", "SWITCH" },
                { "T.INV","R.QT" },
                { "T.INV.2T","TINV" },
                { "T.TEST","TTEST" },
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index c8e51e2..e1408dc 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -2598,6 +2598,7 @@ odf_expr_func_handler (GnmConventionsOut *out, GnmExprFunction const *func)
                { "SUMX2MY2","SUMX2MY2" },
                { "SUMX2PY2","SUMX2PY2" },
                { "SUMXMY2","SUMXMY2" },
+               { "SWITCH", "SWITCH" },
                { "SYD","SYD" },
                { "T","T" },
                { "TAN","TAN" },


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