|
|
@@ -20,6 +20,7 @@ import (
|
|
|
"math/rand"
|
|
|
"reflect"
|
|
|
"regexp"
|
|
|
+ "sort"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
@@ -2839,6 +2840,52 @@ func (fn *formulaFuncs) TRUNC(argsList *list.List) (result string, err error) {
|
|
|
|
|
|
// Statistical functions
|
|
|
|
|
|
+// MEDIAN function returns the statistical median (the middle value) of a list
|
|
|
+// of supplied numbers. The syntax of the function is:
|
|
|
+//
|
|
|
+// MEDIAN(number1,[number2],...)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) MEDIAN(argsList *list.List) (result string, err error) {
|
|
|
+ if argsList.Len() == 0 {
|
|
|
+ err = errors.New("MEDIAN requires at least 1 argument")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ values := []float64{}
|
|
|
+ var median, digits float64
|
|
|
+ for token := argsList.Front(); token != nil; token = token.Next() {
|
|
|
+ arg := token.Value.(formulaArg)
|
|
|
+ switch arg.Type {
|
|
|
+ case ArgString:
|
|
|
+ if digits, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64); err != nil {
|
|
|
+ err = errors.New(formulaErrorVALUE)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ values = append(values, digits)
|
|
|
+ case ArgMatrix:
|
|
|
+ for _, row := range arg.Matrix {
|
|
|
+ for _, value := range row {
|
|
|
+ if value.String == "" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if digits, err = strconv.ParseFloat(value.String, 64); err != nil {
|
|
|
+ err = errors.New(formulaErrorVALUE)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ values = append(values, digits)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sort.Float64s(values)
|
|
|
+ if len(values)%2 == 0 {
|
|
|
+ median = (values[len(values)/2-1] + values[len(values)/2]) / 2
|
|
|
+ } else {
|
|
|
+ median = values[len(values)/2]
|
|
|
+ }
|
|
|
+ result = fmt.Sprintf("%g", median)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
// Information functions
|
|
|
|
|
|
// ISBLANK function tests if a specified cell is blank (empty) and if so,
|
|
|
@@ -2977,6 +3024,28 @@ func (fn *formulaFuncs) ISNONTEXT(argsList *list.List) (result string, err error
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+// ISNUMBER function function tests if a supplied value is a number. If so,
|
|
|
+// the function returns TRUE; Otherwise it returns FALSE. The syntax of the
|
|
|
+// function is:
|
|
|
+//
|
|
|
+// ISNUMBER(value)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) ISNUMBER(argsList *list.List) (result string, err error) {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ err = errors.New("ISNUMBER requires 1 argument")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ token := argsList.Front().Value.(formulaArg)
|
|
|
+ result = "FALSE"
|
|
|
+ if token.Type == ArgString && token.String != "" {
|
|
|
+ if _, err = strconv.Atoi(token.String); err == nil {
|
|
|
+ result = "TRUE"
|
|
|
+ }
|
|
|
+ err = nil
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
// ISODD function tests if a supplied number (or numeric expression) evaluates
|
|
|
// to an odd number, and if so, returns TRUE; Otherwise, the function returns
|
|
|
// FALSE. The syntax of the function is:
|