[gnumeric] Funcs: add SWITCH function.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Funcs: add SWITCH function.
- Date: Fri, 5 Aug 2016 19:09:48 +0000 (UTC)
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]