[gnumeric] Funcs: add textjoin.



commit 6b3c92d7448cb8a4a8a0d225bd6aa8c7392ba2ae
Author: Morten Welinder <terra gnome org>
Date:   Thu Aug 4 10:07:28 2016 -0400

    Funcs: add textjoin.

 ChangeLog                            |    8 +++
 NEWS                                 |    1 +
 doc/C/func.defs                      |   11 ++++
 doc/C/functions.xml                  |   34 +++++++++++++
 plugins/fn-string/functions.c        |   85 ++++++++++++++++++++++++++++++++++
 plugins/fn-string/plugin.xml.in      |    1 +
 plugins/openoffice/openoffice-read.c |    2 +
 src/collect.c                        |    3 +-
 src/collect.h                        |    3 +-
 src/rangefunc-strings.c              |    2 +-
 src/rangefunc-strings.h              |    2 +-
 11 files changed, 148 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 50977d3..ef27f03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-04  Morten Welinder  <terra gnome org>
+
+       * src/rangefunc-strings.c (range_concatenate): Add (unused) user
+       pointer.
+
+       * src/collect.c (string_range_function): Add user pointer.  Caller
+       changed.
+
 2016-06-29  Morten Welinder <terra gnome org>
 
        * configure.ac: Post-release bump.
diff --git a/NEWS b/NEWS
index 8dd1a88..ef6d038 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Jean:
 Morten:
        * Avoid gnome-common dependency.
        * New function CONCAT.
+       * New function TEXTJOIN.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.31
diff --git a/doc/C/func.defs b/doc/C/func.defs
index 81afa94..98322c5 100644
--- a/doc/C/func.defs
+++ b/doc/C/func.defs
@@ -6578,6 +6578,17 @@ The distinction between half-width and full-width characters is described in htt
 @SEEALSO=DOLLAR,FIXED,VALUE
 
 @CATEGORY=String
+@FUNCTION=TEXTJOIN
+@SHORTDESC=the concatenation of the strings @{s1}, @{s2},… delimited by @del
+@SYNTAX=TEXTJOIN(del,blank,s1,s2,…)
+@ARGUMENTDESCRIPTION=@{del}: delimiter
+@{blank}: ignore blanks
+@{s1}: first string
+@{s2}: second string
+@EXCEL=This function is Excel compatible.
+@SEEALSO=CONCATENATE
+
+@CATEGORY=String
 @FUNCTION=TRIM
 @SHORTDESC=@{text} with only single spaces between words
 @SYNTAX=TRIM(text)
diff --git a/doc/C/functions.xml b/doc/C/functions.xml
index df64d13..a659648 100644
--- a/doc/C/functions.xml
+++ b/doc/C/functions.xml
@@ -22398,6 +22398,40 @@
       </para>
       </refsect1>
     </refentry>
+    <refentry id="gnumeric-function-TEXTJOIN">
+      <refmeta>
+        <refentrytitle>
+          <function>TEXTJOIN</function>
+        </refentrytitle>
+      </refmeta>
+      <refnamediv>
+        <refname>
+          <function>TEXTJOIN</function>
+        </refname>
+        <refpurpose>
+        the concatenation of the strings <parameter>s1</parameter>, <parameter>s2</parameter>,… delimited by 
<parameter>del</parameter>
+      </refpurpose>
+      </refnamediv>
+      <refsynopsisdiv>
+        
<synopsis><function>TEXTJOIN</function>(<parameter>del</parameter>,<parameter>blank</parameter>,<parameter>s1</parameter>,<parameter>s2</parameter>,<parameter/>…)</synopsis>
+      </refsynopsisdiv>
+      <refsect1>
+        <title>Arguments</title>
+        <para><parameter>del</parameter>: delimiter</para>
+        <para><parameter>blank</parameter>: ignore blanks</para>
+        <para><parameter>s1</parameter>: first string</para>
+        <para><parameter>s2</parameter>: second string</para>
+      </refsect1>
+      <refsect1>
+        <title>Microsoft Excel Compatibility</title>
+        <para>This function is Excel compatible.</para>
+      </refsect1>
+      <refsect1>
+        <title>See also</title>
+        <para><link linkend="gnumeric-function-CONCATENATE"><function>CONCATENATE</function></link>.
+      </para>
+      </refsect1>
+    </refentry>
     <refentry id="gnumeric-function-TRIM">
       <refmeta>
         <refentrytitle>
diff --git a/plugins/fn-string/functions.c b/plugins/fn-string/functions.c
index c627065..575a181 100644
--- a/plugins/fn-string/functions.c
+++ b/plugins/fn-string/functions.c
@@ -616,6 +616,7 @@ gnumeric_concatenate (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv
 {
        return string_range_function (argc, argv, ei,
                                      range_concatenate,
+                                     NULL,
                                      COLLECT_IGNORE_BLANKS,
                                      GNM_ERROR_VALUE);
 }
@@ -639,6 +640,87 @@ gnumeric_concat (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
 /***************************************************************************/
 
+static GnmFuncHelp const help_textjoin[] = {
+       { GNM_FUNC_HELP_NAME, F_("TEXTJOIN:the concatenation of the strings @{s1}, @{s2},\xe2\x80\xa6 
delimited by @del")},
+       { GNM_FUNC_HELP_ARG, F_("del:delimiter")},
+       { GNM_FUNC_HELP_ARG, F_("blank:ignore blanks")},
+       { GNM_FUNC_HELP_ARG, F_("s1:first string")},
+       { GNM_FUNC_HELP_ARG, F_("s2:second string")},
+       { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
+       { GNM_FUNC_HELP_EXAMPLES, "=TEXTJOIN(\"::\",FALSE,\"aa\",\"bb\")" },
+       { GNM_FUNC_HELP_SEEALSO, "CONCATENATE"},
+       { GNM_FUNC_HELP_END}
+};
+
+struct cb_textjoin {
+       char *delim;
+       gboolean ignore_blanks;
+};
+
+static int
+range_textjoin (GPtrArray *data, char **pres, gpointer user_)
+{
+       struct cb_textjoin *user = user_;
+       GString *res = g_string_new (NULL);
+       gboolean first = TRUE;
+       unsigned ui;
+
+       for (ui = 0; ui < data->len; ui++) {
+               const char *s = g_ptr_array_index (data, ui);
+
+               if (s[0] == 0 && user->ignore_blanks)
+                       continue;
+
+               if (first)
+                       first = FALSE;
+               else
+                       g_string_append (res, user->delim);
+
+               g_string_append (res, s);
+       }
+
+       *pres = g_string_free (res, FALSE);
+       return 0;
+}
+
+static GnmValue *
+gnumeric_textjoin (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
+{
+       GnmValue *v;
+       gboolean err;
+       struct cb_textjoin data;
+
+       data.delim = NULL;
+
+       if (argc < 3)
+               return value_new_error_VALUE (ei->pos);
+
+       v = gnm_expr_eval (argv[0], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+       if (VALUE_IS_ERROR (v))
+               goto done;
+       data.delim = value_get_as_string (v);
+       value_release (v);
+
+       v = gnm_expr_eval (argv[1], ei->pos, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+       if (VALUE_IS_ERROR (v))
+               goto done;
+       data.ignore_blanks = value_get_as_bool (v, &err); // What about err?
+       value_release (v);
+
+       v = string_range_function (argc - 2, argv + 2, ei,
+                                  range_textjoin,
+                                  &data,
+                                  data.ignore_blanks ? COLLECT_IGNORE_BLANKS : 0,
+                                  GNM_ERROR_VALUE);
+
+done:
+       g_free (data.delim);
+
+       return v;
+}
+
+/***************************************************************************/
+
 static GnmFuncHelp const help_rept[] = {
         { GNM_FUNC_HELP_NAME, F_("REPT:@{num} repetitions of string @{text}")},
         { GNM_FUNC_HELP_ARG, F_("text:string")},
@@ -1771,6 +1853,9 @@ GnmFuncDescriptor const string_functions[] = {
         { "text",       "Ss",           help_text,
          gnumeric_text, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
+        { "textjoin", NULL, help_textjoin,
+         NULL, gnumeric_textjoin, NULL, NULL,
+         GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
         { "trim",       "S",                         help_trim,
          gnumeric_trim, NULL, NULL, NULL,
          GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
diff --git a/plugins/fn-string/plugin.xml.in b/plugins/fn-string/plugin.xml.in
index 342822a..9a55792 100644
--- a/plugins/fn-string/plugin.xml.in
+++ b/plugins/fn-string/plugin.xml.in
@@ -42,6 +42,7 @@
                                <function name="substitute"/>
                                <function name="t"/>
                                <function name="text"/>
+                               <function name="textjoin"/>
                                <function name="trim"/>
                                <function name="unichar"/>
                                <function name="unicode"/>
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 00564d2..1a9096f 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -12918,6 +12918,7 @@ oo_func_map_in (GnmConventions const *convs, Workbook *scope,
                { "CHISQ.INV","R.QCHISQ" },
                { "CHISQ.INV.RT","CHIINV" },
                { "CHISQ.TEST","CHITEST" },
+               { "CONCAT", "CONCAT" },
                { "CONFIDENCE.NORM","CONFIDENCE" },
                { "CONFIDENCE.T","CONFIDENCE.T" },
                { "COVARIANCE.P","COVAR" },
@@ -12950,6 +12951,7 @@ oo_func_map_in (GnmConventions const *convs, Workbook *scope,
                { "T.INV","R.QT" },
                { "T.INV.2T","TINV" },
                { "T.TEST","TTEST" },
+               { "TEXTJOIN", "TEXTJOIN" },
                { "VAR.S","VAR" },
                { "VAR.P","VARP" },
                { "WEIBULL.DIST","WEIBULL" },
diff --git a/src/collect.c b/src/collect.c
index 88dc8d0..381ef1e 100644
--- a/src/collect.c
+++ b/src/collect.c
@@ -1036,6 +1036,7 @@ GnmValue *
 string_range_function (int argc, GnmExprConstPtr const *argv,
                       GnmFuncEvalInfo *ei,
                       string_range_function_t func,
+                      gpointer user,
                       CollectFlags flags,
                       GnmStdError func_error)
 {
@@ -1048,7 +1049,7 @@ string_range_function (int argc, GnmExprConstPtr const *argv,
        if (!vals)
                return error;
 
-       err = func (vals, &res);
+       err = func (vals, &res, user);
 
        collect_strings_free (vals);
 
diff --git a/src/collect.h b/src/collect.h
index 413f827..17f68d2 100644
--- a/src/collect.h
+++ b/src/collect.h
@@ -33,7 +33,7 @@ typedef enum {
 typedef int (*float_range_function_t) (gnm_float const *xs, int n, gnm_float *res);
 typedef int (*float_range_function2_t) (gnm_float const *xs, gnm_float const *ys, int n, gnm_float *res);
 typedef int (*float_range_function2d_t) (gnm_float const *xs, gnm_float const *ys, int n, gnm_float *res, 
gpointer data);
-typedef int (*string_range_function_t) (GPtrArray *xs, char**res);
+typedef int (*string_range_function_t) (GPtrArray *xs, char**res, gpointer user);
 
 gnm_float *collect_floats_value (GnmValue const *val,
                                 GnmEvalPos const *ep,
@@ -75,6 +75,7 @@ GnmValue *float_range_function2d (GnmValue const *val0, GnmValue const *val1,
 GnmValue *string_range_function (int argc, GnmExprConstPtr const *argv,
                                 GnmFuncEvalInfo *ei,
                                 string_range_function_t func,
+                                gpointer user,
                                 CollectFlags flags,
                                 GnmStdError func_error);
 
diff --git a/src/rangefunc-strings.c b/src/rangefunc-strings.c
index 5034620..86fe7d1 100644
--- a/src/rangefunc-strings.c
+++ b/src/rangefunc-strings.c
@@ -19,7 +19,7 @@
  * Returns: non-zero on error.
  */
 int
-range_concatenate (GPtrArray *data, char **res)
+range_concatenate (GPtrArray *data, char **res, gpointer user)
 {
        unsigned ui;
        size_t len = 0;
diff --git a/src/rangefunc-strings.h b/src/rangefunc-strings.h
index ffbedb0..7f6f47d 100644
--- a/src/rangefunc-strings.h
+++ b/src/rangefunc-strings.h
@@ -6,7 +6,7 @@
 
 G_BEGIN_DECLS
 
-int range_concatenate (GPtrArray *data, char **res);
+int range_concatenate (GPtrArray *data, char **res, gpointer user);
 
 G_END_DECLS
 


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