1 // Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
2 // this source code is governed by a BSD-style license that can be found in
5 // Package excelize providing a set of functions that allow you to write to and
6 // read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
7 // writing spreadsheet documents generated by Microsoft Excelâ„¢ 2007 and later.
8 // Supports complex components by high compatibility, and provided streaming
9 // API for generating or reading data from a worksheet with huge amounts of
10 // data. This library needs Go version 1.18 or later.
36 "golang.org/x/text/language"
37 "golang.org/x/text/message"
41 // Excel formula errors
42 formulaErrorDIV = "#DIV/0!"
43 formulaErrorNAME = "#NAME?"
44 formulaErrorNA = "#N/A"
45 formulaErrorNUM = "#NUM!"
46 formulaErrorVALUE = "#VALUE!"
47 formulaErrorREF = "#REF!"
48 formulaErrorNULL = "#NULL!"
49 formulaErrorSPILL = "#SPILL!"
50 formulaErrorCALC = "#CALC!"
51 formulaErrorGETTINGDATA = "#GETTING_DATA"
52 // Formula criteria condition enumeration
72 categoryVolumeAndLiquidMeasure
78 matchModeMinGreater = 1
83 searchModeReverseLinear = -1
84 searchModeAscBinary = 2
85 searchModeDescBinary = -2
87 maxFinancialIterations = 128
88 financialPrecision = 1.0e-08
89 // Date and time format regular expressions
90 monthRe = `((jan|january)|(feb|february)|(mar|march)|(apr|april)|(may)|(jun|june)|(jul|july)|(aug|august)|(sep|september)|(oct|october)|(nov|november)|(dec|december))`
91 df1 = `(([0-9])+)/(([0-9])+)/(([0-9])+)`
92 df2 = monthRe + ` (([0-9])+), (([0-9])+)`
93 df3 = `(([0-9])+)-(([0-9])+)-(([0-9])+)`
94 df4 = `(([0-9])+)-` + monthRe + `-(([0-9])+)`
95 datePrefix = `^((` + df1 + `|` + df2 + `|` + df3 + `|` + df4 + `) )?`
96 tfhh = `(([0-9])+) (am|pm)`
97 tfhhmm = `(([0-9])+):(([0-9])+)( (am|pm))?`
98 tfmmss = `(([0-9])+):(([0-9])+\.([0-9])+)( (am|pm))?`
99 tfhhmmss = `(([0-9])+):(([0-9])+):(([0-9])+(\.([0-9])+)?)( (am|pm))?`
100 timeSuffix = `( (` + tfhh + `|` + tfhhmm + `|` + tfmmss + `|` + tfhhmmss + `))?$`
104 // tokenPriority defined basic arithmetic operator priority
105 tokenPriority = map[string]int{
119 month2num = map[string]int{
144 dateFormats = map[string]*regexp.Regexp{
145 "mm/dd/yy": regexp.MustCompile(`^` + df1 + timeSuffix),
146 "mm dd, yy": regexp.MustCompile(`^` + df2 + timeSuffix),
147 "yy-mm-dd": regexp.MustCompile(`^` + df3 + timeSuffix),
148 "yy-mmStr-dd": regexp.MustCompile(`^` + df4 + timeSuffix),
150 timeFormats = map[string]*regexp.Regexp{
151 "hh": regexp.MustCompile(datePrefix + tfhh + `$`),
152 "hh:mm": regexp.MustCompile(datePrefix + tfhhmm + `$`),
153 "mm:ss": regexp.MustCompile(datePrefix + tfmmss + `$`),
154 "hh:mm:ss": regexp.MustCompile(datePrefix + tfhhmmss + `$`),
156 dateOnlyFormats = []*regexp.Regexp{
157 regexp.MustCompile(`^` + df1 + `$`),
158 regexp.MustCompile(`^` + df2 + `$`),
159 regexp.MustCompile(`^` + df3 + `$`),
160 regexp.MustCompile(`^` + df4 + `$`),
162 addressFmtMaps = map[string]func(col, row int) (string, error){
163 "1_TRUE": func(col, row int) (string, error) {
164 return CoordinatesToCellName(col, row, true)
166 "1_FALSE": func(col, row int) (string, error) {
167 return fmt.Sprintf("R%dC%d", row, col), nil
169 "2_TRUE": func(col, row int) (string, error) {
170 column, err := ColumnNumberToName(col)
174 return fmt.Sprintf("%s$%d", column, row), nil
176 "2_FALSE": func(col, row int) (string, error) {
177 return fmt.Sprintf("R%dC[%d]", row, col), nil
179 "3_TRUE": func(col, row int) (string, error) {
180 column, err := ColumnNumberToName(col)
184 return fmt.Sprintf("$%s%d", column, row), nil
186 "3_FALSE": func(col, row int) (string, error) {
187 return fmt.Sprintf("R[%d]C%d", row, col), nil
189 "4_TRUE": func(col, row int) (string, error) {
190 return CoordinatesToCellName(col, row, false)
192 "4_FALSE": func(col, row int) (string, error) {
193 return fmt.Sprintf("R[%d]C[%d]", row, col), nil
196 formulaFormats = []*regexp.Regexp{
197 regexp.MustCompile(`^(\d+)$`),
198 regexp.MustCompile(`^=(.*)$`),
199 regexp.MustCompile(`^<>(.*)$`),
200 regexp.MustCompile(`^<=(.*)$`),
201 regexp.MustCompile(`^>=(.*)$`),
202 regexp.MustCompile(`^<(.*)$`),
203 regexp.MustCompile(`^>(.*)$`),
205 formulaCriterias = []byte{
216 // calcContext defines the formula execution context.
217 type calcContext struct {
220 maxCalcIterations uint
221 iterations map[string]uint
222 iterationsCache map[string]formulaArg
225 // cellRef defines the structure of a cell reference.
226 type cellRef struct {
232 // cellRef defines the structure of a cell range.
233 type cellRange struct {
238 // formulaCriteria defined formula criteria parser result.
239 type formulaCriteria struct {
244 // ArgType is the type of formula argument type.
247 // Formula argument types enumeration.
249 ArgUnknown ArgType = iota
258 // formulaArg is the argument of a formula or function.
259 type formulaArg struct {
264 Matrix [][]formulaArg
268 cellRefs, cellRanges *list.List
271 // Value returns a string data type of the formula argument.
272 func (fa formulaArg) Value() (value string) {
281 return fmt.Sprintf("%g", fa.Number)
290 // ToNumber returns a formula argument with number data type.
291 func (fa formulaArg) ToNumber() formulaArg {
296 n, err = strconv.ParseFloat(fa.String, 64)
298 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
303 return newNumberFormulaArg(n)
306 // ToBool returns a formula argument with boolean data type.
307 func (fa formulaArg) ToBool() formulaArg {
312 b, err = strconv.ParseBool(fa.String)
314 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
321 return newBoolFormulaArg(b)
324 // ToList returns a formula argument with array data type.
325 func (fa formulaArg) ToList() []formulaArg {
328 var args []formulaArg
329 for _, row := range fa.Matrix {
330 args = append(args, row...)
335 case ArgNumber, ArgString, ArgError, ArgUnknown:
336 return []formulaArg{fa}
341 // formulaFuncs is the type of the formula functions.
342 type formulaFuncs struct {
348 // CalcCellValue provides a function to get calculated cell value. This feature
349 // is currently in working processing. Iterative calculation, implicit
350 // intersection, explicit intersection, array formula, table formula and some
351 // other formulas are not supported currently.
353 // Supported formula functions:
807 func (f *File) CalcCellValue(sheet, cell string, opts ...Options) (result string, err error) {
809 rawCellValue = getOptions(opts...).RawCellValue
813 if token, err = f.calcCellValue(&calcContext{
814 entry: fmt.Sprintf("%s!%s", sheet, cell),
815 maxCalcIterations: getOptions(opts...).MaxCalcIterations,
816 iterations: make(map[string]uint),
817 iterationsCache: make(map[string]formulaArg),
818 }, sheet, cell); err != nil {
819 result = token.String
823 styleIdx, _ = f.GetCellStyle(sheet, cell)
825 result = token.Value()
826 if isNum, precision, decimal := isNumeric(result); isNum {
828 result, err = f.formattedValue(&xlsxC{S: styleIdx, V: strings.ToUpper(strconv.FormatFloat(decimal, 'G', 15, 64))}, rawCellValue, CellTypeNumber)
831 if !strings.HasPrefix(result, "0") {
832 result, err = f.formattedValue(&xlsxC{S: styleIdx, V: strings.ToUpper(strconv.FormatFloat(decimal, 'f', -1, 64))}, rawCellValue, CellTypeNumber)
838 // calcCellValue calculate cell value by given context, worksheet name and cell
840 func (f *File) calcCellValue(ctx *calcContext, sheet, cell string) (result formulaArg, err error) {
842 if formula, err = f.getCellFormula(sheet, cell, true); err != nil {
845 ps := efp.ExcelParser()
846 tokens := ps.Parse(formula)
848 return f.cellResolver(ctx, sheet, cell)
850 result, err = f.evalInfixExp(ctx, sheet, cell, tokens)
854 // getPriority calculate arithmetic operator priority.
855 func getPriority(token efp.Token) (pri int) {
856 pri = tokenPriority[token.TValue]
857 if token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix {
860 if isBeginParenthesesToken(token) { // (
866 // newNumberFormulaArg constructs a number formula argument.
867 func newNumberFormulaArg(n float64) formulaArg {
869 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
871 return formulaArg{Type: ArgNumber, Number: n}
874 // newStringFormulaArg constructs a string formula argument.
875 func newStringFormulaArg(s string) formulaArg {
876 return formulaArg{Type: ArgString, String: s}
879 // newMatrixFormulaArg constructs a matrix formula argument.
880 func newMatrixFormulaArg(m [][]formulaArg) formulaArg {
881 return formulaArg{Type: ArgMatrix, Matrix: m}
884 // newListFormulaArg create a list formula argument.
885 func newListFormulaArg(l []formulaArg) formulaArg {
886 return formulaArg{Type: ArgList, List: l}
889 // newBoolFormulaArg constructs a boolean formula argument.
890 func newBoolFormulaArg(b bool) formulaArg {
895 return formulaArg{Type: ArgNumber, Number: n, Boolean: true}
898 // newErrorFormulaArg create an error formula argument of a given type with a
899 // specified error message.
900 func newErrorFormulaArg(formulaError, msg string) formulaArg {
901 return formulaArg{Type: ArgError, String: formulaError, Error: msg}
904 // newEmptyFormulaArg create an empty formula argument.
905 func newEmptyFormulaArg() formulaArg {
906 return formulaArg{Type: ArgEmpty}
909 // evalInfixExp evaluate syntax analysis by given infix expression after
910 // lexical analysis. Evaluate an infix expression containing formulas by
915 // opf - Operation formula
916 // opfd - Operand of the operation formula
917 // opft - Operator of the operation formula
918 // args - Arguments list of the operation formula
920 // TODO: handle subtypes: Nothing, Text, Logical, Error, Concatenation, Intersection, Union
921 func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.Token) (formulaArg, error) {
923 opdStack, optStack, opfStack, opfdStack, opftStack, argsStack := NewStack(), NewStack(), NewStack(), NewStack(), NewStack(), NewStack()
924 var inArray, inArrayRow bool
925 for i := 0; i < len(tokens); i++ {
928 // out of function stack
929 if opfStack.Len() == 0 {
930 if err = f.parseToken(ctx, sheet, token, opdStack, optStack); err != nil {
931 return newEmptyFormulaArg(), err
936 if isFunctionStartToken(token) {
937 if token.TValue == "ARRAY" {
941 if token.TValue == "ARRAYROW" {
946 argsStack.Push(list.New().Init())
947 opftStack.Push(token) // to know which operators belong to a function use the function as a separator
951 // in function stack, walk 2 token at once
952 if opfStack.Len() > 0 {
953 var nextToken efp.Token
954 if i+1 < len(tokens) {
955 nextToken = tokens[i+1]
958 // current token is args or range, skip next token, order required: parse reference first
959 if token.TSubType == efp.TokenSubTypeRange {
960 if opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
961 refTo := f.getDefinedNameRefTo(token.TValue, sheet)
965 // parse reference: must reference at here
966 result, err := f.parseReference(ctx, sheet, token.TValue)
970 opfdStack.Push(result)
973 if nextToken.TType == efp.TokenTypeArgument || nextToken.TType == efp.TokenTypeFunction {
974 // parse reference: reference or range at here
975 refTo := f.getDefinedNameRefTo(token.TValue, sheet)
979 result, err := f.parseReference(ctx, sheet, token.TValue)
983 // when current token is range, next token is argument and opfdStack not empty,
984 // should push value to opfdStack and continue
985 if nextToken.TType == efp.TokenTypeArgument && !opfdStack.Empty() {
986 opfdStack.Push(result)
989 argsStack.Peek().(*list.List).PushBack(result)
994 if isEndParenthesesToken(token) && isBeginParenthesesToken(opftStack.Peek().(efp.Token)) {
995 if arg := argsStack.Peek().(*list.List).Back(); arg != nil {
996 opfdStack.Push(arg.Value.(formulaArg))
997 argsStack.Peek().(*list.List).Remove(arg)
1001 // check current token is opft
1002 if err = f.parseToken(ctx, sheet, token, opfdStack, opftStack); err != nil {
1003 return newEmptyFormulaArg(), err
1006 // current token is arg
1007 if token.TType == efp.TokenTypeArgument {
1008 for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
1009 // calculate trigger
1010 topOpt := opftStack.Peek().(efp.Token)
1011 if err := calculate(opfdStack, topOpt); err != nil {
1012 argsStack.Peek().(*list.List).PushFront(newErrorFormulaArg(formulaErrorVALUE, err.Error()))
1016 if !opfdStack.Empty() {
1017 argsStack.Peek().(*list.List).PushBack(opfdStack.Pop().(formulaArg))
1022 if inArrayRow && isOperand(token) {
1025 if inArrayRow && isFunctionStopToken(token) {
1029 if inArray && isFunctionStopToken(token) {
1030 argsStack.Peek().(*list.List).PushBack(opfdStack.Pop())
1034 if errArg := f.evalInfixExpFunc(ctx, sheet, cell, token, nextToken, opfStack, opdStack, opftStack, opfdStack, argsStack); errArg.Type == ArgError {
1035 return errArg, errors.New(errArg.Error)
1039 for optStack.Len() != 0 {
1040 topOpt := optStack.Peek().(efp.Token)
1041 if err = calculate(opdStack, topOpt); err != nil {
1042 return newEmptyFormulaArg(), err
1046 if opdStack.Len() == 0 {
1047 return newEmptyFormulaArg(), ErrInvalidFormula
1049 return opdStack.Peek().(formulaArg), err
1052 // evalInfixExpFunc evaluate formula function in the infix expression.
1053 func (f *File) evalInfixExpFunc(ctx *calcContext, sheet, cell string, token, nextToken efp.Token, opfStack, opdStack, opftStack, opfdStack, argsStack *Stack) formulaArg {
1054 if !isFunctionStopToken(token) {
1055 return newEmptyFormulaArg()
1057 prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack)
1058 // call formula function to evaluate
1059 arg := callFuncByName(&formulaFuncs{f: f, sheet: sheet, cell: cell, ctx: ctx}, strings.NewReplacer(
1060 "_xlfn.", "", ".", "dot").Replace(opfStack.Peek().(efp.Token).TValue),
1061 []reflect.Value{reflect.ValueOf(argsStack.Peek().(*list.List))})
1062 if arg.Type == ArgError && opfStack.Len() == 1 {
1066 opftStack.Pop() // remove current function separator
1068 if opfStack.Len() > 0 { // still in function stack
1069 if nextToken.TType == efp.TokenTypeOperatorInfix || (opftStack.Len() > 1 && opfdStack.Len() > 0) {
1070 // mathematics calculate in formula function
1072 return newEmptyFormulaArg()
1074 argsStack.Peek().(*list.List).PushBack(arg)
1075 return newEmptyFormulaArg()
1077 if arg.Type == ArgMatrix && len(arg.Matrix) > 0 && len(arg.Matrix[0]) > 0 {
1078 opdStack.Push(arg.Matrix[0][0])
1079 return newEmptyFormulaArg()
1082 return newEmptyFormulaArg()
1085 // prepareEvalInfixExp check the token and stack state for formula function
1087 func prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack *Stack) {
1088 // current token is function stop
1089 for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
1090 // calculate trigger
1091 topOpt := opftStack.Peek().(efp.Token)
1092 if err := calculate(opfdStack, topOpt); err != nil {
1093 argsStack.Peek().(*list.List).PushBack(newErrorFormulaArg(err.Error(), err.Error()))
1100 if opftStack.Len() > 2 && opfdStack.Len() == 1 {
1101 topOpt := opftStack.Pop()
1102 if opftStack.Peek().(efp.Token).TType == efp.TokenTypeOperatorInfix {
1105 opftStack.Push(topOpt)
1107 // push opfd to args
1108 if argument && opfdStack.Len() > 0 {
1109 argsStack.Peek().(*list.List).PushBack(opfdStack.Pop().(formulaArg))
1113 // calcPow evaluate exponentiation arithmetic operations.
1114 func calcPow(rOpd, lOpd formulaArg, opdStack *Stack) error {
1115 lOpdVal := lOpd.ToNumber()
1116 if lOpdVal.Type != ArgNumber {
1117 return errors.New(lOpdVal.Value())
1119 rOpdVal := rOpd.ToNumber()
1120 if rOpdVal.Type != ArgNumber {
1121 return errors.New(rOpdVal.Value())
1123 opdStack.Push(newNumberFormulaArg(math.Pow(lOpdVal.Number, rOpdVal.Number)))
1127 // calcEq evaluate equal arithmetic operations.
1128 func calcEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
1129 opdStack.Push(newBoolFormulaArg(rOpd.Value() == lOpd.Value()))
1133 // calcNEq evaluate not equal arithmetic operations.
1134 func calcNEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
1135 opdStack.Push(newBoolFormulaArg(rOpd.Value() != lOpd.Value()))
1139 // calcL evaluate less than arithmetic operations.
1140 func calcL(rOpd, lOpd formulaArg, opdStack *Stack) error {
1141 if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
1142 opdStack.Push(newBoolFormulaArg(lOpd.Number < rOpd.Number))
1144 if rOpd.Type == ArgString && lOpd.Type == ArgString {
1145 opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) == -1))
1147 if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
1148 opdStack.Push(newBoolFormulaArg(false))
1150 if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
1151 opdStack.Push(newBoolFormulaArg(true))
1156 // calcLe evaluate less than or equal arithmetic operations.
1157 func calcLe(rOpd, lOpd formulaArg, opdStack *Stack) error {
1158 if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
1159 opdStack.Push(newBoolFormulaArg(lOpd.Number <= rOpd.Number))
1161 if rOpd.Type == ArgString && lOpd.Type == ArgString {
1162 opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) != 1))
1164 if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
1165 opdStack.Push(newBoolFormulaArg(false))
1167 if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
1168 opdStack.Push(newBoolFormulaArg(true))
1173 // calcG evaluate greater than arithmetic operations.
1174 func calcG(rOpd, lOpd formulaArg, opdStack *Stack) error {
1175 if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
1176 opdStack.Push(newBoolFormulaArg(lOpd.Number > rOpd.Number))
1178 if rOpd.Type == ArgString && lOpd.Type == ArgString {
1179 opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) == 1))
1181 if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
1182 opdStack.Push(newBoolFormulaArg(true))
1184 if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
1185 opdStack.Push(newBoolFormulaArg(false))
1190 // calcGe evaluate greater than or equal arithmetic operations.
1191 func calcGe(rOpd, lOpd formulaArg, opdStack *Stack) error {
1192 if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
1193 opdStack.Push(newBoolFormulaArg(lOpd.Number >= rOpd.Number))
1195 if rOpd.Type == ArgString && lOpd.Type == ArgString {
1196 opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) != -1))
1198 if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
1199 opdStack.Push(newBoolFormulaArg(true))
1201 if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
1202 opdStack.Push(newBoolFormulaArg(false))
1207 // calcSplice evaluate splice '&' operations.
1208 func calcSplice(rOpd, lOpd formulaArg, opdStack *Stack) error {
1209 opdStack.Push(newStringFormulaArg(lOpd.Value() + rOpd.Value()))
1213 // calcAdd evaluate addition arithmetic operations.
1214 func calcAdd(rOpd, lOpd formulaArg, opdStack *Stack) error {
1215 lOpdVal := lOpd.ToNumber()
1216 if lOpdVal.Type != ArgNumber {
1217 return errors.New(lOpdVal.Value())
1219 rOpdVal := rOpd.ToNumber()
1220 if rOpdVal.Type != ArgNumber {
1221 return errors.New(rOpdVal.Value())
1223 opdStack.Push(newNumberFormulaArg(lOpdVal.Number + rOpdVal.Number))
1227 // calcSubtract evaluate subtraction arithmetic operations.
1228 func calcSubtract(rOpd, lOpd formulaArg, opdStack *Stack) error {
1229 if rOpd.Value() == "" {
1230 rOpd = newNumberFormulaArg(0)
1232 if lOpd.Value() == "" {
1233 lOpd = newNumberFormulaArg(0)
1235 lOpdVal := lOpd.ToNumber()
1236 if lOpdVal.Type != ArgNumber {
1237 return errors.New(lOpdVal.Value())
1239 rOpdVal := rOpd.ToNumber()
1240 if rOpdVal.Type != ArgNumber {
1241 return errors.New(rOpdVal.Value())
1243 opdStack.Push(newNumberFormulaArg(lOpdVal.Number - rOpdVal.Number))
1247 // calcMultiply evaluate multiplication arithmetic operations.
1248 func calcMultiply(rOpd, lOpd formulaArg, opdStack *Stack) error {
1249 lOpdVal := lOpd.ToNumber()
1250 if lOpdVal.Type != ArgNumber {
1251 return errors.New(lOpdVal.Value())
1253 rOpdVal := rOpd.ToNumber()
1254 if rOpdVal.Type != ArgNumber {
1255 return errors.New(rOpdVal.Value())
1257 opdStack.Push(newNumberFormulaArg(lOpdVal.Number * rOpdVal.Number))
1261 // calcDiv evaluate division arithmetic operations.
1262 func calcDiv(rOpd, lOpd formulaArg, opdStack *Stack) error {
1263 lOpdVal := lOpd.ToNumber()
1264 if lOpdVal.Type != ArgNumber {
1265 return errors.New(lOpdVal.Value())
1267 rOpdVal := rOpd.ToNumber()
1268 if rOpdVal.Type != ArgNumber {
1269 return errors.New(rOpdVal.Value())
1271 if rOpdVal.Number == 0 {
1272 return errors.New(formulaErrorDIV)
1274 opdStack.Push(newNumberFormulaArg(lOpdVal.Number / rOpdVal.Number))
1278 // calculate evaluate basic arithmetic operations.
1279 func calculate(opdStack *Stack, opt efp.Token) error {
1280 if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorPrefix {
1281 if opdStack.Len() < 1 {
1282 return ErrInvalidFormula
1284 opd := opdStack.Pop().(formulaArg)
1285 opdStack.Push(newNumberFormulaArg(0 - opd.ToNumber().Number))
1287 if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorInfix {
1288 if opdStack.Len() < 2 {
1289 return ErrInvalidFormula
1291 rOpd := opdStack.Pop().(formulaArg)
1292 lOpd := opdStack.Pop().(formulaArg)
1293 if err := calcSubtract(rOpd, lOpd, opdStack); err != nil {
1297 tokenCalcFunc := map[string]func(rOpd, lOpd formulaArg, opdStack *Stack) error{
1310 if fn, ok := tokenCalcFunc[opt.TValue]; ok {
1311 if opdStack.Len() < 2 {
1312 return ErrInvalidFormula
1314 rOpd := opdStack.Pop().(formulaArg)
1315 lOpd := opdStack.Pop().(formulaArg)
1316 if opt.TValue != "&" {
1317 if rOpd.Value() == "" {
1318 rOpd = newNumberFormulaArg(0)
1320 if lOpd.Value() == "" {
1321 lOpd = newNumberFormulaArg(0)
1324 if rOpd.Type == ArgError {
1325 return errors.New(rOpd.Value())
1327 if lOpd.Type == ArgError {
1328 return errors.New(lOpd.Value())
1330 return fn(rOpd, lOpd, opdStack)
1335 // parseOperatorPrefixToken parse operator prefix token.
1336 func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token efp.Token) (err error) {
1337 if optStack.Len() == 0 {
1338 optStack.Push(token)
1341 tokenPriority := getPriority(token)
1342 topOpt := optStack.Peek().(efp.Token)
1343 topOptPriority := getPriority(topOpt)
1344 if topOpt.TValue == "-" && topOpt.TType == efp.TokenTypeOperatorPrefix && token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix {
1348 if tokenPriority > topOptPriority {
1349 optStack.Push(token)
1352 for tokenPriority <= topOptPriority {
1354 if err = calculate(opdStack, topOpt); err != nil {
1357 if optStack.Len() > 0 {
1358 topOpt = optStack.Peek().(efp.Token)
1359 topOptPriority = getPriority(topOpt)
1364 optStack.Push(token)
1368 // isFunctionStartToken determine if the token is function start.
1369 func isFunctionStartToken(token efp.Token) bool {
1370 return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart
1373 // isFunctionStopToken determine if the token is function stop.
1374 func isFunctionStopToken(token efp.Token) bool {
1375 return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStop
1378 // isBeginParenthesesToken determine if the token is begin parentheses: (.
1379 func isBeginParenthesesToken(token efp.Token) bool {
1380 return token.TType == efp.TokenTypeSubexpression && token.TSubType == efp.TokenSubTypeStart
1383 // isEndParenthesesToken determine if the token is end parentheses: ).
1384 func isEndParenthesesToken(token efp.Token) bool {
1385 return token.TType == efp.TokenTypeSubexpression && token.TSubType == efp.TokenSubTypeStop
1388 // isOperatorPrefixToken determine if the token is parse operator prefix
1390 func isOperatorPrefixToken(token efp.Token) bool {
1391 _, ok := tokenPriority[token.TValue]
1392 return (token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix) || (ok && token.TType == efp.TokenTypeOperatorInfix)
1395 // isOperand determine if the token is parse operand.
1396 func isOperand(token efp.Token) bool {
1397 return token.TType == efp.TokenTypeOperand && (token.TSubType == efp.TokenSubTypeNumber || token.TSubType == efp.TokenSubTypeText || token.TSubType == efp.TokenSubTypeLogical)
1400 // tokenToFormulaArg create a formula argument by given token.
1401 func tokenToFormulaArg(token efp.Token) formulaArg {
1402 switch token.TSubType {
1403 case efp.TokenSubTypeLogical:
1404 return newBoolFormulaArg(strings.EqualFold(token.TValue, "TRUE"))
1405 case efp.TokenSubTypeNumber:
1406 num, _ := strconv.ParseFloat(token.TValue, 64)
1407 return newNumberFormulaArg(num)
1409 return newStringFormulaArg(token.TValue)
1413 // formulaArgToToken create a token by given formula argument.
1414 func formulaArgToToken(arg formulaArg) efp.Token {
1418 return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeLogical}
1420 return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}
1422 return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeText}
1426 // parseToken parse basic arithmetic operator priority and evaluate based on
1427 // operators and operands.
1428 func (f *File) parseToken(ctx *calcContext, sheet string, token efp.Token, opdStack, optStack *Stack) error {
1429 // parse reference: must reference at here
1430 if token.TSubType == efp.TokenSubTypeRange {
1431 refTo := f.getDefinedNameRefTo(token.TValue, sheet)
1433 token.TValue = refTo
1435 result, err := f.parseReference(ctx, sheet, token.TValue)
1437 return errors.New(formulaErrorNAME)
1439 token = formulaArgToToken(result)
1441 if isOperatorPrefixToken(token) {
1442 if err := f.parseOperatorPrefixToken(optStack, opdStack, token); err != nil {
1446 if isBeginParenthesesToken(token) { // (
1447 optStack.Push(token)
1449 if isEndParenthesesToken(token) { // )
1450 for !isBeginParenthesesToken(optStack.Peek().(efp.Token)) { // != (
1451 topOpt := optStack.Peek().(efp.Token)
1452 if err := calculate(opdStack, topOpt); err != nil {
1459 if token.TType == efp.TokenTypeOperatorPostfix && !opdStack.Empty() {
1460 topOpd := opdStack.Pop().(formulaArg)
1461 opdStack.Push(newNumberFormulaArg(topOpd.Number / 100))
1464 if isOperand(token) {
1465 opdStack.Push(tokenToFormulaArg(token))
1470 // parseRef parse reference for a cell, column name or row number.
1471 func parseRef(ref string) (cellRef, bool, bool, error) {
1473 err, colErr, rowErr error
1476 tokens = strings.Split(ref, "!")
1478 if len(tokens) == 2 { // have a worksheet
1479 cr.Sheet, cell = tokens[0], tokens[1]
1481 if cr.Col, cr.Row, err = CellNameToCoordinates(cell); err != nil {
1482 if cr.Col, colErr = ColumnNameToNumber(cell); colErr == nil { // cast to column
1483 return cr, true, false, nil
1485 if cr.Row, rowErr = strconv.Atoi(cell); rowErr == nil { // cast to row
1486 return cr, false, true, nil
1488 return cr, false, false, err
1490 return cr, false, false, err
1493 // prepareCellRange checking and convert cell reference to a cell range.
1494 func (cr *cellRange) prepareCellRange(col, row bool, cellRef cellRef) error {
1496 cellRef.Row = TotalRows
1499 cellRef.Col = MaxColumns
1501 if cellRef.Sheet == "" {
1502 cellRef.Sheet = cr.From.Sheet
1504 if cr.From.Sheet != cellRef.Sheet || cr.To.Sheet != cellRef.Sheet {
1505 return errors.New("invalid reference")
1507 if cr.From.Col > cellRef.Col {
1508 cr.From.Col = cellRef.Col
1510 if cr.From.Row > cellRef.Row {
1511 cr.From.Row = cellRef.Row
1513 if cr.To.Col < cellRef.Col {
1514 cr.To.Col = cellRef.Col
1516 if cr.To.Row < cellRef.Row {
1517 cr.To.Row = cellRef.Row
1522 // parseReference parse reference and extract values by given reference
1523 // characters and default sheet name.
1524 func (f *File) parseReference(ctx *calcContext, sheet, reference string) (formulaArg, error) {
1525 reference = strings.ReplaceAll(reference, "$", "")
1526 ranges, cellRanges, cellRefs := strings.Split(reference, ":"), list.New(), list.New()
1527 if len(ranges) > 1 {
1529 for i, ref := range ranges {
1530 cellRef, col, row, err := parseRef(ref)
1532 return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
1541 if cellRef.Sheet == "" {
1542 cellRef.Sheet = sheet
1544 cr.From, cr.To = cellRef, cellRef
1547 if err := cr.prepareCellRange(col, row, cellRef); err != nil {
1548 return newErrorFormulaArg(formulaErrorNAME, err.Error()), err
1551 cellRanges.PushBack(cr)
1552 return f.rangeResolver(ctx, cellRefs, cellRanges)
1554 cellRef, _, _, err := parseRef(reference)
1556 return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
1558 if cellRef.Sheet == "" {
1559 cellRef.Sheet = sheet
1561 cellRefs.PushBack(cellRef)
1562 return f.rangeResolver(ctx, cellRefs, cellRanges)
1565 // prepareValueRange prepare value range.
1566 func prepareValueRange(cr cellRange, valueRange []int) {
1567 if cr.From.Row < valueRange[0] || valueRange[0] == 0 {
1568 valueRange[0] = cr.From.Row
1570 if cr.From.Col < valueRange[2] || valueRange[2] == 0 {
1571 valueRange[2] = cr.From.Col
1573 if cr.To.Row > valueRange[1] || valueRange[1] == 0 {
1574 valueRange[1] = cr.To.Row
1576 if cr.To.Col > valueRange[3] || valueRange[3] == 0 {
1577 valueRange[3] = cr.To.Col
1581 // prepareValueRef prepare value reference.
1582 func prepareValueRef(cr cellRef, valueRange []int) {
1583 if cr.Row < valueRange[0] || valueRange[0] == 0 {
1584 valueRange[0] = cr.Row
1586 if cr.Col < valueRange[2] || valueRange[2] == 0 {
1587 valueRange[2] = cr.Col
1589 if cr.Row > valueRange[1] || valueRange[1] == 0 {
1590 valueRange[1] = cr.Row
1592 if cr.Col > valueRange[3] || valueRange[3] == 0 {
1593 valueRange[3] = cr.Col
1597 // cellResolver calc cell value by given worksheet name, cell reference and context.
1598 func (f *File) cellResolver(ctx *calcContext, sheet, cell string) (formulaArg, error) {
1604 ref := fmt.Sprintf("%s!%s", sheet, cell)
1605 if formula, _ := f.getCellFormula(sheet, cell, true); len(formula) != 0 {
1607 if ctx.entry != ref {
1608 if ctx.iterations[ref] <= f.options.MaxCalcIterations {
1609 ctx.iterations[ref]++
1611 arg, _ = f.calcCellValue(ctx, sheet, cell)
1612 ctx.iterationsCache[ref] = arg
1616 return ctx.iterationsCache[ref], nil
1620 if value, err = f.GetCellValue(sheet, cell, Options{RawCellValue: true}); err != nil {
1623 arg = newStringFormulaArg(value)
1624 cellType, _ := f.GetCellType(sheet, cell)
1627 return arg.ToBool(), err
1628 case CellTypeNumber, CellTypeUnset:
1629 if arg.Value() == "" {
1630 return newEmptyFormulaArg(), err
1632 return arg.ToNumber(), err
1633 case CellTypeInlineString, CellTypeSharedString:
1636 return newEmptyFormulaArg(), err
1640 // rangeResolver extract value as string from given reference and range list.
1641 // This function will not ignore the empty cell. For example, A1:A2:A2:B3 will
1642 // be reference A1:B3.
1643 func (f *File) rangeResolver(ctx *calcContext, cellRefs, cellRanges *list.List) (arg formulaArg, err error) {
1644 arg.cellRefs, arg.cellRanges = cellRefs, cellRanges
1645 // value range order: from row, to row, from column, to column
1646 valueRange := []int{0, 0, 0, 0}
1648 // prepare value range
1649 for temp := cellRanges.Front(); temp != nil; temp = temp.Next() {
1650 cr := temp.Value.(cellRange)
1651 rng := []int{cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row}
1652 _ = sortCoordinates(rng)
1653 cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row = rng[0], rng[1], rng[2], rng[3]
1654 prepareValueRange(cr, valueRange)
1655 if cr.From.Sheet != "" {
1656 sheet = cr.From.Sheet
1659 for temp := cellRefs.Front(); temp != nil; temp = temp.Next() {
1660 cr := temp.Value.(cellRef)
1664 prepareValueRef(cr, valueRange)
1666 // extract value from ranges
1667 if cellRanges.Len() > 0 {
1668 arg.Type = ArgMatrix
1669 for row := valueRange[0]; row <= valueRange[1]; row++ {
1670 var matrixRow []formulaArg
1671 for col := valueRange[2]; col <= valueRange[3]; col++ {
1673 var value formulaArg
1674 if cell, err = CoordinatesToCellName(col, row); err != nil {
1677 if value, err = f.cellResolver(ctx, sheet, cell); err != nil {
1680 matrixRow = append(matrixRow, value)
1682 arg.Matrix = append(arg.Matrix, matrixRow)
1686 // extract value from references
1687 for temp := cellRefs.Front(); temp != nil; temp = temp.Next() {
1688 cr := temp.Value.(cellRef)
1690 if cell, err = CoordinatesToCellName(cr.Col, cr.Row); err != nil {
1693 if arg, err = f.cellResolver(ctx, cr.Sheet, cell); err != nil {
1696 arg.cellRefs, arg.cellRanges = cellRefs, cellRanges
1701 // callFuncByName calls the no error or only error return function with
1702 // reflect by given receiver, name and parameters.
1703 func callFuncByName(receiver interface{}, name string, params []reflect.Value) (arg formulaArg) {
1704 function := reflect.ValueOf(receiver).MethodByName(name)
1705 if function.IsValid() {
1706 rt := function.Call(params)
1710 arg = rt[0].Interface().(formulaArg)
1713 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("not support %s function", name))
1716 // formulaCriteriaParser parse formula criteria.
1717 func formulaCriteriaParser(exp formulaArg) *formulaCriteria {
1718 prepareValue := func(cond string) (expected float64, err error) {
1720 if strings.HasSuffix(cond, "%") {
1721 cond = strings.TrimSuffix(cond, "%")
1724 if expected, err = strconv.ParseFloat(cond, 64); err != nil {
1727 expected *= percentile
1730 fc, val := &formulaCriteria{}, exp.Value()
1734 for i, re := range formulaFormats {
1735 if match := re.FindStringSubmatch(val); len(match) > 1 {
1736 fc.Condition = newStringFormulaArg(match[1])
1737 if num, err := prepareValue(match[1]); err == nil {
1738 fc.Condition = newNumberFormulaArg(num)
1740 fc.Type = formulaCriterias[i]
1744 if strings.Contains(val, "?") {
1745 val = strings.ReplaceAll(val, "?", ".")
1747 if strings.Contains(val, "*") {
1748 val = strings.ReplaceAll(val, "*", ".*")
1750 fc.Type, fc.Condition = criteriaRegexp, newStringFormulaArg(val)
1751 if num := fc.Condition.ToNumber(); num.Type == ArgNumber {
1757 // formulaCriteriaEval evaluate formula criteria expression.
1758 func formulaCriteriaEval(val formulaArg, criteria *formulaCriteria) (result bool, err error) {
1760 tokenCalcFunc := map[byte]func(rOpd, lOpd formulaArg, opdStack *Stack) error{
1762 criteriaNe: calcNEq,
1768 switch criteria.Type {
1769 case criteriaEq, criteriaLe, criteriaGe, criteriaNe, criteriaL, criteriaG:
1770 if fn, ok := tokenCalcFunc[criteria.Type]; ok {
1771 if _ = fn(criteria.Condition, val, s); s.Len() > 0 {
1772 return s.Pop().(formulaArg).Number == 1, err
1775 case criteriaRegexp:
1776 return regexp.MatchString(criteria.Condition.Value(), val.Value())
1781 // Engineering Functions
1783 // BESSELI function the modified Bessel function, which is equivalent to the
1784 // Bessel function evaluated for purely imaginary arguments. The syntax of
1785 // the Besseli function is:
1788 func (fn *formulaFuncs) BESSELI(argsList *list.List) formulaArg {
1789 if argsList.Len() != 2 {
1790 return newErrorFormulaArg(formulaErrorVALUE, "BESSELI requires 2 numeric arguments")
1792 return fn.bassel(argsList, true)
1795 // BESSELJ function returns the Bessel function, Jn(x), for a specified order
1796 // and value of x. The syntax of the function is:
1799 func (fn *formulaFuncs) BESSELJ(argsList *list.List) formulaArg {
1800 if argsList.Len() != 2 {
1801 return newErrorFormulaArg(formulaErrorVALUE, "BESSELJ requires 2 numeric arguments")
1803 return fn.bassel(argsList, false)
1806 // bassel is an implementation of the formula functions BESSELI and BESSELJ.
1807 func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
1808 x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
1809 if x.Type != ArgNumber {
1812 if n.Type != ArgNumber {
1815 max, x1 := 100, x.Number*0.5
1817 x1 = math.Pow(x1, n.Number)
1818 n1, n2, n3, n4, add := fact(n.Number), 1.0, 0.0, n.Number, false
1821 for result != t && max != 0 {
1837 return newNumberFormulaArg(result)
1840 // BESSELK function calculates the modified Bessel functions, Kn(x), which are
1841 // also known as the hyperbolic Bessel Functions. These are the equivalent of
1842 // the Bessel functions, evaluated for purely imaginary arguments. The syntax
1843 // of the function is:
1846 func (fn *formulaFuncs) BESSELK(argsList *list.List) formulaArg {
1847 if argsList.Len() != 2 {
1848 return newErrorFormulaArg(formulaErrorVALUE, "BESSELK requires 2 numeric arguments")
1850 x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
1851 if x.Type != ArgNumber {
1854 if n.Type != ArgNumber {
1857 if x.Number <= 0 || n.Number < 0 {
1858 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1861 switch math.Floor(n.Number) {
1863 result = fn.besselK0(x)
1865 result = fn.besselK1(x)
1867 result = fn.besselK2(x, n)
1869 return newNumberFormulaArg(result)
1872 // besselK0 is an implementation of the formula function BESSELK.
1873 func (fn *formulaFuncs) besselK0(x formulaArg) float64 {
1876 n2 := x.Number * 0.5
1880 args.PushBack(newNumberFormulaArg(0))
1881 return -math.Log(n2)*fn.BESSELI(args).Number +
1882 (-0.57721566 + y*(0.42278420+y*(0.23069756+y*(0.3488590e-1+y*(0.262698e-2+y*
1883 (0.10750e-3+y*0.74e-5))))))
1886 return math.Exp(-x.Number) / math.Sqrt(x.Number) *
1887 (1.25331414 + y*(-0.7832358e-1+y*(0.2189568e-1+y*(-0.1062446e-1+y*
1888 (0.587872e-2+y*(-0.251540e-2+y*0.53208e-3))))))
1891 // besselK1 is an implementation of the formula function BESSELK.
1892 func (fn *formulaFuncs) besselK1(x formulaArg) float64 {
1899 args.PushBack(newNumberFormulaArg(1))
1900 return math.Log(n2)*fn.BESSELI(args).Number +
1901 (1+y*(0.15443144+y*(-0.67278579+y*(-0.18156897+y*(-0.1919402e-1+y*(-0.110404e-2+y*(-0.4686e-4)))))))/x.Number
1904 return math.Exp(-x.Number) / math.Sqrt(x.Number) *
1905 (1.25331414 + y*(0.23498619+y*(-0.3655620e-1+y*(0.1504268e-1+y*(-0.780353e-2+y*
1906 (0.325614e-2+y*(-0.68245e-3)))))))
1909 // besselK2 is an implementation of the formula function BESSELK.
1910 func (fn *formulaFuncs) besselK2(x, n formulaArg) float64 {
1911 tox, bkm, bk, bkp := 2/x.Number, fn.besselK0(x), fn.besselK1(x), 0.0
1912 for i := 1.0; i < n.Number; i++ {
1913 bkp = bkm + i*tox*bk
1920 // BESSELY function returns the Bessel function, Yn(x), (also known as the
1921 // Weber function or the Neumann function), for a specified order and value
1922 // of x. The syntax of the function is:
1925 func (fn *formulaFuncs) BESSELY(argsList *list.List) formulaArg {
1926 if argsList.Len() != 2 {
1927 return newErrorFormulaArg(formulaErrorVALUE, "BESSELY requires 2 numeric arguments")
1929 x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
1930 if x.Type != ArgNumber {
1933 if n.Type != ArgNumber {
1936 if x.Number <= 0 || n.Number < 0 {
1937 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1940 switch math.Floor(n.Number) {
1942 result = fn.besselY0(x)
1944 result = fn.besselY1(x)
1946 result = fn.besselY2(x, n)
1948 return newNumberFormulaArg(result)
1951 // besselY0 is an implementation of the formula function BESSELY.
1952 func (fn *formulaFuncs) besselY0(x formulaArg) float64 {
1955 y = x.Number * x.Number
1956 f1 := -2957821389.0 + y*(7062834065.0+y*(-512359803.6+y*(10879881.29+y*
1957 (-86327.92757+y*228.4622733))))
1958 f2 := 40076544269.0 + y*(745249964.8+y*(7189466.438+y*
1959 (47447.26470+y*(226.1030244+y))))
1962 args.PushBack(newNumberFormulaArg(0))
1963 return f1/f2 + 0.636619772*fn.BESSELJ(args).Number*math.Log(x.Number)
1967 xx := x.Number - 0.785398164
1968 f1 := 1 + y*(-0.1098628627e-2+y*(0.2734510407e-4+y*(-0.2073370639e-5+y*0.2093887211e-6)))
1969 f2 := -0.1562499995e-1 + y*(0.1430488765e-3+y*(-0.6911147651e-5+y*(0.7621095161e-6+y*
1970 (-0.934945152e-7))))
1971 return math.Sqrt(0.636619772/x.Number) * (math.Sin(xx)*f1 + z*math.Cos(xx)*f2)
1974 // besselY1 is an implementation of the formula function BESSELY.
1975 func (fn *formulaFuncs) besselY1(x formulaArg) float64 {
1977 y := x.Number * x.Number
1978 f1 := x.Number * (-0.4900604943e13 + y*(0.1275274390e13+y*(-0.5153438139e11+y*
1979 (0.7349264551e9+y*(-0.4237922726e7+y*0.8511937935e4)))))
1980 f2 := 0.2499580570e14 + y*(0.4244419664e12+y*(0.3733650367e10+y*(0.2245904002e8+y*
1981 (0.1020426050e6+y*(0.3549632885e3+y)))))
1984 args.PushBack(newNumberFormulaArg(1))
1985 return f1/f2 + 0.636619772*(fn.BESSELJ(args).Number*math.Log(x.Number)-1/x.Number)
1987 return math.Sqrt(0.636619772/x.Number) * math.Sin(x.Number-2.356194491)
1990 // besselY2 is an implementation of the formula function BESSELY.
1991 func (fn *formulaFuncs) besselY2(x, n formulaArg) float64 {
1992 tox, bym, by, byp := 2/x.Number, fn.besselY0(x), fn.besselY1(x), 0.0
1993 for i := 1.0; i < n.Number; i++ {
1994 byp = i*tox*by - bym
2001 // BIN2DEC function converts a Binary (a base-2 number) into a decimal number.
2002 // The syntax of the function is:
2005 func (fn *formulaFuncs) BIN2DEC(argsList *list.List) formulaArg {
2006 if argsList.Len() != 1 {
2007 return newErrorFormulaArg(formulaErrorVALUE, "BIN2DEC requires 1 numeric argument")
2009 token := argsList.Front().Value.(formulaArg)
2010 number := token.ToNumber()
2011 if number.Type != ArgNumber {
2012 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
2014 return fn.bin2dec(token.Value())
2017 // BIN2HEX function converts a Binary (Base 2) number into a Hexadecimal
2018 // (Base 16) number. The syntax of the function is:
2020 // BIN2HEX(number,[places])
2021 func (fn *formulaFuncs) BIN2HEX(argsList *list.List) formulaArg {
2022 if argsList.Len() < 1 {
2023 return newErrorFormulaArg(formulaErrorVALUE, "BIN2HEX requires at least 1 argument")
2025 if argsList.Len() > 2 {
2026 return newErrorFormulaArg(formulaErrorVALUE, "BIN2HEX allows at most 2 arguments")
2028 token := argsList.Front().Value.(formulaArg)
2029 number := token.ToNumber()
2030 if number.Type != ArgNumber {
2031 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
2033 decimal, newList := fn.bin2dec(token.Value()), list.New()
2034 if decimal.Type != ArgNumber {
2037 newList.PushBack(decimal)
2038 if argsList.Len() == 2 {
2039 newList.PushBack(argsList.Back().Value.(formulaArg))
2041 return fn.dec2x("BIN2HEX", newList)
2044 // BIN2OCT function converts a Binary (Base 2) number into an Octal (Base 8)
2045 // number. The syntax of the function is:
2047 // BIN2OCT(number,[places])
2048 func (fn *formulaFuncs) BIN2OCT(argsList *list.List) formulaArg {
2049 if argsList.Len() < 1 {
2050 return newErrorFormulaArg(formulaErrorVALUE, "BIN2OCT requires at least 1 argument")
2052 if argsList.Len() > 2 {
2053 return newErrorFormulaArg(formulaErrorVALUE, "BIN2OCT allows at most 2 arguments")
2055 token := argsList.Front().Value.(formulaArg)
2056 number := token.ToNumber()
2057 if number.Type != ArgNumber {
2058 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
2060 decimal, newList := fn.bin2dec(token.Value()), list.New()
2061 if decimal.Type != ArgNumber {
2064 newList.PushBack(decimal)
2065 if argsList.Len() == 2 {
2066 newList.PushBack(argsList.Back().Value.(formulaArg))
2068 return fn.dec2x("BIN2OCT", newList)
2071 // bin2dec is an implementation of the formula function BIN2DEC.
2072 func (fn *formulaFuncs) bin2dec(number string) formulaArg {
2073 decimal, length := 0.0, len(number)
2074 for i := length; i > 0; i-- {
2075 s := string(number[length-i])
2076 if i == 10 && s == "1" {
2077 decimal += math.Pow(-2.0, float64(i-1))
2081 decimal += math.Pow(2.0, float64(i-1))
2085 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
2088 return newNumberFormulaArg(decimal)
2091 // BITAND function returns the bitwise 'AND' for two supplied integers. The
2092 // syntax of the function is:
2094 // BITAND(number1,number2)
2095 func (fn *formulaFuncs) BITAND(argsList *list.List) formulaArg {
2096 return fn.bitwise("BITAND", argsList)
2099 // BITLSHIFT function returns a supplied integer, shifted left by a specified
2100 // number of bits. The syntax of the function is:
2102 // BITLSHIFT(number1,shift_amount)
2103 func (fn *formulaFuncs) BITLSHIFT(argsList *list.List) formulaArg {
2104 return fn.bitwise("BITLSHIFT", argsList)
2107 // BITOR function returns the bitwise 'OR' for two supplied integers. The
2108 // syntax of the function is:
2110 // BITOR(number1,number2)
2111 func (fn *formulaFuncs) BITOR(argsList *list.List) formulaArg {
2112 return fn.bitwise("BITOR", argsList)
2115 // BITRSHIFT function returns a supplied integer, shifted right by a specified
2116 // number of bits. The syntax of the function is:
2118 // BITRSHIFT(number1,shift_amount)
2119 func (fn *formulaFuncs) BITRSHIFT(argsList *list.List) formulaArg {
2120 return fn.bitwise("BITRSHIFT", argsList)
2123 // BITXOR function returns the bitwise 'XOR' (exclusive 'OR') for two supplied
2124 // integers. The syntax of the function is:
2126 // BITXOR(number1,number2)
2127 func (fn *formulaFuncs) BITXOR(argsList *list.List) formulaArg {
2128 return fn.bitwise("BITXOR", argsList)
2131 // bitwise is an implementation of the formula functions BITAND, BITLSHIFT,
2132 // BITOR, BITRSHIFT and BITXOR.
2133 func (fn *formulaFuncs) bitwise(name string, argsList *list.List) formulaArg {
2134 if argsList.Len() != 2 {
2135 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 numeric arguments", name))
2137 num1, num2 := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
2138 if num1.Type != ArgNumber || num2.Type != ArgNumber {
2139 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
2141 max := math.Pow(2, 48) - 1
2142 if num1.Number < 0 || num1.Number > max || num2.Number < 0 || num2.Number > max {
2143 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
2145 bitwiseFuncMap := map[string]func(a, b int) int{
2146 "BITAND": func(a, b int) int { return a & b },
2147 "BITLSHIFT": func(a, b int) int { return a << uint(b) },
2148 "BITOR": func(a, b int) int { return a | b },
2149 "BITRSHIFT": func(a, b int) int { return a >> uint(b) },
2150 "BITXOR": func(a, b int) int { return a ^ b },
2152 bitwiseFunc := bitwiseFuncMap[name]
2153 return newNumberFormulaArg(float64(bitwiseFunc(int(num1.Number), int(num2.Number))))
2156 // COMPLEX function takes two arguments, representing the real and the
2157 // imaginary coefficients of a complex number, and from these, creates a
2158 // complex number. The syntax of the function is:
2160 // COMPLEX(real_num,i_num,[suffix])
2161 func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
2162 if argsList.Len() < 2 {
2163 return newErrorFormulaArg(formulaErrorVALUE, "COMPLEX requires at least 2 arguments")
2165 if argsList.Len() > 3 {
2166 return newErrorFormulaArg(formulaErrorVALUE, "COMPLEX allows at most 3 arguments")
2168 realNum, i, suffix := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber(), "i"
2169 if realNum.Type != ArgNumber {
2172 if i.Type != ArgNumber {
2175 if argsList.Len() == 3 {
2176 if suffix = strings.ToLower(argsList.Back().Value.(formulaArg).Value()); suffix != "i" && suffix != "j" {
2177 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
2180 return newStringFormulaArg(cmplx2str(complex(realNum.Number, i.Number), suffix))
2183 // cmplx2str replace complex number string characters.
2184 func cmplx2str(num complex128, suffix string) string {
2185 realPart, imagPart := fmt.Sprint(real(num)), fmt.Sprint(imag(num))
2186 isNum, i, decimal := isNumeric(realPart)
2187 if isNum && i > 15 {
2188 realPart = strconv.FormatFloat(decimal, 'G', 15, 64)
2190 isNum, i, decimal = isNumeric(imagPart)
2191 if isNum && i > 15 {
2192 imagPart = strconv.FormatFloat(decimal, 'G', 15, 64)
2201 c = strings.TrimPrefix(c, "(")
2202 c = strings.TrimPrefix(c, "+0+")
2203 c = strings.TrimPrefix(c, "-0+")
2204 c = strings.TrimSuffix(c, ")")
2205 c = strings.TrimPrefix(c, "0+")
2206 if strings.HasPrefix(c, "0-") {
2207 c = "-" + strings.TrimPrefix(c, "0-")
2209 c = strings.TrimPrefix(c, "0+")
2210 c = strings.TrimSuffix(c, "+0i")
2211 c = strings.TrimSuffix(c, "-0i")
2212 c = strings.NewReplacer("+1i", "+i", "-1i", "-i").Replace(c)
2213 c = strings.ReplaceAll(c, "i", suffix)
2217 // str2cmplx convert complex number string characters.
2218 func str2cmplx(c string) string {
2219 c = strings.ReplaceAll(c, "j", "i")
2223 c = strings.NewReplacer("+i", "+1i", "-i", "-1i").Replace(c)
2227 // conversionUnit defined unit info for conversion.
2228 type conversionUnit struct {
2233 // conversionUnits maps info list for unit conversion, that can be used in
2234 // formula function CONVERT.
2235 var conversionUnits = map[string]conversionUnit{
2237 "g": {group: categoryWeightAndMass, allowPrefix: true},
2238 "sg": {group: categoryWeightAndMass, allowPrefix: false},
2239 "lbm": {group: categoryWeightAndMass, allowPrefix: false},
2240 "u": {group: categoryWeightAndMass, allowPrefix: true},
2241 "ozm": {group: categoryWeightAndMass, allowPrefix: false},
2242 "grain": {group: categoryWeightAndMass, allowPrefix: false},
2243 "cwt": {group: categoryWeightAndMass, allowPrefix: false},
2244 "shweight": {group: categoryWeightAndMass, allowPrefix: false},
2245 "uk_cwt": {group: categoryWeightAndMass, allowPrefix: false},
2246 "lcwt": {group: categoryWeightAndMass, allowPrefix: false},
2247 "hweight": {group: categoryWeightAndMass, allowPrefix: false},
2248 "stone": {group: categoryWeightAndMass, allowPrefix: false},
2249 "ton": {group: categoryWeightAndMass, allowPrefix: false},
2250 "uk_ton": {group: categoryWeightAndMass, allowPrefix: false},
2251 "LTON": {group: categoryWeightAndMass, allowPrefix: false},
2252 "brton": {group: categoryWeightAndMass, allowPrefix: false},
2254 "m": {group: categoryDistance, allowPrefix: true},
2255 "mi": {group: categoryDistance, allowPrefix: false},
2256 "Nmi": {group: categoryDistance, allowPrefix: false},
2257 "in": {group: categoryDistance, allowPrefix: false},
2258 "ft": {group: categoryDistance, allowPrefix: false},
2259 "yd": {group: categoryDistance, allowPrefix: false},
2260 "ang": {group: categoryDistance, allowPrefix: true},
2261 "ell": {group: categoryDistance, allowPrefix: false},
2262 "ly": {group: categoryDistance, allowPrefix: false},
2263 "parsec": {group: categoryDistance, allowPrefix: false},
2264 "pc": {group: categoryDistance, allowPrefix: false},
2265 "Pica": {group: categoryDistance, allowPrefix: false},
2266 "Picapt": {group: categoryDistance, allowPrefix: false},
2267 "pica": {group: categoryDistance, allowPrefix: false},
2268 "survey_mi": {group: categoryDistance, allowPrefix: false},
2270 "yr": {group: categoryTime, allowPrefix: false},
2271 "day": {group: categoryTime, allowPrefix: false},
2272 "d": {group: categoryTime, allowPrefix: false},
2273 "hr": {group: categoryTime, allowPrefix: false},
2274 "mn": {group: categoryTime, allowPrefix: false},
2275 "min": {group: categoryTime, allowPrefix: false},
2276 "sec": {group: categoryTime, allowPrefix: true},
2277 "s": {group: categoryTime, allowPrefix: true},
2279 "Pa": {group: categoryPressure, allowPrefix: true},
2280 "p": {group: categoryPressure, allowPrefix: true},
2281 "atm": {group: categoryPressure, allowPrefix: true},
2282 "at": {group: categoryPressure, allowPrefix: true},
2283 "mmHg": {group: categoryPressure, allowPrefix: true},
2284 "psi": {group: categoryPressure, allowPrefix: true},
2285 "Torr": {group: categoryPressure, allowPrefix: true},
2287 "N": {group: categoryForce, allowPrefix: true},
2288 "dyn": {group: categoryForce, allowPrefix: true},
2289 "dy": {group: categoryForce, allowPrefix: true},
2290 "lbf": {group: categoryForce, allowPrefix: false},
2291 "pond": {group: categoryForce, allowPrefix: true},
2293 "J": {group: categoryEnergy, allowPrefix: true},
2294 "e": {group: categoryEnergy, allowPrefix: true},
2295 "c": {group: categoryEnergy, allowPrefix: true},
2296 "cal": {group: categoryEnergy, allowPrefix: true},
2297 "eV": {group: categoryEnergy, allowPrefix: true},
2298 "ev": {group: categoryEnergy, allowPrefix: true},
2299 "HPh": {group: categoryEnergy, allowPrefix: false},
2300 "hh": {group: categoryEnergy, allowPrefix: false},
2301 "Wh": {group: categoryEnergy, allowPrefix: true},
2302 "wh": {group: categoryEnergy, allowPrefix: true},
2303 "flb": {group: categoryEnergy, allowPrefix: false},
2304 "BTU": {group: categoryEnergy, allowPrefix: false},
2305 "btu": {group: categoryEnergy, allowPrefix: false},
2307 "HP": {group: categoryPower, allowPrefix: false},
2308 "h": {group: categoryPower, allowPrefix: false},
2309 "W": {group: categoryPower, allowPrefix: true},
2310 "w": {group: categoryPower, allowPrefix: true},
2311 "PS": {group: categoryPower, allowPrefix: false},
2312 "T": {group: categoryMagnetism, allowPrefix: true},
2313 "ga": {group: categoryMagnetism, allowPrefix: true},
2315 "C": {group: categoryTemperature, allowPrefix: false},
2316 "cel": {group: categoryTemperature, allowPrefix: false},
2317 "F": {group: categoryTemperature, allowPrefix: false},
2318 "fah": {group: categoryTemperature, allowPrefix: false},
2319 "K": {group: categoryTemperature, allowPrefix: false},
2320 "kel": {group: categoryTemperature, allowPrefix: false},
2321 "Rank": {group: categoryTemperature, allowPrefix: false},
2322 "Reau": {group: categoryTemperature, allowPrefix: false},
2324 "l": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2325 "L": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2326 "lt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2327 "tsp": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2328 "tspm": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2329 "tbs": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2330 "oz": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2331 "cup": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2332 "pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2333 "us_pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2334 "uk_pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2335 "qt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2336 "uk_qt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2337 "gal": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2338 "uk_gal": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2339 "ang3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2340 "ang^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2341 "barrel": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2342 "bushel": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2343 "in3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2344 "in^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2345 "ft3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2346 "ft^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2347 "ly3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2348 "ly^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2349 "m3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2350 "m^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true},
2351 "mi3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2352 "mi^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2353 "yd3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2354 "yd^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2355 "Nmi3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2356 "Nmi^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2357 "Pica3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2358 "Pica^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2359 "Picapt3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2360 "Picapt^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2361 "GRT": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2362 "regton": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2363 "MTON": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false},
2365 "ha": {group: categoryArea, allowPrefix: true},
2366 "uk_acre": {group: categoryArea, allowPrefix: false},
2367 "us_acre": {group: categoryArea, allowPrefix: false},
2368 "ang2": {group: categoryArea, allowPrefix: true},
2369 "ang^2": {group: categoryArea, allowPrefix: true},
2370 "ar": {group: categoryArea, allowPrefix: true},
2371 "ft2": {group: categoryArea, allowPrefix: false},
2372 "ft^2": {group: categoryArea, allowPrefix: false},
2373 "in2": {group: categoryArea, allowPrefix: false},
2374 "in^2": {group: categoryArea, allowPrefix: false},
2375 "ly2": {group: categoryArea, allowPrefix: false},
2376 "ly^2": {group: categoryArea, allowPrefix: false},
2377 "m2": {group: categoryArea, allowPrefix: true},
2378 "m^2": {group: categoryArea, allowPrefix: true},
2379 "Morgen": {group: categoryArea, allowPrefix: false},
2380 "mi2": {group: categoryArea, allowPrefix: false},
2381 "mi^2": {group: categoryArea, allowPrefix: false},
2382 "Nmi2": {group: categoryArea, allowPrefix: false},
2383 "Nmi^2": {group: categoryArea, allowPrefix: false},
2384 "Pica2": {group: categoryArea, allowPrefix: false},
2385 "Pica^2": {group: categoryArea, allowPrefix: false},
2386 "Picapt2": {group: categoryArea, allowPrefix: false},
2387 "Picapt^2": {group: categoryArea, allowPrefix: false},
2388 "yd2": {group: categoryArea, allowPrefix: false},
2389 "yd^2": {group: categoryArea, allowPrefix: false},
2391 "byte": {group: categoryInformation, allowPrefix: true},
2392 "bit": {group: categoryInformation, allowPrefix: true},
2394 "m/s": {group: categorySpeed, allowPrefix: true},
2395 "m/sec": {group: categorySpeed, allowPrefix: true},
2396 "m/h": {group: categorySpeed, allowPrefix: true},
2397 "m/hr": {group: categorySpeed, allowPrefix: true},
2398 "mph": {group: categorySpeed, allowPrefix: false},
2399 "admkn": {group: categorySpeed, allowPrefix: false},
2400 "kn": {group: categorySpeed, allowPrefix: false},
2403 // unitConversions maps details of the Units of measure conversion factors,
2404 // organised by group.
2405 var unitConversions = map[byte]map[string]float64{
2406 // conversion uses gram (g) as an intermediate unit
2407 categoryWeightAndMass: {
2409 "sg": 6.85217658567918e-05,
2410 "lbm": 2.20462262184878e-03,
2411 "u": 6.02214179421676e+23,
2412 "ozm": 3.52739619495804e-02,
2413 "grain": 1.54323583529414e+01,
2414 "cwt": 2.20462262184878e-05,
2415 "shweight": 2.20462262184878e-05,
2416 "uk_cwt": 1.96841305522212e-05,
2417 "lcwt": 1.96841305522212e-05,
2418 "hweight": 1.96841305522212e-05,
2419 "stone": 1.57473044417770e-04,
2420 "ton": 1.10231131092439e-06,
2421 "uk_ton": 9.84206527611061e-07,
2422 "LTON": 9.84206527611061e-07,
2423 "brton": 9.84206527611061e-07,
2425 // conversion uses meter (m) as an intermediate unit
2428 "mi": 6.21371192237334e-04,
2429 "Nmi": 5.39956803455724e-04,
2430 "in": 3.93700787401575e+01,
2431 "ft": 3.28083989501312e+00,
2432 "yd": 1.09361329833771e+00,
2434 "ell": 8.74890638670166e-01,
2435 "ly": 1.05700083402462e-16,
2436 "parsec": 3.24077928966473e-17,
2437 "pc": 3.24077928966473e-17,
2438 "Pica": 2.83464566929134e+03,
2439 "Picapt": 2.83464566929134e+03,
2440 "pica": 2.36220472440945e+02,
2441 "survey_mi": 6.21369949494950e-04,
2443 // conversion uses second (s) as an intermediate unit
2445 "yr": 3.16880878140289e-08,
2446 "day": 1.15740740740741e-05,
2447 "d": 1.15740740740741e-05,
2448 "hr": 2.77777777777778e-04,
2449 "mn": 1.66666666666667e-02,
2450 "min": 1.66666666666667e-02,
2454 // conversion uses Pascal (Pa) as an intermediate unit
2458 "atm": 9.86923266716013e-06,
2459 "at": 9.86923266716013e-06,
2460 "mmHg": 7.50063755419211e-03,
2461 "psi": 1.45037737730209e-04,
2462 "Torr": 7.50061682704170e-03,
2464 // conversion uses Newton (N) as an intermediate unit
2469 "lbf": 2.24808923655339e-01,
2470 "pond": 1.01971621297793e+02,
2472 // conversion uses Joule (J) as an intermediate unit
2475 "e": 9.99999519343231e+06,
2476 "c": 2.39006249473467e-01,
2477 "cal": 2.38846190642017e-01,
2478 "eV": 6.24145700000000e+18,
2479 "ev": 6.24145700000000e+18,
2480 "HPh": 3.72506430801000e-07,
2481 "hh": 3.72506430801000e-07,
2482 "Wh": 2.77777916238711e-04,
2483 "wh": 2.77777916238711e-04,
2484 "flb": 2.37304222192651e+01,
2485 "BTU": 9.47815067349015e-04,
2486 "btu": 9.47815067349015e-04,
2488 // conversion uses Horsepower (HP) as an intermediate unit
2492 "W": 7.45699871582270e+02,
2493 "w": 7.45699871582270e+02,
2494 "PS": 1.01386966542400e+00,
2496 // conversion uses Tesla (T) as an intermediate unit
2497 categoryMagnetism: {
2501 // conversion uses litre (l) as an intermediate unit
2502 categoryVolumeAndLiquidMeasure: {
2506 "tsp": 2.02884136211058e+02,
2508 "tbs": 6.76280454036860e+01,
2509 "oz": 3.38140227018430e+01,
2510 "cup": 4.22675283773038e+00,
2511 "pt": 2.11337641886519e+00,
2512 "us_pt": 2.11337641886519e+00,
2513 "uk_pt": 1.75975398639270e+00,
2514 "qt": 1.05668820943259e+00,
2515 "uk_qt": 8.79876993196351e-01,
2516 "gal": 2.64172052358148e-01,
2517 "uk_gal": 2.19969248299088e-01,
2520 "barrel": 6.28981077043211e-03,
2521 "bushel": 2.83775932584017e-02,
2522 "in3": 6.10237440947323e+01,
2523 "in^3": 6.10237440947323e+01,
2524 "ft3": 3.53146667214886e-02,
2525 "ft^3": 3.53146667214886e-02,
2526 "ly3": 1.18093498844171e-51,
2527 "ly^3": 1.18093498844171e-51,
2530 "mi3": 2.39912758578928e-13,
2531 "mi^3": 2.39912758578928e-13,
2532 "yd3": 1.30795061931439e-03,
2533 "yd^3": 1.30795061931439e-03,
2534 "Nmi3": 1.57426214685811e-13,
2535 "Nmi^3": 1.57426214685811e-13,
2536 "Pica3": 2.27769904358706e+07,
2537 "Pica^3": 2.27769904358706e+07,
2538 "Picapt3": 2.27769904358706e+07,
2539 "Picapt^3": 2.27769904358706e+07,
2540 "GRT": 3.53146667214886e-04,
2541 "regton": 3.53146667214886e-04,
2542 "MTON": 8.82866668037215e-04,
2544 // conversion uses hectare (ha) as an intermediate unit
2547 "uk_acre": 2.47105381467165e+00,
2548 "us_acre": 2.47104393046628e+00,
2552 "ft2": 1.07639104167097e+05,
2553 "ft^2": 1.07639104167097e+05,
2554 "in2": 1.55000310000620e+07,
2555 "in^2": 1.55000310000620e+07,
2556 "ly2": 1.11725076312873e-28,
2557 "ly^2": 1.11725076312873e-28,
2561 "mi2": 3.86102158542446e-03,
2562 "mi^2": 3.86102158542446e-03,
2563 "Nmi2": 2.91553349598123e-03,
2564 "Nmi^2": 2.91553349598123e-03,
2565 "Pica2": 8.03521607043214e+10,
2566 "Pica^2": 8.03521607043214e+10,
2567 "Picapt2": 8.03521607043214e+10,
2568 "Picapt^2": 8.03521607043214e+10,
2569 "yd2": 1.19599004630108e+04,
2570 "yd^2": 1.19599004630108e+04,
2572 // conversion uses bit (bit) as an intermediate unit
2573 categoryInformation: {
2577 // conversion uses Meters per Second (m/s) as an intermediate unit
2583 "mph": 2.23693629205440e+00,
2584 "admkn": 1.94260256941567e+00,
2585 "kn": 1.94384449244060e+00,
2589 // conversionMultipliers maps details of the Multiplier prefixes that can be
2590 // used with Units of Measure in CONVERT.
2591 var conversionMultipliers = map[string]float64{
2613 "Yi": math.Pow(2, 80),
2614 "Zi": math.Pow(2, 70),
2615 "Ei": math.Pow(2, 60),
2616 "Pi": math.Pow(2, 50),
2617 "Ti": math.Pow(2, 40),
2618 "Gi": math.Pow(2, 30),
2619 "Mi": math.Pow(2, 20),
2620 "ki": math.Pow(2, 10),
2623 // getUnitDetails check and returns the unit of measure details.
2624 func getUnitDetails(uom string) (unit string, catgory byte, res float64, ok bool) {
2629 if unit, ok := conversionUnits[uom]; ok {
2630 return uom, unit.group, 1, ok
2632 // 1 character standard metric multiplier prefixes
2633 multiplierType := uom[:1]
2635 conversionUnit, ok1 := conversionUnits[uom]
2636 multiplier, ok2 := conversionMultipliers[multiplierType]
2638 if !conversionUnit.allowPrefix {
2642 unitCategory := conversionUnit.group
2643 return uom, unitCategory, multiplier, true
2645 // 2 character standard and binary metric multiplier prefixes
2647 multiplierType += uom[:1]
2650 conversionUnit, ok1 = conversionUnits[uom]
2651 multiplier, ok2 = conversionMultipliers[multiplierType]
2653 if !conversionUnit.allowPrefix {
2657 unitCategory := conversionUnit.group
2658 return uom, unitCategory, multiplier, true
2664 // resolveTemperatureSynonyms returns unit of measure according to a given
2665 // temperature synonyms.
2666 func resolveTemperatureSynonyms(uom string) string {
2678 // convertTemperature returns converted temperature by a given unit of measure.
2679 func convertTemperature(fromUOM, toUOM string, value float64) float64 {
2680 fromUOM = resolveTemperatureSynonyms(fromUOM)
2681 toUOM = resolveTemperatureSynonyms(toUOM)
2682 if fromUOM == toUOM {
2685 // convert to Kelvin
2688 value = (value-32)/1.8 + 273.15
2694 value = value*1.25 + 273.15
2696 // convert from Kelvin
2699 value = (value-273.15)*1.8 + 32
2705 value = (value - 273.15) * 0.8
2710 // CONVERT function converts a number from one unit type (e.g. Yards) to
2711 // another unit type (e.g. Meters). The syntax of the function is:
2713 // CONVERT(number,from_unit,to_unit)
2714 func (fn *formulaFuncs) CONVERT(argsList *list.List) formulaArg {
2715 if argsList.Len() != 3 {
2716 return newErrorFormulaArg(formulaErrorVALUE, "CONVERT requires 3 arguments")
2718 num := argsList.Front().Value.(formulaArg).ToNumber()
2719 if num.Type != ArgNumber {
2722 fromUOM, fromCategory, fromMultiplier, ok1 := getUnitDetails(argsList.Front().Next().Value.(formulaArg).Value())
2723 toUOM, toCategory, toMultiplier, ok2 := getUnitDetails(argsList.Back().Value.(formulaArg).Value())
2724 if !ok1 || !ok2 || fromCategory != toCategory {
2725 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
2727 val := num.Number * fromMultiplier
2728 if fromUOM == toUOM && fromMultiplier == toMultiplier {
2729 return newNumberFormulaArg(val / fromMultiplier)
2730 } else if fromUOM == toUOM {
2731 return newNumberFormulaArg(val / toMultiplier)
2732 } else if fromCategory == categoryTemperature {
2733 return newNumberFormulaArg(convertTemperature(fromUOM, toUOM, val))
2735 fromConversion := unitConversions[fromCategory][fromUOM]
2736 toConversion := unitConversions[fromCategory][toUOM]
2737 baseValue := val * (1 / fromConversion)
2738 return newNumberFormulaArg((baseValue * toConversion) / toMultiplier)
2741 // DEC2BIN function converts a decimal number into a Binary (Base 2) number.
2742 // The syntax of the function is:
2744 // DEC2BIN(number,[places])
2745 func (fn *formulaFuncs) DEC2BIN(argsList *list.List) formulaArg {
2746 return fn.dec2x("DEC2BIN", argsList)
2749 // DEC2HEX function converts a decimal number into a Hexadecimal (Base 16)
2750 // number. The syntax of the function is:
2752 // DEC2HEX(number,[places])
2753 func (fn *formulaFuncs) DEC2HEX(argsList *list.List) formulaArg {
2754 return fn.dec2x("DEC2HEX", argsList)
2757 // DEC2OCT function converts a decimal number into an Octal (Base 8) number.
2758 // The syntax of the function is:
2760 // DEC2OCT(number,[places])
2761 func (fn *formulaFuncs) DEC2OCT(argsList *list.List) formulaArg {
2762 return fn.dec2x("DEC2OCT", argsList)
2765 // dec2x is an implementation of the formula functions DEC2BIN, DEC2HEX and
2767 func (fn *formulaFuncs) dec2x(name string, argsList *list.List) formulaArg {
2768 if argsList.Len() < 1 {
2769 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
2771 if argsList.Len() > 2 {
2772 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 2 arguments", name))
2774 decimal := argsList.Front().Value.(formulaArg).ToNumber()
2775 if decimal.Type != ArgNumber {
2776 return newErrorFormulaArg(formulaErrorVALUE, decimal.Error)
2778 maxLimitMap := map[string]float64{
2782 "BIN2HEX": 549755813887,
2783 "DEC2HEX": 549755813887,
2784 "OCT2HEX": 549755813887,
2785 "BIN2OCT": 536870911,
2786 "DEC2OCT": 536870911,
2787 "HEX2OCT": 536870911,
2789 minLimitMap := map[string]float64{
2793 "BIN2HEX": -549755813888,
2794 "DEC2HEX": -549755813888,
2795 "OCT2HEX": -549755813888,
2796 "BIN2OCT": -536870912,
2797 "DEC2OCT": -536870912,
2798 "HEX2OCT": -536870912,
2800 baseMap := map[string]int{
2811 maxLimit, minLimit := maxLimitMap[name], minLimitMap[name]
2812 base := baseMap[name]
2813 if decimal.Number < minLimit || decimal.Number > maxLimit {
2814 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
2816 n := int64(decimal.Number)
2817 binary := strconv.FormatUint(*(*uint64)(unsafe.Pointer(&n)), base)
2818 if argsList.Len() == 2 {
2819 places := argsList.Back().Value.(formulaArg).ToNumber()
2820 if places.Type != ArgNumber {
2821 return newErrorFormulaArg(formulaErrorVALUE, places.Error)
2823 binaryPlaces := len(binary)
2824 if places.Number < 0 || places.Number > 10 || binaryPlaces > int(places.Number) {
2825 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
2827 return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%s%s", strings.Repeat("0", int(places.Number)-binaryPlaces), binary)))
2829 if decimal.Number < 0 && len(binary) > 10 {
2830 return newStringFormulaArg(strings.ToUpper(binary[len(binary)-10:]))
2832 return newStringFormulaArg(strings.ToUpper(binary))
2835 // DELTA function tests two numbers for equality and returns the Kronecker
2836 // Delta. i.e. the function returns 1 if the two supplied numbers are equal
2837 // and 0 otherwise. The syntax of the function is:
2839 // DELTA(number1,[number2])
2840 func (fn *formulaFuncs) DELTA(argsList *list.List) formulaArg {
2841 if argsList.Len() < 1 {
2842 return newErrorFormulaArg(formulaErrorVALUE, "DELTA requires at least 1 argument")
2844 if argsList.Len() > 2 {
2845 return newErrorFormulaArg(formulaErrorVALUE, "DELTA allows at most 2 arguments")
2847 number1 := argsList.Front().Value.(formulaArg).ToNumber()
2848 if number1.Type != ArgNumber {
2851 number2 := newNumberFormulaArg(0)
2852 if argsList.Len() == 2 {
2853 if number2 = argsList.Back().Value.(formulaArg).ToNumber(); number2.Type != ArgNumber {
2857 return newBoolFormulaArg(number1.Number == number2.Number).ToNumber()
2860 // ERF function calculates the Error Function, integrated between two supplied
2861 // limits. The syntax of the function is:
2863 // ERF(lower_limit,[upper_limit])
2864 func (fn *formulaFuncs) ERF(argsList *list.List) formulaArg {
2865 if argsList.Len() < 1 {
2866 return newErrorFormulaArg(formulaErrorVALUE, "ERF requires at least 1 argument")
2868 if argsList.Len() > 2 {
2869 return newErrorFormulaArg(formulaErrorVALUE, "ERF allows at most 2 arguments")
2871 lower := argsList.Front().Value.(formulaArg).ToNumber()
2872 if lower.Type != ArgNumber {
2875 if argsList.Len() == 2 {
2876 upper := argsList.Back().Value.(formulaArg).ToNumber()
2877 if upper.Type != ArgNumber {
2880 return newNumberFormulaArg(math.Erf(upper.Number) - math.Erf(lower.Number))
2882 return newNumberFormulaArg(math.Erf(lower.Number))
2885 // ERFdotPRECISE function calculates the Error Function, integrated between a
2886 // supplied lower or upper limit and 0. The syntax of the function is:
2889 func (fn *formulaFuncs) ERFdotPRECISE(argsList *list.List) formulaArg {
2890 if argsList.Len() != 1 {
2891 return newErrorFormulaArg(formulaErrorVALUE, "ERF.PRECISE requires 1 argument")
2893 x := argsList.Front().Value.(formulaArg).ToNumber()
2894 if x.Type != ArgNumber {
2897 return newNumberFormulaArg(math.Erf(x.Number))
2900 // erfc is an implementation of the formula functions ERFC and ERFC.PRECISE.
2901 func (fn *formulaFuncs) erfc(name string, argsList *list.List) formulaArg {
2902 if argsList.Len() != 1 {
2903 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 1 argument", name))
2905 x := argsList.Front().Value.(formulaArg).ToNumber()
2906 if x.Type != ArgNumber {
2909 return newNumberFormulaArg(math.Erfc(x.Number))
2912 // ERFC function calculates the Complementary Error Function, integrated
2913 // between a supplied lower limit and infinity. The syntax of the function
2917 func (fn *formulaFuncs) ERFC(argsList *list.List) formulaArg {
2918 return fn.erfc("ERFC", argsList)
2921 // ERFCdotPRECISE function calculates the Complementary Error Function,
2922 // integrated between a supplied lower limit and infinity. The syntax of the
2926 func (fn *formulaFuncs) ERFCdotPRECISE(argsList *list.List) formulaArg {
2927 return fn.erfc("ERFC.PRECISE", argsList)
2930 // GESTEP unction tests whether a supplied number is greater than a supplied
2931 // step size and returns. The syntax of the function is:
2933 // GESTEP(number,[step])
2934 func (fn *formulaFuncs) GESTEP(argsList *list.List) formulaArg {
2935 if argsList.Len() < 1 {
2936 return newErrorFormulaArg(formulaErrorVALUE, "GESTEP requires at least 1 argument")
2938 if argsList.Len() > 2 {
2939 return newErrorFormulaArg(formulaErrorVALUE, "GESTEP allows at most 2 arguments")
2941 number := argsList.Front().Value.(formulaArg).ToNumber()
2942 if number.Type != ArgNumber {
2945 step := newNumberFormulaArg(0)
2946 if argsList.Len() == 2 {
2947 if step = argsList.Back().Value.(formulaArg).ToNumber(); step.Type != ArgNumber {
2951 return newBoolFormulaArg(number.Number >= step.Number).ToNumber()
2954 // HEX2BIN function converts a Hexadecimal (Base 16) number into a Binary
2955 // (Base 2) number. The syntax of the function is:
2957 // HEX2BIN(number,[places])
2958 func (fn *formulaFuncs) HEX2BIN(argsList *list.List) formulaArg {
2959 if argsList.Len() < 1 {
2960 return newErrorFormulaArg(formulaErrorVALUE, "HEX2BIN requires at least 1 argument")
2962 if argsList.Len() > 2 {
2963 return newErrorFormulaArg(formulaErrorVALUE, "HEX2BIN allows at most 2 arguments")
2965 decimal, newList := fn.hex2dec(argsList.Front().Value.(formulaArg).Value()), list.New()
2966 if decimal.Type != ArgNumber {
2969 newList.PushBack(decimal)
2970 if argsList.Len() == 2 {
2971 newList.PushBack(argsList.Back().Value.(formulaArg))
2973 return fn.dec2x("HEX2BIN", newList)
2976 // HEX2DEC function converts a hexadecimal (a base-16 number) into a decimal
2977 // number. The syntax of the function is:
2980 func (fn *formulaFuncs) HEX2DEC(argsList *list.List) formulaArg {
2981 if argsList.Len() != 1 {
2982 return newErrorFormulaArg(formulaErrorVALUE, "HEX2DEC requires 1 numeric argument")
2984 return fn.hex2dec(argsList.Front().Value.(formulaArg).Value())
2987 // HEX2OCT function converts a Hexadecimal (Base 16) number into an Octal
2988 // (Base 8) number. The syntax of the function is:
2990 // HEX2OCT(number,[places])
2991 func (fn *formulaFuncs) HEX2OCT(argsList *list.List) formulaArg {
2992 if argsList.Len() < 1 {
2993 return newErrorFormulaArg(formulaErrorVALUE, "HEX2OCT requires at least 1 argument")
2995 if argsList.Len() > 2 {
2996 return newErrorFormulaArg(formulaErrorVALUE, "HEX2OCT allows at most 2 arguments")
2998 decimal, newList := fn.hex2dec(argsList.Front().Value.(formulaArg).Value()), list.New()
2999 if decimal.Type != ArgNumber {
3002 newList.PushBack(decimal)
3003 if argsList.Len() == 2 {
3004 newList.PushBack(argsList.Back().Value.(formulaArg))
3006 return fn.dec2x("HEX2OCT", newList)
3009 // hex2dec is an implementation of the formula function HEX2DEC.
3010 func (fn *formulaFuncs) hex2dec(number string) formulaArg {
3011 decimal, length := 0.0, len(number)
3012 for i := length; i > 0; i-- {
3013 num, err := strconv.ParseInt(string(number[length-i]), 16, 64)
3015 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3017 if i == 10 && string(number[length-i]) == "F" {
3018 decimal += math.Pow(-16.0, float64(i-1))
3021 decimal += float64(num) * math.Pow(16.0, float64(i-1))
3023 return newNumberFormulaArg(decimal)
3026 // IMABS function returns the absolute value (the modulus) of a complex
3027 // number. The syntax of the function is:
3030 func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
3031 if argsList.Len() != 1 {
3032 return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument")
3034 value := argsList.Front().Value.(formulaArg).Value()
3035 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3037 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3039 return newNumberFormulaArg(cmplx.Abs(inumber))
3042 // IMAGINARY function returns the imaginary coefficient of a supplied complex
3043 // number. The syntax of the function is:
3045 // IMAGINARY(inumber)
3046 func (fn *formulaFuncs) IMAGINARY(argsList *list.List) formulaArg {
3047 if argsList.Len() != 1 {
3048 return newErrorFormulaArg(formulaErrorVALUE, "IMAGINARY requires 1 argument")
3050 value := argsList.Front().Value.(formulaArg).Value()
3051 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3053 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3055 return newNumberFormulaArg(imag(inumber))
3058 // IMARGUMENT function returns the phase (also called the argument) of a
3059 // supplied complex number. The syntax of the function is:
3061 // IMARGUMENT(inumber)
3062 func (fn *formulaFuncs) IMARGUMENT(argsList *list.List) formulaArg {
3063 if argsList.Len() != 1 {
3064 return newErrorFormulaArg(formulaErrorVALUE, "IMARGUMENT requires 1 argument")
3066 value := argsList.Front().Value.(formulaArg).Value()
3067 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3069 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3071 return newNumberFormulaArg(cmplx.Phase(inumber))
3074 // IMCONJUGATE function returns the complex conjugate of a supplied complex
3075 // number. The syntax of the function is:
3077 // IMCONJUGATE(inumber)
3078 func (fn *formulaFuncs) IMCONJUGATE(argsList *list.List) formulaArg {
3079 if argsList.Len() != 1 {
3080 return newErrorFormulaArg(formulaErrorVALUE, "IMCONJUGATE requires 1 argument")
3082 value := argsList.Front().Value.(formulaArg).Value()
3083 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3085 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3087 return newStringFormulaArg(cmplx2str(cmplx.Conj(inumber), value[len(value)-1:]))
3090 // IMCOS function returns the cosine of a supplied complex number. The syntax
3091 // of the function is:
3094 func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
3095 if argsList.Len() != 1 {
3096 return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument")
3098 value := argsList.Front().Value.(formulaArg).Value()
3099 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3101 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3103 return newStringFormulaArg(cmplx2str(cmplx.Cos(inumber), value[len(value)-1:]))
3106 // IMCOSH function returns the hyperbolic cosine of a supplied complex number. The syntax
3107 // of the function is:
3110 func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg {
3111 if argsList.Len() != 1 {
3112 return newErrorFormulaArg(formulaErrorVALUE, "IMCOSH requires 1 argument")
3114 value := argsList.Front().Value.(formulaArg).Value()
3115 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3117 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3119 return newStringFormulaArg(cmplx2str(cmplx.Cosh(inumber), value[len(value)-1:]))
3122 // IMCOT function returns the cotangent of a supplied complex number. The syntax
3123 // of the function is:
3126 func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg {
3127 if argsList.Len() != 1 {
3128 return newErrorFormulaArg(formulaErrorVALUE, "IMCOT requires 1 argument")
3130 value := argsList.Front().Value.(formulaArg).Value()
3131 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3133 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3135 return newStringFormulaArg(cmplx2str(cmplx.Cot(inumber), value[len(value)-1:]))
3138 // IMCSC function returns the cosecant of a supplied complex number. The syntax
3139 // of the function is:
3142 func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
3143 if argsList.Len() != 1 {
3144 return newErrorFormulaArg(formulaErrorVALUE, "IMCSC requires 1 argument")
3146 value := argsList.Front().Value.(formulaArg).Value()
3147 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3149 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3151 num := 1 / cmplx.Sin(inumber)
3152 if cmplx.IsInf(num) {
3153 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3155 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3158 // IMCSCH function returns the hyperbolic cosecant of a supplied complex
3159 // number. The syntax of the function is:
3162 func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
3163 if argsList.Len() != 1 {
3164 return newErrorFormulaArg(formulaErrorVALUE, "IMCSCH requires 1 argument")
3166 value := argsList.Front().Value.(formulaArg).Value()
3167 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3169 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3171 num := 1 / cmplx.Sinh(inumber)
3172 if cmplx.IsInf(num) {
3173 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3175 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3178 // IMDIV function calculates the quotient of two complex numbers (i.e. divides
3179 // one complex number by another). The syntax of the function is:
3181 // IMDIV(inumber1,inumber2)
3182 func (fn *formulaFuncs) IMDIV(argsList *list.List) formulaArg {
3183 if argsList.Len() != 2 {
3184 return newErrorFormulaArg(formulaErrorVALUE, "IMDIV requires 2 arguments")
3186 value := argsList.Front().Value.(formulaArg).Value()
3187 inumber1, err := strconv.ParseComplex(str2cmplx(value), 128)
3189 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3191 inumber2, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
3193 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3195 num := inumber1 / inumber2
3196 if cmplx.IsInf(num) {
3197 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3199 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3202 // IMEXP function returns the exponential of a supplied complex number. The
3203 // syntax of the function is:
3206 func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg {
3207 if argsList.Len() != 1 {
3208 return newErrorFormulaArg(formulaErrorVALUE, "IMEXP requires 1 argument")
3210 value := argsList.Front().Value.(formulaArg).Value()
3211 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3213 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3215 return newStringFormulaArg(cmplx2str(cmplx.Exp(inumber), value[len(value)-1:]))
3218 // IMLN function returns the natural logarithm of a supplied complex number.
3219 // The syntax of the function is:
3222 func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
3223 if argsList.Len() != 1 {
3224 return newErrorFormulaArg(formulaErrorVALUE, "IMLN requires 1 argument")
3226 value := argsList.Front().Value.(formulaArg).Value()
3227 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3229 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3231 num := cmplx.Log(inumber)
3232 if cmplx.IsInf(num) {
3233 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3235 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3238 // IMLOG10 function returns the common (base 10) logarithm of a supplied
3239 // complex number. The syntax of the function is:
3242 func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
3243 if argsList.Len() != 1 {
3244 return newErrorFormulaArg(formulaErrorVALUE, "IMLOG10 requires 1 argument")
3246 value := argsList.Front().Value.(formulaArg).Value()
3247 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3249 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3251 num := cmplx.Log10(inumber)
3252 if cmplx.IsInf(num) {
3253 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3255 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3258 // IMLOG2 function calculates the base 2 logarithm of a supplied complex
3259 // number. The syntax of the function is:
3262 func (fn *formulaFuncs) IMLOG2(argsList *list.List) formulaArg {
3263 if argsList.Len() != 1 {
3264 return newErrorFormulaArg(formulaErrorVALUE, "IMLOG2 requires 1 argument")
3266 value := argsList.Front().Value.(formulaArg).Value()
3267 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3269 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3271 num := cmplx.Log(inumber)
3272 if cmplx.IsInf(num) {
3273 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3275 return newStringFormulaArg(cmplx2str(num/cmplx.Log(2), value[len(value)-1:]))
3278 // IMPOWER function returns a supplied complex number, raised to a given
3279 // power. The syntax of the function is:
3281 // IMPOWER(inumber,number)
3282 func (fn *formulaFuncs) IMPOWER(argsList *list.List) formulaArg {
3283 if argsList.Len() != 2 {
3284 return newErrorFormulaArg(formulaErrorVALUE, "IMPOWER requires 2 arguments")
3286 value := argsList.Front().Value.(formulaArg).Value()
3287 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3289 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3291 number, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
3293 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3295 if inumber == 0 && number == 0 {
3296 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3298 num := cmplx.Pow(inumber, number)
3299 if cmplx.IsInf(num) {
3300 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
3302 return newStringFormulaArg(cmplx2str(num, value[len(value)-1:]))
3305 // IMPRODUCT function calculates the product of two or more complex numbers.
3306 // The syntax of the function is:
3308 // IMPRODUCT(number1,[number2],...)
3309 func (fn *formulaFuncs) IMPRODUCT(argsList *list.List) formulaArg {
3310 product := complex128(1)
3311 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
3312 token := arg.Value.(formulaArg)
3315 if token.Value() == "" {
3318 val, err := strconv.ParseComplex(str2cmplx(token.Value()), 128)
3320 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3322 product = product * val
3324 product = product * complex(token.Number, 0)
3326 for _, row := range token.Matrix {
3327 for _, value := range row {
3328 if value.Value() == "" {
3331 val, err := strconv.ParseComplex(str2cmplx(value.Value()), 128)
3333 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3335 product = product * val
3340 return newStringFormulaArg(cmplx2str(product, "i"))
3343 // IMREAL function returns the real coefficient of a supplied complex number.
3344 // The syntax of the function is:
3347 func (fn *formulaFuncs) IMREAL(argsList *list.List) formulaArg {
3348 if argsList.Len() != 1 {
3349 return newErrorFormulaArg(formulaErrorVALUE, "IMREAL requires 1 argument")
3351 value := argsList.Front().Value.(formulaArg).Value()
3352 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3354 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3356 return newStringFormulaArg(fmt.Sprint(real(inumber)))
3359 // IMSEC function returns the secant of a supplied complex number. The syntax
3360 // of the function is:
3363 func (fn *formulaFuncs) IMSEC(argsList *list.List) formulaArg {
3364 if argsList.Len() != 1 {
3365 return newErrorFormulaArg(formulaErrorVALUE, "IMSEC requires 1 argument")
3367 value := argsList.Front().Value.(formulaArg).Value()
3368 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3370 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3372 return newStringFormulaArg(cmplx2str(1/cmplx.Cos(inumber), value[len(value)-1:]))
3375 // IMSECH function returns the hyperbolic secant of a supplied complex number.
3376 // The syntax of the function is:
3379 func (fn *formulaFuncs) IMSECH(argsList *list.List) formulaArg {
3380 if argsList.Len() != 1 {
3381 return newErrorFormulaArg(formulaErrorVALUE, "IMSECH requires 1 argument")
3383 value := argsList.Front().Value.(formulaArg).Value()
3384 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3386 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3388 return newStringFormulaArg(cmplx2str(1/cmplx.Cosh(inumber), value[len(value)-1:]))
3391 // IMSIN function returns the Sine of a supplied complex number. The syntax of
3395 func (fn *formulaFuncs) IMSIN(argsList *list.List) formulaArg {
3396 if argsList.Len() != 1 {
3397 return newErrorFormulaArg(formulaErrorVALUE, "IMSIN requires 1 argument")
3399 value := argsList.Front().Value.(formulaArg).Value()
3400 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3402 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3404 return newStringFormulaArg(cmplx2str(cmplx.Sin(inumber), value[len(value)-1:]))
3407 // IMSINH function returns the hyperbolic sine of a supplied complex number.
3408 // The syntax of the function is:
3411 func (fn *formulaFuncs) IMSINH(argsList *list.List) formulaArg {
3412 if argsList.Len() != 1 {
3413 return newErrorFormulaArg(formulaErrorVALUE, "IMSINH requires 1 argument")
3415 value := argsList.Front().Value.(formulaArg).Value()
3416 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3418 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3420 return newStringFormulaArg(cmplx2str(cmplx.Sinh(inumber), value[len(value)-1:]))
3423 // IMSQRT function returns the square root of a supplied complex number. The
3424 // syntax of the function is:
3427 func (fn *formulaFuncs) IMSQRT(argsList *list.List) formulaArg {
3428 if argsList.Len() != 1 {
3429 return newErrorFormulaArg(formulaErrorVALUE, "IMSQRT requires 1 argument")
3431 value := argsList.Front().Value.(formulaArg).Value()
3432 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3434 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3436 return newStringFormulaArg(cmplx2str(cmplx.Sqrt(inumber), value[len(value)-1:]))
3439 // IMSUB function calculates the difference between two complex numbers
3440 // (i.e. subtracts one complex number from another). The syntax of the
3443 // IMSUB(inumber1,inumber2)
3444 func (fn *formulaFuncs) IMSUB(argsList *list.List) formulaArg {
3445 if argsList.Len() != 2 {
3446 return newErrorFormulaArg(formulaErrorVALUE, "IMSUB requires 2 arguments")
3448 i1, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
3450 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3452 i2, err := strconv.ParseComplex(str2cmplx(argsList.Back().Value.(formulaArg).Value()), 128)
3454 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3456 return newStringFormulaArg(cmplx2str(i1-i2, "i"))
3459 // IMSUM function calculates the sum of two or more complex numbers. The
3460 // syntax of the function is:
3462 // IMSUM(inumber1,inumber2,...)
3463 func (fn *formulaFuncs) IMSUM(argsList *list.List) formulaArg {
3464 if argsList.Len() < 1 {
3465 return newErrorFormulaArg(formulaErrorVALUE, "IMSUM requires at least 1 argument")
3467 var result complex128
3468 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
3469 token := arg.Value.(formulaArg)
3470 num, err := strconv.ParseComplex(str2cmplx(token.Value()), 128)
3472 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3476 return newStringFormulaArg(cmplx2str(result, "i"))
3479 // IMTAN function returns the tangent of a supplied complex number. The syntax
3480 // of the function is:
3483 func (fn *formulaFuncs) IMTAN(argsList *list.List) formulaArg {
3484 if argsList.Len() != 1 {
3485 return newErrorFormulaArg(formulaErrorVALUE, "IMTAN requires 1 argument")
3487 value := argsList.Front().Value.(formulaArg).Value()
3488 inumber, err := strconv.ParseComplex(str2cmplx(value), 128)
3490 return newErrorFormulaArg(formulaErrorNUM, err.Error())
3492 return newStringFormulaArg(cmplx2str(cmplx.Tan(inumber), value[len(value)-1:]))
3495 // OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2)
3496 // number. The syntax of the function is:
3498 // OCT2BIN(number,[places])
3499 func (fn *formulaFuncs) OCT2BIN(argsList *list.List) formulaArg {
3500 if argsList.Len() < 1 {
3501 return newErrorFormulaArg(formulaErrorVALUE, "OCT2BIN requires at least 1 argument")
3503 if argsList.Len() > 2 {
3504 return newErrorFormulaArg(formulaErrorVALUE, "OCT2BIN allows at most 2 arguments")
3506 token := argsList.Front().Value.(formulaArg)
3507 number := token.ToNumber()
3508 if number.Type != ArgNumber {
3509 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
3511 decimal, newList := fn.oct2dec(token.Value()), list.New()
3512 newList.PushBack(decimal)
3513 if argsList.Len() == 2 {
3514 newList.PushBack(argsList.Back().Value.(formulaArg))
3516 return fn.dec2x("OCT2BIN", newList)
3519 // OCT2DEC function converts an Octal (a base-8 number) into a decimal number.
3520 // The syntax of the function is:
3523 func (fn *formulaFuncs) OCT2DEC(argsList *list.List) formulaArg {
3524 if argsList.Len() != 1 {
3525 return newErrorFormulaArg(formulaErrorVALUE, "OCT2DEC requires 1 numeric argument")
3527 token := argsList.Front().Value.(formulaArg)
3528 number := token.ToNumber()
3529 if number.Type != ArgNumber {
3530 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
3532 return fn.oct2dec(token.Value())
3535 // OCT2HEX function converts an Octal (Base 8) number into a Hexadecimal
3536 // (Base 16) number. The syntax of the function is:
3538 // OCT2HEX(number,[places])
3539 func (fn *formulaFuncs) OCT2HEX(argsList *list.List) formulaArg {
3540 if argsList.Len() < 1 {
3541 return newErrorFormulaArg(formulaErrorVALUE, "OCT2HEX requires at least 1 argument")
3543 if argsList.Len() > 2 {
3544 return newErrorFormulaArg(formulaErrorVALUE, "OCT2HEX allows at most 2 arguments")
3546 token := argsList.Front().Value.(formulaArg)
3547 number := token.ToNumber()
3548 if number.Type != ArgNumber {
3549 return newErrorFormulaArg(formulaErrorVALUE, number.Error)
3551 decimal, newList := fn.oct2dec(token.Value()), list.New()
3552 newList.PushBack(decimal)
3553 if argsList.Len() == 2 {
3554 newList.PushBack(argsList.Back().Value.(formulaArg))
3556 return fn.dec2x("OCT2HEX", newList)
3559 // oct2dec is an implementation of the formula function OCT2DEC.
3560 func (fn *formulaFuncs) oct2dec(number string) formulaArg {
3561 decimal, length := 0.0, len(number)
3562 for i := length; i > 0; i-- {
3563 num, _ := strconv.Atoi(string(number[length-i]))
3564 if i == 10 && string(number[length-i]) == "7" {
3565 decimal += math.Pow(-8.0, float64(i-1))
3568 decimal += float64(num) * math.Pow(8.0, float64(i-1))
3570 return newNumberFormulaArg(decimal)
3573 // Math and Trigonometric Functions
3575 // ABS function returns the absolute value of any supplied number. The syntax
3576 // of the function is:
3579 func (fn *formulaFuncs) ABS(argsList *list.List) formulaArg {
3580 if argsList.Len() != 1 {
3581 return newErrorFormulaArg(formulaErrorVALUE, "ABS requires 1 numeric argument")
3583 arg := argsList.Front().Value.(formulaArg).ToNumber()
3584 if arg.Type == ArgError {
3587 return newNumberFormulaArg(math.Abs(arg.Number))
3590 // ACOS function calculates the arccosine (i.e. the inverse cosine) of a given
3591 // number, and returns an angle, in radians, between 0 and π. The syntax of
3595 func (fn *formulaFuncs) ACOS(argsList *list.List) formulaArg {
3596 if argsList.Len() != 1 {
3597 return newErrorFormulaArg(formulaErrorVALUE, "ACOS requires 1 numeric argument")
3599 arg := argsList.Front().Value.(formulaArg).ToNumber()
3600 if arg.Type == ArgError {
3603 return newNumberFormulaArg(math.Acos(arg.Number))
3606 // ACOSH function calculates the inverse hyperbolic cosine of a supplied number.
3607 // of the function is:
3610 func (fn *formulaFuncs) ACOSH(argsList *list.List) formulaArg {
3611 if argsList.Len() != 1 {
3612 return newErrorFormulaArg(formulaErrorVALUE, "ACOSH requires 1 numeric argument")
3614 arg := argsList.Front().Value.(formulaArg).ToNumber()
3615 if arg.Type == ArgError {
3618 return newNumberFormulaArg(math.Acosh(arg.Number))
3621 // ACOT function calculates the arccotangent (i.e. the inverse cotangent) of a
3622 // given number, and returns an angle, in radians, between 0 and π. The syntax
3623 // of the function is:
3626 func (fn *formulaFuncs) ACOT(argsList *list.List) formulaArg {
3627 if argsList.Len() != 1 {
3628 return newErrorFormulaArg(formulaErrorVALUE, "ACOT requires 1 numeric argument")
3630 arg := argsList.Front().Value.(formulaArg).ToNumber()
3631 if arg.Type == ArgError {
3634 return newNumberFormulaArg(math.Pi/2 - math.Atan(arg.Number))
3637 // ACOTH function calculates the hyperbolic arccotangent (coth) of a supplied
3638 // value. The syntax of the function is:
3641 func (fn *formulaFuncs) ACOTH(argsList *list.List) formulaArg {
3642 if argsList.Len() != 1 {
3643 return newErrorFormulaArg(formulaErrorVALUE, "ACOTH requires 1 numeric argument")
3645 arg := argsList.Front().Value.(formulaArg).ToNumber()
3646 if arg.Type == ArgError {
3649 return newNumberFormulaArg(math.Atanh(1 / arg.Number))
3652 // AGGREGATE function returns the result of a specified operation or function,
3653 // applied to a list or database of values. The syntax of the function is:
3655 // AGGREGATE(function_num,options,ref1,[ref2],...)
3656 func (fn *formulaFuncs) AGGREGATE(argsList *list.List) formulaArg {
3657 if argsList.Len() < 2 {
3658 return newErrorFormulaArg(formulaErrorVALUE, "AGGREGATE requires at least 3 arguments")
3660 var fnNum, opts formulaArg
3661 if fnNum = argsList.Front().Value.(formulaArg).ToNumber(); fnNum.Type != ArgNumber {
3664 subFn, ok := map[int]func(argsList *list.List) formulaArg{
3680 16: fn.PERCENTILEdotINC,
3681 17: fn.QUARTILEdotINC,
3682 18: fn.PERCENTILEdotEXC,
3683 19: fn.QUARTILEdotEXC,
3684 }[int(fnNum.Number)]
3686 return newErrorFormulaArg(formulaErrorVALUE, "AGGREGATE has invalid function_num")
3688 if opts = argsList.Front().Next().Value.(formulaArg).ToNumber(); opts.Type != ArgNumber {
3691 // TODO: apply option argument values to be ignored during the calculation
3692 if int(opts.Number) < 0 || int(opts.Number) > 7 {
3693 return newErrorFormulaArg(formulaErrorVALUE, "AGGREGATE has invalid options")
3695 subArgList := list.New().Init()
3696 for arg := argsList.Front().Next().Next(); arg != nil; arg = arg.Next() {
3697 subArgList.PushBack(arg.Value.(formulaArg))
3699 return subFn(subArgList)
3702 // ARABIC function converts a Roman numeral into an Arabic numeral. The syntax
3703 // of the function is:
3706 func (fn *formulaFuncs) ARABIC(argsList *list.List) formulaArg {
3707 if argsList.Len() != 1 {
3708 return newErrorFormulaArg(formulaErrorVALUE, "ARABIC requires 1 numeric argument")
3710 text := argsList.Front().Value.(formulaArg).Value()
3711 if len(text) > MaxFieldLength {
3712 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
3714 text = strings.ToUpper(text)
3715 number, actualStart, index, isNegative := 0, 0, len(text)-1, false
3716 startIndex, subtractNumber, currentPartValue, currentCharValue, prevCharValue := 0, 0, 0, 0, -1
3717 for index >= 0 && text[index] == ' ' {
3720 for actualStart <= index && text[actualStart] == ' ' {
3723 if actualStart <= index && text[actualStart] == '-' {
3727 charMap := map[rune]int{'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
3728 for index >= actualStart {
3730 startChar := text[startIndex]
3732 for index >= actualStart && (text[index]|' ') == startChar {
3735 currentCharValue = charMap[rune(startChar)]
3736 currentPartValue = (startIndex - index) * currentCharValue
3737 if currentCharValue >= prevCharValue {
3738 number += currentPartValue - subtractNumber
3739 prevCharValue = currentCharValue
3743 subtractNumber += currentPartValue
3745 if subtractNumber != 0 {
3746 number -= subtractNumber
3751 return newNumberFormulaArg(float64(number))
3754 // ASIN function calculates the arcsine (i.e. the inverse sine) of a given
3755 // number, and returns an angle, in radians, between -π/2 and π/2. The syntax
3756 // of the function is:
3759 func (fn *formulaFuncs) ASIN(argsList *list.List) formulaArg {
3760 if argsList.Len() != 1 {
3761 return newErrorFormulaArg(formulaErrorVALUE, "ASIN requires 1 numeric argument")
3763 arg := argsList.Front().Value.(formulaArg).ToNumber()
3764 if arg.Type == ArgError {
3767 return newNumberFormulaArg(math.Asin(arg.Number))
3770 // ASINH function calculates the inverse hyperbolic sine of a supplied number.
3771 // The syntax of the function is:
3774 func (fn *formulaFuncs) ASINH(argsList *list.List) formulaArg {
3775 if argsList.Len() != 1 {
3776 return newErrorFormulaArg(formulaErrorVALUE, "ASINH requires 1 numeric argument")
3778 arg := argsList.Front().Value.(formulaArg).ToNumber()
3779 if arg.Type == ArgError {
3782 return newNumberFormulaArg(math.Asinh(arg.Number))
3785 // ATAN function calculates the arctangent (i.e. the inverse tangent) of a
3786 // given number, and returns an angle, in radians, between -Ï€/2 and +Ï€/2. The
3787 // syntax of the function is:
3790 func (fn *formulaFuncs) ATAN(argsList *list.List) formulaArg {
3791 if argsList.Len() != 1 {
3792 return newErrorFormulaArg(formulaErrorVALUE, "ATAN requires 1 numeric argument")
3794 arg := argsList.Front().Value.(formulaArg).ToNumber()
3795 if arg.Type == ArgError {
3798 return newNumberFormulaArg(math.Atan(arg.Number))
3801 // ATANH function calculates the inverse hyperbolic tangent of a supplied
3802 // number. The syntax of the function is:
3805 func (fn *formulaFuncs) ATANH(argsList *list.List) formulaArg {
3806 if argsList.Len() != 1 {
3807 return newErrorFormulaArg(formulaErrorVALUE, "ATANH requires 1 numeric argument")
3809 arg := argsList.Front().Value.(formulaArg).ToNumber()
3810 if arg.Type == ArgError {
3813 return newNumberFormulaArg(math.Atanh(arg.Number))
3816 // ATAN2 function calculates the arctangent (i.e. the inverse tangent) of a
3817 // given set of x and y coordinates, and returns an angle, in radians, between
3818 // -Ï€/2 and +Ï€/2. The syntax of the function is:
3820 // ATAN2(x_num,y_num)
3821 func (fn *formulaFuncs) ATAN2(argsList *list.List) formulaArg {
3822 if argsList.Len() != 2 {
3823 return newErrorFormulaArg(formulaErrorVALUE, "ATAN2 requires 2 numeric arguments")
3825 x := argsList.Back().Value.(formulaArg).ToNumber()
3826 if x.Type == ArgError {
3829 y := argsList.Front().Value.(formulaArg).ToNumber()
3830 if y.Type == ArgError {
3833 return newNumberFormulaArg(math.Atan2(x.Number, y.Number))
3836 // BASE function converts a number into a supplied base (radix), and returns a
3837 // text representation of the calculated value. The syntax of the function is:
3839 // BASE(number,radix,[min_length])
3840 func (fn *formulaFuncs) BASE(argsList *list.List) formulaArg {
3841 if argsList.Len() < 2 {
3842 return newErrorFormulaArg(formulaErrorVALUE, "BASE requires at least 2 arguments")
3844 if argsList.Len() > 3 {
3845 return newErrorFormulaArg(formulaErrorVALUE, "BASE allows at most 3 arguments")
3849 number := argsList.Front().Value.(formulaArg).ToNumber()
3850 if number.Type == ArgError {
3853 radix := argsList.Front().Next().Value.(formulaArg).ToNumber()
3854 if radix.Type == ArgError {
3857 if int(radix.Number) < 2 || int(radix.Number) > 36 {
3858 return newErrorFormulaArg(formulaErrorVALUE, "radix must be an integer >= 2 and <= 36")
3860 if argsList.Len() > 2 {
3861 if minLength, err = strconv.Atoi(argsList.Back().Value.(formulaArg).Value()); err != nil {
3862 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
3865 result := strconv.FormatInt(int64(number.Number), int(radix.Number))
3866 if len(result) < minLength {
3867 result = strings.Repeat("0", minLength-len(result)) + result
3869 return newStringFormulaArg(strings.ToUpper(result))
3872 // CEILING function rounds a supplied number away from zero, to the nearest
3873 // multiple of a given number. The syntax of the function is:
3875 // CEILING(number,significance)
3876 func (fn *formulaFuncs) CEILING(argsList *list.List) formulaArg {
3877 if argsList.Len() == 0 {
3878 return newErrorFormulaArg(formulaErrorVALUE, "CEILING requires at least 1 argument")
3880 if argsList.Len() > 2 {
3881 return newErrorFormulaArg(formulaErrorVALUE, "CEILING allows at most 2 arguments")
3883 number, significance, res := 0.0, 1.0, 0.0
3884 n := argsList.Front().Value.(formulaArg).ToNumber()
3885 if n.Type == ArgError {
3892 if argsList.Len() > 1 {
3893 s := argsList.Back().Value.(formulaArg).ToNumber()
3894 if s.Type == ArgError {
3897 significance = s.Number
3899 if significance < 0 && number > 0 {
3900 return newErrorFormulaArg(formulaErrorVALUE, "negative sig to CEILING invalid")
3902 if argsList.Len() == 1 {
3903 return newNumberFormulaArg(math.Ceil(number))
3905 number, res = math.Modf(number / significance)
3909 return newNumberFormulaArg(number * significance)
3912 // CEILINGdotMATH function rounds a supplied number up to a supplied multiple
3913 // of significance. The syntax of the function is:
3915 // CEILING.MATH(number,[significance],[mode])
3916 func (fn *formulaFuncs) CEILINGdotMATH(argsList *list.List) formulaArg {
3917 if argsList.Len() == 0 {
3918 return newErrorFormulaArg(formulaErrorVALUE, "CEILING.MATH requires at least 1 argument")
3920 if argsList.Len() > 3 {
3921 return newErrorFormulaArg(formulaErrorVALUE, "CEILING.MATH allows at most 3 arguments")
3923 number, significance, mode := 0.0, 1.0, 1.0
3924 n := argsList.Front().Value.(formulaArg).ToNumber()
3925 if n.Type == ArgError {
3932 if argsList.Len() > 1 {
3933 s := argsList.Front().Next().Value.(formulaArg).ToNumber()
3934 if s.Type == ArgError {
3937 significance = s.Number
3939 if argsList.Len() == 1 {
3940 return newNumberFormulaArg(math.Ceil(number))
3942 if argsList.Len() > 2 {
3943 m := argsList.Back().Value.(formulaArg).ToNumber()
3944 if m.Type == ArgError {
3949 val, res := math.Modf(number / significance)
3953 } else if mode < 0 {
3957 return newNumberFormulaArg(val * significance)
3960 // CEILINGdotPRECISE function rounds a supplied number up (regardless of the
3961 // number's sign), to the nearest multiple of a given number. The syntax of
3964 // CEILING.PRECISE(number,[significance])
3965 func (fn *formulaFuncs) CEILINGdotPRECISE(argsList *list.List) formulaArg {
3966 if argsList.Len() == 0 {
3967 return newErrorFormulaArg(formulaErrorVALUE, "CEILING.PRECISE requires at least 1 argument")
3969 if argsList.Len() > 2 {
3970 return newErrorFormulaArg(formulaErrorVALUE, "CEILING.PRECISE allows at most 2 arguments")
3972 number, significance := 0.0, 1.0
3973 n := argsList.Front().Value.(formulaArg).ToNumber()
3974 if n.Type == ArgError {
3981 if argsList.Len() == 1 {
3982 return newNumberFormulaArg(math.Ceil(number))
3984 if argsList.Len() > 1 {
3985 s := argsList.Back().Value.(formulaArg).ToNumber()
3986 if s.Type == ArgError {
3989 significance = s.Number
3990 significance = math.Abs(significance)
3991 if significance == 0 {
3992 return newNumberFormulaArg(significance)
3995 val, res := math.Modf(number / significance)
4001 return newNumberFormulaArg(val * significance)
4004 // COMBIN function calculates the number of combinations (in any order) of a
4005 // given number objects from a set. The syntax of the function is:
4007 // COMBIN(number,number_chosen)
4008 func (fn *formulaFuncs) COMBIN(argsList *list.List) formulaArg {
4009 if argsList.Len() != 2 {
4010 return newErrorFormulaArg(formulaErrorVALUE, "COMBIN requires 2 argument")
4012 number, chosen, val := 0.0, 0.0, 1.0
4013 n := argsList.Front().Value.(formulaArg).ToNumber()
4014 if n.Type == ArgError {
4018 c := argsList.Back().Value.(formulaArg).ToNumber()
4019 if c.Type == ArgError {
4023 number, chosen = math.Trunc(number), math.Trunc(chosen)
4024 if chosen > number {
4025 return newErrorFormulaArg(formulaErrorVALUE, "COMBIN requires number >= number_chosen")
4027 if chosen == number || chosen == 0 {
4028 return newNumberFormulaArg(1)
4030 for c := float64(1); c <= chosen; c++ {
4031 val *= (number + 1 - c) / c
4033 return newNumberFormulaArg(math.Ceil(val))
4036 // COMBINA function calculates the number of combinations, with repetitions,
4037 // of a given number objects from a set. The syntax of the function is:
4039 // COMBINA(number,number_chosen)
4040 func (fn *formulaFuncs) COMBINA(argsList *list.List) formulaArg {
4041 if argsList.Len() != 2 {
4042 return newErrorFormulaArg(formulaErrorVALUE, "COMBINA requires 2 argument")
4044 var number, chosen float64
4045 n := argsList.Front().Value.(formulaArg).ToNumber()
4046 if n.Type == ArgError {
4050 c := argsList.Back().Value.(formulaArg).ToNumber()
4051 if c.Type == ArgError {
4055 number, chosen = math.Trunc(number), math.Trunc(chosen)
4056 if number < chosen {
4057 return newErrorFormulaArg(formulaErrorVALUE, "COMBINA requires number > number_chosen")
4060 return newNumberFormulaArg(number)
4063 args.PushBack(formulaArg{
4064 String: fmt.Sprintf("%g", number+chosen-1),
4067 args.PushBack(formulaArg{
4068 String: fmt.Sprintf("%g", number-1),
4071 return fn.COMBIN(args)
4074 // COS function calculates the cosine of a given angle. The syntax of the
4078 func (fn *formulaFuncs) COS(argsList *list.List) formulaArg {
4079 if argsList.Len() != 1 {
4080 return newErrorFormulaArg(formulaErrorVALUE, "COS requires 1 numeric argument")
4082 val := argsList.Front().Value.(formulaArg).ToNumber()
4083 if val.Type == ArgError {
4086 return newNumberFormulaArg(math.Cos(val.Number))
4089 // COSH function calculates the hyperbolic cosine (cosh) of a supplied number.
4090 // The syntax of the function is:
4093 func (fn *formulaFuncs) COSH(argsList *list.List) formulaArg {
4094 if argsList.Len() != 1 {
4095 return newErrorFormulaArg(formulaErrorVALUE, "COSH requires 1 numeric argument")
4097 val := argsList.Front().Value.(formulaArg).ToNumber()
4098 if val.Type == ArgError {
4101 return newNumberFormulaArg(math.Cosh(val.Number))
4104 // COT function calculates the cotangent of a given angle. The syntax of the
4108 func (fn *formulaFuncs) COT(argsList *list.List) formulaArg {
4109 if argsList.Len() != 1 {
4110 return newErrorFormulaArg(formulaErrorVALUE, "COT requires 1 numeric argument")
4112 val := argsList.Front().Value.(formulaArg).ToNumber()
4113 if val.Type == ArgError {
4116 if val.Number == 0 {
4117 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4119 return newNumberFormulaArg(1 / math.Tan(val.Number))
4122 // COTH function calculates the hyperbolic cotangent (coth) of a supplied
4123 // angle. The syntax of the function is:
4126 func (fn *formulaFuncs) COTH(argsList *list.List) formulaArg {
4127 if argsList.Len() != 1 {
4128 return newErrorFormulaArg(formulaErrorVALUE, "COTH requires 1 numeric argument")
4130 val := argsList.Front().Value.(formulaArg).ToNumber()
4131 if val.Type == ArgError {
4134 if val.Number == 0 {
4135 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4137 return newNumberFormulaArg((math.Exp(val.Number) + math.Exp(-val.Number)) / (math.Exp(val.Number) - math.Exp(-val.Number)))
4140 // CSC function calculates the cosecant of a given angle. The syntax of the
4144 func (fn *formulaFuncs) CSC(argsList *list.List) formulaArg {
4145 if argsList.Len() != 1 {
4146 return newErrorFormulaArg(formulaErrorVALUE, "CSC requires 1 numeric argument")
4148 val := argsList.Front().Value.(formulaArg).ToNumber()
4149 if val.Type == ArgError {
4152 if val.Number == 0 {
4153 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4155 return newNumberFormulaArg(1 / math.Sin(val.Number))
4158 // CSCH function calculates the hyperbolic cosecant (csch) of a supplied
4159 // angle. The syntax of the function is:
4162 func (fn *formulaFuncs) CSCH(argsList *list.List) formulaArg {
4163 if argsList.Len() != 1 {
4164 return newErrorFormulaArg(formulaErrorVALUE, "CSCH requires 1 numeric argument")
4166 val := argsList.Front().Value.(formulaArg).ToNumber()
4167 if val.Type == ArgError {
4170 if val.Number == 0 {
4171 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4173 return newNumberFormulaArg(1 / math.Sinh(val.Number))
4176 // DECIMAL function converts a text representation of a number in a specified
4177 // base, into a decimal value. The syntax of the function is:
4179 // DECIMAL(text,radix)
4180 func (fn *formulaFuncs) DECIMAL(argsList *list.List) formulaArg {
4181 if argsList.Len() != 2 {
4182 return newErrorFormulaArg(formulaErrorVALUE, "DECIMAL requires 2 numeric arguments")
4184 text := argsList.Front().Value.(formulaArg).Value()
4186 radix := argsList.Back().Value.(formulaArg).ToNumber()
4187 if radix.Type != ArgNumber {
4190 if len(text) > 2 && (strings.HasPrefix(text, "0x") || strings.HasPrefix(text, "0X")) {
4193 val, err := strconv.ParseInt(text, int(radix.Number), 64)
4195 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
4197 return newNumberFormulaArg(float64(val))
4200 // DEGREES function converts radians into degrees. The syntax of the function
4204 func (fn *formulaFuncs) DEGREES(argsList *list.List) formulaArg {
4205 if argsList.Len() != 1 {
4206 return newErrorFormulaArg(formulaErrorVALUE, "DEGREES requires 1 numeric argument")
4208 val := argsList.Front().Value.(formulaArg).ToNumber()
4209 if val.Type == ArgError {
4212 if val.Number == 0 {
4213 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4215 return newNumberFormulaArg(180.0 / math.Pi * val.Number)
4218 // EVEN function rounds a supplied number away from zero (i.e. rounds a
4219 // positive number up and a negative number down), to the next even number.
4220 // The syntax of the function is:
4223 func (fn *formulaFuncs) EVEN(argsList *list.List) formulaArg {
4224 if argsList.Len() != 1 {
4225 return newErrorFormulaArg(formulaErrorVALUE, "EVEN requires 1 numeric argument")
4227 number := argsList.Front().Value.(formulaArg).ToNumber()
4228 if number.Type == ArgError {
4231 sign := math.Signbit(number.Number)
4232 m, frac := math.Modf(number.Number / 2)
4241 return newNumberFormulaArg(val)
4244 // EXP function calculates the value of the mathematical constant e, raised to
4245 // the power of a given number. The syntax of the function is:
4248 func (fn *formulaFuncs) EXP(argsList *list.List) formulaArg {
4249 if argsList.Len() != 1 {
4250 return newErrorFormulaArg(formulaErrorVALUE, "EXP requires 1 numeric argument")
4252 number := argsList.Front().Value.(formulaArg).ToNumber()
4253 if number.Type == ArgError {
4256 return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%g", math.Exp(number.Number))))
4259 // fact returns the factorial of a supplied number.
4260 func fact(number float64) float64 {
4262 for i := float64(2); i <= number; i++ {
4268 // FACT function returns the factorial of a supplied number. The syntax of the
4272 func (fn *formulaFuncs) FACT(argsList *list.List) formulaArg {
4273 if argsList.Len() != 1 {
4274 return newErrorFormulaArg(formulaErrorVALUE, "FACT requires 1 numeric argument")
4276 number := argsList.Front().Value.(formulaArg).ToNumber()
4277 if number.Type == ArgError {
4280 if number.Number < 0 {
4281 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
4283 return newNumberFormulaArg(fact(number.Number))
4286 // FACTDOUBLE function returns the double factorial of a supplied number. The
4287 // syntax of the function is:
4289 // FACTDOUBLE(number)
4290 func (fn *formulaFuncs) FACTDOUBLE(argsList *list.List) formulaArg {
4291 if argsList.Len() != 1 {
4292 return newErrorFormulaArg(formulaErrorVALUE, "FACTDOUBLE requires 1 numeric argument")
4295 number := argsList.Front().Value.(formulaArg).ToNumber()
4296 if number.Type == ArgError {
4299 if number.Number < 0 {
4300 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
4302 for i := math.Trunc(number.Number); i > 1; i -= 2 {
4305 return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%g", val)))
4308 // FLOOR function rounds a supplied number towards zero to the nearest
4309 // multiple of a specified significance. The syntax of the function is:
4311 // FLOOR(number,significance)
4312 func (fn *formulaFuncs) FLOOR(argsList *list.List) formulaArg {
4313 if argsList.Len() != 2 {
4314 return newErrorFormulaArg(formulaErrorVALUE, "FLOOR requires 2 numeric arguments")
4316 number := argsList.Front().Value.(formulaArg).ToNumber()
4317 if number.Type == ArgError {
4320 significance := argsList.Back().Value.(formulaArg).ToNumber()
4321 if significance.Type == ArgError {
4324 if significance.Number < 0 && number.Number >= 0 {
4325 return newErrorFormulaArg(formulaErrorNUM, "invalid arguments to FLOOR")
4327 val := number.Number
4328 val, res := math.Modf(val / significance.Number)
4330 if number.Number < 0 && res < 0 {
4334 return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%g", val*significance.Number)))
4337 // FLOORdotMATH function rounds a supplied number down to a supplied multiple
4338 // of significance. The syntax of the function is:
4340 // FLOOR.MATH(number,[significance],[mode])
4341 func (fn *formulaFuncs) FLOORdotMATH(argsList *list.List) formulaArg {
4342 if argsList.Len() == 0 {
4343 return newErrorFormulaArg(formulaErrorVALUE, "FLOOR.MATH requires at least 1 argument")
4345 if argsList.Len() > 3 {
4346 return newErrorFormulaArg(formulaErrorVALUE, "FLOOR.MATH allows at most 3 arguments")
4348 significance, mode := 1.0, 1.0
4349 number := argsList.Front().Value.(formulaArg).ToNumber()
4350 if number.Type == ArgError {
4353 if number.Number < 0 {
4356 if argsList.Len() > 1 {
4357 s := argsList.Front().Next().Value.(formulaArg).ToNumber()
4358 if s.Type == ArgError {
4361 significance = s.Number
4363 if argsList.Len() == 1 {
4364 return newNumberFormulaArg(math.Floor(number.Number))
4366 if argsList.Len() > 2 {
4367 m := argsList.Back().Value.(formulaArg).ToNumber()
4368 if m.Type == ArgError {
4373 val, res := math.Modf(number.Number / significance)
4374 if res != 0 && number.Number < 0 && mode > 0 {
4377 return newNumberFormulaArg(val * significance)
4380 // FLOORdotPRECISE function rounds a supplied number down to a supplied
4381 // multiple of significance. The syntax of the function is:
4383 // FLOOR.PRECISE(number,[significance])
4384 func (fn *formulaFuncs) FLOORdotPRECISE(argsList *list.List) formulaArg {
4385 if argsList.Len() == 0 {
4386 return newErrorFormulaArg(formulaErrorVALUE, "FLOOR.PRECISE requires at least 1 argument")
4388 if argsList.Len() > 2 {
4389 return newErrorFormulaArg(formulaErrorVALUE, "FLOOR.PRECISE allows at most 2 arguments")
4391 var significance float64
4392 number := argsList.Front().Value.(formulaArg).ToNumber()
4393 if number.Type == ArgError {
4396 if number.Number < 0 {
4399 if argsList.Len() == 1 {
4400 return newNumberFormulaArg(math.Floor(number.Number))
4402 if argsList.Len() > 1 {
4403 s := argsList.Back().Value.(formulaArg).ToNumber()
4404 if s.Type == ArgError {
4407 significance = s.Number
4408 significance = math.Abs(significance)
4409 if significance == 0 {
4410 return newNumberFormulaArg(significance)
4413 val, res := math.Modf(number.Number / significance)
4415 if number.Number < 0 {
4419 return newNumberFormulaArg(val * significance)
4422 // gcd returns the greatest common divisor of two supplied integers.
4423 func gcd(x, y float64) float64 {
4424 x, y = math.Trunc(x), math.Trunc(y)
4441 // GCD function returns the greatest common divisor of two or more supplied
4442 // integers. The syntax of the function is:
4444 // GCD(number1,[number2],...)
4445 func (fn *formulaFuncs) GCD(argsList *list.List) formulaArg {
4446 if argsList.Len() == 0 {
4447 return newErrorFormulaArg(formulaErrorVALUE, "GCD requires at least 1 argument")
4453 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
4454 token := arg.Value.(formulaArg)
4457 num := token.ToNumber()
4458 if num.Type == ArgError {
4465 nums = append(nums, val)
4468 return newErrorFormulaArg(formulaErrorVALUE, "GCD only accepts positive arguments")
4471 return newNumberFormulaArg(nums[0])
4474 for i := 1; i < len(nums); i++ {
4476 return newErrorFormulaArg(formulaErrorVALUE, "GCD only accepts positive arguments")
4478 cd = gcd(cd, nums[i])
4480 return newNumberFormulaArg(cd)
4483 // INT function truncates a supplied number down to the closest integer. The
4484 // syntax of the function is:
4487 func (fn *formulaFuncs) INT(argsList *list.List) formulaArg {
4488 if argsList.Len() != 1 {
4489 return newErrorFormulaArg(formulaErrorVALUE, "INT requires 1 numeric argument")
4491 number := argsList.Front().Value.(formulaArg).ToNumber()
4492 if number.Type == ArgError {
4495 val, frac := math.Modf(number.Number)
4499 return newNumberFormulaArg(val)
4502 // ISOdotCEILING function rounds a supplied number up (regardless of the
4503 // number's sign), to the nearest multiple of a supplied significance. The
4504 // syntax of the function is:
4506 // ISO.CEILING(number,[significance])
4507 func (fn *formulaFuncs) ISOdotCEILING(argsList *list.List) formulaArg {
4508 if argsList.Len() == 0 {
4509 return newErrorFormulaArg(formulaErrorVALUE, "ISO.CEILING requires at least 1 argument")
4511 if argsList.Len() > 2 {
4512 return newErrorFormulaArg(formulaErrorVALUE, "ISO.CEILING allows at most 2 arguments")
4514 var significance float64
4515 number := argsList.Front().Value.(formulaArg).ToNumber()
4516 if number.Type == ArgError {
4519 if number.Number < 0 {
4522 if argsList.Len() == 1 {
4523 return newNumberFormulaArg(math.Ceil(number.Number))
4525 if argsList.Len() > 1 {
4526 s := argsList.Back().Value.(formulaArg).ToNumber()
4527 if s.Type == ArgError {
4530 significance = s.Number
4531 significance = math.Abs(significance)
4532 if significance == 0 {
4533 return newNumberFormulaArg(significance)
4536 val, res := math.Modf(number.Number / significance)
4538 if number.Number > 0 {
4542 return newNumberFormulaArg(val * significance)
4545 // lcm returns the least common multiple of two supplied integers.
4546 func lcm(a, b float64) float64 {
4549 if a == 0 && b == 0 {
4552 return a * b / gcd(a, b)
4555 // LCM function returns the least common multiple of two or more supplied
4556 // integers. The syntax of the function is:
4558 // LCM(number1,[number2],...)
4559 func (fn *formulaFuncs) LCM(argsList *list.List) formulaArg {
4560 if argsList.Len() == 0 {
4561 return newErrorFormulaArg(formulaErrorVALUE, "LCM requires at least 1 argument")
4568 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
4569 token := arg.Value.(formulaArg)
4572 if token.String == "" {
4575 if val, err = strconv.ParseFloat(token.String, 64); err != nil {
4576 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
4581 nums = append(nums, val)
4584 return newErrorFormulaArg(formulaErrorVALUE, "LCM only accepts positive arguments")
4587 return newNumberFormulaArg(nums[0])
4590 for i := 1; i < len(nums); i++ {
4592 return newErrorFormulaArg(formulaErrorVALUE, "LCM only accepts positive arguments")
4594 cm = lcm(cm, nums[i])
4596 return newNumberFormulaArg(cm)
4599 // LN function calculates the natural logarithm of a given number. The syntax
4600 // of the function is:
4603 func (fn *formulaFuncs) LN(argsList *list.List) formulaArg {
4604 if argsList.Len() != 1 {
4605 return newErrorFormulaArg(formulaErrorVALUE, "LN requires 1 numeric argument")
4607 number := argsList.Front().Value.(formulaArg).ToNumber()
4608 if number.Type == ArgError {
4611 return newNumberFormulaArg(math.Log(number.Number))
4614 // LOG function calculates the logarithm of a given number, to a supplied
4615 // base. The syntax of the function is:
4617 // LOG(number,[base])
4618 func (fn *formulaFuncs) LOG(argsList *list.List) formulaArg {
4619 if argsList.Len() == 0 {
4620 return newErrorFormulaArg(formulaErrorVALUE, "LOG requires at least 1 argument")
4622 if argsList.Len() > 2 {
4623 return newErrorFormulaArg(formulaErrorVALUE, "LOG allows at most 2 arguments")
4626 number := argsList.Front().Value.(formulaArg).ToNumber()
4627 if number.Type == ArgError {
4630 if argsList.Len() > 1 {
4631 b := argsList.Back().Value.(formulaArg).ToNumber()
4632 if b.Type == ArgError {
4637 if number.Number == 0 {
4638 return newErrorFormulaArg(formulaErrorNUM, formulaErrorDIV)
4641 return newErrorFormulaArg(formulaErrorNUM, formulaErrorDIV)
4644 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
4646 return newNumberFormulaArg(math.Log(number.Number) / math.Log(base))
4649 // LOG10 function calculates the base 10 logarithm of a given number. The
4650 // syntax of the function is:
4653 func (fn *formulaFuncs) LOG10(argsList *list.List) formulaArg {
4654 if argsList.Len() != 1 {
4655 return newErrorFormulaArg(formulaErrorVALUE, "LOG10 requires 1 numeric argument")
4657 number := argsList.Front().Value.(formulaArg).ToNumber()
4658 if number.Type == ArgError {
4661 return newNumberFormulaArg(math.Log10(number.Number))
4664 // minor function implement a minor of a matrix A is the determinant of some
4665 // smaller square matrix.
4666 func minor(sqMtx [][]float64, idx int) [][]float64 {
4668 for i := range sqMtx {
4673 for j := range sqMtx {
4677 row = append(row, sqMtx[i][j])
4679 ret = append(ret, row)
4684 // det determinant of the 2x2 matrix.
4685 func det(sqMtx [][]float64) float64 {
4686 if len(sqMtx) == 2 {
4691 return m00*m11 - m10*m01
4693 var res, sgn float64 = 0, 1
4694 for j := range sqMtx {
4695 res += sgn * sqMtx[0][j] * det(minor(sqMtx, j))
4701 // newNumberMatrix converts a formula arguments matrix to a number matrix.
4702 func newNumberMatrix(arg formulaArg, phalanx bool) (numMtx [][]float64, ele formulaArg) {
4703 rows := len(arg.Matrix)
4704 for r, row := range arg.Matrix {
4705 if phalanx && len(row) != rows {
4706 ele = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
4709 numMtx = append(numMtx, make([]float64, len(row)))
4710 for c, cell := range row {
4711 if cell.Type != ArgNumber {
4712 ele = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
4715 numMtx[r][c] = cell.Number
4721 // newFormulaArgMatrix converts the number formula arguments matrix to a
4722 // formula arguments matrix.
4723 func newFormulaArgMatrix(numMtx [][]float64) (arg [][]formulaArg) {
4724 for r, row := range numMtx {
4725 arg = append(arg, make([]formulaArg, len(row)))
4726 for c, cell := range row {
4727 arg[r][c] = newNumberFormulaArg(cell)
4733 // MDETERM calculates the determinant of a square matrix. The
4734 // syntax of the function is:
4737 func (fn *formulaFuncs) MDETERM(argsList *list.List) (result formulaArg) {
4738 if argsList.Len() < 1 {
4739 return newErrorFormulaArg(formulaErrorVALUE, "MDETERM requires 1 argument")
4741 numMtx, errArg := newNumberMatrix(argsList.Front().Value.(formulaArg), true)
4742 if errArg.Type == ArgError {
4745 return newNumberFormulaArg(det(numMtx))
4748 // cofactorMatrix returns the matrix A of cofactors.
4749 func cofactorMatrix(i, j int, A [][]float64) float64 {
4750 N, sign := len(A), -1.0
4756 for m := 0; m < N; m++ {
4757 for n := j + 1; n < N; n++ {
4760 B[m] = B[m][:len(B[m])-1]
4762 for k := i + 1; k < N; k++ {
4766 return sign * det(B)
4769 // adjugateMatrix returns transpose of the cofactor matrix A with Cramer's
4771 func adjugateMatrix(A [][]float64) (adjA [][]float64) {
4774 for i := 0; i < N; i++ {
4775 adjA = append(adjA, make([]float64, N))
4776 for j := 0; j < N; j++ {
4777 for m := 0; m < N; m++ {
4778 for n := 0; n < N; n++ {
4779 for x := len(B); x <= m; x++ {
4780 B = append(B, []float64{})
4782 for k := len(B[m]); k <= n; k++ {
4783 B[m] = append(B[m], 0)
4788 adjA[i][j] = cofactorMatrix(j, i, B)
4794 // MINVERSE function calculates the inverse of a square matrix. The syntax of
4798 func (fn *formulaFuncs) MINVERSE(argsList *list.List) formulaArg {
4799 if argsList.Len() != 1 {
4800 return newErrorFormulaArg(formulaErrorVALUE, "MINVERSE requires 1 argument")
4802 numMtx, errArg := newNumberMatrix(argsList.Front().Value.(formulaArg), true)
4803 if errArg.Type == ArgError {
4806 if detM := det(numMtx); detM != 0 {
4807 datM, invertM := 1/detM, adjugateMatrix(numMtx)
4808 for i := 0; i < len(invertM); i++ {
4809 for j := 0; j < len(invertM[i]); j++ {
4810 invertM[i][j] *= datM
4813 return newMatrixFormulaArg(newFormulaArgMatrix(invertM))
4815 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
4818 // MMULT function calculates the matrix product of two arrays
4819 // (representing matrices). The syntax of the function is:
4821 // MMULT(array1,array2)
4822 func (fn *formulaFuncs) MMULT(argsList *list.List) formulaArg {
4823 if argsList.Len() != 2 {
4824 return newErrorFormulaArg(formulaErrorVALUE, "MMULT requires 2 argument")
4826 arr1 := argsList.Front().Value.(formulaArg)
4827 arr2 := argsList.Back().Value.(formulaArg)
4828 if arr1.Type == ArgNumber && arr2.Type == ArgNumber {
4829 return newNumberFormulaArg(arr1.Number * arr2.Number)
4831 numMtx1, errArg1 := newNumberMatrix(arr1, false)
4832 if errArg1.Type == ArgError {
4835 numMtx2, errArg2 := newNumberMatrix(arr2, false)
4836 if errArg2.Type == ArgError {
4839 array2Rows, array2Cols := len(numMtx2), len(numMtx2[0])
4840 if len(numMtx1[0]) != array2Rows {
4841 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
4843 var numMtx [][]float64
4844 var row1, row []float64
4846 for i := 0; i < len(numMtx1); i++ {
4847 numMtx = append(numMtx, []float64{})
4850 for j := 0; j < array2Cols; j++ {
4852 for k := 0; k < array2Rows; k++ {
4853 sum += row1[k] * numMtx2[k][j]
4855 for l := len(row); l <= j; l++ {
4856 row = append(row, 0)
4862 return newMatrixFormulaArg(newFormulaArgMatrix(numMtx))
4865 // MOD function returns the remainder of a division between two supplied
4866 // numbers. The syntax of the function is:
4868 // MOD(number,divisor)
4869 func (fn *formulaFuncs) MOD(argsList *list.List) formulaArg {
4870 if argsList.Len() != 2 {
4871 return newErrorFormulaArg(formulaErrorVALUE, "MOD requires 2 numeric arguments")
4873 number := argsList.Front().Value.(formulaArg).ToNumber()
4874 if number.Type == ArgError {
4877 divisor := argsList.Back().Value.(formulaArg).ToNumber()
4878 if divisor.Type == ArgError {
4881 if divisor.Number == 0 {
4882 return newErrorFormulaArg(formulaErrorDIV, "MOD divide by zero")
4884 trunc, rem := math.Modf(number.Number / divisor.Number)
4888 return newNumberFormulaArg(number.Number - divisor.Number*trunc)
4891 // MROUND function rounds a supplied number up or down to the nearest multiple
4892 // of a given number. The syntax of the function is:
4894 // MROUND(number,multiple)
4895 func (fn *formulaFuncs) MROUND(argsList *list.List) formulaArg {
4896 if argsList.Len() != 2 {
4897 return newErrorFormulaArg(formulaErrorVALUE, "MROUND requires 2 numeric arguments")
4899 n := argsList.Front().Value.(formulaArg).ToNumber()
4900 if n.Type == ArgError {
4903 multiple := argsList.Back().Value.(formulaArg).ToNumber()
4904 if multiple.Type == ArgError {
4907 if multiple.Number == 0 {
4908 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
4910 if multiple.Number < 0 && n.Number > 0 ||
4911 multiple.Number > 0 && n.Number < 0 {
4912 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
4914 number, res := math.Modf(n.Number / multiple.Number)
4915 if math.Trunc(res+0.5) > 0 {
4918 return newNumberFormulaArg(number * multiple.Number)
4921 // MULTINOMIAL function calculates the ratio of the factorial of a sum of
4922 // supplied values to the product of factorials of those values. The syntax of
4925 // MULTINOMIAL(number1,[number2],...)
4926 func (fn *formulaFuncs) MULTINOMIAL(argsList *list.List) formulaArg {
4927 val, num, denom := 0.0, 0.0, 1.0
4929 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
4930 token := arg.Value.(formulaArg)
4933 if token.String == "" {
4936 if val, err = strconv.ParseFloat(token.String, 64); err != nil {
4937 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
4945 return newNumberFormulaArg(fact(num) / denom)
4948 // MUNIT function returns the unit matrix for a specified dimension. The
4949 // syntax of the function is:
4952 func (fn *formulaFuncs) MUNIT(argsList *list.List) (result formulaArg) {
4953 if argsList.Len() != 1 {
4954 return newErrorFormulaArg(formulaErrorVALUE, "MUNIT requires 1 numeric argument")
4956 dimension := argsList.Back().Value.(formulaArg).ToNumber()
4957 if dimension.Type == ArgError || dimension.Number < 0 {
4958 return newErrorFormulaArg(formulaErrorVALUE, dimension.Error)
4960 matrix := make([][]formulaArg, 0, int(dimension.Number))
4961 for i := 0; i < int(dimension.Number); i++ {
4962 row := make([]formulaArg, int(dimension.Number))
4963 for j := 0; j < int(dimension.Number); j++ {
4965 row[j] = newNumberFormulaArg(1.0)
4967 row[j] = newNumberFormulaArg(0.0)
4970 matrix = append(matrix, row)
4972 return newMatrixFormulaArg(matrix)
4975 // ODD function ounds a supplied number away from zero (i.e. rounds a positive
4976 // number up and a negative number down), to the next odd number. The syntax
4977 // of the function is:
4980 func (fn *formulaFuncs) ODD(argsList *list.List) formulaArg {
4981 if argsList.Len() != 1 {
4982 return newErrorFormulaArg(formulaErrorVALUE, "ODD requires 1 numeric argument")
4984 number := argsList.Back().Value.(formulaArg).ToNumber()
4985 if number.Type == ArgError {
4988 if number.Number == 0 {
4989 return newNumberFormulaArg(1)
4991 sign := math.Signbit(number.Number)
4992 m, frac := math.Modf((number.Number - 1) / 2)
5001 return newNumberFormulaArg(val)
5004 // PI function returns the value of the mathematical constant π (pi), accurate
5005 // to 15 digits (14 decimal places). The syntax of the function is:
5008 func (fn *formulaFuncs) PI(argsList *list.List) formulaArg {
5009 if argsList.Len() != 0 {
5010 return newErrorFormulaArg(formulaErrorVALUE, "PI accepts no arguments")
5012 return newNumberFormulaArg(math.Pi)
5015 // POWER function calculates a given number, raised to a supplied power.
5016 // The syntax of the function is:
5018 // POWER(number,power)
5019 func (fn *formulaFuncs) POWER(argsList *list.List) formulaArg {
5020 if argsList.Len() != 2 {
5021 return newErrorFormulaArg(formulaErrorVALUE, "POWER requires 2 numeric arguments")
5023 x := argsList.Front().Value.(formulaArg).ToNumber()
5024 if x.Type == ArgError {
5027 y := argsList.Back().Value.(formulaArg).ToNumber()
5028 if y.Type == ArgError {
5031 if x.Number == 0 && y.Number == 0 {
5032 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
5034 if x.Number == 0 && y.Number < 0 {
5035 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
5037 return newNumberFormulaArg(math.Pow(x.Number, y.Number))
5040 // PRODUCT function returns the product (multiplication) of a supplied set of
5041 // numerical values. The syntax of the function is:
5043 // PRODUCT(number1,[number2],...)
5044 func (fn *formulaFuncs) PRODUCT(argsList *list.List) formulaArg {
5046 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5047 token := arg.Value.(formulaArg)
5050 num := token.ToNumber()
5051 if num.Type != ArgNumber {
5054 product = product * num.Number
5056 product = product * token.Number
5058 for _, row := range token.Matrix {
5059 for _, cell := range row {
5060 if cell.Type == ArgNumber {
5061 product *= cell.Number
5067 return newNumberFormulaArg(product)
5070 // QUOTIENT function returns the integer portion of a division between two
5071 // supplied numbers. The syntax of the function is:
5073 // QUOTIENT(numerator,denominator)
5074 func (fn *formulaFuncs) QUOTIENT(argsList *list.List) formulaArg {
5075 if argsList.Len() != 2 {
5076 return newErrorFormulaArg(formulaErrorVALUE, "QUOTIENT requires 2 numeric arguments")
5078 x := argsList.Front().Value.(formulaArg).ToNumber()
5079 if x.Type == ArgError {
5082 y := argsList.Back().Value.(formulaArg).ToNumber()
5083 if y.Type == ArgError {
5087 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
5089 return newNumberFormulaArg(math.Trunc(x.Number / y.Number))
5092 // RADIANS function converts radians into degrees. The syntax of the function is:
5095 func (fn *formulaFuncs) RADIANS(argsList *list.List) formulaArg {
5096 if argsList.Len() != 1 {
5097 return newErrorFormulaArg(formulaErrorVALUE, "RADIANS requires 1 numeric argument")
5099 angle := argsList.Front().Value.(formulaArg).ToNumber()
5100 if angle.Type == ArgError {
5103 return newNumberFormulaArg(math.Pi / 180.0 * angle.Number)
5106 // RAND function generates a random real number between 0 and 1. The syntax of
5110 func (fn *formulaFuncs) RAND(argsList *list.List) formulaArg {
5111 if argsList.Len() != 0 {
5112 return newErrorFormulaArg(formulaErrorVALUE, "RAND accepts no arguments")
5114 return newNumberFormulaArg(rand.New(rand.NewSource(time.Now().UnixNano())).Float64())
5117 // RANDBETWEEN function generates a random integer between two supplied
5118 // integers. The syntax of the function is:
5120 // RANDBETWEEN(bottom,top)
5121 func (fn *formulaFuncs) RANDBETWEEN(argsList *list.List) formulaArg {
5122 if argsList.Len() != 2 {
5123 return newErrorFormulaArg(formulaErrorVALUE, "RANDBETWEEN requires 2 numeric arguments")
5125 bottom := argsList.Front().Value.(formulaArg).ToNumber()
5126 if bottom.Type == ArgError {
5129 top := argsList.Back().Value.(formulaArg).ToNumber()
5130 if top.Type == ArgError {
5133 if top.Number < bottom.Number {
5134 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
5136 num := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(int64(top.Number - bottom.Number + 1))
5137 return newNumberFormulaArg(float64(num + int64(bottom.Number)))
5140 // romanNumerals defined a numeral system that originated in ancient Rome and
5141 // remained the usual way of writing numbers throughout Europe well into the
5142 // Late Middle Ages.
5143 type romanNumerals struct {
5148 var romanTable = [][]romanNumerals{
5254 // ROMAN function converts an arabic number to Roman. I.e. for a supplied
5255 // integer, the function returns a text string depicting the roman numeral
5256 // form of the number. The syntax of the function is:
5258 // ROMAN(number,[form])
5259 func (fn *formulaFuncs) ROMAN(argsList *list.List) formulaArg {
5260 if argsList.Len() == 0 {
5261 return newErrorFormulaArg(formulaErrorVALUE, "ROMAN requires at least 1 argument")
5263 if argsList.Len() > 2 {
5264 return newErrorFormulaArg(formulaErrorVALUE, "ROMAN allows at most 2 arguments")
5267 number := argsList.Front().Value.(formulaArg).ToNumber()
5268 if number.Type == ArgError {
5271 if argsList.Len() > 1 {
5272 f := argsList.Back().Value.(formulaArg).ToNumber()
5273 if f.Type == ArgError {
5276 form = int(f.Number)
5279 } else if form > 4 {
5283 decimalTable := romanTable[0]
5286 decimalTable = romanTable[1]
5288 decimalTable = romanTable[2]
5290 decimalTable = romanTable[3]
5292 decimalTable = romanTable[4]
5294 val := math.Trunc(number.Number)
5295 buf := bytes.Buffer{}
5296 for _, r := range decimalTable {
5298 buf.WriteString(r.s)
5302 return newStringFormulaArg(buf.String())
5308 closest roundMode = iota
5313 // round rounds a supplied number up or down.
5314 func (fn *formulaFuncs) round(number, digits float64, mode roundMode) float64 {
5315 var significance float64
5317 significance = math.Pow(1/10.0, digits)
5319 significance = math.Pow(10.0, -digits)
5321 val, res := math.Modf(number / significance)
5324 const eps = 0.499999999
5327 } else if res <= -eps {
5338 return val * significance
5341 // ROUND function rounds a supplied number up or down, to a specified number
5342 // of decimal places. The syntax of the function is:
5344 // ROUND(number,num_digits)
5345 func (fn *formulaFuncs) ROUND(argsList *list.List) formulaArg {
5346 if argsList.Len() != 2 {
5347 return newErrorFormulaArg(formulaErrorVALUE, "ROUND requires 2 numeric arguments")
5349 number := argsList.Front().Value.(formulaArg).ToNumber()
5350 if number.Type == ArgError {
5353 digits := argsList.Back().Value.(formulaArg).ToNumber()
5354 if digits.Type == ArgError {
5357 return newNumberFormulaArg(fn.round(number.Number, digits.Number, closest))
5360 // ROUNDDOWN function rounds a supplied number down towards zero, to a
5361 // specified number of decimal places. The syntax of the function is:
5363 // ROUNDDOWN(number,num_digits)
5364 func (fn *formulaFuncs) ROUNDDOWN(argsList *list.List) formulaArg {
5365 if argsList.Len() != 2 {
5366 return newErrorFormulaArg(formulaErrorVALUE, "ROUNDDOWN requires 2 numeric arguments")
5368 number := argsList.Front().Value.(formulaArg).ToNumber()
5369 if number.Type == ArgError {
5372 digits := argsList.Back().Value.(formulaArg).ToNumber()
5373 if digits.Type == ArgError {
5376 return newNumberFormulaArg(fn.round(number.Number, digits.Number, down))
5379 // ROUNDUP function rounds a supplied number up, away from zero, to a
5380 // specified number of decimal places. The syntax of the function is:
5382 // ROUNDUP(number,num_digits)
5383 func (fn *formulaFuncs) ROUNDUP(argsList *list.List) formulaArg {
5384 if argsList.Len() != 2 {
5385 return newErrorFormulaArg(formulaErrorVALUE, "ROUNDUP requires 2 numeric arguments")
5387 number := argsList.Front().Value.(formulaArg).ToNumber()
5388 if number.Type == ArgError {
5391 digits := argsList.Back().Value.(formulaArg).ToNumber()
5392 if digits.Type == ArgError {
5395 return newNumberFormulaArg(fn.round(number.Number, digits.Number, up))
5398 // SEC function calculates the secant of a given angle. The syntax of the
5402 func (fn *formulaFuncs) SEC(argsList *list.List) formulaArg {
5403 if argsList.Len() != 1 {
5404 return newErrorFormulaArg(formulaErrorVALUE, "SEC requires 1 numeric argument")
5406 number := argsList.Front().Value.(formulaArg).ToNumber()
5407 if number.Type == ArgError {
5410 return newNumberFormulaArg(math.Cos(number.Number))
5413 // SECH function calculates the hyperbolic secant (sech) of a supplied angle.
5414 // The syntax of the function is:
5417 func (fn *formulaFuncs) SECH(argsList *list.List) formulaArg {
5418 if argsList.Len() != 1 {
5419 return newErrorFormulaArg(formulaErrorVALUE, "SECH requires 1 numeric argument")
5421 number := argsList.Front().Value.(formulaArg).ToNumber()
5422 if number.Type == ArgError {
5425 return newNumberFormulaArg(1 / math.Cosh(number.Number))
5428 // SERIESSUM function returns the sum of a power series. The syntax of the
5431 // SERIESSUM(x,n,m,coefficients)
5432 func (fn *formulaFuncs) SERIESSUM(argsList *list.List) formulaArg {
5433 if argsList.Len() != 4 {
5434 return newErrorFormulaArg(formulaErrorVALUE, "SERIESSUM requires 4 arguments")
5436 var x, n, m formulaArg
5437 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
5440 if n = argsList.Front().Next().Value.(formulaArg).ToNumber(); n.Type != ArgNumber {
5443 if m = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); m.Type != ArgNumber {
5446 var result, i float64
5447 for _, coefficient := range argsList.Back().Value.(formulaArg).ToList() {
5448 if coefficient.Value() == "" {
5451 num := coefficient.ToNumber()
5452 if num.Type != ArgNumber {
5455 result += num.Number * math.Pow(x.Number, n.Number+(m.Number*i))
5458 return newNumberFormulaArg(result)
5461 // SIGN function returns the arithmetic sign (+1, -1 or 0) of a supplied
5462 // number. I.e. if the number is positive, the Sign function returns +1, if
5463 // the number is negative, the function returns -1 and if the number is 0
5464 // (zero), the function returns 0. The syntax of the function is:
5467 func (fn *formulaFuncs) SIGN(argsList *list.List) formulaArg {
5468 if argsList.Len() != 1 {
5469 return newErrorFormulaArg(formulaErrorVALUE, "SIGN requires 1 numeric argument")
5471 val := argsList.Front().Value.(formulaArg).ToNumber()
5472 if val.Type == ArgError {
5476 return newNumberFormulaArg(-1)
5479 return newNumberFormulaArg(1)
5481 return newNumberFormulaArg(0)
5484 // SIN function calculates the sine of a given angle. The syntax of the
5488 func (fn *formulaFuncs) SIN(argsList *list.List) formulaArg {
5489 if argsList.Len() != 1 {
5490 return newErrorFormulaArg(formulaErrorVALUE, "SIN requires 1 numeric argument")
5492 number := argsList.Front().Value.(formulaArg).ToNumber()
5493 if number.Type == ArgError {
5496 return newNumberFormulaArg(math.Sin(number.Number))
5499 // SINH function calculates the hyperbolic sine (sinh) of a supplied number.
5500 // The syntax of the function is:
5503 func (fn *formulaFuncs) SINH(argsList *list.List) formulaArg {
5504 if argsList.Len() != 1 {
5505 return newErrorFormulaArg(formulaErrorVALUE, "SINH requires 1 numeric argument")
5507 number := argsList.Front().Value.(formulaArg).ToNumber()
5508 if number.Type == ArgError {
5511 return newNumberFormulaArg(math.Sinh(number.Number))
5514 // SQRT function calculates the positive square root of a supplied number. The
5515 // syntax of the function is:
5518 func (fn *formulaFuncs) SQRT(argsList *list.List) formulaArg {
5519 if argsList.Len() != 1 {
5520 return newErrorFormulaArg(formulaErrorVALUE, "SQRT requires 1 numeric argument")
5522 value := argsList.Front().Value.(formulaArg).ToNumber()
5523 if value.Type == ArgError {
5526 if value.Number < 0 {
5527 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
5529 return newNumberFormulaArg(math.Sqrt(value.Number))
5532 // SQRTPI function returns the square root of a supplied number multiplied by
5533 // the mathematical constant, π. The syntax of the function is:
5536 func (fn *formulaFuncs) SQRTPI(argsList *list.List) formulaArg {
5537 if argsList.Len() != 1 {
5538 return newErrorFormulaArg(formulaErrorVALUE, "SQRTPI requires 1 numeric argument")
5540 number := argsList.Front().Value.(formulaArg).ToNumber()
5541 if number.Type == ArgError {
5544 return newNumberFormulaArg(math.Sqrt(number.Number * math.Pi))
5547 // STDEV function calculates the sample standard deviation of a supplied set
5548 // of values. The syntax of the function is:
5550 // STDEV(number1,[number2],...)
5551 func (fn *formulaFuncs) STDEV(argsList *list.List) formulaArg {
5552 if argsList.Len() < 1 {
5553 return newErrorFormulaArg(formulaErrorVALUE, "STDEV requires at least 1 argument")
5555 return fn.stdev(false, argsList)
5558 // STDEVdotS function calculates the sample standard deviation of a supplied
5559 // set of values. The syntax of the function is:
5561 // STDEV.S(number1,[number2],...)
5562 func (fn *formulaFuncs) STDEVdotS(argsList *list.List) formulaArg {
5563 if argsList.Len() < 1 {
5564 return newErrorFormulaArg(formulaErrorVALUE, "STDEV.S requires at least 1 argument")
5566 return fn.stdev(false, argsList)
5569 // STDEVA function estimates standard deviation based on a sample. The
5570 // standard deviation is a measure of how widely values are dispersed from
5571 // the average value (the mean). The syntax of the function is:
5573 // STDEVA(number1,[number2],...)
5574 func (fn *formulaFuncs) STDEVA(argsList *list.List) formulaArg {
5575 if argsList.Len() < 1 {
5576 return newErrorFormulaArg(formulaErrorVALUE, "STDEVA requires at least 1 argument")
5578 return fn.stdev(true, argsList)
5581 // calcStdevPow is part of the implementation stdev.
5582 func calcStdevPow(result, count float64, n, m formulaArg) (float64, float64) {
5584 result = math.Pow(n.Number-m.Number, 2)
5586 result += math.Pow(n.Number-m.Number, 2)
5589 return result, count
5592 // calcStdev is part of the implementation stdev.
5593 func calcStdev(stdeva bool, result, count float64, mean, token formulaArg) (float64, float64) {
5594 for _, row := range token.ToList() {
5595 if row.Type == ArgNumber || row.Type == ArgString {
5596 if !stdeva && (row.Value() == "TRUE" || row.Value() == "FALSE") {
5598 } else if stdeva && (row.Value() == "TRUE" || row.Value() == "FALSE") {
5600 if num.Type == ArgNumber {
5601 result, count = calcStdevPow(result, count, num, mean)
5605 num := row.ToNumber()
5606 if num.Type == ArgNumber {
5607 result, count = calcStdevPow(result, count, num, mean)
5612 return result, count
5615 // stdev is an implementation of the formula functions STDEV and STDEVA.
5616 func (fn *formulaFuncs) stdev(stdeva bool, argsList *list.List) formulaArg {
5617 count, result := -1.0, -1.0
5620 mean = fn.AVERAGEA(argsList)
5622 mean = fn.AVERAGE(argsList)
5624 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5625 token := arg.Value.(formulaArg)
5627 case ArgString, ArgNumber:
5628 if !stdeva && (token.Value() == "TRUE" || token.Value() == "FALSE") {
5630 } else if stdeva && (token.Value() == "TRUE" || token.Value() == "FALSE") {
5631 num := token.ToBool()
5632 if num.Type == ArgNumber {
5633 result, count = calcStdevPow(result, count, num, mean)
5637 num := token.ToNumber()
5638 if num.Type == ArgNumber {
5639 result, count = calcStdevPow(result, count, num, mean)
5642 case ArgList, ArgMatrix:
5643 result, count = calcStdev(stdeva, result, count, mean, token)
5646 if count > 0 && result >= 0 {
5647 return newNumberFormulaArg(math.Sqrt(result / count))
5649 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
5652 // POISSONdotDIST function calculates the Poisson Probability Mass Function or
5653 // the Cumulative Poisson Probability Function for a supplied set of
5654 // parameters. The syntax of the function is:
5656 // POISSON.DIST(x,mean,cumulative)
5657 func (fn *formulaFuncs) POISSONdotDIST(argsList *list.List) formulaArg {
5658 if argsList.Len() != 3 {
5659 return newErrorFormulaArg(formulaErrorVALUE, "POISSON.DIST requires 3 arguments")
5661 return fn.POISSON(argsList)
5664 // POISSON function calculates the Poisson Probability Mass Function or the
5665 // Cumulative Poisson Probability Function for a supplied set of parameters.
5666 // The syntax of the function is:
5668 // POISSON(x,mean,cumulative)
5669 func (fn *formulaFuncs) POISSON(argsList *list.List) formulaArg {
5670 if argsList.Len() != 3 {
5671 return newErrorFormulaArg(formulaErrorVALUE, "POISSON requires 3 arguments")
5673 var x, mean, cumulative formulaArg
5674 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
5677 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
5680 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
5683 if x.Number < 0 || mean.Number <= 0 {
5684 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
5686 if cumulative.Number == 1 {
5688 floor := math.Floor(x.Number)
5689 for i := 0; i <= int(floor); i++ {
5690 summer += math.Pow(mean.Number, float64(i)) / fact(float64(i))
5692 return newNumberFormulaArg(math.Exp(0-mean.Number) * summer)
5694 return newNumberFormulaArg(math.Exp(0-mean.Number) * math.Pow(mean.Number, x.Number) / fact(x.Number))
5697 // prepareProbArgs checking and prepare arguments for the formula function
5699 func prepareProbArgs(argsList *list.List) []formulaArg {
5700 if argsList.Len() < 3 {
5701 return []formulaArg{newErrorFormulaArg(formulaErrorVALUE, "PROB requires at least 3 arguments")}
5703 if argsList.Len() > 4 {
5704 return []formulaArg{newErrorFormulaArg(formulaErrorVALUE, "PROB requires at most 4 arguments")}
5706 var lower, upper formulaArg
5707 xRange := argsList.Front().Value.(formulaArg)
5708 probRange := argsList.Front().Next().Value.(formulaArg)
5709 if lower = argsList.Front().Next().Next().Value.(formulaArg); lower.Type != ArgNumber {
5710 return []formulaArg{newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)}
5713 if argsList.Len() == 4 {
5714 if upper = argsList.Back().Value.(formulaArg); upper.Type != ArgNumber {
5715 return []formulaArg{newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)}
5718 nR1, nR2 := len(xRange.Matrix), len(probRange.Matrix)
5719 if nR1 == 0 || nR2 == 0 {
5720 return []formulaArg{newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)}
5723 return []formulaArg{newErrorFormulaArg(formulaErrorNA, formulaErrorNA)}
5725 nC1, nC2 := len(xRange.Matrix[0]), len(probRange.Matrix[0])
5727 return []formulaArg{newErrorFormulaArg(formulaErrorNA, formulaErrorNA)}
5729 return []formulaArg{xRange, probRange, lower, upper}
5732 // PROB function calculates the probability associated with a given range. The
5733 // syntax of the function is:
5735 // PROB(x_range,prob_range,lower_limit,[upper_limit])
5736 func (fn *formulaFuncs) PROB(argsList *list.List) formulaArg {
5737 args := prepareProbArgs(argsList)
5741 xRange, probRange, lower, upper := args[0], args[1], args[2], args[3]
5742 var sum, res, fP, fW float64
5744 for r := 0; r < len(xRange.Matrix) && !stop; r++ {
5745 for c := 0; c < len(xRange.Matrix[0]) && !stop; c++ {
5746 p := probRange.Matrix[r][c]
5747 x := xRange.Matrix[r][c]
5748 if p.Type == ArgNumber && x.Type == ArgNumber {
5749 if fP, fW = p.Number, x.Number; fP < 0 || fP > 1 {
5753 if sum += fP; fW >= lower.Number && fW <= upper.Number {
5758 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
5761 if stop || math.Abs(sum-1) > 1.0e-7 {
5762 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
5764 return newNumberFormulaArg(res)
5767 // SUBTOTAL function performs a specified calculation (e.g. the sum, product,
5768 // average, etc.) for a supplied set of values. The syntax of the function is:
5770 // SUBTOTAL(function_num,ref1,[ref2],...)
5771 func (fn *formulaFuncs) SUBTOTAL(argsList *list.List) formulaArg {
5772 if argsList.Len() < 2 {
5773 return newErrorFormulaArg(formulaErrorVALUE, "SUBTOTAL requires at least 2 arguments")
5775 var fnNum formulaArg
5776 if fnNum = argsList.Front().Value.(formulaArg).ToNumber(); fnNum.Type != ArgNumber {
5779 subFn, ok := map[int]func(argsList *list.List) formulaArg{
5780 1: fn.AVERAGE, 101: fn.AVERAGE,
5781 2: fn.COUNT, 102: fn.COUNT,
5782 3: fn.COUNTA, 103: fn.COUNTA,
5783 4: fn.MAX, 104: fn.MAX,
5784 5: fn.MIN, 105: fn.MIN,
5785 6: fn.PRODUCT, 106: fn.PRODUCT,
5786 7: fn.STDEV, 107: fn.STDEV,
5787 8: fn.STDEVP, 108: fn.STDEVP,
5788 9: fn.SUM, 109: fn.SUM,
5789 10: fn.VAR, 110: fn.VAR,
5790 11: fn.VARP, 111: fn.VARP,
5791 }[int(fnNum.Number)]
5793 return newErrorFormulaArg(formulaErrorVALUE, "SUBTOTAL has invalid function_num")
5795 subArgList := list.New().Init()
5796 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
5797 subArgList.PushBack(arg.Value.(formulaArg))
5799 return subFn(subArgList)
5802 // SUM function adds together a supplied set of numbers and returns the sum of
5803 // these values. The syntax of the function is:
5805 // SUM(number1,[number2],...)
5806 func (fn *formulaFuncs) SUM(argsList *list.List) formulaArg {
5808 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5809 token := arg.Value.(formulaArg)
5814 if num := token.ToNumber(); num.Type == ArgNumber {
5820 for _, row := range token.Matrix {
5821 for _, value := range row {
5822 if num := value.ToNumber(); num.Type == ArgNumber {
5829 return newNumberFormulaArg(sum)
5832 // SUMIF function finds the values in a supplied array, that satisfy a given
5833 // criteria, and returns the sum of the corresponding values in a second
5834 // supplied array. The syntax of the function is:
5836 // SUMIF(range,criteria,[sum_range])
5837 func (fn *formulaFuncs) SUMIF(argsList *list.List) formulaArg {
5838 if argsList.Len() < 2 {
5839 return newErrorFormulaArg(formulaErrorVALUE, "SUMIF requires at least 2 arguments")
5841 criteria := formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg))
5842 rangeMtx := argsList.Front().Value.(formulaArg).Matrix
5843 var sumRange [][]formulaArg
5844 if argsList.Len() == 3 {
5845 sumRange = argsList.Back().Value.(formulaArg).Matrix
5849 for rowIdx, row := range rangeMtx {
5850 for colIdx, cell := range row {
5852 if arg.Type == ArgEmpty {
5855 if ok, _ := formulaCriteriaEval(arg, criteria); ok {
5856 if argsList.Len() == 3 {
5857 if len(sumRange) > rowIdx && len(sumRange[rowIdx]) > colIdx {
5858 arg = sumRange[rowIdx][colIdx]
5861 if arg.Type == ArgNumber {
5867 return newNumberFormulaArg(sum)
5870 // SUMIFS function finds values in one or more supplied arrays, that satisfy a
5871 // set of criteria, and returns the sum of the corresponding values in a
5872 // further supplied array. The syntax of the function is:
5874 // SUMIFS(sum_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
5875 func (fn *formulaFuncs) SUMIFS(argsList *list.List) formulaArg {
5876 if argsList.Len() < 3 {
5877 return newErrorFormulaArg(formulaErrorVALUE, "SUMIFS requires at least 3 arguments")
5879 if argsList.Len()%2 != 1 {
5880 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
5882 var args []formulaArg
5883 sum, sumRange := 0.0, argsList.Front().Value.(formulaArg).Matrix
5884 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
5885 args = append(args, arg.Value.(formulaArg))
5887 for _, ref := range formulaIfsMatch(args) {
5888 if ref.Row >= len(sumRange) || ref.Col >= len(sumRange[ref.Row]) {
5889 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
5891 if num := sumRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber {
5895 return newNumberFormulaArg(sum)
5898 // sumproduct is an implementation of the formula function SUMPRODUCT.
5899 func (fn *formulaFuncs) sumproduct(argsList *list.List) formulaArg {
5906 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5907 token := arg.Value.(formulaArg)
5908 if argType == ArgUnknown {
5909 argType = token.Type
5911 if token.Type != argType {
5912 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
5915 case ArgString, ArgNumber:
5916 if num := token.ToNumber(); num.Type == ArgNumber {
5917 sum = fn.PRODUCT(argsList).Number
5920 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
5922 args := token.ToList()
5925 res = make([]float64, n)
5926 for i := range res {
5931 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
5933 for i, value := range args {
5934 num := value.ToNumber()
5935 if num.Type != ArgNumber && value.Value() != "" {
5936 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
5938 res[i] = res[i] * num.Number
5942 for _, r := range res {
5945 return newNumberFormulaArg(sum)
5948 // SUMPRODUCT function returns the sum of the products of the corresponding
5949 // values in a set of supplied arrays. The syntax of the function is:
5951 // SUMPRODUCT(array1,[array2],[array3],...)
5952 func (fn *formulaFuncs) SUMPRODUCT(argsList *list.List) formulaArg {
5953 if argsList.Len() < 1 {
5954 return newErrorFormulaArg(formulaErrorVALUE, "SUMPRODUCT requires at least 1 argument")
5956 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5957 if token := arg.Value.(formulaArg); token.Type == ArgError {
5961 return fn.sumproduct(argsList)
5964 // SUMSQ function returns the sum of squares of a supplied set of values. The
5965 // syntax of the function is:
5967 // SUMSQ(number1,[number2],...)
5968 func (fn *formulaFuncs) SUMSQ(argsList *list.List) formulaArg {
5971 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
5972 token := arg.Value.(formulaArg)
5975 if token.String == "" {
5978 if val, err = strconv.ParseFloat(token.String, 64); err != nil {
5979 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
5983 sq += token.Number * token.Number
5985 for _, row := range token.Matrix {
5986 for _, value := range row {
5987 if value.Value() == "" {
5990 if val, err = strconv.ParseFloat(value.Value(), 64); err != nil {
5991 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
5998 return newNumberFormulaArg(sq)
6001 // sumx is an implementation of the formula functions SUMX2MY2, SUMX2PY2 and
6003 func (fn *formulaFuncs) sumx(name string, argsList *list.List) formulaArg {
6004 if argsList.Len() != 2 {
6005 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 arguments", name))
6007 array1 := argsList.Front().Value.(formulaArg)
6008 array2 := argsList.Back().Value.(formulaArg)
6009 left, right := array1.ToList(), array2.ToList()
6011 if n != len(right) {
6012 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
6015 for i := 0; i < n; i++ {
6016 if lhs, rhs := left[i].ToNumber(), right[i].ToNumber(); lhs.Number != 0 && rhs.Number != 0 {
6019 result += lhs.Number*lhs.Number - rhs.Number*rhs.Number
6021 result += lhs.Number*lhs.Number + rhs.Number*rhs.Number
6023 result += (lhs.Number - rhs.Number) * (lhs.Number - rhs.Number)
6027 return newNumberFormulaArg(result)
6030 // SUMX2MY2 function returns the sum of the differences of squares of two
6031 // supplied sets of values. The syntax of the function is:
6033 // SUMX2MY2(array_x,array_y)
6034 func (fn *formulaFuncs) SUMX2MY2(argsList *list.List) formulaArg {
6035 return fn.sumx("SUMX2MY2", argsList)
6038 // SUMX2PY2 function returns the sum of the sum of squares of two supplied sets
6039 // of values. The syntax of the function is:
6041 // SUMX2PY2(array_x,array_y)
6042 func (fn *formulaFuncs) SUMX2PY2(argsList *list.List) formulaArg {
6043 return fn.sumx("SUMX2PY2", argsList)
6046 // SUMXMY2 function returns the sum of the squares of differences between
6047 // corresponding values in two supplied arrays. The syntax of the function
6050 // SUMXMY2(array_x,array_y)
6051 func (fn *formulaFuncs) SUMXMY2(argsList *list.List) formulaArg {
6052 return fn.sumx("SUMXMY2", argsList)
6055 // TAN function calculates the tangent of a given angle. The syntax of the
6059 func (fn *formulaFuncs) TAN(argsList *list.List) formulaArg {
6060 if argsList.Len() != 1 {
6061 return newErrorFormulaArg(formulaErrorVALUE, "TAN requires 1 numeric argument")
6063 number := argsList.Front().Value.(formulaArg).ToNumber()
6064 if number.Type == ArgError {
6067 return newNumberFormulaArg(math.Tan(number.Number))
6070 // TANH function calculates the hyperbolic tangent (tanh) of a supplied
6071 // number. The syntax of the function is:
6074 func (fn *formulaFuncs) TANH(argsList *list.List) formulaArg {
6075 if argsList.Len() != 1 {
6076 return newErrorFormulaArg(formulaErrorVALUE, "TANH requires 1 numeric argument")
6078 number := argsList.Front().Value.(formulaArg).ToNumber()
6079 if number.Type == ArgError {
6082 return newNumberFormulaArg(math.Tanh(number.Number))
6085 // TRUNC function truncates a supplied number to a specified number of decimal
6086 // places. The syntax of the function is:
6088 // TRUNC(number,[number_digits])
6089 func (fn *formulaFuncs) TRUNC(argsList *list.List) formulaArg {
6090 if argsList.Len() == 0 {
6091 return newErrorFormulaArg(formulaErrorVALUE, "TRUNC requires at least 1 argument")
6093 var digits, adjust, rtrim float64
6095 number := argsList.Front().Value.(formulaArg).ToNumber()
6096 if number.Type == ArgError {
6099 if argsList.Len() > 1 {
6100 d := argsList.Back().Value.(formulaArg).ToNumber()
6101 if d.Type == ArgError {
6105 digits = math.Floor(digits)
6107 adjust = math.Pow(10, digits)
6108 x := int((math.Abs(number.Number) - math.Abs(float64(int(number.Number)))) * adjust)
6110 if rtrim, err = strconv.ParseFloat(strings.TrimRight(strconv.Itoa(x), "0"), 64); err != nil {
6111 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
6114 if (digits > 0) && (rtrim < adjust/10) {
6115 return newNumberFormulaArg(number.Number)
6117 return newNumberFormulaArg(float64(int(number.Number*adjust)) / adjust)
6120 // Statistical Functions
6122 // AVEDEV function calculates the average deviation of a supplied set of
6123 // values. The syntax of the function is:
6125 // AVEDEV(number1,[number2],...)
6126 func (fn *formulaFuncs) AVEDEV(argsList *list.List) formulaArg {
6127 if argsList.Len() == 0 {
6128 return newErrorFormulaArg(formulaErrorVALUE, "AVEDEV requires at least 1 argument")
6130 average := fn.AVERAGE(argsList)
6131 if average.Type != ArgNumber {
6132 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
6134 result, count := 0.0, 0.0
6135 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
6136 num := arg.Value.(formulaArg).ToNumber()
6137 if num.Type != ArgNumber {
6138 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
6140 result += math.Abs(num.Number - average.Number)
6143 return newNumberFormulaArg(result / count)
6146 // AVERAGE function returns the arithmetic mean of a list of supplied numbers.
6147 // The syntax of the function is:
6149 // AVERAGE(number1,[number2],...)
6150 func (fn *formulaFuncs) AVERAGE(argsList *list.List) formulaArg {
6151 var args []formulaArg
6152 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
6153 args = append(args, arg.Value.(formulaArg))
6155 count, sum := fn.countSum(false, args)
6157 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
6159 return newNumberFormulaArg(sum / count)
6162 // AVERAGEA function returns the arithmetic mean of a list of supplied numbers
6163 // with text cell and zero values. The syntax of the function is:
6165 // AVERAGEA(number1,[number2],...)
6166 func (fn *formulaFuncs) AVERAGEA(argsList *list.List) formulaArg {
6167 var args []formulaArg
6168 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
6169 args = append(args, arg.Value.(formulaArg))
6171 count, sum := fn.countSum(true, args)
6173 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
6175 return newNumberFormulaArg(sum / count)
6178 // AVERAGEIF function finds the values in a supplied array that satisfy a
6179 // specified criteria, and returns the average (i.e. the statistical mean) of
6180 // the corresponding values in a second supplied array. The syntax of the
6183 // AVERAGEIF(range,criteria,[average_range])
6184 func (fn *formulaFuncs) AVERAGEIF(argsList *list.List) formulaArg {
6185 if argsList.Len() < 2 {
6186 return newErrorFormulaArg(formulaErrorVALUE, "AVERAGEIF requires at least 2 arguments")
6189 criteria = formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg))
6190 rangeMtx = argsList.Front().Value.(formulaArg).Matrix
6191 cellRange [][]formulaArg
6197 if argsList.Len() == 3 {
6198 cellRange = argsList.Back().Value.(formulaArg).Matrix
6200 for rowIdx, row := range rangeMtx {
6201 for colIdx, col := range row {
6202 fromVal := col.Value()
6206 if col.Type == ArgString && criteria.Condition.Type != ArgString {
6209 ok, _ = formulaCriteriaEval(col, criteria)
6211 if argsList.Len() == 3 {
6212 if len(cellRange) > rowIdx && len(cellRange[rowIdx]) > colIdx {
6213 fromVal = cellRange[rowIdx][colIdx].Value()
6216 if val, err = strconv.ParseFloat(fromVal, 64); err != nil {
6219 args = append(args, newNumberFormulaArg(val))
6223 count, sum := fn.countSum(false, args)
6225 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
6227 return newNumberFormulaArg(sum / count)
6230 // AVERAGEIFS function finds entries in one or more arrays, that satisfy a set
6231 // of supplied criteria, and returns the average (i.e. the statistical mean)
6232 // of the corresponding values in a further supplied array. The syntax of the
6235 // AVERAGEIFS(average_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
6236 func (fn *formulaFuncs) AVERAGEIFS(argsList *list.List) formulaArg {
6237 if argsList.Len() < 3 {
6238 return newErrorFormulaArg(formulaErrorVALUE, "AVERAGEIFS requires at least 3 arguments")
6240 if argsList.Len()%2 != 1 {
6241 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
6243 var args []formulaArg
6244 sum, sumRange := 0.0, argsList.Front().Value.(formulaArg).Matrix
6245 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
6246 args = append(args, arg.Value.(formulaArg))
6249 for _, ref := range formulaIfsMatch(args) {
6250 if num := sumRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber {
6256 return newErrorFormulaArg(formulaErrorDIV, "AVERAGEIF divide by zero")
6258 return newNumberFormulaArg(sum / count)
6261 // getBetaHelperContFrac continued fractions for the beta function.
6262 func getBetaHelperContFrac(fX, fA, fB float64) float64 {
6263 var a1, b1, a2, b2, fnorm, cfnew, cf, rm float64
6264 a1, b1, b2 = 1, 1, 1-(fA+fB)/(fA+1)*fX
6266 a2, fnorm, cf = 0, 1, 1
6272 fMaxIter, fMachEps := 50000.0, 2.22045e-016
6274 for rm < fMaxIter && !bfinished {
6276 d2m := rm * (fB - rm) * fX / ((apl2m - 1) * apl2m)
6277 d2m1 := -(fA + rm) * (fA + fB + rm) * fX / (apl2m * (apl2m + 1))
6278 a1 = (a2 + d2m*a1) * fnorm
6279 b1 = (b2 + d2m*b1) * fnorm
6280 a2 = a1 + d2m1*a2*fnorm
6281 b2 = b1 + d2m1*b2*fnorm
6285 bfinished = math.Abs(cf-cfnew) < math.Abs(cf)*fMachEps
6293 // getLanczosSum uses a variant of the Lanczos sum with a rational function.
6294 func getLanczosSum(fZ float64) float64 {
6296 23531376880.41075968857200767445163675473,
6297 42919803642.64909876895789904700198885093,
6298 35711959237.35566804944018545154716670596,
6299 17921034426.03720969991975575445893111267,
6300 6039542586.35202800506429164430729792107,
6301 1439720407.311721673663223072794912393972,
6302 248874557.8620541565114603864132294232163,
6303 31426415.58540019438061423162831820536287,
6304 2876370.628935372441225409051620849613599,
6305 186056.2653952234950402949897160456992822,
6306 8071.672002365816210638002902272250613822,
6307 210.8242777515793458725097339207133627117,
6308 2.506628274631000270164908177133837338626,
6325 var sumNum, sumDenom, zInv float64
6328 sumDenom = denom[12]
6329 for i := 11; i >= 0; i-- {
6333 sumDenom += denom[i]
6339 for i := 1; i <= 12; i++ {
6343 sumDenom += denom[i]
6346 return sumNum / sumDenom
6349 // getBeta return beta distribution.
6350 func getBeta(fAlpha, fBeta float64) float64 {
6359 const maxGammaArgument = 171.624376956302
6360 if fA+fB < maxGammaArgument {
6361 return math.Gamma(fA) / math.Gamma(fA+fB) * math.Gamma(fB)
6363 fg := 6.024680040776729583740234375
6365 fLanczos := getLanczosSum(fA)
6366 fLanczos /= getLanczosSum(fA + fB)
6367 fLanczos *= getLanczosSum(fB)
6368 fABgm := fA + fB + fgm
6369 fLanczos *= math.Sqrt((fABgm / (fA + fgm)) / (fB + fgm))
6370 fTempA := fB / (fA + fgm)
6371 fTempB := fA / (fB + fgm)
6372 fResult := math.Exp(-fA*math.Log1p(fTempA) - fB*math.Log1p(fTempB) - fgm)
6377 // getBetaDistPDF is an implementation for the Beta probability density
6379 func getBetaDistPDF(fX, fA, fB float64) float64 {
6380 if fX <= 0 || fX >= 1 {
6383 fLogDblMax, fLogDblMin := math.Log(1.79769e+308), math.Log(2.22507e-308)
6384 fLogY := math.Log(0.5 - fX + 0.5)
6386 fLogY = math.Log1p(-fX)
6388 fLogX := math.Log(fX)
6389 fAm1LogX := (fA - 1) * fLogX
6390 fBm1LogY := (fB - 1) * fLogY
6391 fLogBeta := getLogBeta(fA, fB)
6392 if fAm1LogX < fLogDblMax && fAm1LogX > fLogDblMin && fBm1LogY < fLogDblMax &&
6393 fBm1LogY > fLogDblMin && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin &&
6394 fAm1LogX+fBm1LogY < fLogDblMax && fAm1LogX+fBm1LogY > fLogDblMin {
6395 return math.Pow(fX, fA-1) * math.Pow(0.5-fX+0.5, fB-1) / getBeta(fA, fB)
6397 return math.Exp(fAm1LogX + fBm1LogY - fLogBeta)
6400 // getLogBeta return beta with logarithm.
6401 func getLogBeta(fAlpha, fBeta float64) float64 {
6404 fA, fB = fAlpha, fBeta
6406 fA, fB = fBeta, fAlpha
6408 fg := 6.024680040776729583740234375
6410 fLanczos := getLanczosSum(fA)
6411 fLanczos /= getLanczosSum(fA + fB)
6412 fLanczos *= getLanczosSum(fB)
6413 fLogLanczos := math.Log(fLanczos)
6414 fABgm := fA + fB + fgm
6415 fLogLanczos += 0.5 * (math.Log(fABgm) - math.Log(fA+fgm) - math.Log(fB+fgm))
6416 fTempA := fB / (fA + fgm)
6417 fTempB := fA / (fB + fgm)
6418 fResult := -fA*math.Log1p(fTempA) - fB*math.Log1p(fTempB) - fgm
6419 fResult += fLogLanczos
6423 // getBetaDist is an implementation for the beta distribution function.
6424 func getBetaDist(fXin, fAlpha, fBeta float64) float64 {
6432 return math.Pow(fXin, fAlpha)
6435 return -math.Expm1(fBeta * math.Log1p(-fXin))
6438 fY, flnY := (0.5-fXin)+0.5, math.Log1p(-fXin)
6439 fX, flnX := fXin, math.Log(fXin)
6440 fA, fB := fAlpha, fBeta
6441 bReflect := fXin > fAlpha/(fAlpha+fBeta)
6448 flnY = math.Log(fXin)
6450 fResult = getBetaHelperContFrac(fX, fA, fB) / fA
6451 fP, fQ := fA/(fA+fB), fB/(fA+fB)
6453 if fA > 1 && fB > 1 && fP < 0.97 && fQ < 0.97 {
6454 fTemp = getBetaDistPDF(fX, fA, fB) * fX * fY
6456 fTemp = math.Exp(fA*flnX + fB*flnY - getLogBeta(fA, fB))
6460 fResult = 0.5 - fResult + 0.5
6465 // prepareBETAdotDISTArgs checking and prepare arguments for the formula
6466 // function BETA.DIST.
6467 func (fn *formulaFuncs) prepareBETAdotDISTArgs(argsList *list.List) formulaArg {
6468 if argsList.Len() < 4 {
6469 return newErrorFormulaArg(formulaErrorVALUE, "BETA.DIST requires at least 4 arguments")
6471 if argsList.Len() > 6 {
6472 return newErrorFormulaArg(formulaErrorVALUE, "BETA.DIST requires at most 6 arguments")
6474 x := argsList.Front().Value.(formulaArg).ToNumber()
6475 if x.Type != ArgNumber {
6478 alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
6479 if alpha.Type != ArgNumber {
6482 beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
6483 if beta.Type != ArgNumber {
6486 if alpha.Number <= 0 || beta.Number <= 0 {
6487 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6489 cumulative := argsList.Front().Next().Next().Next().Value.(formulaArg).ToBool()
6490 if cumulative.Type != ArgNumber {
6493 a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
6494 if argsList.Len() > 4 {
6495 if a = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
6499 if argsList.Len() == 6 {
6500 if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
6504 return newListFormulaArg([]formulaArg{x, alpha, beta, cumulative, a, b})
6507 // BETAdotDIST function calculates the cumulative beta distribution function
6508 // or the probability density function of the Beta distribution, for a
6509 // supplied set of parameters. The syntax of the function is:
6511 // BETA.DIST(x,alpha,beta,cumulative,[A],[B])
6512 func (fn *formulaFuncs) BETAdotDIST(argsList *list.List) formulaArg {
6513 args := fn.prepareBETAdotDISTArgs(argsList)
6514 if args.Type != ArgList {
6517 x, alpha, beta, cumulative, a, b := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5]
6518 if x.Number < a.Number || x.Number > b.Number {
6519 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6521 if a.Number == b.Number {
6522 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6524 scale := b.Number - a.Number
6525 x.Number = (x.Number - a.Number) / scale
6526 if cumulative.Number == 1 {
6527 return newNumberFormulaArg(getBetaDist(x.Number, alpha.Number, beta.Number))
6529 return newNumberFormulaArg(getBetaDistPDF(x.Number, alpha.Number, beta.Number) / scale)
6532 // BETADIST function calculates the cumulative beta probability density
6533 // function for a supplied set of parameters. The syntax of the function is:
6535 // BETADIST(x,alpha,beta,[A],[B])
6536 func (fn *formulaFuncs) BETADIST(argsList *list.List) formulaArg {
6537 if argsList.Len() < 3 {
6538 return newErrorFormulaArg(formulaErrorVALUE, "BETADIST requires at least 3 arguments")
6540 if argsList.Len() > 5 {
6541 return newErrorFormulaArg(formulaErrorVALUE, "BETADIST requires at most 5 arguments")
6543 x := argsList.Front().Value.(formulaArg).ToNumber()
6544 if x.Type != ArgNumber {
6547 alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
6548 if alpha.Type != ArgNumber {
6551 beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
6552 if beta.Type != ArgNumber {
6555 if alpha.Number <= 0 || beta.Number <= 0 {
6556 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6558 a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
6559 if argsList.Len() > 3 {
6560 if a = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
6564 if argsList.Len() == 5 {
6565 if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
6569 if x.Number < a.Number || x.Number > b.Number {
6570 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6572 if a.Number == b.Number {
6573 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6575 return newNumberFormulaArg(getBetaDist((x.Number-a.Number)/(b.Number-a.Number), alpha.Number, beta.Number))
6578 // d1mach returns double precision real machine constants.
6579 func d1mach(i int) float64 {
6581 2.2250738585072014e-308,
6582 1.7976931348623158e+308,
6583 1.1102230246251565e-16,
6584 2.2204460492503131e-16,
6585 0.301029995663981195,
6593 // chebyshevInit determines the number of terms for the double precision
6594 // orthogonal series "dos" needed to insure the error is no larger
6595 // than "eta". Ordinarily eta will be chosen to be one-tenth machine
6597 func chebyshevInit(nos int, eta float64, dos []float64) int {
6602 for ii := 1; ii <= nos; ii++ {
6604 e += math.Abs(dos[i])
6612 // chebyshevEval evaluates the n-term Chebyshev series "a" at "x".
6613 func chebyshevEval(n int, x float64, a []float64) float64 {
6614 if n < 1 || n > 1000 || x < -1.1 || x > 1.1 {
6617 twox, b0, b1, b2 := x*2, 0.0, 0.0, 0.0
6618 for i := 1; i <= n; i++ {
6621 b0 = twox*b1 - b2 + a[n-i]
6623 return (b0 - b2) * 0.5
6626 // lgammacor is an implementation for the log(gamma) correction.
6627 func lgammacor(x float64) float64 {
6628 algmcs := []float64{
6629 0.1666389480451863247205729650822, -0.1384948176067563840732986059135e-4,
6630 0.9810825646924729426157171547487e-8, -0.1809129475572494194263306266719e-10,
6631 0.6221098041892605227126015543416e-13, -0.3399615005417721944303330599666e-15,
6632 0.2683181998482698748957538846666e-17, -0.2868042435334643284144622399999e-19,
6633 0.3962837061046434803679306666666e-21, -0.6831888753985766870111999999999e-23,
6634 0.1429227355942498147573333333333e-24, -0.3547598158101070547199999999999e-26,
6635 0.1025680058010470912000000000000e-27, -0.3401102254316748799999999999999e-29,
6636 0.1276642195630062933333333333333e-30,
6638 nalgm := chebyshevInit(15, d1mach(3), algmcs)
6639 xbig := 1.0 / math.Sqrt(d1mach(3))
6640 xmax := math.Exp(math.Min(math.Log(d1mach(2)/12.0), -math.Log(12.0*d1mach(1))))
6643 } else if x >= xmax {
6644 return 4.930380657631324e-32
6645 } else if x < xbig {
6647 return chebyshevEval(nalgm, tmp*tmp*2.0-1.0, algmcs) / x
6649 return 1.0 / (x * 12.0)
6652 // logrelerr compute the relative error logarithm.
6653 func logrelerr(x float64) float64 {
6654 alnrcs := []float64{
6655 0.10378693562743769800686267719098e+1, -0.13364301504908918098766041553133,
6656 0.19408249135520563357926199374750e-1, -0.30107551127535777690376537776592e-2,
6657 0.48694614797154850090456366509137e-3, -0.81054881893175356066809943008622e-4,
6658 0.13778847799559524782938251496059e-4, -0.23802210894358970251369992914935e-5,
6659 0.41640416213865183476391859901989e-6, -0.73595828378075994984266837031998e-7,
6660 0.13117611876241674949152294345011e-7, -0.23546709317742425136696092330175e-8,
6661 0.42522773276034997775638052962567e-9, -0.77190894134840796826108107493300e-10,
6662 0.14075746481359069909215356472191e-10, -0.25769072058024680627537078627584e-11,
6663 0.47342406666294421849154395005938e-12, -0.87249012674742641745301263292675e-13,
6664 0.16124614902740551465739833119115e-13, -0.29875652015665773006710792416815e-14,
6665 0.55480701209082887983041321697279e-15, -0.10324619158271569595141333961932e-15,
6666 0.19250239203049851177878503244868e-16, -0.35955073465265150011189707844266e-17,
6667 0.67264542537876857892194574226773e-18, -0.12602624168735219252082425637546e-18,
6668 0.23644884408606210044916158955519e-19, -0.44419377050807936898878389179733e-20,
6669 0.83546594464034259016241293994666e-21, -0.15731559416479562574899253521066e-21,
6670 0.29653128740247422686154369706666e-22, -0.55949583481815947292156013226666e-23,
6671 0.10566354268835681048187284138666e-23, -0.19972483680670204548314999466666e-24,
6672 0.37782977818839361421049855999999e-25, -0.71531586889081740345038165333333e-26,
6673 0.13552488463674213646502024533333e-26, -0.25694673048487567430079829333333e-27,
6674 0.48747756066216949076459519999999e-28, -0.92542112530849715321132373333333e-29,
6675 0.17578597841760239233269760000000e-29, -0.33410026677731010351377066666666e-30,
6676 0.63533936180236187354180266666666e-31,
6678 nlnrel := chebyshevInit(43, 0.1*d1mach(3), alnrcs)
6682 if math.Abs(x) <= 0.375 {
6683 return x * (1.0 - x*chebyshevEval(nlnrel, x/0.375, alnrcs))
6685 return math.Log(x + 1.0)
6688 // logBeta is an implementation for the log of the beta distribution
6690 func logBeta(a, b float64) float64 {
6691 corr, p, q := 0.0, a, a
6702 return math.MaxFloat64
6705 corr = lgammacor(p) + lgammacor(q) - lgammacor(p+q)
6706 f1 := q * logrelerr(-p/(p+q))
6707 return math.Log(q)*-0.5 + 0.918938533204672741780329736406 + corr + (p-0.5)*math.Log(p/(p+q)) + math.Nextafter(f1, f1)
6710 corr = lgammacor(q) - lgammacor(p+q)
6711 val, _ := math.Lgamma(p)
6712 return val + corr + p - p*math.Log(p+q) + (q-0.5)*logrelerr(-p/(p+q))
6714 return math.Log(math.Gamma(p) * (math.Gamma(q) / math.Gamma(p+q)))
6717 // pbetaRaw is a part of pbeta for the beta distribution.
6718 func pbetaRaw(alnsml, ans, eps, p, pin, q, sml, x, y float64) float64 {
6720 xb := p*math.Log(y) + q*math.Log(1.0-y) - logBeta(p, q) - math.Log(q)
6721 ib := int(math.Max(xb/alnsml, 0.0))
6722 term := math.Exp(xb - float64(ib)*alnsml)
6723 c := 1.0 / (1.0 - y)
6724 p1 := q * c / (p + q - 1.0)
6727 if q == float64(n) {
6730 for i := 1; i <= n; i++ {
6731 if p1 <= 1 && term/eps <= finsum {
6735 term = (q - xi + 1.0) * c * term / (p + q - xi)
6741 finsum = finsum + term
6746 if y != x || p != pin {
6749 ans = math.Max(math.Min(ans, 1.0), 0.0)
6753 // pbeta returns distribution function of the beta distribution.
6754 func pbeta(x, pin, qin float64) (ans float64) {
6756 alneps := math.Log(eps)
6758 alnsml := math.Log(sml)
6767 if (p+q)*y/(p+1.0) < eps {
6768 xb := p*math.Log(math.Max(y, sml)) - math.Log(p) - logBeta(p, q)
6769 if xb > alnsml && y != 0.0 {
6772 if y != x || p != pin {
6776 ps := q - math.Floor(q)
6780 xb := p*math.Log(y) - logBeta(ps, p) - math.Log(p)
6785 n := int(math.Max(alneps/math.Log(y), 4.0))
6786 for i := 1; i <= n; i++ {
6788 term = term * (xi - ps) * y / xi
6789 ans = ans + term/(p+xi)
6793 ans = pbetaRaw(alnsml, ans, eps, p, pin, q, sml, x, y)
6798 // betainvProbIterator is a part of betainv for the inverse of the beta
6800 func betainvProbIterator(alpha1, alpha3, beta1, beta2, beta3, logBeta, maxCumulative, prob1, prob2 float64) float64 {
6801 var i, j, prev, prop4 float64
6803 for prob := 0; prob < 1000; prob++ {
6804 prop3 := pbeta(beta3, alpha1, beta1)
6805 prop3 = (prop3 - prob1) * math.Exp(logBeta+prob2*math.Log(beta3)+beta2*math.Log(1.0-beta3))
6806 if prop3*prop4 <= 0 {
6807 prev = math.Max(math.Abs(j), maxCumulative)
6810 for iteratorCount := 0; iteratorCount < 1000; iteratorCount++ {
6812 if math.Abs(j) < prev {
6814 if i >= 0 && i <= 1.0 {
6818 if math.Abs(prop3) <= alpha3 {
6821 if i != 0 && i != 1.0 {
6831 beta3, prop4 = i, prop3
6836 // calcBetainv is an implementation for the quantile of the beta
6838 func calcBetainv(probability, alpha, beta, lower, upper float64) float64 {
6839 minCumulative, maxCumulative := 1.0e-300, 3.0e-308
6840 lowerBound, upperBound := maxCumulative, 1.0-2.22e-16
6842 var alpha1, alpha2, beta1, beta2, beta3, prob1, x, y float64
6843 if probability <= 0.5 {
6844 prob1, alpha1, beta1 = probability, alpha, beta
6846 prob1, alpha1, beta1, needSwap = 1.0-probability, beta, alpha, true
6848 logBetaNum := logBeta(alpha, beta)
6849 prob2 := math.Sqrt(-math.Log(prob1 * prob1))
6850 prob3 := prob2 - (prob2*0.27061+2.3075)/(prob2*(prob2*0.04481+0.99229)+1)
6851 if alpha1 > 1 && beta1 > 1 {
6852 alpha2, beta2, prob2 = 1/(alpha1+alpha1-1), 1/(beta1+beta1-1), (prob3*prob3-3)/6
6853 x = 2 / (alpha2 + beta2)
6854 y = prob3*math.Sqrt(x+prob2)/x - (beta2-alpha2)*(prob2+5/6.0-2/(x*3))
6855 beta3 = alpha1 / (alpha1 + beta1*math.Exp(y+y))
6857 beta2, prob2 = 1/(beta1*9), beta1+beta1
6858 beta2 = prob2 * math.Pow(1-beta2+prob3*math.Sqrt(beta2), 3)
6860 beta3 = 1 - math.Exp((math.Log((1-prob1)*beta1)+logBetaNum)/beta1)
6862 beta2 = (prob2 + alpha1*4 - 2) / beta2
6864 beta3 = math.Exp((logBetaNum + math.Log(alpha1*prob1)) / alpha1)
6866 beta3 = 1 - 2/(beta2+1)
6870 beta2, prob2 = 1-beta1, 1-alpha1
6871 if beta3 < lowerBound {
6873 } else if beta3 > upperBound {
6876 alpha3 := math.Max(minCumulative, math.Pow(10.0, -13.0-2.5/(alpha1*alpha1)-0.5/(prob1*prob1)))
6877 beta3 = betainvProbIterator(alpha1, alpha3, beta1, beta2, beta3, logBetaNum, maxCumulative, prob1, prob2)
6881 return (upper-lower)*beta3 + lower
6884 // betainv is an implementation of the formula functions BETAINV and
6886 func (fn *formulaFuncs) betainv(name string, argsList *list.List) formulaArg {
6887 if argsList.Len() < 3 {
6888 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 3 arguments", name))
6890 if argsList.Len() > 5 {
6891 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at most 5 arguments", name))
6893 probability := argsList.Front().Value.(formulaArg).ToNumber()
6894 if probability.Type != ArgNumber {
6897 if probability.Number <= 0 || probability.Number >= 1 {
6898 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6900 alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
6901 if alpha.Type != ArgNumber {
6904 beta := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
6905 if beta.Type != ArgNumber {
6908 if alpha.Number <= 0 || beta.Number <= 0 {
6909 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6911 a, b := newNumberFormulaArg(0), newNumberFormulaArg(1)
6912 if argsList.Len() > 3 {
6913 if a = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); a.Type != ArgNumber {
6917 if argsList.Len() == 5 {
6918 if b = argsList.Back().Value.(formulaArg).ToNumber(); b.Type != ArgNumber {
6922 if a.Number == b.Number {
6923 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
6925 return newNumberFormulaArg(calcBetainv(probability.Number, alpha.Number, beta.Number, a.Number, b.Number))
6928 // BETAINV function uses an iterative procedure to calculate the inverse of
6929 // the cumulative beta probability density function for a supplied
6930 // probability. The syntax of the function is:
6932 // BETAINV(probability,alpha,beta,[A],[B])
6933 func (fn *formulaFuncs) BETAINV(argsList *list.List) formulaArg {
6934 return fn.betainv("BETAINV", argsList)
6937 // BETAdotINV function uses an iterative procedure to calculate the inverse of
6938 // the cumulative beta probability density function for a supplied
6939 // probability. The syntax of the function is:
6941 // BETA.INV(probability,alpha,beta,[A],[B])
6942 func (fn *formulaFuncs) BETAdotINV(argsList *list.List) formulaArg {
6943 return fn.betainv("BETA.INV", argsList)
6946 // incompleteGamma is an implementation of the incomplete gamma function.
6947 func incompleteGamma(a, x float64) float64 {
6950 for n := 0; n <= max; n++ {
6952 for i := 1; i <= n; i++ {
6953 divisor *= a + float64(i)
6955 summer += math.Pow(x, float64(n)) / divisor
6957 return math.Pow(x, a) * math.Exp(0-x) * summer
6960 // binomCoeff implement binomial coefficient calculation.
6961 func binomCoeff(n, k float64) float64 {
6962 return fact(n) / (fact(k) * fact(n-k))
6965 // binomdist implement binomial distribution calculation.
6966 func binomdist(x, n, p float64) float64 {
6967 return binomCoeff(n, x) * math.Pow(p, x) * math.Pow(1-p, n-x)
6970 // BINOMdotDIST function returns the Binomial Distribution probability for a
6971 // given number of successes from a specified number of trials. The syntax of
6974 // BINOM.DIST(number_s,trials,probability_s,cumulative)
6975 func (fn *formulaFuncs) BINOMdotDIST(argsList *list.List) formulaArg {
6976 if argsList.Len() != 4 {
6977 return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST requires 4 arguments")
6979 return fn.BINOMDIST(argsList)
6982 // BINOMDIST function returns the Binomial Distribution probability of a
6983 // specified number of successes out of a specified number of trials. The
6984 // syntax of the function is:
6986 // BINOMDIST(number_s,trials,probability_s,cumulative)
6987 func (fn *formulaFuncs) BINOMDIST(argsList *list.List) formulaArg {
6988 if argsList.Len() != 4 {
6989 return newErrorFormulaArg(formulaErrorVALUE, "BINOMDIST requires 4 arguments")
6991 var s, trials, probability, cumulative formulaArg
6992 if s = argsList.Front().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
6995 if trials = argsList.Front().Next().Value.(formulaArg).ToNumber(); trials.Type != ArgNumber {
6998 if s.Number < 0 || s.Number > trials.Number {
6999 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7001 if probability = argsList.Back().Prev().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
7005 if probability.Number < 0 || probability.Number > 1 {
7006 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7008 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
7011 if cumulative.Number == 1 {
7013 for i := 0; i <= int(s.Number); i++ {
7014 bm += binomdist(float64(i), trials.Number, probability.Number)
7016 return newNumberFormulaArg(bm)
7018 return newNumberFormulaArg(binomdist(s.Number, trials.Number, probability.Number))
7021 // BINOMdotDISTdotRANGE function returns the Binomial Distribution probability
7022 // for the number of successes from a specified number of trials falling into
7023 // a specified range.
7025 // BINOM.DIST.RANGE(trials,probability_s,number_s,[number_s2])
7026 func (fn *formulaFuncs) BINOMdotDISTdotRANGE(argsList *list.List) formulaArg {
7027 if argsList.Len() < 3 {
7028 return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST.RANGE requires at least 3 arguments")
7030 if argsList.Len() > 4 {
7031 return newErrorFormulaArg(formulaErrorVALUE, "BINOM.DIST.RANGE requires at most 4 arguments")
7033 trials := argsList.Front().Value.(formulaArg).ToNumber()
7034 if trials.Type != ArgNumber {
7037 probability := argsList.Front().Next().Value.(formulaArg).ToNumber()
7038 if probability.Type != ArgNumber {
7041 if probability.Number < 0 || probability.Number > 1 {
7042 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7044 num1 := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
7045 if num1.Type != ArgNumber {
7048 if num1.Number < 0 || num1.Number > trials.Number {
7049 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7052 if argsList.Len() > 3 {
7053 if num2 = argsList.Back().Value.(formulaArg).ToNumber(); num2.Type != ArgNumber {
7057 if num2.Number < 0 || num2.Number > trials.Number {
7058 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7061 for i := num1.Number; i <= num2.Number; i++ {
7062 sum += binomdist(i, trials.Number, probability.Number)
7064 return newNumberFormulaArg(sum)
7067 // binominv implement inverse of the binomial distribution calculation.
7068 func binominv(n, p, alpha float64) float64 {
7069 q, i, sum, max := 1-p, 0.0, 0.0, 0.0
7072 factor := math.Pow(q, n)
7074 for i = 0; i < n && sum < alpha; i++ {
7075 factor *= (n - i) / (i + 1) * p / q
7080 factor := math.Pow(p, n)
7081 sum, max = 1-factor, n
7082 for i = 0; i < max && sum >= alpha; i++ {
7083 factor *= (n - i) / (i + 1) * q / p
7089 // BINOMdotINV function returns the inverse of the Cumulative Binomial
7090 // Distribution. The syntax of the function is:
7092 // BINOM.INV(trials,probability_s,alpha)
7093 func (fn *formulaFuncs) BINOMdotINV(argsList *list.List) formulaArg {
7094 if argsList.Len() != 3 {
7095 return newErrorFormulaArg(formulaErrorVALUE, "BINOM.INV requires 3 numeric arguments")
7097 trials := argsList.Front().Value.(formulaArg).ToNumber()
7098 if trials.Type != ArgNumber {
7101 if trials.Number < 0 {
7102 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7104 probability := argsList.Front().Next().Value.(formulaArg).ToNumber()
7105 if probability.Type != ArgNumber {
7108 if probability.Number <= 0 || probability.Number >= 1 {
7109 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7111 alpha := argsList.Back().Value.(formulaArg).ToNumber()
7112 if alpha.Type != ArgNumber {
7115 if alpha.Number <= 0 || alpha.Number >= 1 {
7116 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7118 return newNumberFormulaArg(binominv(trials.Number, probability.Number, alpha.Number))
7121 // CHIDIST function calculates the right-tailed probability of the chi-square
7122 // distribution. The syntax of the function is:
7124 // CHIDIST(x,degrees_freedom)
7125 func (fn *formulaFuncs) CHIDIST(argsList *list.List) formulaArg {
7126 if argsList.Len() != 2 {
7127 return newErrorFormulaArg(formulaErrorVALUE, "CHIDIST requires 2 numeric arguments")
7129 x := argsList.Front().Value.(formulaArg).ToNumber()
7130 if x.Type != ArgNumber {
7133 degrees := argsList.Back().Value.(formulaArg).ToNumber()
7134 if degrees.Type != ArgNumber {
7137 logSqrtPi, sqrtPi := math.Log(math.Sqrt(math.Pi)), 1/math.Sqrt(math.Pi)
7138 var e, s, z, c, y float64
7139 a, x1, even := x.Number/2, x.Number, int(degrees.Number)%2 == 0
7140 if degrees.Number > 1 {
7144 args.PushBack(newNumberFormulaArg(-math.Sqrt(x1)))
7145 o := fn.NORMSDIST(args)
7150 if degrees.Number > 2 {
7151 x1 = (degrees.Number - 1) / 2
7164 s += math.Exp(c*z - a - e)
7167 return newNumberFormulaArg(s)
7169 e = sqrtPi / math.Sqrt(a)
7179 return newNumberFormulaArg(c*y + s)
7181 return newNumberFormulaArg(s)
7184 // CHIINV function calculates the inverse of the right-tailed probability of
7185 // the Chi-Square Distribution. The syntax of the function is:
7187 // CHIINV(probability,deg_freedom)
7188 func (fn *formulaFuncs) CHIINV(argsList *list.List) formulaArg {
7189 if argsList.Len() != 2 {
7190 return newErrorFormulaArg(formulaErrorVALUE, "CHIINV requires 2 numeric arguments")
7192 probability := argsList.Front().Value.(formulaArg).ToNumber()
7193 if probability.Type != ArgNumber {
7196 if probability.Number <= 0 || probability.Number > 1 {
7197 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7199 deg := argsList.Back().Value.(formulaArg).ToNumber()
7200 if deg.Type != ArgNumber {
7204 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7206 return newNumberFormulaArg(gammainv(1-probability.Number, 0.5*deg.Number, 2.0))
7209 // CHITEST function uses the chi-square test to calculate the probability that
7210 // the differences between two supplied data sets (of observed and expected
7211 // frequencies), are likely to be simply due to sampling error, or if they are
7212 // likely to be real. The syntax of the function is:
7214 // CHITEST(actual_range,expected_range)
7215 func (fn *formulaFuncs) CHITEST(argsList *list.List) formulaArg {
7216 if argsList.Len() != 2 {
7217 return newErrorFormulaArg(formulaErrorVALUE, "CHITEST requires 2 arguments")
7219 actual, expected := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
7220 actualList, expectedList := actual.ToList(), expected.ToList()
7221 rows := len(actual.Matrix)
7223 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
7225 columns := len(actualList) / rows
7226 if len(actualList) != len(expectedList) || len(actualList) == 1 {
7227 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
7231 for i := 0; i < len(actualList); i++ {
7232 a, e := actualList[i].ToNumber(), expectedList[i].ToNumber()
7233 if a.Type == ArgNumber && e.Type == ArgNumber {
7235 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
7238 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7240 result += (a.Number - e.Number) * (a.Number - e.Number) / e.Number
7244 degrees = columns - 1
7245 } else if columns == 1 {
7248 degrees = (columns - 1) * (rows - 1)
7251 args.PushBack(newNumberFormulaArg(result))
7252 args.PushBack(newNumberFormulaArg(float64(degrees)))
7253 return fn.CHIDIST(args)
7256 // getGammaSeries calculates a power-series of the gamma function.
7257 func getGammaSeries(fA, fX float64) float64 {
7259 fHalfMachEps = 2.22045e-016 / 2
7265 for fSummand/fSum > fHalfMachEps && nCount <= 10000 {
7266 fDenomfactor = fDenomfactor + 1
7267 fSummand = fSummand * fX / fDenomfactor
7268 fSum = fSum + fSummand
7274 // getGammaContFraction returns continued fraction with odd items of the gamma
7276 func getGammaContFraction(fA, fX float64) float64 {
7278 fBigInv = 2.22045e-016
7279 fHalfMachEps = fBigInv / 2
7283 fDenom = fX + 2 - fA
7288 fApprox = fPkm1 / fQkm1
7291 for !bFinished && fCount < 10000 {
7299 fPk = math.Nextafter(f1, f1) - math.Nextafter(f2, f2)
7302 fQk = math.Nextafter(f3, f3) - math.Nextafter(f4, f4)
7306 bFinished = math.Abs((fApprox-fR)/fR) <= fHalfMachEps
7309 fPkm2, fPkm1, fQkm2, fQkm1 = fPkm1, fPk, fQkm1, fQk
7310 if math.Abs(fPk) > fBig {
7311 // reduce a fraction does not change the value
7312 fPkm2 = fPkm2 * fBigInv
7313 fPkm1 = fPkm1 * fBigInv
7314 fQkm2 = fQkm2 * fBigInv
7315 fQkm1 = fQkm1 * fBigInv
7321 // getLogGammaHelper is a part of implementation of the function getLogGamma.
7322 func getLogGammaHelper(fZ float64) float64 {
7323 _fg := 6.024680040776729583740234375
7324 zgHelp := fZ + _fg - 0.5
7325 return math.Log(getLanczosSum(fZ)) + (fZ-0.5)*math.Log(zgHelp) - zgHelp
7328 // getGammaHelper is a part of implementation of the function getLogGamma.
7329 func getGammaHelper(fZ float64) float64 {
7331 gamma = getLanczosSum(fZ)
7332 fg = 6.024680040776729583740234375
7333 zgHelp = fZ + fg - 0.5
7334 // avoid intermediate overflow
7335 halfpower = math.Pow(zgHelp, fZ/2-0.25)
7338 gamma /= math.Exp(zgHelp)
7340 if fZ <= 20 && fZ == math.Floor(fZ) {
7341 gamma = math.Round(gamma)
7346 // getLogGamma calculates the natural logarithm of the gamma function.
7347 func getLogGamma(fZ float64) float64 {
7348 fMaxGammaArgument := 171.624376956302
7349 if fZ >= fMaxGammaArgument {
7350 return getLogGammaHelper(fZ)
7353 return math.Log(getGammaHelper(fZ))
7356 return math.Log(getGammaHelper(fZ+1) / fZ)
7358 return getLogGammaHelper(fZ+2) - math.Log(fZ+1) - math.Log(fZ)
7361 // getLowRegIGamma returns lower regularized incomplete gamma function.
7362 func getLowRegIGamma(fA, fX float64) float64 {
7363 lnFactor := fA*math.Log(fX) - fX - getLogGamma(fA)
7364 factor := math.Exp(lnFactor)
7366 return 1 - factor*getGammaContFraction(fA, fX)
7368 return factor * getGammaSeries(fA, fX)
7371 // getChiSqDistCDF returns left tail for the Chi-Square distribution.
7372 func getChiSqDistCDF(fX, fDF float64) float64 {
7376 return getLowRegIGamma(fDF/2, fX/2)
7379 // getChiSqDistPDF calculates the probability density function for the
7380 // Chi-Square distribution.
7381 func getChiSqDistPDF(fX, fDF float64) float64 {
7382 if fDF*fX > 1391000 {
7383 return math.Exp((0.5*fDF-1)*math.Log(fX*0.5) - 0.5*fX - math.Log(2) - getLogGamma(0.5*fDF))
7385 var fCount, fValue float64
7386 if math.Mod(fDF, 2) < 0.5 {
7390 fValue = 1 / math.Sqrt(fX*2*math.Pi)
7394 fValue *= fX / fCount
7398 fValue = math.Exp(math.Log(fValue) - fX/2)
7400 fValue *= math.Exp(-fX / 2)
7405 // CHISQdotDIST function calculates the Probability Density Function or the
7406 // Cumulative Distribution Function for the Chi-Square Distribution. The
7407 // syntax of the function is:
7409 // CHISQ.DIST(x,degrees_freedom,cumulative)
7410 func (fn *formulaFuncs) CHISQdotDIST(argsList *list.List) formulaArg {
7411 if argsList.Len() != 3 {
7412 return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.DIST requires 3 arguments")
7414 var x, degrees, cumulative formulaArg
7415 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
7418 if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
7421 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
7425 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7427 maxDeg := math.Pow10(10)
7428 if degrees.Number < 1 || degrees.Number >= maxDeg {
7429 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7431 if cumulative.Number == 1 {
7432 return newNumberFormulaArg(getChiSqDistCDF(x.Number, degrees.Number))
7434 return newNumberFormulaArg(getChiSqDistPDF(x.Number, degrees.Number))
7437 // CHISQdotDISTdotRT function calculates the right-tailed probability of the
7438 // Chi-Square Distribution. The syntax of the function is:
7440 // CHISQ.DIST.RT(x,degrees_freedom)
7441 func (fn *formulaFuncs) CHISQdotDISTdotRT(argsList *list.List) formulaArg {
7442 if argsList.Len() != 2 {
7443 return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.DIST.RT requires 2 numeric arguments")
7445 return fn.CHIDIST(argsList)
7448 // CHISQdotTEST function performs the chi-square test on two supplied data sets
7449 // (of observed and expected frequencies), and returns the probability that
7450 // the differences between the sets are simply due to sampling error. The
7451 // syntax of the function is:
7453 // CHISQ.TEST(actual_range,expected_range)
7454 func (fn *formulaFuncs) CHISQdotTEST(argsList *list.List) formulaArg {
7455 if argsList.Len() != 2 {
7456 return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.TEST requires 2 arguments")
7458 return fn.CHITEST(argsList)
7461 // hasChangeOfSign check if the sign has been changed.
7462 func hasChangeOfSign(u, w float64) bool {
7463 return (u < 0 && w > 0) || (u > 0 && w < 0)
7466 // calcInverseIterator directly maps the required parameters for inverse
7467 // distribution functions.
7468 type calcInverseIterator struct {
7473 // callBack implements the callback function for the inverse iterator.
7474 func (iterator *calcInverseIterator) callBack(x float64) float64 {
7475 if iterator.name == "CHISQ.INV" {
7476 return iterator.fp - getChiSqDistCDF(x, iterator.fDF)
7478 return iterator.fp - getTDist(x, iterator.fDF, iterator.nT)
7481 // inverseQuadraticInterpolation inverse quadratic interpolation with
7482 // additional brackets.
7483 func inverseQuadraticInterpolation(iterator calcInverseIterator, fAx, fAy, fBx, fBy float64) float64 {
7485 fXEps := 2.22045e-016
7486 fPx, fPy, fQx, fQy, fRx, fRy := fAx, fAy, fBx, fBy, fAx, fAy
7487 fSx := 0.5 * (fAx + fBx)
7488 bHasToInterpolate := true
7490 for nCount < 500 && math.Abs(fRy) > fYEps && (fBx-fAx) > math.Max(math.Abs(fAx), math.Abs(fBx))*fXEps {
7491 if bHasToInterpolate {
7492 if fPy != fQy && fQy != fRy && fRy != fPy {
7493 fSx = fPx*fRy*fQy/(fRy-fPy)/(fQy-fPy) + fRx*fQy*fPy/(fQy-fRy)/(fPy-fRy) +
7494 fQx*fPy*fRy/(fPy-fQy)/(fRy-fQy)
7495 bHasToInterpolate = (fAx < fSx) && (fSx < fBx)
7497 bHasToInterpolate = false
7500 if !bHasToInterpolate {
7501 fSx = 0.5 * (fAx + fBx)
7503 bHasToInterpolate = true
7505 fPx, fQx, fRx, fPy, fQy = fQx, fRx, fSx, fQy, fRy
7506 fRy = iterator.callBack(fSx)
7507 if hasChangeOfSign(fAy, fRy) {
7512 bHasToInterpolate = bHasToInterpolate && (math.Abs(fRy)*2 <= math.Abs(fQy))
7518 // calcIterateInverse function calculates the iteration for inverse
7520 func calcIterateInverse(iterator calcInverseIterator, fAx, fBx float64) float64 {
7521 fAy, fBy := iterator.callBack(fAx), iterator.callBack(fBx)
7524 for nCount = 0; nCount < 1000 && !hasChangeOfSign(fAy, fBy); nCount++ {
7525 if math.Abs(fAy) <= math.Abs(fBy) {
7527 fAx += 2 * (fAx - fBx)
7533 fAy = iterator.callBack(fAx)
7536 fBx += 2 * (fBx - fAx)
7539 fBy = iterator.callBack(fBx)
7542 if fAy == 0 || fBy == 0 {
7545 return inverseQuadraticInterpolation(iterator, fAx, fAy, fBx, fBy)
7548 // CHISQdotINV function calculates the inverse of the left-tailed probability
7549 // of the Chi-Square Distribution. The syntax of the function is:
7551 // CHISQ.INV(probability,degrees_freedom)
7552 func (fn *formulaFuncs) CHISQdotINV(argsList *list.List) formulaArg {
7553 if argsList.Len() != 2 {
7554 return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.INV requires 2 numeric arguments")
7556 var probability, degrees formulaArg
7557 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
7560 if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
7563 if probability.Number < 0 || probability.Number >= 1 {
7564 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7566 if degrees.Number < 1 || degrees.Number > math.Pow10(10) {
7567 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7569 return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
7571 fp: probability.Number,
7572 fDF: degrees.Number,
7573 }, degrees.Number/2, degrees.Number))
7576 // CHISQdotINVdotRT function calculates the inverse of the right-tailed
7577 // probability of the Chi-Square Distribution. The syntax of the function is:
7579 // CHISQ.INV.RT(probability,degrees_freedom)
7580 func (fn *formulaFuncs) CHISQdotINVdotRT(argsList *list.List) formulaArg {
7581 if argsList.Len() != 2 {
7582 return newErrorFormulaArg(formulaErrorVALUE, "CHISQ.INV.RT requires 2 numeric arguments")
7584 return fn.CHIINV(argsList)
7587 // confidence is an implementation of the formula functions CONFIDENCE and
7589 func (fn *formulaFuncs) confidence(name string, argsList *list.List) formulaArg {
7590 if argsList.Len() != 3 {
7591 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 numeric arguments", name))
7593 alpha := argsList.Front().Value.(formulaArg).ToNumber()
7594 if alpha.Type != ArgNumber {
7597 if alpha.Number <= 0 || alpha.Number >= 1 {
7598 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7600 stdDev := argsList.Front().Next().Value.(formulaArg).ToNumber()
7601 if stdDev.Type != ArgNumber {
7604 if stdDev.Number <= 0 {
7605 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7607 size := argsList.Back().Value.(formulaArg).ToNumber()
7608 if size.Type != ArgNumber {
7611 if size.Number < 1 {
7612 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7616 args.PushBack(newNumberFormulaArg(alpha.Number / 2))
7617 args.PushBack(newNumberFormulaArg(0))
7618 args.PushBack(newNumberFormulaArg(1))
7619 return newNumberFormulaArg(-fn.NORMINV(args).Number * (stdDev.Number / math.Sqrt(size.Number)))
7622 // CONFIDENCE function uses a Normal Distribution to calculate a confidence
7623 // value that can be used to construct the Confidence Interval for a
7624 // population mean, for a supplied probability and sample size. It is assumed
7625 // that the standard deviation of the population is known. The syntax of the
7628 // CONFIDENCE(alpha,standard_dev,size)
7629 func (fn *formulaFuncs) CONFIDENCE(argsList *list.List) formulaArg {
7630 return fn.confidence("CONFIDENCE", argsList)
7633 // CONFIDENCEdotNORM function uses a Normal Distribution to calculate a
7634 // confidence value that can be used to construct the confidence interval for
7635 // a population mean, for a supplied probability and sample size. It is
7636 // assumed that the standard deviation of the population is known. The syntax
7637 // of the function is:
7639 // CONFIDENCE.NORM(alpha,standard_dev,size)
7640 func (fn *formulaFuncs) CONFIDENCEdotNORM(argsList *list.List) formulaArg {
7641 return fn.confidence("CONFIDENCE.NORM", argsList)
7644 // CONFIDENCEdotT function uses a Student's T-Distribution to calculate a
7645 // confidence value that can be used to construct the confidence interval for
7646 // a population mean, for a supplied probablity and supplied sample size. It
7647 // is assumed that the standard deviation of the population is known. The
7648 // syntax of the function is:
7650 // CONFIDENCE.T(alpha,standard_dev,size)
7651 func (fn *formulaFuncs) CONFIDENCEdotT(argsList *list.List) formulaArg {
7652 if argsList.Len() != 3 {
7653 return newErrorFormulaArg(formulaErrorVALUE, "CONFIDENCE.T requires 3 arguments")
7655 var alpha, standardDev, size formulaArg
7656 if alpha = argsList.Front().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
7659 if standardDev = argsList.Front().Next().Value.(formulaArg).ToNumber(); standardDev.Type != ArgNumber {
7662 if size = argsList.Back().Value.(formulaArg).ToNumber(); size.Type != ArgNumber {
7665 if alpha.Number <= 0 || alpha.Number >= 1 || standardDev.Number <= 0 || size.Number < 1 {
7666 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
7668 if size.Number == 1 {
7669 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
7671 return newNumberFormulaArg(standardDev.Number * calcIterateInverse(calcInverseIterator{
7672 name: "CONFIDENCE.T",
7674 fDF: size.Number - 1,
7676 }, size.Number/2, size.Number) / math.Sqrt(size.Number))
7679 // covar is an implementation of the formula functions COVAR, COVARIANCE.P and
7681 func (fn *formulaFuncs) covar(name string, argsList *list.List) formulaArg {
7682 if argsList.Len() != 2 {
7683 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 arguments", name))
7685 array1 := argsList.Front().Value.(formulaArg)
7686 array2 := argsList.Back().Value.(formulaArg)
7687 left, right := array1.ToList(), array2.ToList()
7689 if n != len(right) {
7690 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
7692 l1, l2 := list.New(), list.New()
7695 result, skip := 0.0, 0
7696 mean1, mean2 := fn.AVERAGE(l1), fn.AVERAGE(l2)
7697 for i := 0; i < n; i++ {
7698 arg1 := left[i].ToNumber()
7699 arg2 := right[i].ToNumber()
7700 if arg1.Type == ArgError || arg2.Type == ArgError {
7704 result += (arg1.Number - mean1.Number) * (arg2.Number - mean2.Number)
7706 if name == "COVARIANCE.S" {
7707 return newNumberFormulaArg(result / float64(n-skip-1))
7709 return newNumberFormulaArg(result / float64(n-skip))
7712 // COVAR function calculates the covariance of two supplied sets of values. The
7713 // syntax of the function is:
7715 // COVAR(array1,array2)
7716 func (fn *formulaFuncs) COVAR(argsList *list.List) formulaArg {
7717 return fn.covar("COVAR", argsList)
7720 // COVARIANCEdotP function calculates the population covariance of two supplied
7721 // sets of values. The syntax of the function is:
7723 // COVARIANCE.P(array1,array2)
7724 func (fn *formulaFuncs) COVARIANCEdotP(argsList *list.List) formulaArg {
7725 return fn.covar("COVARIANCE.P", argsList)
7728 // COVARIANCEdotS function calculates the sample covariance of two supplied
7729 // sets of values. The syntax of the function is:
7731 // COVARIANCE.S(array1,array2)
7732 func (fn *formulaFuncs) COVARIANCEdotS(argsList *list.List) formulaArg {
7733 return fn.covar("COVARIANCE.S", argsList)
7736 // calcStringCountSum is part of the implementation countSum.
7737 func calcStringCountSum(countText bool, count, sum float64, num, arg formulaArg) (float64, float64) {
7738 if countText && num.Type == ArgError && arg.String != "" {
7741 if num.Type == ArgNumber {
7748 // countSum get count and sum for a formula arguments array.
7749 func (fn *formulaFuncs) countSum(countText bool, args []formulaArg) (count, sum float64) {
7750 for _, arg := range args {
7753 if countText || !arg.Boolean {
7758 if !countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
7760 } else if countText && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
7762 if num.Type == ArgNumber {
7768 num := arg.ToNumber()
7769 count, sum = calcStringCountSum(countText, count, sum, num, arg)
7770 case ArgList, ArgMatrix:
7771 cnt, summary := fn.countSum(countText, arg.ToList())
7779 // CORREL function calculates the Pearson Product-Moment Correlation
7780 // Coefficient for two sets of values. The syntax of the function is:
7782 // CORREL(array1,array2)
7783 func (fn *formulaFuncs) CORREL(argsList *list.List) formulaArg {
7784 if argsList.Len() != 2 {
7785 return newErrorFormulaArg(formulaErrorVALUE, "CORREL requires 2 arguments")
7787 array1 := argsList.Front().Value.(formulaArg)
7788 array2 := argsList.Back().Value.(formulaArg)
7789 left, right := array1.ToList(), array2.ToList()
7791 if n != len(right) {
7792 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
7794 l1, l2, l3 := list.New(), list.New(), list.New()
7795 for i := 0; i < n; i++ {
7796 if lhs, rhs := left[i].ToNumber(), right[i].ToNumber(); lhs.Number != 0 && rhs.Number != 0 {
7801 stdev1, stdev2 := fn.STDEV(l1), fn.STDEV(l2)
7802 if stdev1.Number == 0 || stdev2.Number == 0 {
7803 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
7805 mean1, mean2, skip := fn.AVERAGE(l1), fn.AVERAGE(l2), 0
7806 for i := 0; i < n; i++ {
7807 lhs, rhs := left[i].ToNumber(), right[i].ToNumber()
7808 if lhs.Number == 0 || rhs.Number == 0 {
7812 l3.PushBack(newNumberFormulaArg((lhs.Number - mean1.Number) * (rhs.Number - mean2.Number)))
7814 return newNumberFormulaArg(fn.SUM(l3).Number / float64(n-skip-1) / stdev1.Number / stdev2.Number)
7817 // COUNT function returns the count of numeric values in a supplied set of
7818 // cells or values. This count includes both numbers and dates. The syntax of
7821 // COUNT(value1,[value2],...)
7822 func (fn *formulaFuncs) COUNT(argsList *list.List) formulaArg {
7824 for token := argsList.Front(); token != nil; token = token.Next() {
7825 arg := token.Value.(formulaArg)
7828 if num := arg.ToNumber(); num.Type == ArgNumber {
7834 for _, row := range arg.Matrix {
7835 for _, cell := range row {
7836 if cell.Type == ArgNumber {
7843 return newNumberFormulaArg(float64(count))
7846 // COUNTA function returns the number of non-blanks within a supplied set of
7847 // cells or values. The syntax of the function is:
7849 // COUNTA(value1,[value2],...)
7850 func (fn *formulaFuncs) COUNTA(argsList *list.List) formulaArg {
7852 for token := argsList.Front(); token != nil; token = token.Next() {
7853 arg := token.Value.(formulaArg)
7856 if arg.String != "" {
7862 for _, row := range arg.ToList() {
7865 if row.String != "" {
7874 return newNumberFormulaArg(float64(count))
7877 // COUNTBLANK function returns the number of blank cells in a supplied range.
7878 // The syntax of the function is:
7880 // COUNTBLANK(range)
7881 func (fn *formulaFuncs) COUNTBLANK(argsList *list.List) formulaArg {
7882 if argsList.Len() != 1 {
7883 return newErrorFormulaArg(formulaErrorVALUE, "COUNTBLANK requires 1 argument")
7886 for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
7887 if cell.Type == ArgEmpty {
7891 return newNumberFormulaArg(count)
7894 // COUNTIF function returns the number of cells within a supplied range, that
7895 // satisfy a given criteria. The syntax of the function is:
7897 // COUNTIF(range,criteria)
7898 func (fn *formulaFuncs) COUNTIF(argsList *list.List) formulaArg {
7899 if argsList.Len() != 2 {
7900 return newErrorFormulaArg(formulaErrorVALUE, "COUNTIF requires 2 arguments")
7903 criteria = formulaCriteriaParser(argsList.Front().Next().Value.(formulaArg))
7906 for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
7907 if cell.Type == ArgString && criteria.Condition.Type != ArgString {
7910 if ok, _ := formulaCriteriaEval(cell, criteria); ok {
7914 return newNumberFormulaArg(count)
7917 // formulaIfsMatch function returns cells reference array which match criteria.
7918 func formulaIfsMatch(args []formulaArg) (cellRefs []cellRef) {
7919 for i := 0; i < len(args)-1; i += 2 {
7921 matrix, criteria := args[i].Matrix, formulaCriteriaParser(args[i+1])
7923 for rowIdx, row := range matrix {
7924 for colIdx, col := range row {
7925 if ok, _ := formulaCriteriaEval(col, criteria); ok {
7926 match = append(match, cellRef{Col: colIdx, Row: rowIdx})
7932 for _, ref := range cellRefs {
7933 value := matrix[ref.Row][ref.Col]
7934 if ok, _ := formulaCriteriaEval(value, criteria); ok {
7935 match = append(match, ref)
7944 // COUNTIFS function returns the number of rows within a table, that satisfy a
7945 // set of given criteria. The syntax of the function is:
7947 // COUNTIFS(criteria_range1,criteria1,[criteria_range2,criteria2],...)
7948 func (fn *formulaFuncs) COUNTIFS(argsList *list.List) formulaArg {
7949 if argsList.Len() < 2 {
7950 return newErrorFormulaArg(formulaErrorVALUE, "COUNTIFS requires at least 2 arguments")
7952 if argsList.Len()%2 != 0 {
7953 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
7955 var args []formulaArg
7956 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
7957 args = append(args, arg.Value.(formulaArg))
7959 return newNumberFormulaArg(float64(len(formulaIfsMatch(args))))
7962 // CRITBINOM function returns the inverse of the Cumulative Binomial
7963 // Distribution. I.e. for a specific number of independent trials, the
7964 // function returns the smallest value (number of successes) for which the
7965 // cumulative binomial distribution is greater than or equal to a specified
7966 // value. The syntax of the function is:
7968 // CRITBINOM(trials,probability_s,alpha)
7969 func (fn *formulaFuncs) CRITBINOM(argsList *list.List) formulaArg {
7970 if argsList.Len() != 3 {
7971 return newErrorFormulaArg(formulaErrorVALUE, "CRITBINOM requires 3 numeric arguments")
7973 return fn.BINOMdotINV(argsList)
7976 // DEVSQ function calculates the sum of the squared deviations from the sample
7977 // mean. The syntax of the function is:
7979 // DEVSQ(number1,[number2],...)
7980 func (fn *formulaFuncs) DEVSQ(argsList *list.List) formulaArg {
7981 if argsList.Len() < 1 {
7982 return newErrorFormulaArg(formulaErrorVALUE, "DEVSQ requires at least 1 numeric argument")
7984 avg, count, result := fn.AVERAGE(argsList), -1, 0.0
7985 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
7986 for _, cell := range arg.Value.(formulaArg).ToList() {
7987 if cell.Type != ArgNumber {
7992 result = math.Pow(cell.Number-avg.Number, 2)
7995 result += math.Pow(cell.Number-avg.Number, 2)
7999 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8001 return newNumberFormulaArg(result)
8004 // FISHER function calculates the Fisher Transformation for a supplied value.
8005 // The syntax of the function is:
8008 func (fn *formulaFuncs) FISHER(argsList *list.List) formulaArg {
8009 if argsList.Len() != 1 {
8010 return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
8012 token := argsList.Front().Value.(formulaArg)
8015 arg := token.ToNumber()
8016 if arg.Type == ArgNumber {
8017 if arg.Number <= -1 || arg.Number >= 1 {
8018 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8020 return newNumberFormulaArg(0.5 * math.Log((1+arg.Number)/(1-arg.Number)))
8023 if token.Number <= -1 || token.Number >= 1 {
8024 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8026 return newNumberFormulaArg(0.5 * math.Log((1+token.Number)/(1-token.Number)))
8028 return newErrorFormulaArg(formulaErrorVALUE, "FISHER requires 1 numeric argument")
8031 // FISHERINV function calculates the inverse of the Fisher Transformation and
8032 // returns a value between -1 and +1. The syntax of the function is:
8035 func (fn *formulaFuncs) FISHERINV(argsList *list.List) formulaArg {
8036 if argsList.Len() != 1 {
8037 return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
8039 token := argsList.Front().Value.(formulaArg)
8042 arg := token.ToNumber()
8043 if arg.Type == ArgNumber {
8044 return newNumberFormulaArg((math.Exp(2*arg.Number) - 1) / (math.Exp(2*arg.Number) + 1))
8047 return newNumberFormulaArg((math.Exp(2*token.Number) - 1) / (math.Exp(2*token.Number) + 1))
8049 return newErrorFormulaArg(formulaErrorVALUE, "FISHERINV requires 1 numeric argument")
8052 // FORECAST function predicts a future point on a linear trend line fitted to a
8053 // supplied set of x- and y- values. The syntax of the function is:
8055 // FORECAST(x,known_y's,known_x's)
8056 func (fn *formulaFuncs) FORECAST(argsList *list.List) formulaArg {
8057 return fn.pearsonProduct("FORECAST", 3, argsList)
8060 // FORECASTdotLINEAR function predicts a future point on a linear trend line
8061 // fitted to a supplied set of x- and y- values. The syntax of the function is:
8063 // FORECAST.LINEAR(x,known_y's,known_x's)
8064 func (fn *formulaFuncs) FORECASTdotLINEAR(argsList *list.List) formulaArg {
8065 return fn.pearsonProduct("FORECAST.LINEAR", 3, argsList)
8068 // maritxToSortedColumnList convert matrix formula arguments to a ascending
8069 // order list by column.
8070 func maritxToSortedColumnList(arg formulaArg) formulaArg {
8071 mtx, cols := []formulaArg{}, len(arg.Matrix[0])
8072 for colIdx := 0; colIdx < cols; colIdx++ {
8073 for _, row := range arg.Matrix {
8075 if cell.Type == ArgError {
8078 if cell.Type == ArgNumber {
8079 mtx = append(mtx, cell)
8083 argsList := newListFormulaArg(mtx)
8084 sort.Slice(argsList.List, func(i, j int) bool {
8085 return argsList.List[i].Number < argsList.List[j].Number
8090 // FREQUENCY function to count how many children fall into different age
8091 // ranges. The syntax of the function is:
8093 // FREQUENCY(data_array,bins_array)
8094 func (fn *formulaFuncs) FREQUENCY(argsList *list.List) formulaArg {
8095 if argsList.Len() != 2 {
8096 return newErrorFormulaArg(formulaErrorVALUE, "FREQUENCY requires 2 arguments")
8098 data, bins := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
8099 if len(data.Matrix) == 0 {
8100 data.Matrix = [][]formulaArg{{data}}
8102 if len(bins.Matrix) == 0 {
8103 bins.Matrix = [][]formulaArg{{bins}}
8106 dataMtx, binsMtx formulaArg
8110 if dataMtx = maritxToSortedColumnList(data); dataMtx.Type != ArgList {
8113 if binsMtx = maritxToSortedColumnList(bins); binsMtx.Type != ArgList {
8116 for row := 0; row < len(binsMtx.List)+1; row++ {
8117 rows := []formulaArg{}
8118 for col := 0; col < 1; col++ {
8119 rows = append(rows, newNumberFormulaArg(0))
8123 for j = 0; j < len(binsMtx.List); j++ {
8125 for i < len(dataMtx.List) && dataMtx.List[i].Number <= binsMtx.List[j].Number {
8129 c[j] = []formulaArg{newNumberFormulaArg(n)}
8131 c[j] = []formulaArg{newNumberFormulaArg(float64(len(dataMtx.List) - i))}
8133 c[1], c[2] = c[2], c[1]
8135 return newMatrixFormulaArg(c)
8138 // GAMMA function returns the value of the Gamma Function, Γ(n), for a
8139 // specified number, n. The syntax of the function is:
8142 func (fn *formulaFuncs) GAMMA(argsList *list.List) formulaArg {
8143 if argsList.Len() != 1 {
8144 return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
8146 number := argsList.Front().Value.(formulaArg).ToNumber()
8147 if number.Type != ArgNumber {
8148 return newErrorFormulaArg(formulaErrorVALUE, "GAMMA requires 1 numeric argument")
8150 if number.Number <= 0 {
8151 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8153 return newNumberFormulaArg(math.Gamma(number.Number))
8156 // GAMMAdotDIST function returns the Gamma Distribution, which is frequently
8157 // used to provide probabilities for values that may have a skewed
8158 // distribution, such as queuing analysis.
8160 // GAMMA.DIST(x,alpha,beta,cumulative)
8161 func (fn *formulaFuncs) GAMMAdotDIST(argsList *list.List) formulaArg {
8162 if argsList.Len() != 4 {
8163 return newErrorFormulaArg(formulaErrorVALUE, "GAMMA.DIST requires 4 arguments")
8165 return fn.GAMMADIST(argsList)
8168 // GAMMADIST function returns the Gamma Distribution, which is frequently used
8169 // to provide probabilities for values that may have a skewed distribution,
8170 // such as queuing analysis.
8172 // GAMMADIST(x,alpha,beta,cumulative)
8173 func (fn *formulaFuncs) GAMMADIST(argsList *list.List) formulaArg {
8174 if argsList.Len() != 4 {
8175 return newErrorFormulaArg(formulaErrorVALUE, "GAMMADIST requires 4 arguments")
8177 var x, alpha, beta, cumulative formulaArg
8178 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
8182 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8184 if alpha = argsList.Front().Next().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
8187 if beta = argsList.Back().Prev().Value.(formulaArg).ToNumber(); beta.Type != ArgNumber {
8190 if alpha.Number <= 0 || beta.Number <= 0 {
8191 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8193 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
8196 if cumulative.Number == 1 {
8197 return newNumberFormulaArg(incompleteGamma(alpha.Number, x.Number/beta.Number) / math.Gamma(alpha.Number))
8199 return newNumberFormulaArg((1 / (math.Pow(beta.Number, alpha.Number) * math.Gamma(alpha.Number))) * math.Pow(x.Number, alpha.Number-1) * math.Exp(0-(x.Number/beta.Number)))
8202 // gammainv returns the inverse of the Gamma distribution for the specified
8204 func gammainv(probability, alpha, beta float64) float64 {
8205 xLo, xHi := 0.0, alpha*beta*5
8206 dx, x, xNew, result := 1024.0, 1.0, 1.0, 0.0
8207 for i := 0; math.Abs(dx) > 8.88e-016 && i <= 256; i++ {
8208 result = incompleteGamma(alpha, x/beta) / math.Gamma(alpha)
8209 e := result - probability
8217 pdf := (1 / (math.Pow(beta, alpha) * math.Gamma(alpha))) * math.Pow(x, alpha-1) * math.Exp(0-(x/beta))
8222 if xNew < xLo || xNew > xHi || pdf == 0 {
8223 xNew = (xLo + xHi) / 2
8231 // GAMMAdotINV function returns the inverse of the Gamma Cumulative
8232 // Distribution. The syntax of the function is:
8234 // GAMMA.INV(probability,alpha,beta)
8235 func (fn *formulaFuncs) GAMMAdotINV(argsList *list.List) formulaArg {
8236 if argsList.Len() != 3 {
8237 return newErrorFormulaArg(formulaErrorVALUE, "GAMMA.INV requires 3 arguments")
8239 return fn.GAMMAINV(argsList)
8242 // GAMMAINV function returns the inverse of the Gamma Cumulative Distribution.
8243 // The syntax of the function is:
8245 // GAMMAINV(probability,alpha,beta)
8246 func (fn *formulaFuncs) GAMMAINV(argsList *list.List) formulaArg {
8247 if argsList.Len() != 3 {
8248 return newErrorFormulaArg(formulaErrorVALUE, "GAMMAINV requires 3 arguments")
8250 var probability, alpha, beta formulaArg
8251 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
8254 if probability.Number < 0 || probability.Number >= 1 {
8255 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8257 if alpha = argsList.Front().Next().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
8260 if beta = argsList.Back().Value.(formulaArg).ToNumber(); beta.Type != ArgNumber {
8263 if alpha.Number <= 0 || beta.Number <= 0 {
8264 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8266 return newNumberFormulaArg(gammainv(probability.Number, alpha.Number, beta.Number))
8269 // GAMMALN function returns the natural logarithm of the Gamma Function, Γ
8270 // (n). The syntax of the function is:
8273 func (fn *formulaFuncs) GAMMALN(argsList *list.List) formulaArg {
8274 if argsList.Len() != 1 {
8275 return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
8277 x := argsList.Front().Value.(formulaArg).ToNumber()
8278 if x.Type != ArgNumber {
8279 return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument")
8282 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8284 return newNumberFormulaArg(math.Log(math.Gamma(x.Number)))
8287 // GAMMALNdotPRECISE function returns the natural logarithm of the Gamma
8288 // Function, Γ(n). The syntax of the function is:
8290 // GAMMALN.PRECISE(x)
8291 func (fn *formulaFuncs) GAMMALNdotPRECISE(argsList *list.List) formulaArg {
8292 if argsList.Len() != 1 {
8293 return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN.PRECISE requires 1 numeric argument")
8295 x := argsList.Front().Value.(formulaArg).ToNumber()
8296 if x.Type != ArgNumber {
8300 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8302 return newNumberFormulaArg(getLogGamma(x.Number))
8305 // GAUSS function returns the probability that a member of a standard normal
8306 // population will fall between the mean and a specified number of standard
8307 // deviations from the mean. The syntax of the function is:
8310 func (fn *formulaFuncs) GAUSS(argsList *list.List) formulaArg {
8311 if argsList.Len() != 1 {
8312 return newErrorFormulaArg(formulaErrorVALUE, "GAUSS requires 1 numeric argument")
8314 args := list.New().Init()
8315 args.PushBack(argsList.Front().Value.(formulaArg))
8316 args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
8317 args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
8318 args.PushBack(newBoolFormulaArg(true))
8319 normdist := fn.NORMDIST(args)
8320 if normdist.Type != ArgNumber {
8323 return newNumberFormulaArg(normdist.Number - 0.5)
8326 // GEOMEAN function calculates the geometric mean of a supplied set of values.
8327 // The syntax of the function is:
8329 // GEOMEAN(number1,[number2],...)
8330 func (fn *formulaFuncs) GEOMEAN(argsList *list.List) formulaArg {
8331 if argsList.Len() < 1 {
8332 return newErrorFormulaArg(formulaErrorVALUE, "GEOMEAN requires at least 1 numeric argument")
8334 product := fn.PRODUCT(argsList)
8335 if product.Type != ArgNumber {
8338 count := fn.COUNT(argsList)
8339 min := fn.MIN(argsList)
8340 if product.Number > 0 && min.Number > 0 {
8341 return newNumberFormulaArg(math.Pow(product.Number, 1/count.Number))
8343 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8346 // getNewMatrix create matrix by given columns and rows.
8347 func getNewMatrix(c, r int) (matrix [][]float64) {
8348 for i := 0; i < c; i++ {
8349 for j := 0; j < r; j++ {
8350 for x := len(matrix); x <= i; x++ {
8351 matrix = append(matrix, []float64{})
8353 for y := len(matrix[i]); y <= j; y++ {
8354 matrix[i] = append(matrix[i], 0)
8362 // approxSub subtract two values, if signs are identical and the values are
8363 // equal, will be returns 0 instead of calculating the subtraction.
8364 func approxSub(a, b float64) float64 {
8365 if ((a < 0 && b < 0) || (a > 0 && b > 0)) && math.Abs(a-b) < 2.22045e-016 {
8371 // matrixClone return a copy of all elements of the original matrix.
8372 func matrixClone(matrix [][]float64) (cloneMatrix [][]float64) {
8373 for i := 0; i < len(matrix); i++ {
8374 for j := 0; j < len(matrix[i]); j++ {
8375 for x := len(cloneMatrix); x <= i; x++ {
8376 cloneMatrix = append(cloneMatrix, []float64{})
8378 for k := len(cloneMatrix[i]); k <= j; k++ {
8379 cloneMatrix[i] = append(cloneMatrix[i], 0)
8381 cloneMatrix[i][j] = matrix[i][j]
8387 // trendGrowthMatrixInfo defined matrix checking result.
8388 type trendGrowthMatrixInfo struct {
8389 trendType, nCX, nCY, nRX, nRY, M, N int
8390 mtxX, mtxY [][]float64
8393 // prepareTrendGrowthMtxX is a part of implementation of the trend growth prepare.
8394 func prepareTrendGrowthMtxX(mtxX [][]float64) [][]float64 {
8396 for i := 0; i < len(mtxX); i++ {
8397 for j := 0; j < len(mtxX[i]); j++ {
8398 if mtxX[i][j] == 0 {
8401 for x := len(mtx); x <= j; x++ {
8402 mtx = append(mtx, []float64{})
8404 for y := len(mtx[j]); y <= i; y++ {
8405 mtx[j] = append(mtx[j], 0)
8407 mtx[j][i] = mtxX[i][j]
8413 // prepareTrendGrowthMtxY is a part of implementation of the trend growth prepare.
8414 func prepareTrendGrowthMtxY(bLOG bool, mtxY [][]float64) [][]float64 {
8416 for i := 0; i < len(mtxY); i++ {
8417 for j := 0; j < len(mtxY[i]); j++ {
8418 if mtxY[i][j] == 0 {
8421 for x := len(mtx); x <= j; x++ {
8422 mtx = append(mtx, []float64{})
8424 for y := len(mtx[j]); y <= i; y++ {
8425 mtx[j] = append(mtx[j], 0)
8427 mtx[j][i] = mtxY[i][j]
8431 var pNewY [][]float64
8432 for i := 0; i < len(mtxY); i++ {
8433 for j := 0; j < len(mtxY[i]); j++ {
8438 for x := len(pNewY); x <= j; x++ {
8439 pNewY = append(pNewY, []float64{})
8441 for y := len(pNewY[j]); y <= i; y++ {
8442 pNewY[j] = append(pNewY[j], 0)
8444 pNewY[j][i] = math.Log(fVal)
8452 // prepareTrendGrowth check and return the result.
8453 func prepareTrendGrowth(bLOG bool, mtxX, mtxY [][]float64) (*trendGrowthMatrixInfo, formulaArg) {
8454 var nCX, nRX, M, N, trendType int
8455 nRY, nCY := len(mtxY), len(mtxY[0])
8457 newY := prepareTrendGrowthMtxY(bLOG, mtxY)
8459 return nil, newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8461 var newX [][]float64
8463 nRX, nCX = len(mtxX), len(mtxX[0])
8464 if newX = prepareTrendGrowthMtxX(mtxX); newX == nil {
8465 return nil, newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
8467 if nCX == nCY && nRX == nRY {
8468 trendType, M, N = 1, 1, cntY // simple regression
8469 } else if nCY != 1 && nRY != 1 {
8470 return nil, newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
8471 } else if nCY == 1 {
8473 return nil, newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
8475 trendType, M, N = 2, nCX, nRY
8476 } else if nCX != nCY {
8477 return nil, newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
8479 trendType, M, N = 3, nRX, nCY
8482 newX = getNewMatrix(nCY, nRY)
8485 for i := 0; i < nRY; i++ {
8486 for j := 0; j < nCY; j++ {
8491 trendType, M, N = 1, 1, cntY
8493 return &trendGrowthMatrixInfo{
8494 trendType: trendType,
8503 }, newEmptyFormulaArg()
8506 // calcPosition calculate position for matrix by given index.
8507 func calcPosition(mtx [][]float64, idx int) (row, col int) {
8508 rowSize := len(mtx[0])
8513 row = idx - col*rowSize
8517 // getDouble returns float64 data type value in the matrix by given index.
8518 func getDouble(mtx [][]float64, idx int) float64 {
8519 row, col := calcPosition(mtx, idx)
8520 return mtx[col][row]
8523 // putDouble set a float64 data type value in the matrix by given index.
8524 func putDouble(mtx [][]float64, idx int, val float64) {
8525 row, col := calcPosition(mtx, idx)
8529 // calcMeanOverAll returns mean of the given matrix by over all element.
8530 func calcMeanOverAll(mtx [][]float64, n int) float64 {
8532 for i := 0; i < len(mtx); i++ {
8533 for j := 0; j < len(mtx[i]); j++ {
8537 return sum / float64(n)
8540 // calcSumProduct returns uses the matrices as vectors of length M over all
8542 func calcSumProduct(mtxA, mtxB [][]float64, m int) float64 {
8544 for i := 0; i < m; i++ {
8545 sum += getDouble(mtxA, i) * getDouble(mtxB, i)
8550 // calcColumnMeans calculates means of the columns of matrix.
8551 func calcColumnMeans(mtxX, mtxRes [][]float64, c, r int) {
8552 for i := 0; i < c; i++ {
8554 for k := 0; k < r; k++ {
8557 putDouble(mtxRes, i, sum/float64(r))
8561 // calcColumnsDelta calculates subtract of the columns of matrix.
8562 func calcColumnsDelta(mtx, columnMeans [][]float64, c, r int) {
8563 for i := 0; i < c; i++ {
8564 for k := 0; k < r; k++ {
8565 mtx[i][k] = approxSub(mtx[i][k], getDouble(columnMeans, i))
8570 // calcSign returns sign by given value, no mathematical signum, but used to
8571 // switch between adding and subtracting.
8572 func calcSign(val float64) float64 {
8579 // calcColsMaximumNorm is a special version for use within QR
8580 // decomposition. Maximum norm of column index c starting in row index r;
8581 // matrix A has count n rows.
8582 func calcColsMaximumNorm(mtxA [][]float64, c, r, n int) float64 {
8584 for row := r; row < n; row++ {
8585 if norm < math.Abs(mtxA[c][row]) {
8586 norm = math.Abs(mtxA[c][row])
8592 // calcFastMult returns multiply n x m matrix A with m x l matrix B to n x l matrix R.
8593 func calcFastMult(mtxA, mtxB, mtxR [][]float64, n, m, l int) {
8595 for row := 0; row < n; row++ {
8596 for col := 0; col < l; col++ {
8598 for k := 0; k < m; k++ {
8599 sum += mtxA[k][row] * mtxB[col][k]
8601 mtxR[col][row] = sum
8606 // calcRowsEuclideanNorm is a special version for use within QR
8607 // decomposition. Euclidean norm of column index c starting in row index r;
8608 // matrix a has count n rows.
8609 func calcRowsEuclideanNorm(mtxA [][]float64, c, r, n int) float64 {
8611 for row := r; row < n; row++ {
8612 norm += mtxA[c][row] * mtxA[c][row]
8614 return math.Sqrt(norm)
8617 // calcRowsSumProduct is a special version for use within QR decomposition.
8618 // <A(a);B(b)> starting in row index r;
8619 // a and b are indices of columns, matrices A and B have count n rows.
8620 func calcRowsSumProduct(mtxA [][]float64, a int, mtxB [][]float64, b, r, n int) float64 {
8622 for row := r; row < n; row++ {
8623 result += mtxA[a][row] * mtxB[b][row]
8628 // calcSolveWithUpperRightTriangle solve for X in R*X=S using back substitution.
8629 func calcSolveWithUpperRightTriangle(mtxA [][]float64, vecR []float64, mtxS [][]float64, k int, bIsTransposed bool) {
8631 for rowp1 := k; rowp1 > 0; rowp1-- {
8633 sum := getDouble(mtxS, row)
8634 for col := rowp1; col < k; col++ {
8636 sum -= mtxA[row][col] * getDouble(mtxS, col)
8638 sum -= mtxA[col][row] * getDouble(mtxS, col)
8641 putDouble(mtxS, row, sum/vecR[row])
8645 // calcRowQRDecomposition calculates a QR decomposition with Householder
8647 func calcRowQRDecomposition(mtxA [][]float64, vecR []float64, k, n int) bool {
8648 for col := 0; col < k; col++ {
8649 scale := calcColsMaximumNorm(mtxA, col, col, n)
8653 for row := col; row < n; row++ {
8654 mtxA[col][row] = mtxA[col][row] / scale
8656 euclid := calcRowsEuclideanNorm(mtxA, col, col, n)
8657 factor := 1.0 / euclid / (euclid + math.Abs(mtxA[col][col]))
8658 signum := calcSign(mtxA[col][col])
8659 mtxA[col][col] = mtxA[col][col] + signum*euclid
8660 vecR[col] = -signum * scale * euclid
8661 // apply Householder transformation to A
8662 for c := col + 1; c < k; c++ {
8663 sum := calcRowsSumProduct(mtxA, col, mtxA, c, col, n)
8664 for row := col; row < n; row++ {
8665 mtxA[c][row] = mtxA[c][row] - sum*factor*mtxA[col][row]
8672 // calcApplyColsHouseholderTransformation transposed matrices A and Y.
8673 func calcApplyColsHouseholderTransformation(mtxA [][]float64, r int, mtxY [][]float64, n int) {
8674 denominator := calcColsSumProduct(mtxA, r, mtxA, r, r, n)
8675 numerator := calcColsSumProduct(mtxA, r, mtxY, 0, r, n)
8676 factor := 2 * (numerator / denominator)
8677 for col := r; col < n; col++ {
8678 putDouble(mtxY, col, getDouble(mtxY, col)-factor*mtxA[col][r])
8682 // calcRowMeans calculates means of the rows of matrix.
8683 func calcRowMeans(mtxX, mtxRes [][]float64, c, r int) {
8684 for k := 0; k < r; k++ {
8686 for i := 0; i < c; i++ {
8689 mtxRes[k][0] = fSum / float64(c)
8693 // calcRowsDelta calculates subtract of the rows of matrix.
8694 func calcRowsDelta(mtx, rowMeans [][]float64, c, r int) {
8695 for k := 0; k < r; k++ {
8696 for i := 0; i < c; i++ {
8697 mtx[i][k] = approxSub(mtx[i][k], rowMeans[k][0])
8702 // calcColumnMaximumNorm returns maximum norm of row index R starting in col
8703 // index C; matrix A has count N columns.
8704 func calcColumnMaximumNorm(mtxA [][]float64, r, c, n int) float64 {
8706 for col := c; col < n; col++ {
8707 if norm < math.Abs(mtxA[col][r]) {
8708 norm = math.Abs(mtxA[col][r])
8714 // calcColsEuclideanNorm returns euclidean norm of row index R starting in
8715 // column index C; matrix A has count N columns.
8716 func calcColsEuclideanNorm(mtxA [][]float64, r, c, n int) float64 {
8718 for col := c; col < n; col++ {
8719 norm += (mtxA[col][r]) * (mtxA[col][r])
8721 return math.Sqrt(norm)
8724 // calcColsSumProduct returns sum product for given matrix.
8725 func calcColsSumProduct(mtxA [][]float64, a int, mtxB [][]float64, b, c, n int) float64 {
8727 for col := c; col < n; col++ {
8728 result += mtxA[col][a] * mtxB[col][b]
8733 // calcColQRDecomposition same with transposed matrix A, N is count of
8734 // columns, k count of rows.
8735 func calcColQRDecomposition(mtxA [][]float64, vecR []float64, k, n int) bool {
8737 for row := 0; row < k; row++ {
8738 // calculate vector u of the householder transformation
8739 scale := calcColumnMaximumNorm(mtxA, row, row, n)
8743 for col := row; col < n; col++ {
8744 mtxA[col][row] = mtxA[col][row] / scale
8746 euclid := calcColsEuclideanNorm(mtxA, row, row, n)
8747 factor := 1 / euclid / (euclid + math.Abs(mtxA[row][row]))
8748 signum := calcSign(mtxA[row][row])
8749 mtxA[row][row] = mtxA[row][row] + signum*euclid
8750 vecR[row] = -signum * scale * euclid
8751 // apply Householder transformation to A
8752 for r := row + 1; r < k; r++ {
8753 sum = calcColsSumProduct(mtxA, row, mtxA, r, row, n)
8754 for col := row; col < n; col++ {
8755 mtxA[col][r] = mtxA[col][r] - sum*factor*mtxA[col][row]
8762 // calcApplyRowsHouseholderTransformation applies a Householder transformation to a
8763 // column vector Y with is given as Nx1 Matrix. The vector u, from which the
8764 // Householder transformation is built, is the column part in matrix A, with
8765 // column index c, starting with row index c. A is the result of the QR
8766 // decomposition as obtained from calcRowQRDecomposition.
8767 func calcApplyRowsHouseholderTransformation(mtxA [][]float64, c int, mtxY [][]float64, n int) {
8768 denominator := calcRowsSumProduct(mtxA, c, mtxA, c, c, n)
8769 numerator := calcRowsSumProduct(mtxA, c, mtxY, 0, c, n)
8770 factor := 2 * (numerator / denominator)
8771 for row := c; row < n; row++ {
8772 putDouble(mtxY, row, getDouble(mtxY, row)-factor*mtxA[c][row])
8776 // calcTrendGrowthSimpleRegression calculate simple regression for the calcTrendGrowth.
8777 func calcTrendGrowthSimpleRegression(bConstant, bGrowth bool, mtxY, mtxX, newX, mtxRes [][]float64, meanY float64, N int) {
8780 meanX = calcMeanOverAll(mtxX, N)
8781 for i := 0; i < len(mtxX); i++ {
8782 for j := 0; j < len(mtxX[i]); j++ {
8783 mtxX[i][j] = approxSub(mtxX[i][j], meanX)
8787 sumXY := calcSumProduct(mtxX, mtxY, N)
8788 sumX2 := calcSumProduct(mtxX, mtxX, N)
8789 slope := sumXY / sumX2
8791 var intercept float64
8793 intercept = meanY - slope*meanX
8794 for i := 0; i < len(mtxRes); i++ {
8795 for j := 0; j < len(mtxRes[i]); j++ {
8796 help = newX[i][j]*slope + intercept
8798 mtxRes[i][j] = math.Exp(help)
8805 for i := 0; i < len(mtxRes); i++ {
8806 for j := 0; j < len(mtxRes[i]); j++ {
8807 help = newX[i][j] * slope
8809 mtxRes[i][j] = math.Exp(help)
8818 // calcTrendGrowthMultipleRegressionPart1 calculate multiple regression for the
8820 func calcTrendGrowthMultipleRegressionPart1(bConstant, bGrowth bool, mtxY, mtxX, newX, mtxRes [][]float64, meanY float64, RXN, K, N int) {
8821 vecR := make([]float64, N) // for QR decomposition
8822 means := getNewMatrix(K, 1) // mean of each column
8823 slopes := getNewMatrix(1, K) // from b1 to bK
8824 if len(means) == 0 || len(slopes) == 0 {
8828 calcColumnMeans(mtxX, means, K, N)
8829 calcColumnsDelta(mtxX, means, K, N)
8831 if !calcRowQRDecomposition(mtxX, vecR, K, N) {
8834 // Later on we will divide by elements of vecR, so make sure that they aren't zero.
8835 bIsSingular := false
8836 for row := 0; row < K && !bIsSingular; row++ {
8837 bIsSingular = bIsSingular || vecR[row] == 0
8842 for col := 0; col < K; col++ {
8843 calcApplyRowsHouseholderTransformation(mtxX, col, mtxY, N)
8845 for col := 0; col < K; col++ {
8846 putDouble(slopes, col, getDouble(mtxY, col))
8848 calcSolveWithUpperRightTriangle(mtxX, vecR, slopes, K, false)
8849 // Fill result matrix
8850 calcFastMult(newX, slopes, mtxRes, RXN, K, 1)
8852 intercept := meanY - calcSumProduct(means, slopes, K)
8853 for row := 0; row < RXN; row++ {
8854 mtxRes[0][row] = mtxRes[0][row] + intercept
8858 for i := 0; i < RXN; i++ {
8859 putDouble(mtxRes, i, math.Exp(getDouble(mtxRes, i)))
8864 // calcTrendGrowthMultipleRegressionPart2 calculate multiple regression for the
8866 func calcTrendGrowthMultipleRegressionPart2(bConstant, bGrowth bool, mtxY, mtxX, newX, mtxRes [][]float64, meanY float64, nCXN, K, N int) {
8867 vecR := make([]float64, N) // for QR decomposition
8868 means := getNewMatrix(K, 1) // mean of each row
8869 slopes := getNewMatrix(K, 1) // row from b1 to bK
8870 if len(means) == 0 || len(slopes) == 0 {
8874 calcRowMeans(mtxX, means, N, K)
8875 calcRowsDelta(mtxX, means, N, K)
8877 if !calcColQRDecomposition(mtxX, vecR, K, N) {
8880 // later on we will divide by elements of vecR, so make sure that they aren't zero
8881 bIsSingular := false
8882 for row := 0; row < K && !bIsSingular; row++ {
8883 bIsSingular = bIsSingular || vecR[row] == 0
8888 for row := 0; row < K; row++ {
8889 calcApplyColsHouseholderTransformation(mtxX, row, mtxY, N)
8891 for col := 0; col < K; col++ {
8892 putDouble(slopes, col, getDouble(mtxY, col))
8894 calcSolveWithUpperRightTriangle(mtxX, vecR, slopes, K, true)
8895 // fill result matrix
8896 calcFastMult(slopes, newX, mtxRes, 1, K, nCXN)
8898 fIntercept := meanY - calcSumProduct(means, slopes, K)
8899 for col := 0; col < nCXN; col++ {
8900 mtxRes[col][0] = mtxRes[col][0] + fIntercept
8904 for i := 0; i < nCXN; i++ {
8905 putDouble(mtxRes, i, math.Exp(getDouble(mtxRes, i)))
8910 // calcTrendGrowthRegression is a part of implementation of the calcTrendGrowth.
8911 func calcTrendGrowthRegression(bConstant, bGrowth bool, trendType, nCXN, nRXN, K, N int, mtxY, mtxX, newX, mtxRes [][]float64) {
8912 if len(mtxRes) == 0 {
8917 copyX, copyY := matrixClone(mtxX), matrixClone(mtxY)
8918 mtxX, mtxY = copyX, copyY
8919 meanY = calcMeanOverAll(mtxY, N)
8920 for i := 0; i < len(mtxY); i++ {
8921 for j := 0; j < len(mtxY[i]); j++ {
8922 mtxY[i][j] = approxSub(mtxY[i][j], meanY)
8928 calcTrendGrowthSimpleRegression(bConstant, bGrowth, mtxY, mtxX, newX, mtxRes, meanY, N)
8930 calcTrendGrowthMultipleRegressionPart1(bConstant, bGrowth, mtxY, mtxX, newX, mtxRes, meanY, nRXN, K, N)
8932 calcTrendGrowthMultipleRegressionPart2(bConstant, bGrowth, mtxY, mtxX, newX, mtxRes, meanY, nCXN, K, N)
8936 // calcTrendGrowth returns values along a predicted exponential trend.
8937 func calcTrendGrowth(mtxY, mtxX, newX [][]float64, bConstant, bGrowth bool) ([][]float64, formulaArg) {
8938 getMatrixParams, errArg := prepareTrendGrowth(bGrowth, mtxX, mtxY)
8939 if errArg.Type != ArgEmpty {
8942 trendType := getMatrixParams.trendType
8943 nCX := getMatrixParams.nCX
8944 nRX := getMatrixParams.nRX
8945 K := getMatrixParams.M
8946 N := getMatrixParams.N
8947 mtxX = getMatrixParams.mtxX
8948 mtxY = getMatrixParams.mtxY
8949 // checking if data samples are enough
8950 if (bConstant && (N < K+1)) || (!bConstant && (N < K)) || (N < 1) || (K < 1) {
8953 // set the default newX if necessary
8954 nCXN, nRXN := nCX, nRX
8956 newX = matrixClone(mtxX) // mtxX will be changed to X-meanX
8958 nRXN, nCXN = len(newX[0]), len(newX)
8959 if (trendType == 2 && K != nCXN) || (trendType == 3 && K != nRXN) {
8963 var mtxRes [][]float64
8966 mtxRes = getNewMatrix(nCXN, nRXN)
8968 mtxRes = getNewMatrix(1, nRXN)
8970 mtxRes = getNewMatrix(nCXN, 1)
8972 calcTrendGrowthRegression(bConstant, bGrowth, trendType, nCXN, nRXN, K, N, mtxY, mtxX, newX, mtxRes)
8973 return mtxRes, errArg
8976 // trendGrowth is an implementation of the formula functions GROWTH and TREND.
8977 func (fn *formulaFuncs) trendGrowth(name string, argsList *list.List) formulaArg {
8978 if argsList.Len() < 1 {
8979 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
8981 if argsList.Len() > 4 {
8982 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 4 arguments", name))
8984 var knowY, knowX, newX [][]float64
8985 var errArg formulaArg
8986 constArg := newBoolFormulaArg(true)
8987 knowY, errArg = newNumberMatrix(argsList.Front().Value.(formulaArg), false)
8988 if errArg.Type == ArgError {
8991 if argsList.Len() > 1 {
8992 knowX, errArg = newNumberMatrix(argsList.Front().Next().Value.(formulaArg), false)
8993 if errArg.Type == ArgError {
8997 if argsList.Len() > 2 {
8998 newX, errArg = newNumberMatrix(argsList.Front().Next().Next().Value.(formulaArg), false)
8999 if errArg.Type == ArgError {
9003 if argsList.Len() > 3 {
9004 if constArg = argsList.Back().Value.(formulaArg).ToBool(); constArg.Type != ArgNumber {
9008 var mtxNewX [][]float64
9009 for i := 0; i < len(newX); i++ {
9010 for j := 0; j < len(newX[i]); j++ {
9011 for x := len(mtxNewX); x <= j; x++ {
9012 mtxNewX = append(mtxNewX, []float64{})
9014 for k := len(mtxNewX[j]); k <= i; k++ {
9015 mtxNewX[j] = append(mtxNewX[j], 0)
9017 mtxNewX[j][i] = newX[i][j]
9020 mtx, errArg := calcTrendGrowth(knowY, knowX, mtxNewX, constArg.Number == 1, name == "GROWTH")
9021 if errArg.Type != ArgEmpty {
9024 return newMatrixFormulaArg(newFormulaArgMatrix(mtx))
9027 // GROWTH function calculates the exponential growth curve through a given set
9028 // of y-values and (optionally), one or more sets of x-values. The function
9029 // then extends the curve to calculate additional y-values for a further
9030 // supplied set of new x-values. The syntax of the function is:
9032 // GROWTH(known_y's,[known_x's],[new_x's],[const])
9033 func (fn *formulaFuncs) GROWTH(argsList *list.List) formulaArg {
9034 return fn.trendGrowth("GROWTH", argsList)
9037 // HARMEAN function calculates the harmonic mean of a supplied set of values.
9038 // The syntax of the function is:
9040 // HARMEAN(number1,[number2],...)
9041 func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg {
9042 if argsList.Len() < 1 {
9043 return newErrorFormulaArg(formulaErrorVALUE, "HARMEAN requires at least 1 argument")
9045 if min := fn.MIN(argsList); min.Number < 0 {
9046 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9048 number, val, cnt := 0.0, 0.0, 0.0
9049 for token := argsList.Front(); token != nil; token = token.Next() {
9050 arg := token.Value.(formulaArg)
9053 num := arg.ToNumber()
9054 if num.Type != ArgNumber {
9062 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9067 return newNumberFormulaArg(1 / (val / cnt))
9070 // checkHYPGEOMDISTArgs checking arguments for the formula function HYPGEOMDIST
9071 // and HYPGEOM.DIST.
9072 func checkHYPGEOMDISTArgs(sampleS, numberSample, populationS, numberPop formulaArg) bool {
9073 return sampleS.Number < 0 ||
9074 sampleS.Number > math.Min(numberSample.Number, populationS.Number) ||
9075 sampleS.Number < math.Max(0, numberSample.Number-numberPop.Number+populationS.Number) ||
9076 numberSample.Number <= 0 ||
9077 numberSample.Number > numberPop.Number ||
9078 populationS.Number <= 0 ||
9079 populationS.Number > numberPop.Number ||
9080 numberPop.Number <= 0
9083 // prepareHYPGEOMDISTArgs prepare arguments for the formula function
9084 // HYPGEOMDIST and HYPGEOM.DIST.
9085 func (fn *formulaFuncs) prepareHYPGEOMDISTArgs(name string, argsList *list.List) formulaArg {
9086 if name == "HYPGEOMDIST" && argsList.Len() != 4 {
9087 return newErrorFormulaArg(formulaErrorVALUE, "HYPGEOMDIST requires 4 numeric arguments")
9089 if name == "HYPGEOM.DIST" && argsList.Len() != 5 {
9090 return newErrorFormulaArg(formulaErrorVALUE, "HYPGEOM.DIST requires 5 arguments")
9092 var sampleS, numberSample, populationS, numberPop, cumulative formulaArg
9093 if sampleS = argsList.Front().Value.(formulaArg).ToNumber(); sampleS.Type != ArgNumber {
9096 if numberSample = argsList.Front().Next().Value.(formulaArg).ToNumber(); numberSample.Type != ArgNumber {
9099 if populationS = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); populationS.Type != ArgNumber {
9102 if numberPop = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); numberPop.Type != ArgNumber {
9105 if checkHYPGEOMDISTArgs(sampleS, numberSample, populationS, numberPop) {
9106 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9108 if name == "HYPGEOM.DIST" {
9109 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
9113 return newListFormulaArg([]formulaArg{sampleS, numberSample, populationS, numberPop, cumulative})
9116 // HYPGEOMdotDIST function returns the value of the hypergeometric distribution
9117 // for a specified number of successes from a population sample. The function
9118 // can calculate the cumulative distribution or the probability density
9119 // function. The syntax of the function is:
9121 // HYPGEOM.DIST(sample_s,number_sample,population_s,number_pop,cumulative)
9122 func (fn *formulaFuncs) HYPGEOMdotDIST(argsList *list.List) formulaArg {
9123 args := fn.prepareHYPGEOMDISTArgs("HYPGEOM.DIST", argsList)
9124 if args.Type != ArgList {
9127 sampleS, numberSample, populationS, numberPop, cumulative := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4]
9128 if cumulative.Number == 1 {
9130 for i := 0; i <= int(sampleS.Number); i++ {
9131 res += binomCoeff(populationS.Number, float64(i)) *
9132 binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-float64(i)) /
9133 binomCoeff(numberPop.Number, numberSample.Number)
9135 return newNumberFormulaArg(res)
9137 return newNumberFormulaArg(binomCoeff(populationS.Number, sampleS.Number) *
9138 binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-sampleS.Number) /
9139 binomCoeff(numberPop.Number, numberSample.Number))
9142 // HYPGEOMDIST function returns the value of the hypergeometric distribution
9143 // for a given number of successes from a sample of a population. The syntax
9144 // of the function is:
9146 // HYPGEOMDIST(sample_s,number_sample,population_s,number_pop)
9147 func (fn *formulaFuncs) HYPGEOMDIST(argsList *list.List) formulaArg {
9148 args := fn.prepareHYPGEOMDISTArgs("HYPGEOMDIST", argsList)
9149 if args.Type != ArgList {
9152 sampleS, numberSample, populationS, numberPop := args.List[0], args.List[1], args.List[2], args.List[3]
9153 return newNumberFormulaArg(binomCoeff(populationS.Number, sampleS.Number) *
9154 binomCoeff(numberPop.Number-populationS.Number, numberSample.Number-sampleS.Number) /
9155 binomCoeff(numberPop.Number, numberSample.Number))
9158 // INTERCEPT function calculates the intercept (the value at the intersection
9159 // of the y axis) of the linear regression line through a supplied set of x-
9160 // and y- values. The syntax of the function is:
9162 // INTERCEPT(known_y's,known_x's)
9163 func (fn *formulaFuncs) INTERCEPT(argsList *list.List) formulaArg {
9164 return fn.pearsonProduct("INTERCEPT", 2, argsList)
9167 // KURT function calculates the kurtosis of a supplied set of values. The
9168 // syntax of the function is:
9170 // KURT(number1,[number2],...)
9171 func (fn *formulaFuncs) KURT(argsList *list.List) formulaArg {
9172 if argsList.Len() < 1 {
9173 return newErrorFormulaArg(formulaErrorVALUE, "KURT requires at least 1 argument")
9175 mean, stdev := fn.AVERAGE(argsList), fn.STDEV(argsList)
9176 if stdev.Number > 0 {
9177 count, summer := 0.0, 0.0
9178 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
9179 token := arg.Value.(formulaArg)
9181 case ArgString, ArgNumber:
9182 num := token.ToNumber()
9183 if num.Type == ArgError {
9186 summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
9188 case ArgList, ArgMatrix:
9189 for _, row := range token.ToList() {
9190 if row.Type == ArgNumber || row.Type == ArgString {
9191 num := row.ToNumber()
9192 if num.Type == ArgError {
9195 summer += math.Pow((num.Number-mean.Number)/stdev.Number, 4)
9202 return newNumberFormulaArg(summer*(count*(count+1)/((count-1)*(count-2)*(count-3))) - (3 * math.Pow(count-1, 2) / ((count - 2) * (count - 3))))
9205 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
9208 // EXPONdotDIST function returns the value of the exponential distribution for
9209 // a give value of x. The user can specify whether the probability density
9210 // function or the cumulative distribution function is used. The syntax of the
9211 // Expondist function is:
9213 // EXPON.DIST(x,lambda,cumulative)
9214 func (fn *formulaFuncs) EXPONdotDIST(argsList *list.List) formulaArg {
9215 if argsList.Len() != 3 {
9216 return newErrorFormulaArg(formulaErrorVALUE, "EXPON.DIST requires 3 arguments")
9218 return fn.EXPONDIST(argsList)
9221 // EXPONDIST function returns the value of the exponential distribution for a
9222 // give value of x. The user can specify whether the probability density
9223 // function or the cumulative distribution function is used. The syntax of the
9224 // Expondist function is:
9226 // EXPONDIST(x,lambda,cumulative)
9227 func (fn *formulaFuncs) EXPONDIST(argsList *list.List) formulaArg {
9228 if argsList.Len() != 3 {
9229 return newErrorFormulaArg(formulaErrorVALUE, "EXPONDIST requires 3 arguments")
9231 var x, lambda, cumulative formulaArg
9232 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9235 if lambda = argsList.Front().Next().Value.(formulaArg).ToNumber(); lambda.Type != ArgNumber {
9238 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
9242 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9244 if lambda.Number <= 0 {
9245 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9247 if cumulative.Number == 1 {
9248 return newNumberFormulaArg(1 - math.Exp(-lambda.Number*x.Number))
9250 return newNumberFormulaArg(lambda.Number * math.Exp(-lambda.Number*x.Number))
9253 // FdotDIST function calculates the Probability Density Function or the
9254 // Cumulative Distribution Function for the F Distribution. This function is
9255 // frequently used to measure the degree of diversity between two data
9256 // sets. The syntax of the function is:
9258 // F.DIST(x,deg_freedom1,deg_freedom2,cumulative)
9259 func (fn *formulaFuncs) FdotDIST(argsList *list.List) formulaArg {
9260 if argsList.Len() != 4 {
9261 return newErrorFormulaArg(formulaErrorVALUE, "F.DIST requires 4 arguments")
9263 var x, deg1, deg2, cumulative formulaArg
9264 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9267 if deg1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); deg1.Type != ArgNumber {
9270 if deg2 = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); deg2.Type != ArgNumber {
9273 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
9277 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9279 maxDeg := math.Pow10(10)
9280 if deg1.Number < 1 || deg1.Number >= maxDeg {
9281 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9283 if deg2.Number < 1 || deg2.Number >= maxDeg {
9284 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9286 if cumulative.Number == 1 {
9287 return newNumberFormulaArg(1 - getBetaDist(deg2.Number/(deg2.Number+deg1.Number*x.Number), deg2.Number/2, deg1.Number/2))
9289 return newNumberFormulaArg(math.Gamma((deg2.Number+deg1.Number)/2) / (math.Gamma(deg1.Number/2) * math.Gamma(deg2.Number/2)) * math.Pow(deg1.Number/deg2.Number, deg1.Number/2) * (math.Pow(x.Number, (deg1.Number-2)/2) / math.Pow(1+(deg1.Number/deg2.Number)*x.Number, (deg1.Number+deg2.Number)/2)))
9292 // FDIST function calculates the (right-tailed) F Probability Distribution,
9293 // which measures the degree of diversity between two data sets. The syntax
9294 // of the function is:
9296 // FDIST(x,deg_freedom1,deg_freedom2)
9297 func (fn *formulaFuncs) FDIST(argsList *list.List) formulaArg {
9298 if argsList.Len() != 3 {
9299 return newErrorFormulaArg(formulaErrorVALUE, "FDIST requires 3 arguments")
9301 var x, deg1, deg2 formulaArg
9302 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9305 if deg1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); deg1.Type != ArgNumber {
9308 if deg2 = argsList.Back().Value.(formulaArg).ToNumber(); deg2.Type != ArgNumber {
9312 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9314 maxDeg := math.Pow10(10)
9315 if deg1.Number < 1 || deg1.Number >= maxDeg {
9316 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9318 if deg2.Number < 1 || deg2.Number >= maxDeg {
9319 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9322 args.PushBack(newNumberFormulaArg(deg1.Number * x.Number / (deg1.Number*x.Number + deg2.Number)))
9323 args.PushBack(newNumberFormulaArg(0.5 * deg1.Number))
9324 args.PushBack(newNumberFormulaArg(0.5 * deg2.Number))
9325 args.PushBack(newNumberFormulaArg(0))
9326 args.PushBack(newNumberFormulaArg(1))
9327 return newNumberFormulaArg(1 - fn.BETADIST(args).Number)
9330 // FdotDISTdotRT function calculates the (right-tailed) F Probability
9331 // Distribution, which measures the degree of diversity between two data sets.
9332 // The syntax of the function is:
9334 // F.DIST.RT(x,deg_freedom1,deg_freedom2)
9335 func (fn *formulaFuncs) FdotDISTdotRT(argsList *list.List) formulaArg {
9336 if argsList.Len() != 3 {
9337 return newErrorFormulaArg(formulaErrorVALUE, "F.DIST.RT requires 3 arguments")
9339 return fn.FDIST(argsList)
9342 // prepareFinvArgs checking and prepare arguments for the formula functions
9343 // F.INV, F.INV.RT and FINV.
9344 func (fn *formulaFuncs) prepareFinvArgs(name string, argsList *list.List) formulaArg {
9345 if argsList.Len() != 3 {
9346 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 arguments", name))
9348 var probability, d1, d2 formulaArg
9349 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
9352 if d1 = argsList.Front().Next().Value.(formulaArg).ToNumber(); d1.Type != ArgNumber {
9355 if d2 = argsList.Back().Value.(formulaArg).ToNumber(); d2.Type != ArgNumber {
9358 if probability.Number <= 0 || probability.Number > 1 {
9359 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9361 if d1.Number < 1 || d1.Number >= math.Pow10(10) {
9362 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9364 if d2.Number < 1 || d2.Number >= math.Pow10(10) {
9365 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9367 return newListFormulaArg([]formulaArg{probability, d1, d2})
9370 // FdotINV function calculates the inverse of the Cumulative F Distribution
9371 // for a supplied probability. The syntax of the F.Inv function is:
9373 // F.INV(probability,deg_freedom1,deg_freedom2)
9374 func (fn *formulaFuncs) FdotINV(argsList *list.List) formulaArg {
9375 args := fn.prepareFinvArgs("F.INV", argsList)
9376 if args.Type != ArgList {
9379 probability, d1, d2 := args.List[0], args.List[1], args.List[2]
9380 return newNumberFormulaArg((1/calcBetainv(1-probability.Number, d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
9383 // FdotINVdotRT function calculates the inverse of the (right-tailed) F
9384 // Probability Distribution for a supplied probability. The syntax of the
9387 // F.INV.RT(probability,deg_freedom1,deg_freedom2)
9388 func (fn *formulaFuncs) FdotINVdotRT(argsList *list.List) formulaArg {
9389 args := fn.prepareFinvArgs("F.INV.RT", argsList)
9390 if args.Type != ArgList {
9393 probability, d1, d2 := args.List[0], args.List[1], args.List[2]
9394 return newNumberFormulaArg((1/calcBetainv(1-(1-probability.Number), d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
9397 // FINV function calculates the inverse of the (right-tailed) F Probability
9398 // Distribution for a supplied probability. The syntax of the function is:
9400 // FINV(probability,deg_freedom1,deg_freedom2)
9401 func (fn *formulaFuncs) FINV(argsList *list.List) formulaArg {
9402 args := fn.prepareFinvArgs("FINV", argsList)
9403 if args.Type != ArgList {
9406 probability, d1, d2 := args.List[0], args.List[1], args.List[2]
9407 return newNumberFormulaArg((1/calcBetainv(1-(1-probability.Number), d2.Number/2, d1.Number/2, 0, 1) - 1) * (d2.Number / d1.Number))
9410 // FdotTEST function returns the F-Test for two supplied arrays. I.e. the
9411 // function returns the two-tailed probability that the variances in the two
9412 // supplied arrays are not significantly different. The syntax of the Ftest
9415 // F.TEST(array1,array2)
9416 func (fn *formulaFuncs) FdotTEST(argsList *list.List) formulaArg {
9417 if argsList.Len() != 2 {
9418 return newErrorFormulaArg(formulaErrorVALUE, "F.TEST requires 2 arguments")
9420 array1 := argsList.Front().Value.(formulaArg)
9421 array2 := argsList.Back().Value.(formulaArg)
9422 left, right := array1.ToList(), array2.ToList()
9423 collectMatrix := func(args []formulaArg) (n, accu float64) {
9425 for _, arg := range args {
9426 if num := arg.ToNumber(); num.Type == ArgNumber {
9437 nums, accu := collectMatrix(left)
9440 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
9442 f1 := accu / (nums - 1)
9444 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
9446 nums, accu = collectMatrix(right)
9449 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
9451 f2 := accu / (nums - 1)
9453 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
9456 args.PushBack(newNumberFormulaArg(f1 / f2))
9457 args.PushBack(newNumberFormulaArg(f3))
9458 args.PushBack(newNumberFormulaArg(f4))
9459 probability := (1 - fn.FDIST(args).Number) * 2
9460 if probability > 1 {
9461 probability = 2 - probability
9463 return newNumberFormulaArg(probability)
9466 // FTEST function returns the F-Test for two supplied arrays. I.e. the function
9467 // returns the two-tailed probability that the variances in the two supplied
9468 // arrays are not significantly different. The syntax of the Ftest function
9471 // FTEST(array1,array2)
9472 func (fn *formulaFuncs) FTEST(argsList *list.List) formulaArg {
9473 if argsList.Len() != 2 {
9474 return newErrorFormulaArg(formulaErrorVALUE, "FTEST requires 2 arguments")
9476 return fn.FdotTEST(argsList)
9479 // LOGINV function calculates the inverse of the Cumulative Log-Normal
9480 // Distribution Function of x, for a supplied probability. The syntax of the
9483 // LOGINV(probability,mean,standard_dev)
9484 func (fn *formulaFuncs) LOGINV(argsList *list.List) formulaArg {
9485 if argsList.Len() != 3 {
9486 return newErrorFormulaArg(formulaErrorVALUE, "LOGINV requires 3 arguments")
9488 var probability, mean, stdDev formulaArg
9489 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
9492 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
9495 if stdDev = argsList.Back().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
9498 if probability.Number <= 0 || probability.Number >= 1 {
9499 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9501 if stdDev.Number <= 0 {
9502 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9505 args.PushBack(probability)
9506 args.PushBack(newNumberFormulaArg(0))
9507 args.PushBack(newNumberFormulaArg(1))
9508 norminv := fn.NORMINV(args)
9509 return newNumberFormulaArg(math.Exp(mean.Number + stdDev.Number*norminv.Number))
9512 // LOGNORMdotINV function calculates the inverse of the Cumulative Log-Normal
9513 // Distribution Function of x, for a supplied probability. The syntax of the
9516 // LOGNORM.INV(probability,mean,standard_dev)
9517 func (fn *formulaFuncs) LOGNORMdotINV(argsList *list.List) formulaArg {
9518 if argsList.Len() != 3 {
9519 return newErrorFormulaArg(formulaErrorVALUE, "LOGNORM.INV requires 3 arguments")
9521 return fn.LOGINV(argsList)
9524 // LOGNORMdotDIST function calculates the Log-Normal Probability Density
9525 // Function or the Cumulative Log-Normal Distribution Function for a supplied
9526 // value of x. The syntax of the function is:
9528 // LOGNORM.DIST(x,mean,standard_dev,cumulative)
9529 func (fn *formulaFuncs) LOGNORMdotDIST(argsList *list.List) formulaArg {
9530 if argsList.Len() != 4 {
9531 return newErrorFormulaArg(formulaErrorVALUE, "LOGNORM.DIST requires 4 arguments")
9533 var x, mean, stdDev, cumulative formulaArg
9534 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9537 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
9540 if stdDev = argsList.Back().Prev().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
9543 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
9546 if x.Number <= 0 || stdDev.Number <= 0 {
9547 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9549 if cumulative.Number == 1 {
9551 args.PushBack(newNumberFormulaArg((math.Log(x.Number) - mean.Number) / stdDev.Number))
9552 args.PushBack(newNumberFormulaArg(0))
9553 args.PushBack(newNumberFormulaArg(1))
9554 args.PushBack(cumulative)
9555 return fn.NORMDIST(args)
9557 return newNumberFormulaArg((1 / (math.Sqrt(2*math.Pi) * stdDev.Number * x.Number)) *
9558 math.Exp(0-(math.Pow(math.Log(x.Number)-mean.Number, 2)/(2*math.Pow(stdDev.Number, 2)))))
9561 // LOGNORMDIST function calculates the Cumulative Log-Normal Distribution
9562 // Function at a supplied value of x. The syntax of the function is:
9564 // LOGNORMDIST(x,mean,standard_dev)
9565 func (fn *formulaFuncs) LOGNORMDIST(argsList *list.List) formulaArg {
9566 if argsList.Len() != 3 {
9567 return newErrorFormulaArg(formulaErrorVALUE, "LOGNORMDIST requires 3 arguments")
9569 var x, mean, stdDev formulaArg
9570 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9573 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
9576 if stdDev = argsList.Back().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
9579 if x.Number <= 0 || stdDev.Number <= 0 {
9580 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9583 args.PushBack(newNumberFormulaArg((math.Log(x.Number) - mean.Number) / stdDev.Number))
9584 return fn.NORMSDIST(args)
9587 // MODE function returns the statistical mode (the most frequently occurring
9588 // value) of a list of supplied numbers. If there are 2 or more most
9589 // frequently occurring values in the supplied data, the function returns the
9590 // lowest of these values The syntax of the function is:
9592 // MODE(number1,[number2],...)
9593 func (fn *formulaFuncs) MODE(argsList *list.List) formulaArg {
9594 if argsList.Len() < 1 {
9595 return newErrorFormulaArg(formulaErrorVALUE, "MODE requires at least 1 argument")
9597 var values []float64
9598 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
9599 cells := arg.Value.(formulaArg)
9600 if cells.Type != ArgMatrix && cells.Type != ArgNumber {
9601 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
9603 for _, cell := range cells.ToList() {
9604 if cell.Type == ArgNumber {
9605 values = append(values, cell.Number)
9609 sort.Float64s(values)
9611 var count, modeCnt int
9613 for i := 0; i < cnt; i++ {
9615 for j := 0; j < cnt; j++ {
9616 if j != i && values[j] == values[i] {
9620 if count > modeCnt {
9626 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9628 return newNumberFormulaArg(mode)
9631 // MODEdotMULT function returns a vertical array of the statistical modes
9632 // (the most frequently occurring values) within a list of supplied numbers.
9633 // The syntax of the function is:
9635 // MODE.MULT(number1,[number2],...)
9636 func (fn *formulaFuncs) MODEdotMULT(argsList *list.List) formulaArg {
9637 if argsList.Len() < 1 {
9638 return newErrorFormulaArg(formulaErrorVALUE, "MODE.MULT requires at least 1 argument")
9640 var values []float64
9641 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
9642 cells := arg.Value.(formulaArg)
9643 if cells.Type != ArgMatrix && cells.Type != ArgNumber {
9644 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
9646 for _, cell := range cells.ToList() {
9647 if cell.Type == ArgNumber {
9648 values = append(values, cell.Number)
9652 sort.Float64s(values)
9654 var count, modeCnt int
9655 var mtx [][]formulaArg
9656 for i := 0; i < cnt; i++ {
9658 for j := i + 1; j < cnt; j++ {
9659 if values[i] == values[j] {
9663 if count > modeCnt {
9665 mtx = [][]formulaArg{}
9666 mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
9667 } else if count == modeCnt {
9668 mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
9672 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9674 return newMatrixFormulaArg(mtx)
9677 // MODEdotSNGL function returns the statistical mode (the most frequently
9678 // occurring value) within a list of supplied numbers. If there are 2 or more
9679 // most frequently occurring values in the supplied data, the function returns
9680 // the lowest of these values. The syntax of the function is:
9682 // MODE.SNGL(number1,[number2],...)
9683 func (fn *formulaFuncs) MODEdotSNGL(argsList *list.List) formulaArg {
9684 if argsList.Len() < 1 {
9685 return newErrorFormulaArg(formulaErrorVALUE, "MODE.SNGL requires at least 1 argument")
9687 return fn.MODE(argsList)
9690 // NEGBINOMdotDIST function calculates the probability mass function or the
9691 // cumulative distribution function for the Negative Binomial Distribution.
9692 // This gives the probability that there will be a given number of failures
9693 // before a required number of successes is achieved. The syntax of the
9696 // NEGBINOM.DIST(number_f,number_s,probability_s,cumulative)
9697 func (fn *formulaFuncs) NEGBINOMdotDIST(argsList *list.List) formulaArg {
9698 if argsList.Len() != 4 {
9699 return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOM.DIST requires 4 arguments")
9701 var f, s, probability, cumulative formulaArg
9702 if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
9705 if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
9708 if probability = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
9711 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
9714 if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
9715 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9717 if cumulative.Number == 1 {
9718 return newNumberFormulaArg(1 - getBetaDist(1-probability.Number, f.Number+1, s.Number))
9720 return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
9723 // NEGBINOMDIST function calculates the Negative Binomial Distribution for a
9724 // given set of parameters. This gives the probability that there will be a
9725 // specified number of failures before a required number of successes is
9726 // achieved. The syntax of the function is:
9728 // NEGBINOMDIST(number_f,number_s,probability_s)
9729 func (fn *formulaFuncs) NEGBINOMDIST(argsList *list.List) formulaArg {
9730 if argsList.Len() != 3 {
9731 return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOMDIST requires 3 arguments")
9733 var f, s, probability formulaArg
9734 if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
9737 if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
9740 if probability = argsList.Back().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
9743 if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
9744 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
9746 return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
9749 // NORMdotDIST function calculates the Normal Probability Density Function or
9750 // the Cumulative Normal Distribution. Function for a supplied set of
9751 // parameters. The syntax of the function is:
9753 // NORM.DIST(x,mean,standard_dev,cumulative)
9754 func (fn *formulaFuncs) NORMdotDIST(argsList *list.List) formulaArg {
9755 if argsList.Len() != 4 {
9756 return newErrorFormulaArg(formulaErrorVALUE, "NORM.DIST requires 4 arguments")
9758 return fn.NORMDIST(argsList)
9761 // NORMDIST function calculates the Normal Probability Density Function or the
9762 // Cumulative Normal Distribution. Function for a supplied set of parameters.
9763 // The syntax of the function is:
9765 // NORMDIST(x,mean,standard_dev,cumulative)
9766 func (fn *formulaFuncs) NORMDIST(argsList *list.List) formulaArg {
9767 if argsList.Len() != 4 {
9768 return newErrorFormulaArg(formulaErrorVALUE, "NORMDIST requires 4 arguments")
9770 var x, mean, stdDev, cumulative formulaArg
9771 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
9774 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
9777 if stdDev = argsList.Back().Prev().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
9780 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type == ArgError {
9783 if stdDev.Number < 0 {
9784 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9786 if cumulative.Number == 1 {
9787 return newNumberFormulaArg(0.5 * (1 + math.Erf((x.Number-mean.Number)/(stdDev.Number*math.Sqrt(2)))))
9789 return newNumberFormulaArg((1 / (math.Sqrt(2*math.Pi) * stdDev.Number)) * math.Exp(0-(math.Pow(x.Number-mean.Number, 2)/(2*(stdDev.Number*stdDev.Number)))))
9792 // NORMdotINV function calculates the inverse of the Cumulative Normal
9793 // Distribution Function for a supplied value of x, and a supplied
9794 // distribution mean & standard deviation. The syntax of the function is:
9796 // NORM.INV(probability,mean,standard_dev)
9797 func (fn *formulaFuncs) NORMdotINV(argsList *list.List) formulaArg {
9798 if argsList.Len() != 3 {
9799 return newErrorFormulaArg(formulaErrorVALUE, "NORM.INV requires 3 arguments")
9801 return fn.NORMINV(argsList)
9804 // NORMINV function calculates the inverse of the Cumulative Normal
9805 // Distribution Function for a supplied value of x, and a supplied
9806 // distribution mean & standard deviation. The syntax of the function is:
9808 // NORMINV(probability,mean,standard_dev)
9809 func (fn *formulaFuncs) NORMINV(argsList *list.List) formulaArg {
9810 if argsList.Len() != 3 {
9811 return newErrorFormulaArg(formulaErrorVALUE, "NORMINV requires 3 arguments")
9813 var prob, mean, stdDev formulaArg
9814 if prob = argsList.Front().Value.(formulaArg).ToNumber(); prob.Type != ArgNumber {
9817 if mean = argsList.Front().Next().Value.(formulaArg).ToNumber(); mean.Type != ArgNumber {
9820 if stdDev = argsList.Back().Value.(formulaArg).ToNumber(); stdDev.Type != ArgNumber {
9823 if prob.Number < 0 || prob.Number > 1 {
9824 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9826 if stdDev.Number < 0 {
9827 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
9829 inv, err := norminv(prob.Number)
9831 return newErrorFormulaArg(err.Error(), err.Error())
9833 return newNumberFormulaArg(inv*stdDev.Number + mean.Number)
9836 // NORMdotSdotDIST function calculates the Standard Normal Cumulative
9837 // Distribution Function for a supplied value. The syntax of the function
9841 func (fn *formulaFuncs) NORMdotSdotDIST(argsList *list.List) formulaArg {
9842 if argsList.Len() != 2 {
9843 return newErrorFormulaArg(formulaErrorVALUE, "NORM.S.DIST requires 2 numeric arguments")
9845 args := list.New().Init()
9846 args.PushBack(argsList.Front().Value.(formulaArg))
9847 args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
9848 args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
9849 args.PushBack(argsList.Back().Value.(formulaArg))
9850 return fn.NORMDIST(args)
9853 // NORMSDIST function calculates the Standard Normal Cumulative Distribution
9854 // Function for a supplied value. The syntax of the function is:
9857 func (fn *formulaFuncs) NORMSDIST(argsList *list.List) formulaArg {
9858 if argsList.Len() != 1 {
9859 return newErrorFormulaArg(formulaErrorVALUE, "NORMSDIST requires 1 numeric argument")
9861 args := list.New().Init()
9862 args.PushBack(argsList.Front().Value.(formulaArg))
9863 args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
9864 args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
9865 args.PushBack(formulaArg{Type: ArgNumber, Number: 1, Boolean: true})
9866 return fn.NORMDIST(args)
9869 // NORMSINV function calculates the inverse of the Standard Normal Cumulative
9870 // Distribution Function for a supplied probability value. The syntax of the
9873 // NORMSINV(probability)
9874 func (fn *formulaFuncs) NORMSINV(argsList *list.List) formulaArg {
9875 if argsList.Len() != 1 {
9876 return newErrorFormulaArg(formulaErrorVALUE, "NORMSINV requires 1 numeric argument")
9878 args := list.New().Init()
9879 args.PushBack(argsList.Front().Value.(formulaArg))
9880 args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
9881 args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
9882 return fn.NORMINV(args)
9885 // NORMdotSdotINV function calculates the inverse of the Standard Normal
9886 // Cumulative Distribution Function for a supplied probability value. The
9887 // syntax of the function is:
9889 // NORM.S.INV(probability)
9890 func (fn *formulaFuncs) NORMdotSdotINV(argsList *list.List) formulaArg {
9891 if argsList.Len() != 1 {
9892 return newErrorFormulaArg(formulaErrorVALUE, "NORM.S.INV requires 1 numeric argument")
9894 args := list.New().Init()
9895 args.PushBack(argsList.Front().Value.(formulaArg))
9896 args.PushBack(formulaArg{Type: ArgNumber, Number: 0})
9897 args.PushBack(formulaArg{Type: ArgNumber, Number: 1})
9898 return fn.NORMINV(args)
9901 // norminv returns the inverse of the normal cumulative distribution for the
9903 func norminv(p float64) (float64, error) {
9904 a := map[int]float64{
9905 1: -3.969683028665376e+01, 2: 2.209460984245205e+02, 3: -2.759285104469687e+02,
9906 4: 1.383577518672690e+02, 5: -3.066479806614716e+01, 6: 2.506628277459239e+00,
9908 b := map[int]float64{
9909 1: -5.447609879822406e+01, 2: 1.615858368580409e+02, 3: -1.556989798598866e+02,
9910 4: 6.680131188771972e+01, 5: -1.328068155288572e+01,
9912 c := map[int]float64{
9913 1: -7.784894002430293e-03, 2: -3.223964580411365e-01, 3: -2.400758277161838e+00,
9914 4: -2.549732539343734e+00, 5: 4.374664141464968e+00, 6: 2.938163982698783e+00,
9916 d := map[int]float64{
9917 1: 7.784695709041462e-03, 2: 3.224671290700398e-01, 3: 2.445134137142996e+00,
9918 4: 3.754408661907416e+00,
9920 pLow := 0.02425 // Use lower region approx. below this
9921 pHigh := 1 - pLow // Use upper region approx. above this
9922 if 0 < p && p < pLow {
9923 // Rational approximation for lower region.
9924 q := math.Sqrt(-2 * math.Log(p))
9925 return (((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q + c[6]) /
9926 ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q + 1), nil
9927 } else if pLow <= p && p <= pHigh {
9928 // Rational approximation for central region.
9931 f1 := ((((a[1]*r+a[2])*r+a[3])*r+a[4])*r + a[5]) * r
9932 f2 := (b[1]*r + b[2]) * r
9933 f3 := ((math.Nextafter(f2, f2)+b[3])*r + b[4]) * r
9934 f4 := (math.Nextafter(f3, f3) + b[5]) * r
9935 return (math.Nextafter(f1, f1) + a[6]) * q /
9936 (math.Nextafter(f4, f4) + 1), nil
9937 } else if pHigh < p && p < 1 {
9938 // Rational approximation for upper region.
9939 q := math.Sqrt(-2 * math.Log(1-p))
9940 return -(((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q + c[6]) /
9941 ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q + 1), nil
9943 return 0, errors.New(formulaErrorNUM)
9946 // kth is an implementation of the formula functions LARGE and SMALL.
9947 func (fn *formulaFuncs) kth(name string, argsList *list.List) formulaArg {
9948 if argsList.Len() != 2 {
9949 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 arguments", name))
9951 array := argsList.Front().Value.(formulaArg).ToList()
9952 argK := argsList.Back().Value.(formulaArg).ToNumber()
9953 if argK.Type != ArgNumber {
9956 k := int(argK.Number)
9958 return newErrorFormulaArg(formulaErrorNUM, "k should be > 0")
9961 for _, arg := range array {
9962 if arg.Type == ArgNumber {
9963 data = append(data, arg.Number)
9967 return newErrorFormulaArg(formulaErrorNUM, "k should be <= length of array")
9970 if name == "LARGE" {
9971 return newNumberFormulaArg(data[len(data)-k])
9973 return newNumberFormulaArg(data[k-1])
9976 // LARGE function returns the k'th largest value from an array of numeric
9977 // values. The syntax of the function is:
9980 func (fn *formulaFuncs) LARGE(argsList *list.List) formulaArg {
9981 return fn.kth("LARGE", argsList)
9984 // MAX function returns the largest value from a supplied set of numeric
9985 // values. The syntax of the function is:
9987 // MAX(number1,[number2],...)
9988 func (fn *formulaFuncs) MAX(argsList *list.List) formulaArg {
9989 if argsList.Len() == 0 {
9990 return newErrorFormulaArg(formulaErrorVALUE, "MAX requires at least 1 argument")
9992 return fn.max(false, argsList)
9995 // MAXA function returns the largest value from a supplied set of numeric
9996 // values, while counting text and the logical value FALSE as the value 0 and
9997 // counting the logical value TRUE as the value 1. The syntax of the function
10000 // MAXA(number1,[number2],...)
10001 func (fn *formulaFuncs) MAXA(argsList *list.List) formulaArg {
10002 if argsList.Len() == 0 {
10003 return newErrorFormulaArg(formulaErrorVALUE, "MAXA requires at least 1 argument")
10005 return fn.max(true, argsList)
10008 // MAXIFS function returns the maximum value from a subset of values that are
10009 // specified according to one or more criteria. The syntax of the function
10012 // MAXIFS(max_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
10013 func (fn *formulaFuncs) MAXIFS(argsList *list.List) formulaArg {
10014 if argsList.Len() < 3 {
10015 return newErrorFormulaArg(formulaErrorVALUE, "MAXIFS requires at least 3 arguments")
10017 if argsList.Len()%2 != 1 {
10018 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10020 var args []formulaArg
10021 max, maxRange := -math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
10022 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
10023 args = append(args, arg.Value.(formulaArg))
10025 for _, ref := range formulaIfsMatch(args) {
10026 if num := maxRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && max < num.Number {
10030 if max == -math.MaxFloat64 {
10033 return newNumberFormulaArg(max)
10036 // calcListMatrixMax is part of the implementation max.
10037 func calcListMatrixMax(maxa bool, max float64, arg formulaArg) float64 {
10038 for _, cell := range arg.ToList() {
10039 if cell.Type == ArgNumber && cell.Number > max {
10040 if maxa && cell.Boolean || !cell.Boolean {
10048 // max is an implementation of the formula functions MAX and MAXA.
10049 func (fn *formulaFuncs) max(maxa bool, argsList *list.List) formulaArg {
10050 max := -math.MaxFloat64
10051 for token := argsList.Front(); token != nil; token = token.Next() {
10052 arg := token.Value.(formulaArg)
10055 if !maxa && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
10058 num := arg.ToBool()
10059 if num.Type == ArgNumber && num.Number > max {
10064 num := arg.ToNumber()
10065 if num.Type != ArgError && num.Number > max {
10069 if arg.Number > max {
10072 case ArgList, ArgMatrix:
10073 max = calcListMatrixMax(maxa, max, arg)
10078 if max == -math.MaxFloat64 {
10081 return newNumberFormulaArg(max)
10084 // MEDIAN function returns the statistical median (the middle value) of a list
10085 // of supplied numbers. The syntax of the function is:
10087 // MEDIAN(number1,[number2],...)
10088 func (fn *formulaFuncs) MEDIAN(argsList *list.List) formulaArg {
10089 if argsList.Len() == 0 {
10090 return newErrorFormulaArg(formulaErrorVALUE, "MEDIAN requires at least 1 argument")
10092 var values []float64
10094 for token := argsList.Front(); token != nil; token = token.Next() {
10095 arg := token.Value.(formulaArg)
10098 value := arg.ToNumber()
10099 if value.Type != ArgNumber {
10102 values = append(values, value.Number)
10104 values = append(values, arg.Number)
10106 for _, row := range arg.Matrix {
10107 for _, cell := range row {
10108 if cell.Type == ArgNumber {
10109 values = append(values, cell.Number)
10115 if len(values) == 0 {
10116 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10118 sort.Float64s(values)
10119 if len(values)%2 == 0 {
10120 median = (values[len(values)/2-1] + values[len(values)/2]) / 2
10122 median = values[len(values)/2]
10124 return newNumberFormulaArg(median)
10127 // MIN function returns the smallest value from a supplied set of numeric
10128 // values. The syntax of the function is:
10130 // MIN(number1,[number2],...)
10131 func (fn *formulaFuncs) MIN(argsList *list.List) formulaArg {
10132 if argsList.Len() == 0 {
10133 return newErrorFormulaArg(formulaErrorVALUE, "MIN requires at least 1 argument")
10135 return fn.min(false, argsList)
10138 // MINA function returns the smallest value from a supplied set of numeric
10139 // values, while counting text and the logical value FALSE as the value 0 and
10140 // counting the logical value TRUE as the value 1. The syntax of the function
10143 // MINA(number1,[number2],...)
10144 func (fn *formulaFuncs) MINA(argsList *list.List) formulaArg {
10145 if argsList.Len() == 0 {
10146 return newErrorFormulaArg(formulaErrorVALUE, "MINA requires at least 1 argument")
10148 return fn.min(true, argsList)
10151 // MINIFS function returns the minimum value from a subset of values that are
10152 // specified according to one or more criteria. The syntax of the function
10155 // MINIFS(min_range,criteria_range1,criteria1,[criteria_range2,criteria2],...)
10156 func (fn *formulaFuncs) MINIFS(argsList *list.List) formulaArg {
10157 if argsList.Len() < 3 {
10158 return newErrorFormulaArg(formulaErrorVALUE, "MINIFS requires at least 3 arguments")
10160 if argsList.Len()%2 != 1 {
10161 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10163 var args []formulaArg
10164 min, minRange := math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
10165 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
10166 args = append(args, arg.Value.(formulaArg))
10168 for _, ref := range formulaIfsMatch(args) {
10169 if num := minRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && min > num.Number {
10173 if min == math.MaxFloat64 {
10176 return newNumberFormulaArg(min)
10179 // calcListMatrixMin is part of the implementation min.
10180 func calcListMatrixMin(mina bool, min float64, arg formulaArg) float64 {
10181 for _, cell := range arg.ToList() {
10182 if cell.Type == ArgNumber && cell.Number < min {
10183 if mina && cell.Boolean || !cell.Boolean {
10191 // min is an implementation of the formula functions MIN and MINA.
10192 func (fn *formulaFuncs) min(mina bool, argsList *list.List) formulaArg {
10193 min := math.MaxFloat64
10194 for token := argsList.Front(); token != nil; token = token.Next() {
10195 arg := token.Value.(formulaArg)
10198 if !mina && (arg.Value() == "TRUE" || arg.Value() == "FALSE") {
10201 num := arg.ToBool()
10202 if num.Type == ArgNumber && num.Number < min {
10207 num := arg.ToNumber()
10208 if num.Type != ArgError && num.Number < min {
10212 if arg.Number < min {
10215 case ArgList, ArgMatrix:
10216 min = calcListMatrixMin(mina, min, arg)
10221 if min == math.MaxFloat64 {
10224 return newNumberFormulaArg(min)
10227 // pearsonProduct is an implementation of the formula functions FORECAST,
10228 // FORECAST.LINEAR, INTERCEPT, PEARSON, RSQ and SLOPE.
10229 func (fn *formulaFuncs) pearsonProduct(name string, n int, argsList *list.List) formulaArg {
10230 if argsList.Len() != n {
10231 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires %d arguments", name, n))
10234 array1 := argsList.Back().Value.(formulaArg).ToList()
10235 array2 := argsList.Front().Value.(formulaArg).ToList()
10236 if name == "PEARSON" || name == "RSQ" {
10237 array1, array2 = array2, array1
10240 if fx = argsList.Front().Value.(formulaArg).ToNumber(); fx.Type != ArgNumber {
10243 array2 = argsList.Front().Next().Value.(formulaArg).ToList()
10245 if len(array1) != len(array2) {
10246 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10248 var sum, deltaX, deltaY, x, y, length float64
10249 for i := 0; i < len(array1); i++ {
10250 num1, num2 := array1[i], array2[i]
10251 if !(num1.Type == ArgNumber && num2.Type == ArgNumber) {
10260 for i := 0; i < len(array1); i++ {
10261 num1, num2 := array1[i], array2[i]
10262 if !(num1.Type == ArgNumber && num2.Type == ArgNumber) {
10265 sum += (num1.Number - x) * (num2.Number - y)
10266 deltaX += (num1.Number - x) * (num1.Number - x)
10267 deltaY += (num2.Number - y) * (num2.Number - y)
10269 if sum*deltaX*deltaY == 0 {
10270 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
10272 return newNumberFormulaArg(map[string]float64{
10273 "FORECAST": y + sum/deltaX*(fx.Number-x),
10274 "FORECAST.LINEAR": y + sum/deltaX*(fx.Number-x),
10275 "INTERCEPT": y - sum/deltaX*x,
10276 "PEARSON": sum / math.Sqrt(deltaX*deltaY),
10277 "RSQ": math.Pow(sum/math.Sqrt(deltaX*deltaY), 2),
10278 "SLOPE": sum / deltaX,
10282 // PEARSON function calculates the Pearson Product-Moment Correlation
10283 // Coefficient for two sets of values. The syntax of the function is:
10285 // PEARSON(array1,array2)
10286 func (fn *formulaFuncs) PEARSON(argsList *list.List) formulaArg {
10287 return fn.pearsonProduct("PEARSON", 2, argsList)
10290 // PERCENTILEdotEXC function returns the k'th percentile (i.e. the value below
10291 // which k% of the data values fall) for a supplied range of values and a
10292 // supplied k (between 0 & 1 exclusive).The syntax of the function is:
10294 // PERCENTILE.EXC(array,k)
10295 func (fn *formulaFuncs) PERCENTILEdotEXC(argsList *list.List) formulaArg {
10296 if argsList.Len() != 2 {
10297 return newErrorFormulaArg(formulaErrorVALUE, "PERCENTILE.EXC requires 2 arguments")
10299 array := argsList.Front().Value.(formulaArg).ToList()
10300 k := argsList.Back().Value.(formulaArg).ToNumber()
10301 if k.Type != ArgNumber {
10304 if k.Number <= 0 || k.Number >= 1 {
10305 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10307 var numbers []float64
10308 for _, arg := range array {
10309 if arg.Type == ArgError {
10310 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10312 if arg.Type == ArgNumber {
10313 numbers = append(numbers, arg.Number)
10316 cnt := len(numbers)
10317 sort.Float64s(numbers)
10318 idx := k.Number * (float64(cnt) + 1)
10319 base := math.Floor(idx)
10321 proportion := math.Nextafter(idx, idx) - base
10322 return newNumberFormulaArg(numbers[int(next)] + ((numbers[int(base)] - numbers[int(next)]) * proportion))
10325 // PERCENTILEdotINC function returns the k'th percentile (i.e. the value below
10326 // which k% of the data values fall) for a supplied range of values and a
10327 // supplied k. The syntax of the function is:
10329 // PERCENTILE.INC(array,k)
10330 func (fn *formulaFuncs) PERCENTILEdotINC(argsList *list.List) formulaArg {
10331 if argsList.Len() != 2 {
10332 return newErrorFormulaArg(formulaErrorVALUE, "PERCENTILE.INC requires 2 arguments")
10334 return fn.PERCENTILE(argsList)
10337 // PERCENTILE function returns the k'th percentile (i.e. the value below which
10338 // k% of the data values fall) for a supplied range of values and a supplied
10339 // k. The syntax of the function is:
10341 // PERCENTILE(array,k)
10342 func (fn *formulaFuncs) PERCENTILE(argsList *list.List) formulaArg {
10343 if argsList.Len() != 2 {
10344 return newErrorFormulaArg(formulaErrorVALUE, "PERCENTILE requires 2 arguments")
10346 array := argsList.Front().Value.(formulaArg).ToList()
10347 k := argsList.Back().Value.(formulaArg).ToNumber()
10348 if k.Type != ArgNumber {
10351 if k.Number < 0 || k.Number > 1 {
10352 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10354 var numbers []float64
10355 for _, arg := range array {
10356 if arg.Type == ArgError {
10359 if arg.Type == ArgNumber {
10360 numbers = append(numbers, arg.Number)
10363 cnt := len(numbers)
10364 sort.Float64s(numbers)
10365 idx := k.Number * (float64(cnt) - 1)
10366 base := math.Floor(idx)
10368 return newNumberFormulaArg(numbers[int(idx)])
10371 proportion := math.Nextafter(idx, idx) - base
10372 return newNumberFormulaArg(numbers[int(base)] + ((numbers[int(next)] - numbers[int(base)]) * proportion))
10375 // percentrank is an implementation of the formula functions PERCENTRANK and
10376 // PERCENTRANK.INC.
10377 func (fn *formulaFuncs) percentrank(name string, argsList *list.List) formulaArg {
10378 if argsList.Len() != 2 && argsList.Len() != 3 {
10379 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 or 3 arguments", name))
10381 array := argsList.Front().Value.(formulaArg).ToList()
10382 x := argsList.Front().Next().Value.(formulaArg).ToNumber()
10383 if x.Type != ArgNumber {
10386 var numbers []float64
10387 for _, arg := range array {
10388 if arg.Type == ArgError {
10389 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10391 if arg.Type == ArgNumber {
10392 numbers = append(numbers, arg.Number)
10395 cnt := len(numbers)
10396 sort.Float64s(numbers)
10397 if x.Number < numbers[0] || x.Number > numbers[cnt-1] {
10398 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10400 pos, significance := float64(inFloat64Slice(numbers, x.Number)), newNumberFormulaArg(3)
10401 if argsList.Len() == 3 {
10402 if significance = argsList.Back().Value.(formulaArg).ToNumber(); significance.Type != ArgNumber {
10403 return significance
10405 if significance.Number < 1 {
10406 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s arguments significance should be > 1", name))
10412 for cmp < x.Number {
10414 cmp = numbers[int(pos)]
10417 pos += (x.Number - numbers[int(pos)]) / (cmp - numbers[int(pos)])
10419 pow := math.Pow(10, significance.Number)
10420 digit := pow * pos / (float64(cnt) - 1)
10421 if name == "PERCENTRANK.EXC" {
10422 digit = pow * (pos + 1) / (float64(cnt) + 1)
10424 return newNumberFormulaArg(math.Floor(digit) / pow)
10427 // PERCENTRANKdotEXC function calculates the relative position, between 0 and
10428 // 1 (exclusive), of a specified value within a supplied array. The syntax of
10429 // the function is:
10431 // PERCENTRANK.EXC(array,x,[significance])
10432 func (fn *formulaFuncs) PERCENTRANKdotEXC(argsList *list.List) formulaArg {
10433 return fn.percentrank("PERCENTRANK.EXC", argsList)
10436 // PERCENTRANKdotINC function calculates the relative position, between 0 and
10437 // 1 (inclusive), of a specified value within a supplied array.The syntax of
10438 // the function is:
10440 // PERCENTRANK.INC(array,x,[significance])
10441 func (fn *formulaFuncs) PERCENTRANKdotINC(argsList *list.List) formulaArg {
10442 return fn.percentrank("PERCENTRANK.INC", argsList)
10445 // PERCENTRANK function calculates the relative position of a specified value,
10446 // within a set of values, as a percentage. The syntax of the function is:
10448 // PERCENTRANK(array,x,[significance])
10449 func (fn *formulaFuncs) PERCENTRANK(argsList *list.List) formulaArg {
10450 return fn.percentrank("PERCENTRANK", argsList)
10453 // PERMUT function calculates the number of permutations of a specified number
10454 // of objects from a set of objects. The syntax of the function is:
10456 // PERMUT(number,number_chosen)
10457 func (fn *formulaFuncs) PERMUT(argsList *list.List) formulaArg {
10458 if argsList.Len() != 2 {
10459 return newErrorFormulaArg(formulaErrorVALUE, "PERMUT requires 2 numeric arguments")
10461 number := argsList.Front().Value.(formulaArg).ToNumber()
10462 chosen := argsList.Back().Value.(formulaArg).ToNumber()
10463 if number.Type != ArgNumber {
10466 if chosen.Type != ArgNumber {
10469 if number.Number < chosen.Number {
10470 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10472 return newNumberFormulaArg(math.Round(fact(number.Number) / fact(number.Number-chosen.Number)))
10475 // PERMUTATIONA function calculates the number of permutations, with
10476 // repetitions, of a specified number of objects from a set. The syntax of
10477 // the function is:
10479 // PERMUTATIONA(number,number_chosen)
10480 func (fn *formulaFuncs) PERMUTATIONA(argsList *list.List) formulaArg {
10481 if argsList.Len() < 1 {
10482 return newErrorFormulaArg(formulaErrorVALUE, "PERMUTATIONA requires 2 numeric arguments")
10484 number := argsList.Front().Value.(formulaArg).ToNumber()
10485 chosen := argsList.Back().Value.(formulaArg).ToNumber()
10486 if number.Type != ArgNumber {
10489 if chosen.Type != ArgNumber {
10492 num, numChosen := math.Floor(number.Number), math.Floor(chosen.Number)
10493 if num < 0 || numChosen < 0 {
10494 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10496 return newNumberFormulaArg(math.Pow(num, numChosen))
10499 // PHI function returns the value of the density function for a standard normal
10500 // distribution for a supplied number. The syntax of the function is:
10503 func (fn *formulaFuncs) PHI(argsList *list.List) formulaArg {
10504 if argsList.Len() != 1 {
10505 return newErrorFormulaArg(formulaErrorVALUE, "PHI requires 1 argument")
10507 x := argsList.Front().Value.(formulaArg).ToNumber()
10508 if x.Type != ArgNumber {
10511 return newNumberFormulaArg(0.39894228040143268 * math.Exp(-(x.Number*x.Number)/2))
10514 // QUARTILE function returns a requested quartile of a supplied range of
10515 // values. The syntax of the function is:
10517 // QUARTILE(array,quart)
10518 func (fn *formulaFuncs) QUARTILE(argsList *list.List) formulaArg {
10519 if argsList.Len() != 2 {
10520 return newErrorFormulaArg(formulaErrorVALUE, "QUARTILE requires 2 arguments")
10522 quart := argsList.Back().Value.(formulaArg).ToNumber()
10523 if quart.Type != ArgNumber {
10526 if quart.Number < 0 || quart.Number > 4 {
10527 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10529 args := list.New().Init()
10530 args.PushBack(argsList.Front().Value.(formulaArg))
10531 args.PushBack(newNumberFormulaArg(quart.Number / 4))
10532 return fn.PERCENTILE(args)
10535 // QUARTILEdotEXC function returns a requested quartile of a supplied range of
10536 // values, based on a percentile range of 0 to 1 exclusive. The syntax of the
10539 // QUARTILE.EXC(array,quart)
10540 func (fn *formulaFuncs) QUARTILEdotEXC(argsList *list.List) formulaArg {
10541 if argsList.Len() != 2 {
10542 return newErrorFormulaArg(formulaErrorVALUE, "QUARTILE.EXC requires 2 arguments")
10544 quart := argsList.Back().Value.(formulaArg).ToNumber()
10545 if quart.Type != ArgNumber {
10548 if quart.Number <= 0 || quart.Number >= 4 {
10549 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10551 args := list.New().Init()
10552 args.PushBack(argsList.Front().Value.(formulaArg))
10553 args.PushBack(newNumberFormulaArg(quart.Number / 4))
10554 return fn.PERCENTILEdotEXC(args)
10557 // QUARTILEdotINC function returns a requested quartile of a supplied range of
10558 // values. The syntax of the function is:
10560 // QUARTILE.INC(array,quart)
10561 func (fn *formulaFuncs) QUARTILEdotINC(argsList *list.List) formulaArg {
10562 if argsList.Len() != 2 {
10563 return newErrorFormulaArg(formulaErrorVALUE, "QUARTILE.INC requires 2 arguments")
10565 return fn.QUARTILE(argsList)
10568 // rank is an implementation of the formula functions RANK and RANK.EQ.
10569 func (fn *formulaFuncs) rank(name string, argsList *list.List) formulaArg {
10570 if argsList.Len() < 2 {
10571 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 2 arguments", name))
10573 if argsList.Len() > 3 {
10574 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at most 3 arguments", name))
10576 num := argsList.Front().Value.(formulaArg).ToNumber()
10577 if num.Type != ArgNumber {
10581 for _, arg := range argsList.Front().Next().Value.(formulaArg).ToList() {
10582 if arg.Type == ArgNumber {
10583 arr = append(arr, arg.Number)
10587 order := newNumberFormulaArg(0)
10588 if argsList.Len() == 3 {
10589 if order = argsList.Back().Value.(formulaArg).ToNumber(); order.Type != ArgNumber {
10593 if order.Number == 0 {
10594 sort.Sort(sort.Reverse(sort.Float64Slice(arr)))
10596 if idx := inFloat64Slice(arr, num.Number); idx != -1 {
10597 return newNumberFormulaArg(float64(idx + 1))
10599 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10602 // RANKdotEQ function returns the statistical rank of a given value, within a
10603 // supplied array of values. If there are duplicate values in the list, these
10604 // are given the same rank. The syntax of the function is:
10606 // RANK.EQ(number,ref,[order])
10607 func (fn *formulaFuncs) RANKdotEQ(argsList *list.List) formulaArg {
10608 return fn.rank("RANK.EQ", argsList)
10611 // RANK function returns the statistical rank of a given value, within a
10612 // supplied array of values. If there are duplicate values in the list, these
10613 // are given the same rank. The syntax of the function is:
10615 // RANK(number,ref,[order])
10616 func (fn *formulaFuncs) RANK(argsList *list.List) formulaArg {
10617 return fn.rank("RANK", argsList)
10620 // RSQ function calculates the square of the Pearson Product-Moment Correlation
10621 // Coefficient for two supplied sets of values. The syntax of the function
10624 // RSQ(known_y's,known_x's)
10625 func (fn *formulaFuncs) RSQ(argsList *list.List) formulaArg {
10626 return fn.pearsonProduct("RSQ", 2, argsList)
10629 // skew is an implementation of the formula functions SKEW and SKEW.P.
10630 func (fn *formulaFuncs) skew(name string, argsList *list.List) formulaArg {
10631 if argsList.Len() < 1 {
10632 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
10634 mean := fn.AVERAGE(argsList)
10635 var stdDev formulaArg
10636 var count, summer float64
10637 if name == "SKEW" {
10638 stdDev = fn.STDEV(argsList)
10640 stdDev = fn.STDEVP(argsList)
10642 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
10643 token := arg.Value.(formulaArg)
10644 switch token.Type {
10645 case ArgNumber, ArgString:
10646 num := token.ToNumber()
10647 if num.Type == ArgError {
10650 summer += math.Pow((num.Number-mean.Number)/stdDev.Number, 3)
10652 case ArgList, ArgMatrix:
10653 for _, cell := range token.ToList() {
10654 if cell.Type != ArgNumber {
10657 summer += math.Pow((cell.Number-mean.Number)/stdDev.Number, 3)
10663 if name == "SKEW" {
10664 return newNumberFormulaArg(summer * (count / ((count - 1) * (count - 2))))
10666 return newNumberFormulaArg(summer / count)
10668 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
10671 // SKEW function calculates the skewness of the distribution of a supplied set
10672 // of values. The syntax of the function is:
10674 // SKEW(number1,[number2],...)
10675 func (fn *formulaFuncs) SKEW(argsList *list.List) formulaArg {
10676 return fn.skew("SKEW", argsList)
10679 // SKEWdotP function calculates the skewness of the distribution of a supplied
10680 // set of values. The syntax of the function is:
10682 // SKEW.P(number1,[number2],...)
10683 func (fn *formulaFuncs) SKEWdotP(argsList *list.List) formulaArg {
10684 return fn.skew("SKEW.P", argsList)
10687 // SLOPE returns the slope of the linear regression line through data points in
10688 // known_y's and known_x's. The slope is the vertical distance divided by the
10689 // horizontal distance between any two points on the line, which is the rate
10690 // of change along the regression line. The syntax of the function is:
10692 // SLOPE(known_y's,known_x's)
10693 func (fn *formulaFuncs) SLOPE(argsList *list.List) formulaArg {
10694 return fn.pearsonProduct("SLOPE", 2, argsList)
10697 // SMALL function returns the k'th smallest value from an array of numeric
10698 // values. The syntax of the function is:
10701 func (fn *formulaFuncs) SMALL(argsList *list.List) formulaArg {
10702 return fn.kth("SMALL", argsList)
10705 // STANDARDIZE function returns a normalized value of a distribution that is
10706 // characterized by a supplied mean and standard deviation. The syntax of the
10709 // STANDARDIZE(x,mean,standard_dev)
10710 func (fn *formulaFuncs) STANDARDIZE(argsList *list.List) formulaArg {
10711 if argsList.Len() != 3 {
10712 return newErrorFormulaArg(formulaErrorVALUE, "STANDARDIZE requires 3 arguments")
10714 x := argsList.Front().Value.(formulaArg).ToNumber()
10715 if x.Type != ArgNumber {
10718 mean := argsList.Front().Next().Value.(formulaArg).ToNumber()
10719 if mean.Type != ArgNumber {
10722 stdDev := argsList.Back().Value.(formulaArg).ToNumber()
10723 if stdDev.Type != ArgNumber {
10726 if stdDev.Number <= 0 {
10727 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10729 return newNumberFormulaArg((x.Number - mean.Number) / stdDev.Number)
10732 // stdevp is an implementation of the formula functions STDEVP, STDEV.P and
10734 func (fn *formulaFuncs) stdevp(name string, argsList *list.List) formulaArg {
10735 if argsList.Len() < 1 {
10736 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
10739 if name == "STDEVPA" {
10742 varp := fn.vars(fnName, argsList)
10743 if varp.Type != ArgNumber {
10746 return newNumberFormulaArg(math.Sqrt(varp.Number))
10749 // STDEVP function calculates the standard deviation of a supplied set of
10750 // values. The syntax of the function is:
10752 // STDEVP(number1,[number2],...)
10753 func (fn *formulaFuncs) STDEVP(argsList *list.List) formulaArg {
10754 return fn.stdevp("STDEVP", argsList)
10757 // STDEVdotP function calculates the standard deviation of a supplied set of
10760 // STDEV.P( number1, [number2], ... )
10761 func (fn *formulaFuncs) STDEVdotP(argsList *list.List) formulaArg {
10762 return fn.stdevp("STDEV.P", argsList)
10765 // STDEVPA function calculates the standard deviation of a supplied set of
10766 // values. The syntax of the function is:
10768 // STDEVPA(number1,[number2],...)
10769 func (fn *formulaFuncs) STDEVPA(argsList *list.List) formulaArg {
10770 return fn.stdevp("STDEVPA", argsList)
10773 // STEYX function calculates the standard error for the line of best fit,
10774 // through a supplied set of x- and y- values. The syntax of the function is:
10776 // STEYX(known_y's,known_x's)
10777 func (fn *formulaFuncs) STEYX(argsList *list.List) formulaArg {
10778 if argsList.Len() != 2 {
10779 return newErrorFormulaArg(formulaErrorVALUE, "STEYX requires 2 arguments")
10781 array1 := argsList.Back().Value.(formulaArg).ToList()
10782 array2 := argsList.Front().Value.(formulaArg).ToList()
10783 if len(array1) != len(array2) {
10784 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
10786 var count, sumX, sumY, squareX, squareY, sigmaXY float64
10787 for i := 0; i < len(array1); i++ {
10788 num1, num2 := array1[i], array2[i]
10789 if !(num1.Type == ArgNumber && num2.Type == ArgNumber) {
10792 sumX += num1.Number
10793 sumY += num2.Number
10794 squareX += num1.Number * num1.Number
10795 squareY += num2.Number * num2.Number
10796 sigmaXY += num1.Number * num2.Number
10800 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
10802 dx, dy := sumX/count, sumY/count
10803 sigma1 := squareY - 2*dy*sumY + count*dy*dy
10804 sigma2 := sigmaXY - dy*sumX - sumY*dx + count*dy*dx
10805 sigma3 := squareX - 2*dx*sumX + count*dx*dx
10806 return newNumberFormulaArg(math.Sqrt((sigma1 - (sigma2*sigma2)/sigma3) / (count - 2)))
10809 // getTDist is an implementation for the beta distribution probability density
10811 func getTDist(T, fDF, nType float64) float64 {
10815 res = 0.5 * getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
10817 res = getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
10819 res = math.Pow(1+(T*T/fDF), -(fDF+1)/2) / (math.Sqrt(fDF) * getBeta(0.5, fDF/2.0))
10821 X := fDF / (T*T + fDF)
10822 R := 0.5 * getBetaDist(X, 0.5*fDF, 0.5)
10831 // TdotDIST function calculates the one-tailed Student's T Distribution, which
10832 // is a continuous probability distribution that is frequently used for
10833 // testing hypotheses on small sample data sets. The syntax of the function
10836 // T.DIST(x,degrees_freedom,cumulative)
10837 func (fn *formulaFuncs) TdotDIST(argsList *list.List) formulaArg {
10838 if argsList.Len() != 3 {
10839 return newErrorFormulaArg(formulaErrorVALUE, "T.DIST requires 3 arguments")
10841 var x, degrees, cumulative formulaArg
10842 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
10845 if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10848 if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
10851 if cumulative.Number == 1 && degrees.Number < 1 {
10852 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10854 if cumulative.Number == 0 {
10855 if degrees.Number < 0 {
10856 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10858 if degrees.Number == 0 {
10859 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
10861 return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 3))
10863 return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 4))
10866 // TdotDISTdot2T function calculates the two-tailed Student's T Distribution,
10867 // which is a continuous probability distribution that is frequently used for
10868 // testing hypotheses on small sample data sets. The syntax of the function
10871 // T.DIST.2T(x,degrees_freedom)
10872 func (fn *formulaFuncs) TdotDISTdot2T(argsList *list.List) formulaArg {
10873 if argsList.Len() != 2 {
10874 return newErrorFormulaArg(formulaErrorVALUE, "T.DIST.2T requires 2 arguments")
10876 var x, degrees formulaArg
10877 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
10880 if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10883 if x.Number < 0 || degrees.Number < 1 {
10884 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10886 return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 2))
10889 // TdotDISTdotRT function calculates the right-tailed Student's T Distribution,
10890 // which is a continuous probability distribution that is frequently used for
10891 // testing hypotheses on small sample data sets. The syntax of the function
10894 // T.DIST.RT(x,degrees_freedom)
10895 func (fn *formulaFuncs) TdotDISTdotRT(argsList *list.List) formulaArg {
10896 if argsList.Len() != 2 {
10897 return newErrorFormulaArg(formulaErrorVALUE, "T.DIST.RT requires 2 arguments")
10899 var x, degrees formulaArg
10900 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
10903 if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10906 if degrees.Number < 1 {
10907 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10909 v := getTDist(x.Number, degrees.Number, 1)
10913 return newNumberFormulaArg(v)
10916 // TDIST function calculates the Student's T Distribution, which is a
10917 // continuous probability distribution that is frequently used for testing
10918 // hypotheses on small sample data sets. The syntax of the function is:
10920 // TDIST(x,degrees_freedom,tails)
10921 func (fn *formulaFuncs) TDIST(argsList *list.List) formulaArg {
10922 if argsList.Len() != 3 {
10923 return newErrorFormulaArg(formulaErrorVALUE, "TDIST requires 3 arguments")
10925 var x, degrees, tails formulaArg
10926 if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
10929 if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10932 if tails = argsList.Back().Value.(formulaArg).ToNumber(); tails.Type != ArgNumber {
10935 if x.Number < 0 || degrees.Number < 1 || (tails.Number != 1 && tails.Number != 2) {
10936 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10938 return newNumberFormulaArg(getTDist(x.Number, degrees.Number, tails.Number))
10941 // TdotINV function calculates the left-tailed inverse of the Student's T
10942 // Distribution, which is a continuous probability distribution that is
10943 // frequently used for testing hypotheses on small sample data sets. The
10944 // syntax of the function is:
10946 // T.INV(probability,degrees_freedom)
10947 func (fn *formulaFuncs) TdotINV(argsList *list.List) formulaArg {
10948 if argsList.Len() != 2 {
10949 return newErrorFormulaArg(formulaErrorVALUE, "T.INV requires 2 arguments")
10951 var probability, degrees formulaArg
10952 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
10955 if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10958 if probability.Number <= 0 || probability.Number >= 1 || degrees.Number < 1 {
10959 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10961 if probability.Number < 0.5 {
10962 return newNumberFormulaArg(-calcIterateInverse(calcInverseIterator{
10964 fp: 1 - probability.Number,
10965 fDF: degrees.Number,
10967 }, degrees.Number/2, degrees.Number))
10969 return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
10971 fp: probability.Number,
10972 fDF: degrees.Number,
10974 }, degrees.Number/2, degrees.Number))
10977 // TdotINVdot2T function calculates the inverse of the two-tailed Student's T
10978 // Distribution, which is a continuous probability distribution that is
10979 // frequently used for testing hypotheses on small sample data sets. The
10980 // syntax of the function is:
10982 // T.INV.2T(probability,degrees_freedom)
10983 func (fn *formulaFuncs) TdotINVdot2T(argsList *list.List) formulaArg {
10984 if argsList.Len() != 2 {
10985 return newErrorFormulaArg(formulaErrorVALUE, "T.INV.2T requires 2 arguments")
10987 var probability, degrees formulaArg
10988 if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
10991 if degrees = argsList.Back().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
10994 if probability.Number <= 0 || probability.Number > 1 || degrees.Number < 1 {
10995 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
10997 return newNumberFormulaArg(calcIterateInverse(calcInverseIterator{
10999 fp: probability.Number,
11000 fDF: degrees.Number,
11002 }, degrees.Number/2, degrees.Number))
11005 // TINV function calculates the inverse of the two-tailed Student's T
11006 // Distribution, which is a continuous probability distribution that is
11007 // frequently used for testing hypotheses on small sample data sets. The
11008 // syntax of the function is:
11010 // TINV(probability,degrees_freedom)
11011 func (fn *formulaFuncs) TINV(argsList *list.List) formulaArg {
11012 if argsList.Len() != 2 {
11013 return newErrorFormulaArg(formulaErrorVALUE, "TINV requires 2 arguments")
11015 return fn.TdotINVdot2T(argsList)
11018 // TREND function calculates the linear trend line through a given set of
11019 // y-values and (optionally), a given set of x-values. The function then
11020 // extends the linear trendline to calculate additional y-values for a further
11021 // supplied set of new x-values. The syntax of the function is:
11023 // TREND(known_y's,[known_x's],[new_x's],[const])
11024 func (fn *formulaFuncs) TREND(argsList *list.List) formulaArg {
11025 return fn.trendGrowth("TREND", argsList)
11028 // tTest calculates the probability associated with the Student's T Test.
11029 func tTest(bTemplin bool, mtx1, mtx2 [][]formulaArg, c1, c2, r1, r2 int) (float64, float64, bool) {
11030 var cnt1, cnt2, sum1, sumSqr1, sum2, sumSqr2 float64
11031 var fVal formulaArg
11032 for i := 0; i < c1; i++ {
11033 for j := 0; j < r1; j++ {
11034 if fVal = mtx1[i][j]; fVal.Type == ArgNumber {
11035 sum1 += fVal.Number
11036 sumSqr1 += fVal.Number * fVal.Number
11041 for i := 0; i < c2; i++ {
11042 for j := 0; j < r2; j++ {
11043 if fVal = mtx2[i][j]; fVal.Type == ArgNumber {
11044 sum2 += fVal.Number
11045 sumSqr2 += fVal.Number * fVal.Number
11050 if cnt1 < 2.0 || cnt2 < 2.0 {
11054 fS1 := (sumSqr1 - sum1*sum1/cnt1) / (cnt1 - 1) / cnt1
11055 fS2 := (sumSqr2 - sum2*sum2/cnt2) / (cnt2 - 1) / cnt2
11059 c := fS1 / (fS1 + fS2)
11060 return math.Abs(sum1/cnt1-sum2/cnt2) / math.Sqrt(fS1+fS2), 1 / (c*c/(cnt1-1) + (1-c)*(1-c)/(cnt2-1)), true
11062 fS1 := (sumSqr1 - sum1*sum1/cnt1) / (cnt1 - 1)
11063 fS2 := (sumSqr2 - sum2*sum2/cnt2) / (cnt2 - 1)
11064 return math.Abs(sum1/cnt1-sum2/cnt2) / math.Sqrt((cnt1-1)*fS1+(cnt2-1)*fS2) * math.Sqrt(cnt1*cnt2*(cnt1+cnt2-2)/(cnt1+cnt2)), cnt1 + cnt2 - 2, true
11067 // tTest is an implementation of the formula function TTEST.
11068 func (fn *formulaFuncs) tTest(mtx1, mtx2 [][]formulaArg, fTails, fTyp float64) formulaArg {
11070 c1, c2, r1, r2, ok := len(mtx1), len(mtx2), len(mtx1[0]), len(mtx2[0]), true
11072 if c1 != c2 || r1 != r2 {
11073 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11075 var cnt, sum1, sum2, sumSqrD float64
11076 var fVal1, fVal2 formulaArg
11077 for i := 0; i < c1; i++ {
11078 for j := 0; j < r1; j++ {
11079 fVal1, fVal2 = mtx1[i][j], mtx2[i][j]
11080 if fVal1.Type != ArgNumber || fVal2.Type != ArgNumber {
11083 sum1 += fVal1.Number
11084 sum2 += fVal2.Number
11085 sumSqrD += (fVal1.Number - fVal2.Number) * (fVal1.Number - fVal2.Number)
11090 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11092 sumD := sum1 - sum2
11093 divider := cnt*sumSqrD - sumD*sumD
11095 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
11097 fT = math.Abs(sumD) * math.Sqrt((cnt-1)/divider)
11099 } else if fTyp == 2 {
11100 fT, fF, ok = tTest(false, mtx1, mtx2, c1, c2, r1, r2)
11102 fT, fF, ok = tTest(true, mtx1, mtx2, c1, c2, r1, r2)
11105 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11107 return newNumberFormulaArg(getTDist(fT, fF, fTails))
11110 // TTEST function calculates the probability associated with the Student's T
11111 // Test, which is commonly used for identifying whether two data sets are
11112 // likely to have come from the same two underlying populations with the same
11113 // mean. The syntax of the function is:
11115 // TTEST(array1,array2,tails,type)
11116 func (fn *formulaFuncs) TTEST(argsList *list.List) formulaArg {
11117 if argsList.Len() != 4 {
11118 return newErrorFormulaArg(formulaErrorVALUE, "TTEST requires 4 arguments")
11120 var array1, array2, tails, typeArg formulaArg
11121 array1 = argsList.Front().Value.(formulaArg)
11122 array2 = argsList.Front().Next().Value.(formulaArg)
11123 if tails = argsList.Front().Next().Next().Value.(formulaArg); tails.Type != ArgNumber {
11124 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11126 if typeArg = argsList.Back().Value.(formulaArg); typeArg.Type != ArgNumber {
11127 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11129 if len(array1.Matrix) == 0 || len(array2.Matrix) == 0 {
11130 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11132 if tails.Number != 1 && tails.Number != 2 {
11133 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11135 if typeArg.Number != 1 && typeArg.Number != 2 && typeArg.Number != 3 {
11136 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11138 return fn.tTest(array1.Matrix, array2.Matrix, tails.Number, typeArg.Number)
11141 // TdotTEST function calculates the probability associated with the Student's T
11142 // Test, which is commonly used for identifying whether two data sets are
11143 // likely to have come from the same two underlying populations with the same
11144 // mean. The syntax of the function is:
11146 // T.TEST(array1,array2,tails,type)
11147 func (fn *formulaFuncs) TdotTEST(argsList *list.List) formulaArg {
11148 if argsList.Len() != 4 {
11149 return newErrorFormulaArg(formulaErrorVALUE, "T.TEST requires 4 arguments")
11151 return fn.TTEST(argsList)
11154 // TRIMMEAN function calculates the trimmed mean (or truncated mean) of a
11155 // supplied set of values. The syntax of the function is:
11157 // TRIMMEAN(array,percent)
11158 func (fn *formulaFuncs) TRIMMEAN(argsList *list.List) formulaArg {
11159 if argsList.Len() != 2 {
11160 return newErrorFormulaArg(formulaErrorVALUE, "TRIMMEAN requires 2 arguments")
11162 percent := argsList.Back().Value.(formulaArg).ToNumber()
11163 if percent.Type != ArgNumber {
11166 if percent.Number < 0 || percent.Number >= 1 {
11167 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
11170 arrArg := argsList.Front().Value.(formulaArg).ToList()
11171 for _, cell := range arrArg {
11172 if cell.Type != ArgNumber {
11175 arr = append(arr, cell.Number)
11177 discard := math.Floor(float64(len(arr)) * percent.Number / 2)
11179 for i := 0; i < int(discard); i++ {
11184 arr = arr[:len(arr)-1]
11188 args := list.New().Init()
11189 for _, ele := range arr {
11190 args.PushBack(newNumberFormulaArg(ele))
11192 return fn.AVERAGE(args)
11195 // vars is an implementation of the formula functions VAR, VARA, VARP, VAR.P
11196 // VAR.S and VARPA.
11197 func (fn *formulaFuncs) vars(name string, argsList *list.List) formulaArg {
11198 if argsList.Len() < 1 {
11199 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
11201 summerA, summerB, count := 0.0, 0.0, 0.0
11203 if name == "VAR" || name == "VAR.S" || name == "VARA" {
11206 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
11207 for _, token := range arg.Value.(formulaArg).ToList() {
11208 if token.Value() == "" {
11211 num := token.ToNumber()
11212 if token.Value() != "TRUE" && num.Type == ArgNumber {
11213 summerA += num.Number * num.Number
11214 summerB += num.Number
11218 num = token.ToBool()
11219 if num.Type == ArgNumber {
11220 summerA += num.Number * num.Number
11221 summerB += num.Number
11225 if name == "VARA" || name == "VARPA" {
11230 if count > minimum {
11233 return newNumberFormulaArg((summerA - summerB) / (count * (count - minimum)))
11235 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
11238 // VAR function returns the sample variance of a supplied set of values. The
11239 // syntax of the function is:
11241 // VAR(number1,[number2],...)
11242 func (fn *formulaFuncs) VAR(argsList *list.List) formulaArg {
11243 return fn.vars("VAR", argsList)
11246 // VARA function calculates the sample variance of a supplied set of values.
11247 // The syntax of the function is:
11249 // VARA(number1,[number2],...)
11250 func (fn *formulaFuncs) VARA(argsList *list.List) formulaArg {
11251 return fn.vars("VARA", argsList)
11254 // VARP function returns the Variance of a given set of values. The syntax of
11255 // the function is:
11257 // VARP(number1,[number2],...)
11258 func (fn *formulaFuncs) VARP(argsList *list.List) formulaArg {
11259 return fn.vars("VARP", argsList)
11262 // VARdotP function returns the Variance of a given set of values. The syntax
11263 // of the function is:
11265 // VAR.P(number1,[number2],...)
11266 func (fn *formulaFuncs) VARdotP(argsList *list.List) formulaArg {
11267 return fn.vars("VAR.P", argsList)
11270 // VARdotS function calculates the sample variance of a supplied set of
11271 // values. The syntax of the function is:
11273 // VAR.S(number1,[number2],...)
11274 func (fn *formulaFuncs) VARdotS(argsList *list.List) formulaArg {
11275 return fn.vars("VAR.S", argsList)
11278 // VARPA function returns the Variance of a given set of values. The syntax of
11279 // the function is:
11281 // VARPA(number1,[number2],...)
11282 func (fn *formulaFuncs) VARPA(argsList *list.List) formulaArg {
11283 return fn.vars("VARPA", argsList)
11286 // WEIBULL function calculates the Weibull Probability Density Function or the
11287 // Weibull Cumulative Distribution Function for a supplied set of parameters.
11288 // The syntax of the function is:
11290 // WEIBULL(x,alpha,beta,cumulative)
11291 func (fn *formulaFuncs) WEIBULL(argsList *list.List) formulaArg {
11292 if argsList.Len() != 4 {
11293 return newErrorFormulaArg(formulaErrorVALUE, "WEIBULL requires 4 arguments")
11295 x := argsList.Front().Value.(formulaArg).ToNumber()
11296 alpha := argsList.Front().Next().Value.(formulaArg).ToNumber()
11297 beta := argsList.Back().Prev().Value.(formulaArg).ToNumber()
11298 if alpha.Type == ArgNumber && beta.Type == ArgNumber && x.Type == ArgNumber {
11299 if alpha.Number < 0 || alpha.Number <= 0 || beta.Number <= 0 {
11300 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11302 cumulative := argsList.Back().Value.(formulaArg).ToBool()
11303 if cumulative.Boolean && cumulative.Number == 1 {
11304 return newNumberFormulaArg(1 - math.Exp(0-math.Pow(x.Number/beta.Number, alpha.Number)))
11306 return newNumberFormulaArg((alpha.Number / math.Pow(beta.Number, alpha.Number)) *
11307 math.Pow(x.Number, alpha.Number-1) * math.Exp(0-math.Pow(x.Number/beta.Number, alpha.Number)))
11309 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11312 // WEIBULLdotDIST function calculates the Weibull Probability Density Function
11313 // or the Weibull Cumulative Distribution Function for a supplied set of
11314 // parameters. The syntax of the function is:
11316 // WEIBULL.DIST(x,alpha,beta,cumulative)
11317 func (fn *formulaFuncs) WEIBULLdotDIST(argsList *list.List) formulaArg {
11318 if argsList.Len() != 4 {
11319 return newErrorFormulaArg(formulaErrorVALUE, "WEIBULL.DIST requires 4 arguments")
11321 return fn.WEIBULL(argsList)
11324 // ZdotTEST function calculates the one-tailed probability value of the
11325 // Z-Test. The syntax of the function is:
11327 // Z.TEST(array,x,[sigma])
11328 func (fn *formulaFuncs) ZdotTEST(argsList *list.List) formulaArg {
11329 argsLen := argsList.Len()
11331 return newErrorFormulaArg(formulaErrorVALUE, "Z.TEST requires at least 2 arguments")
11334 return newErrorFormulaArg(formulaErrorVALUE, "Z.TEST accepts at most 3 arguments")
11336 return fn.ZTEST(argsList)
11339 // ZTEST function calculates the one-tailed probability value of the Z-Test.
11340 // The syntax of the function is:
11342 // ZTEST(array,x,[sigma])
11343 func (fn *formulaFuncs) ZTEST(argsList *list.List) formulaArg {
11344 argsLen := argsList.Len()
11346 return newErrorFormulaArg(formulaErrorVALUE, "ZTEST requires at least 2 arguments")
11349 return newErrorFormulaArg(formulaErrorVALUE, "ZTEST accepts at most 3 arguments")
11351 arrArg, arrArgs := argsList.Front().Value.(formulaArg), list.New()
11352 arrArgs.PushBack(arrArg)
11353 arr := fn.AVERAGE(arrArgs)
11354 if arr.Type == ArgError {
11355 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11357 x := argsList.Front().Next().Value.(formulaArg).ToNumber()
11358 if x.Type == ArgError {
11361 sigma := argsList.Back().Value.(formulaArg).ToNumber()
11362 if sigma.Type == ArgError {
11366 sigma = fn.STDEV(arrArgs).ToNumber()
11368 normsdistArg := list.New()
11369 div := sigma.Number / math.Sqrt(float64(len(arrArg.ToList())))
11371 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
11373 normsdistArg.PushBack(newNumberFormulaArg((arr.Number - x.Number) / div))
11374 return newNumberFormulaArg(1 - fn.NORMSDIST(normsdistArg).Number)
11377 // Information Functions
11379 // ERRORdotTYPE function receives an error value and returns an integer, that
11380 // tells you the type of the supplied error. The syntax of the function is:
11382 // ERROR.TYPE(error_val)
11383 func (fn *formulaFuncs) ERRORdotTYPE(argsList *list.List) formulaArg {
11384 if argsList.Len() != 1 {
11385 return newErrorFormulaArg(formulaErrorVALUE, "ERROR.TYPE requires 1 argument")
11387 token := argsList.Front().Value.(formulaArg)
11388 if token.Type == ArgError {
11389 for i, errType := range []string{
11390 formulaErrorNULL, formulaErrorDIV, formulaErrorVALUE, formulaErrorREF,
11391 formulaErrorNAME, formulaErrorNUM, formulaErrorNA,
11393 if errType == token.String {
11394 return newNumberFormulaArg(float64(i) + 1)
11398 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11401 // ISBLANK function tests if a specified cell is blank (empty) and if so,
11402 // returns TRUE; Otherwise the function returns FALSE. The syntax of the
11406 func (fn *formulaFuncs) ISBLANK(argsList *list.List) formulaArg {
11407 if argsList.Len() != 1 {
11408 return newErrorFormulaArg(formulaErrorVALUE, "ISBLANK requires 1 argument")
11410 token := argsList.Front().Value.(formulaArg)
11411 switch token.Type {
11412 case ArgUnknown, ArgEmpty:
11413 return newBoolFormulaArg(true)
11415 return newBoolFormulaArg(false)
11419 // ISERR function tests if an initial supplied expression (or value) returns
11420 // any Excel Error, except the #N/A error. If so, the function returns the
11421 // logical value TRUE; If the supplied value is not an error or is the #N/A
11422 // error, the ISERR function returns FALSE. The syntax of the function is:
11425 func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
11426 if argsList.Len() != 1 {
11427 return newErrorFormulaArg(formulaErrorVALUE, "ISERR requires 1 argument")
11429 token := argsList.Front().Value.(formulaArg)
11431 if token.Type == ArgError {
11432 for _, errType := range []string{
11433 formulaErrorDIV, formulaErrorNAME, formulaErrorNUM,
11434 formulaErrorVALUE, formulaErrorREF, formulaErrorNULL,
11435 formulaErrorSPILL, formulaErrorCALC, formulaErrorGETTINGDATA,
11437 if errType == token.String {
11442 return newBoolFormulaArg(result)
11445 // ISERROR function tests if an initial supplied expression (or value) returns
11446 // an Excel Error, and if so, returns the logical value TRUE; Otherwise the
11447 // function returns FALSE. The syntax of the function is:
11450 func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
11451 if argsList.Len() != 1 {
11452 return newErrorFormulaArg(formulaErrorVALUE, "ISERROR requires 1 argument")
11454 token := argsList.Front().Value.(formulaArg)
11456 if token.Type == ArgError {
11457 for _, errType := range []string{
11458 formulaErrorDIV, formulaErrorNAME, formulaErrorNA, formulaErrorNUM,
11459 formulaErrorVALUE, formulaErrorREF, formulaErrorNULL, formulaErrorSPILL,
11460 formulaErrorCALC, formulaErrorGETTINGDATA,
11462 if errType == token.String {
11467 return newBoolFormulaArg(result)
11470 // ISEVEN function tests if a supplied number (or numeric expression)
11471 // evaluates to an even number, and if so, returns TRUE; Otherwise, the
11472 // function returns FALSE. The syntax of the function is:
11475 func (fn *formulaFuncs) ISEVEN(argsList *list.List) formulaArg {
11476 if argsList.Len() != 1 {
11477 return newErrorFormulaArg(formulaErrorVALUE, "ISEVEN requires 1 argument")
11479 token := argsList.Front().Value.(formulaArg)
11480 switch token.Type {
11482 return newBoolFormulaArg(true)
11483 case ArgNumber, ArgString:
11484 num := token.ToNumber()
11485 if num.Type != ArgNumber {
11486 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11488 if num.Number == 1 {
11489 return newBoolFormulaArg(false)
11491 return newBoolFormulaArg(num.Number == num.Number/2*2)
11493 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11497 // ISFORMULA function tests if a specified cell contains a formula, and if so,
11498 // returns TRUE; Otherwise, the function returns FALSE. The syntax of the
11501 // ISFORMULA(reference)
11502 func (fn *formulaFuncs) ISFORMULA(argsList *list.List) formulaArg {
11503 if argsList.Len() != 1 {
11504 return newErrorFormulaArg(formulaErrorVALUE, "ISFORMULA requires 1 argument")
11506 arg := argsList.Front().Value.(formulaArg)
11507 if arg.cellRefs != nil && arg.cellRefs.Len() == 1 {
11508 ref := arg.cellRefs.Front().Value.(cellRef)
11509 cell, _ := CoordinatesToCellName(ref.Col, ref.Row)
11510 if formula, _ := fn.f.GetCellFormula(ref.Sheet, cell); len(formula) > 0 {
11511 return newBoolFormulaArg(true)
11514 return newBoolFormulaArg(false)
11517 // ISLOGICAL function tests if a supplied value (or expression) returns a
11518 // logical value (i.e. evaluates to True or False). If so, the function
11519 // returns TRUE; Otherwise, it returns FALSE. The syntax of the function is:
11521 // ISLOGICAL(value)
11522 func (fn *formulaFuncs) ISLOGICAL(argsList *list.List) formulaArg {
11523 if argsList.Len() != 1 {
11524 return newErrorFormulaArg(formulaErrorVALUE, "ISLOGICAL requires 1 argument")
11526 val := argsList.Front().Value.(formulaArg).Value()
11527 if strings.EqualFold("TRUE", val) || strings.EqualFold("FALSE", val) {
11528 return newBoolFormulaArg(true)
11530 return newBoolFormulaArg(false)
11533 // ISNA function tests if an initial supplied expression (or value) returns
11534 // the Excel #N/A Error, and if so, returns TRUE; Otherwise the function
11535 // returns FALSE. The syntax of the function is:
11538 func (fn *formulaFuncs) ISNA(argsList *list.List) formulaArg {
11539 if argsList.Len() != 1 {
11540 return newErrorFormulaArg(formulaErrorVALUE, "ISNA requires 1 argument")
11542 token := argsList.Front().Value.(formulaArg)
11544 if token.Type == ArgError && token.String == formulaErrorNA {
11547 return newStringFormulaArg(result)
11550 // ISNONTEXT function tests if a supplied value is text. If not, the
11551 // function returns TRUE; If the supplied value is text, the function returns
11552 // FALSE. The syntax of the function is:
11554 // ISNONTEXT(value)
11555 func (fn *formulaFuncs) ISNONTEXT(argsList *list.List) formulaArg {
11556 if argsList.Len() != 1 {
11557 return newErrorFormulaArg(formulaErrorVALUE, "ISNONTEXT requires 1 argument")
11559 if argsList.Front().Value.(formulaArg).Type == ArgString {
11560 return newBoolFormulaArg(false)
11562 return newBoolFormulaArg(true)
11565 // ISNUMBER function tests if a supplied value is a number. If so,
11566 // the function returns TRUE; Otherwise it returns FALSE. The syntax of the
11570 func (fn *formulaFuncs) ISNUMBER(argsList *list.List) formulaArg {
11571 if argsList.Len() != 1 {
11572 return newErrorFormulaArg(formulaErrorVALUE, "ISNUMBER requires 1 argument")
11574 if argsList.Front().Value.(formulaArg).Type == ArgNumber {
11575 return newBoolFormulaArg(true)
11577 return newBoolFormulaArg(false)
11580 // ISODD function tests if a supplied number (or numeric expression) evaluates
11581 // to an odd number, and if so, returns TRUE; Otherwise, the function returns
11582 // FALSE. The syntax of the function is:
11585 func (fn *formulaFuncs) ISODD(argsList *list.List) formulaArg {
11586 if argsList.Len() != 1 {
11587 return newErrorFormulaArg(formulaErrorVALUE, "ISODD requires 1 argument")
11589 arg := argsList.Front().Value.(formulaArg).ToNumber()
11590 if arg.Type != ArgNumber {
11591 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11593 if int(arg.Number) != int(arg.Number)/2*2 {
11594 return newBoolFormulaArg(true)
11596 return newBoolFormulaArg(false)
11599 // ISREF function tests if a supplied value is a reference. If so, the
11600 // function returns TRUE; Otherwise it returns FALSE. The syntax of the
11604 func (fn *formulaFuncs) ISREF(argsList *list.List) formulaArg {
11605 if argsList.Len() != 1 {
11606 return newErrorFormulaArg(formulaErrorVALUE, "ISREF requires 1 argument")
11608 arg := argsList.Front().Value.(formulaArg)
11609 if arg.cellRanges != nil && arg.cellRanges.Len() > 0 || arg.cellRefs != nil && arg.cellRefs.Len() > 0 {
11610 return newBoolFormulaArg(true)
11612 return newBoolFormulaArg(false)
11615 // ISTEXT function tests if a supplied value is text, and if so, returns TRUE;
11616 // Otherwise, the function returns FALSE. The syntax of the function is:
11619 func (fn *formulaFuncs) ISTEXT(argsList *list.List) formulaArg {
11620 if argsList.Len() != 1 {
11621 return newErrorFormulaArg(formulaErrorVALUE, "ISTEXT requires 1 argument")
11623 token := argsList.Front().Value.(formulaArg)
11624 if token.ToNumber().Type != ArgError {
11625 return newBoolFormulaArg(false)
11627 return newBoolFormulaArg(token.Type == ArgString)
11630 // N function converts data into a numeric value. The syntax of the function
11634 func (fn *formulaFuncs) N(argsList *list.List) formulaArg {
11635 if argsList.Len() != 1 {
11636 return newErrorFormulaArg(formulaErrorVALUE, "N requires 1 argument")
11638 token, num := argsList.Front().Value.(formulaArg), 0.0
11639 if token.Type == ArgError {
11642 if arg := token.ToNumber(); arg.Type == ArgNumber {
11645 if token.Value() == "TRUE" {
11648 return newNumberFormulaArg(num)
11651 // NA function returns the Excel #N/A error. This error message has the
11652 // meaning 'value not available' and is produced when an Excel Formula is
11653 // unable to find a value that it needs. The syntax of the function is:
11656 func (fn *formulaFuncs) NA(argsList *list.List) formulaArg {
11657 if argsList.Len() != 0 {
11658 return newErrorFormulaArg(formulaErrorVALUE, "NA accepts no arguments")
11660 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11663 // SHEET function returns the Sheet number for a specified reference. The
11664 // syntax of the function is:
11667 func (fn *formulaFuncs) SHEET(argsList *list.List) formulaArg {
11668 if argsList.Len() > 1 {
11669 return newErrorFormulaArg(formulaErrorVALUE, "SHEET accepts at most 1 argument")
11671 if argsList.Len() == 0 {
11672 idx, _ := fn.f.GetSheetIndex(fn.sheet)
11673 return newNumberFormulaArg(float64(idx + 1))
11675 arg := argsList.Front().Value.(formulaArg)
11676 if sheetIdx, _ := fn.f.GetSheetIndex(arg.Value()); sheetIdx != -1 {
11677 return newNumberFormulaArg(float64(sheetIdx + 1))
11679 if arg.cellRanges != nil && arg.cellRanges.Len() > 0 {
11680 if sheetIdx, _ := fn.f.GetSheetIndex(arg.cellRanges.Front().Value.(cellRange).From.Sheet); sheetIdx != -1 {
11681 return newNumberFormulaArg(float64(sheetIdx + 1))
11684 if arg.cellRefs != nil && arg.cellRefs.Len() > 0 {
11685 if sheetIdx, _ := fn.f.GetSheetIndex(arg.cellRefs.Front().Value.(cellRef).Sheet); sheetIdx != -1 {
11686 return newNumberFormulaArg(float64(sheetIdx + 1))
11689 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11692 // SHEETS function returns the number of sheets in a supplied reference. The
11693 // result includes sheets that are Visible, Hidden or Very Hidden. The syntax
11694 // of the function is:
11696 // SHEETS([reference])
11697 func (fn *formulaFuncs) SHEETS(argsList *list.List) formulaArg {
11698 if argsList.Len() > 1 {
11699 return newErrorFormulaArg(formulaErrorVALUE, "SHEETS accepts at most 1 argument")
11701 if argsList.Len() == 0 {
11702 return newNumberFormulaArg(float64(len(fn.f.GetSheetList())))
11704 arg := argsList.Front().Value.(formulaArg)
11705 sheetMap := map[string]struct{}{}
11706 if arg.cellRanges != nil && arg.cellRanges.Len() > 0 {
11707 for rng := arg.cellRanges.Front(); rng != nil; rng = rng.Next() {
11708 sheetMap[rng.Value.(cellRange).From.Sheet] = struct{}{}
11711 if arg.cellRefs != nil && arg.cellRefs.Len() > 0 {
11712 for ref := arg.cellRefs.Front(); ref != nil; ref = ref.Next() {
11713 sheetMap[ref.Value.(cellRef).Sheet] = struct{}{}
11716 if len(sheetMap) > 0 {
11717 return newNumberFormulaArg(float64(len(sheetMap)))
11719 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11722 // TYPE function returns an integer that represents the value's data type. The
11723 // syntax of the function is:
11726 func (fn *formulaFuncs) TYPE(argsList *list.List) formulaArg {
11727 if argsList.Len() != 1 {
11728 return newErrorFormulaArg(formulaErrorVALUE, "TYPE requires 1 argument")
11730 token := argsList.Front().Value.(formulaArg)
11731 switch token.Type {
11733 return newNumberFormulaArg(16)
11735 return newNumberFormulaArg(64)
11736 case ArgNumber, ArgEmpty:
11738 return newNumberFormulaArg(4)
11740 return newNumberFormulaArg(1)
11742 return newNumberFormulaArg(2)
11746 // T function tests if a supplied value is text and if so, returns the
11747 // supplied text; Otherwise, the function returns an empty text string. The
11748 // syntax of the function is:
11751 func (fn *formulaFuncs) T(argsList *list.List) formulaArg {
11752 if argsList.Len() != 1 {
11753 return newErrorFormulaArg(formulaErrorVALUE, "T requires 1 argument")
11755 token := argsList.Front().Value.(formulaArg)
11756 if token.Type == ArgError {
11759 if token.Type == ArgNumber {
11760 return newStringFormulaArg("")
11762 return newStringFormulaArg(token.Value())
11765 // Logical Functions
11767 // AND function tests a number of supplied conditions and returns TRUE or
11768 // FALSE. The syntax of the function is:
11770 // AND(logical_test1,[logical_test2],...)
11771 func (fn *formulaFuncs) AND(argsList *list.List) formulaArg {
11772 if argsList.Len() == 0 {
11773 return newErrorFormulaArg(formulaErrorVALUE, "AND requires at least 1 argument")
11775 if argsList.Len() > 30 {
11776 return newErrorFormulaArg(formulaErrorVALUE, "AND accepts at most 30 arguments")
11779 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
11780 token := arg.Value.(formulaArg)
11781 switch token.Type {
11785 if token.String == "TRUE" {
11788 if token.String == "FALSE" {
11789 return newStringFormulaArg(token.String)
11791 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11793 and = and && token.Number != 0
11796 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11799 return newBoolFormulaArg(and)
11802 // FALSE function returns the logical value FALSE. The syntax of the
11806 func (fn *formulaFuncs) FALSE(argsList *list.List) formulaArg {
11807 if argsList.Len() != 0 {
11808 return newErrorFormulaArg(formulaErrorVALUE, "FALSE takes no arguments")
11810 return newBoolFormulaArg(false)
11813 // IFERROR function receives two values (or expressions) and tests if the
11814 // first of these evaluates to an error. The syntax of the function is:
11816 // IFERROR(value,value_if_error)
11817 func (fn *formulaFuncs) IFERROR(argsList *list.List) formulaArg {
11818 if argsList.Len() != 2 {
11819 return newErrorFormulaArg(formulaErrorVALUE, "IFERROR requires 2 arguments")
11821 value := argsList.Front().Value.(formulaArg)
11822 if value.Type != ArgError {
11823 if value.Type == ArgEmpty {
11824 return newNumberFormulaArg(0)
11828 return argsList.Back().Value.(formulaArg)
11831 // IFNA function tests if an initial supplied value (or expression) evaluates
11832 // to the Excel #N/A error. If so, the function returns a second supplied
11833 // value; Otherwise the function returns the first supplied value. The syntax
11834 // of the function is:
11836 // IFNA(value,value_if_na)
11837 func (fn *formulaFuncs) IFNA(argsList *list.List) formulaArg {
11838 if argsList.Len() != 2 {
11839 return newErrorFormulaArg(formulaErrorVALUE, "IFNA requires 2 arguments")
11841 arg := argsList.Front().Value.(formulaArg)
11842 if arg.Type == ArgError && arg.String == formulaErrorNA {
11843 return argsList.Back().Value.(formulaArg)
11848 // IFS function tests a number of supplied conditions and returns the result
11849 // corresponding to the first condition that evaluates to TRUE. If none of
11850 // the supplied conditions evaluate to TRUE, the function returns the #N/A
11853 // IFS(logical_test1,value_if_true1,[logical_test2,value_if_true2],...)
11854 func (fn *formulaFuncs) IFS(argsList *list.List) formulaArg {
11855 if argsList.Len() < 2 {
11856 return newErrorFormulaArg(formulaErrorVALUE, "IFS requires at least 2 arguments")
11858 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
11859 if arg.Value.(formulaArg).ToBool().Number == 1 {
11860 return arg.Next().Value.(formulaArg)
11864 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11867 // NOT function returns the opposite to a supplied logical value. The syntax
11868 // of the function is:
11871 func (fn *formulaFuncs) NOT(argsList *list.List) formulaArg {
11872 if argsList.Len() != 1 {
11873 return newErrorFormulaArg(formulaErrorVALUE, "NOT requires 1 argument")
11875 token := argsList.Front().Value.(formulaArg)
11876 switch token.Type {
11877 case ArgString, ArgList:
11878 if strings.ToUpper(token.String) == "TRUE" {
11879 return newBoolFormulaArg(false)
11881 if strings.ToUpper(token.String) == "FALSE" {
11882 return newBoolFormulaArg(true)
11885 return newBoolFormulaArg(!(token.Number != 0))
11889 return newErrorFormulaArg(formulaErrorVALUE, "NOT expects 1 boolean or numeric argument")
11892 // OR function tests a number of supplied conditions and returns either TRUE
11893 // or FALSE. The syntax of the function is:
11895 // OR(logical_test1,[logical_test2],...)
11896 func (fn *formulaFuncs) OR(argsList *list.List) formulaArg {
11897 if argsList.Len() == 0 {
11898 return newErrorFormulaArg(formulaErrorVALUE, "OR requires at least 1 argument")
11900 if argsList.Len() > 30 {
11901 return newErrorFormulaArg(formulaErrorVALUE, "OR accepts at most 30 arguments")
11904 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
11905 token := arg.Value.(formulaArg)
11906 switch token.Type {
11910 if token.String == "FALSE" {
11913 if token.String == "TRUE" {
11917 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11919 if or = token.Number != 0; or {
11920 return newStringFormulaArg(strings.ToUpper(strconv.FormatBool(or)))
11924 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
11927 return newStringFormulaArg(strings.ToUpper(strconv.FormatBool(or)))
11930 // SWITCH function compares a number of supplied values to a supplied test
11931 // expression and returns a result corresponding to the first value that
11932 // matches the test expression. A default value can be supplied, to be
11933 // returned if none of the supplied values match the test expression. The
11934 // syntax of the function is:
11936 // SWITCH(expression,value1,result1,[value2,result2],[value3,result3],...,[default])
11937 func (fn *formulaFuncs) SWITCH(argsList *list.List) formulaArg {
11938 if argsList.Len() < 3 {
11939 return newErrorFormulaArg(formulaErrorVALUE, "SWITCH requires at least 3 arguments")
11941 target := argsList.Front().Value.(formulaArg)
11942 argCount := argsList.Len() - 1
11943 switchCount := int(math.Floor(float64(argCount) / 2))
11944 hasDefaultClause := argCount%2 != 0
11945 result := newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
11946 if hasDefaultClause {
11947 result = argsList.Back().Value.(formulaArg)
11949 if switchCount > 0 {
11950 arg := argsList.Front()
11951 for i := 0; i < switchCount; i++ {
11953 if target.Value() == arg.Value.(formulaArg).Value() {
11954 result = arg.Next().Value.(formulaArg)
11963 // TRUE function returns the logical value TRUE. The syntax of the function
11967 func (fn *formulaFuncs) TRUE(argsList *list.List) formulaArg {
11968 if argsList.Len() != 0 {
11969 return newErrorFormulaArg(formulaErrorVALUE, "TRUE takes no arguments")
11971 return newBoolFormulaArg(true)
11974 // calcXor checking if numeric cell exists and count it by given arguments
11975 // sequence for the formula function XOR.
11976 func calcXor(argsList *list.List) formulaArg {
11977 count, ok := 0, false
11978 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
11979 token := arg.Value.(formulaArg)
11980 switch token.Type {
11985 if token.Number != 0 {
11989 for _, value := range token.ToList() {
11990 if num := value.ToNumber(); num.Type == ArgNumber {
11992 if num.Number != 0 {
12000 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12002 return newBoolFormulaArg(count%2 != 0)
12005 // XOR function returns the Exclusive Or logical operation for one or more
12006 // supplied conditions. I.e. the Xor function returns TRUE if an odd number
12007 // of the supplied conditions evaluate to TRUE, and FALSE otherwise. The
12008 // syntax of the function is:
12010 // XOR(logical_test1,[logical_test2],...)
12011 func (fn *formulaFuncs) XOR(argsList *list.List) formulaArg {
12012 if argsList.Len() < 1 {
12013 return newErrorFormulaArg(formulaErrorVALUE, "XOR requires at least 1 argument")
12015 return calcXor(argsList)
12018 // Date and Time Functions
12020 // DATE returns a date, from a user-supplied year, month and day. The syntax
12021 // of the function is:
12023 // DATE(year,month,day)
12024 func (fn *formulaFuncs) DATE(argsList *list.List) formulaArg {
12025 if argsList.Len() != 3 {
12026 return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
12028 year := argsList.Front().Value.(formulaArg).ToNumber()
12029 month := argsList.Front().Next().Value.(formulaArg).ToNumber()
12030 day := argsList.Back().Value.(formulaArg).ToNumber()
12031 if year.Type != ArgNumber || month.Type != ArgNumber || day.Type != ArgNumber {
12032 return newErrorFormulaArg(formulaErrorVALUE, "DATE requires 3 number arguments")
12034 d := makeDate(int(year.Number), time.Month(month.Number), int(day.Number))
12035 return newStringFormulaArg(timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), d)+1, false).String())
12038 // calcDateDif is an implementation of the formula function DATEDIF,
12039 // calculation difference between two dates.
12040 func calcDateDif(unit string, diff float64, seq []int, startArg, endArg formulaArg) float64 {
12041 ey, sy, em, sm, ed, sd := seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]
12044 diff = endArg.Number - startArg.Number
12050 diff = endArg.Number - daysBetween(excelMinTime1900.Unix(), makeDate(ey, time.Month(smMD), sd)) - 1
12052 diff = float64(em - sm)
12061 if em < sm || (em == sm && ed < sd) {
12064 s := daysBetween(excelMinTime1900.Unix(), makeDate(syYD, time.Month(em), ed))
12065 e := daysBetween(excelMinTime1900.Unix(), makeDate(sy, time.Month(sm), sd))
12071 // DATEDIF function calculates the number of days, months, or years between
12072 // two dates. The syntax of the function is:
12074 // DATEDIF(start_date,end_date,unit)
12075 func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
12076 if argsList.Len() != 3 {
12077 return newErrorFormulaArg(formulaErrorVALUE, "DATEDIF requires 3 number arguments")
12079 startArg, endArg := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber()
12080 if startArg.Type != ArgNumber || endArg.Type != ArgNumber {
12083 if startArg.Number > endArg.Number {
12084 return newErrorFormulaArg(formulaErrorNUM, "start_date > end_date")
12086 if startArg.Number == endArg.Number {
12087 return newNumberFormulaArg(0)
12089 unit := strings.ToLower(argsList.Back().Value.(formulaArg).Value())
12090 startDate, endDate := timeFromExcelTime(startArg.Number, false), timeFromExcelTime(endArg.Number, false)
12091 sy, smm, sd := startDate.Date()
12092 ey, emm, ed := endDate.Date()
12093 sm, em, diff := int(smm), int(emm), 0.0
12096 diff = float64(ey - sy)
12097 if em < sm || (em == sm && ed < sd) {
12110 diff = float64(yDiff*12 + mDiff)
12111 case "d", "md", "ym", "yd":
12112 diff = calcDateDif(unit, diff, []int{ey, sy, em, sm, ed, sd}, startArg, endArg)
12114 return newErrorFormulaArg(formulaErrorVALUE, "DATEDIF has invalid unit")
12116 return newNumberFormulaArg(diff)
12119 // isDateOnlyFmt check if the given string matches date-only format regular expressions.
12120 func isDateOnlyFmt(dateString string) bool {
12121 for _, df := range dateOnlyFormats {
12122 subMatch := df.FindStringSubmatch(dateString)
12123 if len(subMatch) > 1 {
12130 // isTimeOnlyFmt check if the given string matches time-only format regular expressions.
12131 func isTimeOnlyFmt(timeString string) bool {
12132 for _, tf := range timeFormats {
12133 subMatch := tf.FindStringSubmatch(timeString)
12134 if len(subMatch) > 1 {
12141 // strToTimePatternHandler1 parse and convert the given string in pattern
12143 func strToTimePatternHandler1(subMatch []string) (h, m int, s float64, err error) {
12144 h, err = strconv.Atoi(subMatch[0])
12148 // strToTimePatternHandler2 parse and convert the given string in pattern
12149 // hh:mm to the time.
12150 func strToTimePatternHandler2(subMatch []string) (h, m int, s float64, err error) {
12151 if h, err = strconv.Atoi(subMatch[0]); err != nil {
12154 m, err = strconv.Atoi(subMatch[2])
12158 // strToTimePatternHandler3 parse and convert the given string in pattern
12159 // mm:ss to the time.
12160 func strToTimePatternHandler3(subMatch []string) (h, m int, s float64, err error) {
12161 if m, err = strconv.Atoi(subMatch[0]); err != nil {
12164 s, err = strconv.ParseFloat(subMatch[2], 64)
12168 // strToTimePatternHandler4 parse and convert the given string in pattern
12169 // hh:mm:ss to the time.
12170 func strToTimePatternHandler4(subMatch []string) (h, m int, s float64, err error) {
12171 if h, err = strconv.Atoi(subMatch[0]); err != nil {
12174 if m, err = strconv.Atoi(subMatch[2]); err != nil {
12177 s, err = strconv.ParseFloat(subMatch[4], 64)
12181 // strToTime parse and convert the given string to the time.
12182 func strToTime(str string) (int, int, float64, bool, bool, formulaArg) {
12183 var subMatch []string
12185 for key, tf := range timeFormats {
12186 subMatch = tf.FindStringSubmatch(str)
12187 if len(subMatch) > 1 {
12193 return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12195 dateIsEmpty := subMatch[1] == ""
12196 subMatch = subMatch[49:]
12199 last = subMatch[l-1]
12206 if handler, ok := map[string]func(match []string) (int, int, float64, error){
12207 "hh": strToTimePatternHandler1,
12208 "hh:mm": strToTimePatternHandler2,
12209 "mm:ss": strToTimePatternHandler3,
12210 "hh:mm:ss": strToTimePatternHandler4,
12212 if hours, minutes, seconds, err = handler(subMatch); err != nil {
12213 return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12217 return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12220 if hours > 12 || seconds >= 60 {
12221 return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12222 } else if hours == 12 {
12225 } else if hours >= 24 || seconds >= 10000 {
12226 return 0, 0, 0, false, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12228 return hours, minutes, seconds, pm, dateIsEmpty, newEmptyFormulaArg()
12231 // strToDatePatternHandler1 parse and convert the given string in pattern
12232 // mm/dd/yy to the date.
12233 func strToDatePatternHandler1(subMatch []string) (int, int, int, bool, error) {
12234 var year, month, day int
12236 if month, err = strconv.Atoi(subMatch[1]); err != nil {
12237 return 0, 0, 0, false, err
12239 if day, err = strconv.Atoi(subMatch[3]); err != nil {
12240 return 0, 0, 0, false, err
12242 if year, err = strconv.Atoi(subMatch[5]); err != nil {
12243 return 0, 0, 0, false, err
12245 if year < 0 || year > 9999 || (year > 99 && year < 1900) {
12246 return 0, 0, 0, false, ErrParameterInvalid
12248 return formatYear(year), month, day, subMatch[8] == "", err
12251 // strToDatePatternHandler2 parse and convert the given string in pattern mm
12252 // dd, yy to the date.
12253 func strToDatePatternHandler2(subMatch []string) (int, int, int, bool, error) {
12254 var year, month, day int
12256 month = month2num[subMatch[1]]
12257 if day, err = strconv.Atoi(subMatch[14]); err != nil {
12258 return 0, 0, 0, false, err
12260 if year, err = strconv.Atoi(subMatch[16]); err != nil {
12261 return 0, 0, 0, false, err
12263 if year < 0 || year > 9999 || (year > 99 && year < 1900) {
12264 return 0, 0, 0, false, ErrParameterInvalid
12266 return formatYear(year), month, day, subMatch[19] == "", err
12269 // strToDatePatternHandler3 parse and convert the given string in pattern
12270 // yy-mm-dd to the date.
12271 func strToDatePatternHandler3(subMatch []string) (int, int, int, bool, error) {
12272 var year, month, day int
12273 v1, err := strconv.Atoi(subMatch[1])
12275 return 0, 0, 0, false, err
12277 v2, err := strconv.Atoi(subMatch[3])
12279 return 0, 0, 0, false, err
12281 v3, err := strconv.Atoi(subMatch[5])
12283 return 0, 0, 0, false, err
12285 if v1 >= 1900 && v1 < 10000 {
12289 } else if v1 > 0 && v1 < 13 {
12294 return 0, 0, 0, false, ErrParameterInvalid
12296 return year, month, day, subMatch[8] == "", err
12299 // strToDatePatternHandler4 parse and convert the given string in pattern
12300 // yy-mmStr-dd, yy to the date.
12301 func strToDatePatternHandler4(subMatch []string) (int, int, int, bool, error) {
12302 var year, month, day int
12304 if year, err = strconv.Atoi(subMatch[16]); err != nil {
12305 return 0, 0, 0, false, err
12307 month = month2num[subMatch[3]]
12308 if day, err = strconv.Atoi(subMatch[1]); err != nil {
12309 return 0, 0, 0, false, err
12311 return formatYear(year), month, day, subMatch[19] == "", err
12314 // strToDate parse and convert the given string to the date.
12315 func strToDate(str string) (int, int, int, bool, formulaArg) {
12316 var subMatch []string
12318 for key, df := range dateFormats {
12319 subMatch = df.FindStringSubmatch(str)
12320 if len(subMatch) > 1 {
12326 return 0, 0, 0, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12330 year, month, day int
12333 if handler, ok := map[string]func(match []string) (int, int, int, bool, error){
12334 "mm/dd/yy": strToDatePatternHandler1,
12335 "mm dd, yy": strToDatePatternHandler2,
12336 "yy-mm-dd": strToDatePatternHandler3,
12337 "yy-mmStr-dd": strToDatePatternHandler4,
12339 if year, month, day, timeIsEmpty, err = handler(subMatch); err != nil {
12340 return 0, 0, 0, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12343 if !validateDate(year, month, day) {
12344 return 0, 0, 0, false, newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12346 return year, month, day, timeIsEmpty, newEmptyFormulaArg()
12349 // DATEVALUE function converts a text representation of a date into an Excel
12350 // date. For example, the function converts a text string representing a
12351 // date, into the serial number that represents the date in Excels' date-time
12352 // code. The syntax of the function is:
12354 // DATEVALUE(date_text)
12355 func (fn *formulaFuncs) DATEVALUE(argsList *list.List) formulaArg {
12356 if argsList.Len() != 1 {
12357 return newErrorFormulaArg(formulaErrorVALUE, "DATEVALUE requires 1 argument")
12359 dateText := argsList.Front().Value.(formulaArg).Value()
12360 if !isDateOnlyFmt(dateText) {
12361 if _, _, _, _, _, err := strToTime(dateText); err.Type == ArgError {
12365 y, m, d, _, err := strToDate(dateText)
12366 if err.Type == ArgError {
12369 return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), makeDate(y, time.Month(m), d)) + 1)
12372 // DAY function returns the day of a date, represented by a serial number. The
12373 // day is given as an integer ranging from 1 to 31. The syntax of the
12376 // DAY(serial_number)
12377 func (fn *formulaFuncs) DAY(argsList *list.List) formulaArg {
12378 if argsList.Len() != 1 {
12379 return newErrorFormulaArg(formulaErrorVALUE, "DAY requires exactly 1 argument")
12381 arg := argsList.Front().Value.(formulaArg)
12382 num := arg.ToNumber()
12383 if num.Type != ArgNumber {
12384 dateString := strings.ToLower(arg.Value())
12385 if !isDateOnlyFmt(dateString) {
12386 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12390 _, _, day, _, err := strToDate(dateString)
12391 if err.Type == ArgError {
12394 return newNumberFormulaArg(float64(day))
12396 if num.Number < 0 {
12397 return newErrorFormulaArg(formulaErrorNUM, "DAY only accepts positive argument")
12399 if num.Number <= 60 {
12400 return newNumberFormulaArg(math.Mod(num.Number, 31.0))
12402 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Day()))
12405 // DAYS function returns the number of days between two supplied dates. The
12406 // syntax of the function is:
12408 // DAYS(end_date,start_date)
12409 func (fn *formulaFuncs) DAYS(argsList *list.List) formulaArg {
12410 if argsList.Len() != 2 {
12411 return newErrorFormulaArg(formulaErrorVALUE, "DAYS requires 2 arguments")
12413 args := fn.prepareDataValueArgs(2, argsList)
12414 if args.Type != ArgList {
12417 end, start := args.List[0], args.List[1]
12418 return newNumberFormulaArg(end.Number - start.Number)
12421 // DAYS360 function returns the number of days between 2 dates, based on a
12422 // 360-day year (12 x 30 months). The syntax of the function is:
12424 // DAYS360(start_date,end_date,[method])
12425 func (fn *formulaFuncs) DAYS360(argsList *list.List) formulaArg {
12426 if argsList.Len() < 2 {
12427 return newErrorFormulaArg(formulaErrorVALUE, "DAYS360 requires at least 2 arguments")
12429 if argsList.Len() > 3 {
12430 return newErrorFormulaArg(formulaErrorVALUE, "DAYS360 requires at most 3 arguments")
12432 startDate := toExcelDateArg(argsList.Front().Value.(formulaArg))
12433 if startDate.Type != ArgNumber {
12436 endDate := toExcelDateArg(argsList.Front().Next().Value.(formulaArg))
12437 if endDate.Type != ArgNumber {
12440 start, end := timeFromExcelTime(startDate.Number, false), timeFromExcelTime(endDate.Number, false)
12441 sy, sm, sd, ey, em, ed := start.Year(), int(start.Month()), start.Day(), end.Year(), int(end.Month()), end.Day()
12442 method := newBoolFormulaArg(false)
12443 if argsList.Len() > 2 {
12444 if method = argsList.Back().Value.(formulaArg).ToBool(); method.Type != ArgNumber {
12448 if method.Number == 1 {
12456 if getDaysInMonth(sy, sm) == sd {
12468 return newNumberFormulaArg(float64(360*(ey-sy) + 30*(em-sm) + (ed - sd)))
12471 // ISOWEEKNUM function returns the ISO week number of a supplied date. The
12472 // syntax of the function is:
12474 // ISOWEEKNUM(date)
12475 func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
12476 if argsList.Len() != 1 {
12477 return newErrorFormulaArg(formulaErrorVALUE, "ISOWEEKNUM requires 1 argument")
12479 date := argsList.Front().Value.(formulaArg)
12480 num := date.ToNumber()
12482 if num.Type != ArgNumber {
12483 dateString := strings.ToLower(date.Value())
12484 if !isDateOnlyFmt(dateString) {
12485 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12489 y, m, d, _, err := strToDate(dateString)
12490 if err.Type == ArgError {
12493 _, weekNum = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC).ISOWeek()
12495 if num.Number < 0 {
12496 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12498 _, weekNum = timeFromExcelTime(num.Number, false).ISOWeek()
12500 return newNumberFormulaArg(float64(weekNum))
12503 // EDATE function returns a date that is a specified number of months before or
12504 // after a supplied start date. The syntax of function is:
12506 // EDATE(start_date,months)
12507 func (fn *formulaFuncs) EDATE(argsList *list.List) formulaArg {
12508 if argsList.Len() != 2 {
12509 return newErrorFormulaArg(formulaErrorVALUE, "EDATE requires 2 arguments")
12511 date := argsList.Front().Value.(formulaArg)
12512 num := date.ToNumber()
12513 var dateTime time.Time
12514 if num.Type != ArgNumber {
12515 dateString := strings.ToLower(date.Value())
12516 if !isDateOnlyFmt(dateString) {
12517 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12521 y, m, d, _, err := strToDate(dateString)
12522 if err.Type == ArgError {
12525 dateTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location())
12527 if num.Number < 0 {
12528 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12530 dateTime = timeFromExcelTime(num.Number, false)
12532 month := argsList.Back().Value.(formulaArg).ToNumber()
12533 if month.Type != ArgNumber {
12536 y, d := dateTime.Year(), dateTime.Day()
12537 m := int(dateTime.Month()) + int(month.Number)
12538 if month.Number < 0 {
12539 y -= int(math.Ceil(-1 * float64(m) / 12))
12541 if month.Number > 11 {
12542 y += int(math.Floor(float64(m) / 12))
12544 if m = m % 12; m < 0 {
12548 if days := getDaysInMonth(y, m); d > days {
12552 result, _ := timeToExcelTime(time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC), false)
12553 return newNumberFormulaArg(result)
12556 // EOMONTH function returns the last day of the month, that is a specified
12557 // number of months before or after an initial supplied start date. The syntax
12558 // of the function is:
12560 // EOMONTH(start_date,months)
12561 func (fn *formulaFuncs) EOMONTH(argsList *list.List) formulaArg {
12562 if argsList.Len() != 2 {
12563 return newErrorFormulaArg(formulaErrorVALUE, "EOMONTH requires 2 arguments")
12565 date := argsList.Front().Value.(formulaArg)
12566 num := date.ToNumber()
12567 var dateTime time.Time
12568 if num.Type != ArgNumber {
12569 dateString := strings.ToLower(date.Value())
12570 if !isDateOnlyFmt(dateString) {
12571 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12575 y, m, d, _, err := strToDate(dateString)
12576 if err.Type == ArgError {
12579 dateTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location())
12581 if num.Number < 0 {
12582 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12584 dateTime = timeFromExcelTime(num.Number, false)
12586 months := argsList.Back().Value.(formulaArg).ToNumber()
12587 if months.Type != ArgNumber {
12590 y, m := dateTime.Year(), int(dateTime.Month())+int(months.Number)-1
12592 y -= int(math.Ceil(-1 * float64(m) / 12))
12595 y += int(math.Floor(float64(m) / 12))
12597 if m = m % 12; m < 0 {
12600 result, _ := timeToExcelTime(time.Date(y, time.Month(m+1), getDaysInMonth(y, m+1), 0, 0, 0, 0, time.UTC), false)
12601 return newNumberFormulaArg(result)
12604 // HOUR function returns an integer representing the hour component of a
12605 // supplied Excel time. The syntax of the function is:
12607 // HOUR(serial_number)
12608 func (fn *formulaFuncs) HOUR(argsList *list.List) formulaArg {
12609 if argsList.Len() != 1 {
12610 return newErrorFormulaArg(formulaErrorVALUE, "HOUR requires exactly 1 argument")
12612 date := argsList.Front().Value.(formulaArg)
12613 num := date.ToNumber()
12614 if num.Type != ArgNumber {
12615 timeString := strings.ToLower(date.Value())
12616 if !isTimeOnlyFmt(timeString) {
12617 _, _, _, _, err := strToDate(timeString)
12618 if err.Type == ArgError {
12622 h, _, _, pm, _, err := strToTime(timeString)
12623 if err.Type == ArgError {
12629 return newNumberFormulaArg(float64(h))
12631 if num.Number < 0 {
12632 return newErrorFormulaArg(formulaErrorNUM, "HOUR only accepts positive argument")
12634 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Hour()))
12637 // MINUTE function returns an integer representing the minute component of a
12638 // supplied Excel time. The syntax of the function is:
12640 // MINUTE(serial_number)
12641 func (fn *formulaFuncs) MINUTE(argsList *list.List) formulaArg {
12642 if argsList.Len() != 1 {
12643 return newErrorFormulaArg(formulaErrorVALUE, "MINUTE requires exactly 1 argument")
12645 date := argsList.Front().Value.(formulaArg)
12646 num := date.ToNumber()
12647 if num.Type != ArgNumber {
12648 timeString := strings.ToLower(date.Value())
12649 if !isTimeOnlyFmt(timeString) {
12650 _, _, _, _, err := strToDate(timeString)
12651 if err.Type == ArgError {
12655 _, m, _, _, _, err := strToTime(timeString)
12656 if err.Type == ArgError {
12659 return newNumberFormulaArg(float64(m))
12661 if num.Number < 0 {
12662 return newErrorFormulaArg(formulaErrorNUM, "MINUTE only accepts positive argument")
12664 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Minute()))
12667 // MONTH function returns the month of a date represented by a serial number.
12668 // The month is given as an integer, ranging from 1 (January) to 12
12669 // (December). The syntax of the function is:
12671 // MONTH(serial_number)
12672 func (fn *formulaFuncs) MONTH(argsList *list.List) formulaArg {
12673 if argsList.Len() != 1 {
12674 return newErrorFormulaArg(formulaErrorVALUE, "MONTH requires exactly 1 argument")
12676 arg := argsList.Front().Value.(formulaArg)
12677 num := arg.ToNumber()
12678 if num.Type != ArgNumber {
12679 dateString := strings.ToLower(arg.Value())
12680 if !isDateOnlyFmt(dateString) {
12681 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12685 _, month, _, _, err := strToDate(dateString)
12686 if err.Type == ArgError {
12689 return newNumberFormulaArg(float64(month))
12691 if num.Number < 0 {
12692 return newErrorFormulaArg(formulaErrorNUM, "MONTH only accepts positive argument")
12694 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Month()))
12697 // genWeekendMask generate weekend mask of a series of seven 0's and 1's which
12698 // represent the seven weekdays, starting from Monday.
12699 func genWeekendMask(weekend int) []byte {
12700 if masks, ok := map[int][]int{
12701 1: {5, 6}, 2: {6, 0}, 3: {0, 1}, 4: {1, 2}, 5: {2, 3}, 6: {3, 4}, 7: {4, 5},
12702 11: {6}, 12: {0}, 13: {1}, 14: {2}, 15: {3}, 16: {4}, 17: {5},
12704 mask := make([]byte, 7)
12705 for _, idx := range masks {
12713 // isWorkday check if the date is workday.
12714 func isWorkday(weekendMask []byte, date float64) bool {
12715 dateTime := timeFromExcelTime(date, false)
12716 weekday := dateTime.Weekday()
12717 if weekday == time.Sunday {
12720 return weekendMask[weekday-1] == 0
12723 // prepareWorkday returns weekend mask and workdays pre week by given days
12724 // counted as weekend.
12725 func prepareWorkday(weekend formulaArg) ([]byte, int) {
12726 weekendArg := weekend.ToNumber()
12727 if weekendArg.Type != ArgNumber {
12730 var weekendMask []byte
12731 var workdaysPerWeek int
12732 if len(weekend.Value()) == 7 {
12733 // possible string values for the weekend argument
12734 for _, mask := range weekend.Value() {
12735 if mask != '0' && mask != '1' {
12738 weekendMask = append(weekendMask, byte(mask)-48)
12741 weekendMask = genWeekendMask(int(weekendArg.Number))
12743 for _, mask := range weekendMask {
12748 return weekendMask, workdaysPerWeek
12751 // toExcelDateArg function converts a text representation of a time, into an
12752 // Excel date time number formula argument.
12753 func toExcelDateArg(arg formulaArg) formulaArg {
12754 num := arg.ToNumber()
12755 if num.Type != ArgNumber {
12756 dateString := strings.ToLower(arg.Value())
12757 if !isDateOnlyFmt(dateString) {
12758 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
12762 y, m, d, _, err := strToDate(dateString)
12763 if err.Type == ArgError {
12766 num.Number, _ = timeToExcelTime(time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC), false)
12767 return newNumberFormulaArg(num.Number)
12769 if arg.Number < 0 {
12770 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
12775 // prepareHolidays function converts array type formula arguments to into an
12776 // Excel date time number formula arguments list.
12777 func prepareHolidays(args formulaArg) []int {
12779 for _, arg := range args.ToList() {
12780 num := toExcelDateArg(arg)
12781 if num.Type != ArgNumber {
12784 holidays = append(holidays, int(math.Ceil(num.Number)))
12789 // workdayIntl is an implementation of the formula function WORKDAY.INTL.
12790 func workdayIntl(endDate, sign int, holidays []int, weekendMask []byte, startDate float64) int {
12791 for i := 0; i < len(holidays); i++ {
12792 holiday := holidays[i]
12794 if holiday > endDate {
12798 if holiday < endDate {
12803 if holiday > int(math.Ceil(startDate)) {
12804 if isWorkday(weekendMask, float64(holiday)) {
12806 for !isWorkday(weekendMask, float64(endDate)) {
12812 if holiday < int(math.Ceil(startDate)) {
12813 if isWorkday(weekendMask, float64(holiday)) {
12815 for !isWorkday(weekendMask, float64(endDate)) {
12825 // NETWORKDAYS function calculates the number of work days between two supplied
12826 // dates (including the start and end date). The calculation includes all
12827 // weekdays (Mon - Fri), excluding a supplied list of holidays. The syntax of
12828 // the function is:
12830 // NETWORKDAYS(start_date,end_date,[holidays])
12831 func (fn *formulaFuncs) NETWORKDAYS(argsList *list.List) formulaArg {
12832 if argsList.Len() < 2 {
12833 return newErrorFormulaArg(formulaErrorVALUE, "NETWORKDAYS requires at least 2 arguments")
12835 if argsList.Len() > 3 {
12836 return newErrorFormulaArg(formulaErrorVALUE, "NETWORKDAYS requires at most 3 arguments")
12839 args.PushBack(argsList.Front().Value.(formulaArg))
12840 args.PushBack(argsList.Front().Next().Value.(formulaArg))
12841 args.PushBack(newNumberFormulaArg(1))
12842 if argsList.Len() == 3 {
12843 args.PushBack(argsList.Back().Value.(formulaArg))
12845 return fn.NETWORKDAYSdotINTL(args)
12848 // NETWORKDAYSdotINTL function calculates the number of whole work days between
12849 // two supplied dates, excluding weekends and holidays. The function allows
12850 // the user to specify which days are counted as weekends and holidays. The
12851 // syntax of the function is:
12853 // NETWORKDAYS.INTL(start_date,end_date,[weekend],[holidays])
12854 func (fn *formulaFuncs) NETWORKDAYSdotINTL(argsList *list.List) formulaArg {
12855 if argsList.Len() < 2 {
12856 return newErrorFormulaArg(formulaErrorVALUE, "NETWORKDAYS.INTL requires at least 2 arguments")
12858 if argsList.Len() > 4 {
12859 return newErrorFormulaArg(formulaErrorVALUE, "NETWORKDAYS.INTL requires at most 4 arguments")
12861 startDate := toExcelDateArg(argsList.Front().Value.(formulaArg))
12862 if startDate.Type != ArgNumber {
12865 endDate := toExcelDateArg(argsList.Front().Next().Value.(formulaArg))
12866 if endDate.Type != ArgNumber {
12869 weekend := newNumberFormulaArg(1)
12870 if argsList.Len() > 2 {
12871 weekend = argsList.Front().Next().Next().Value.(formulaArg)
12874 if argsList.Len() == 4 {
12875 holidays = prepareHolidays(argsList.Back().Value.(formulaArg))
12876 sort.Ints(holidays)
12878 weekendMask, workdaysPerWeek := prepareWorkday(weekend)
12879 if workdaysPerWeek == 0 {
12880 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12883 if startDate.Number > endDate.Number {
12885 temp := startDate.Number
12886 startDate.Number = endDate.Number
12887 endDate.Number = temp
12889 offset := endDate.Number - startDate.Number
12890 count := int(math.Floor(offset/7) * float64(workdaysPerWeek))
12891 daysMod := int(offset) % 7
12893 if isWorkday(weekendMask, endDate.Number-float64(daysMod)) {
12898 for i := 0; i < len(holidays); i++ {
12899 holiday := float64(holidays[i])
12900 if isWorkday(weekendMask, holiday) && holiday >= startDate.Number && holiday <= endDate.Number {
12904 return newNumberFormulaArg(float64(sign * count))
12907 // WORKDAY function returns a date that is a supplied number of working days
12908 // (excluding weekends and holidays) ahead of a given start date. The syntax
12909 // of the function is:
12911 // WORKDAY(start_date,days,[holidays])
12912 func (fn *formulaFuncs) WORKDAY(argsList *list.List) formulaArg {
12913 if argsList.Len() < 2 {
12914 return newErrorFormulaArg(formulaErrorVALUE, "WORKDAY requires at least 2 arguments")
12916 if argsList.Len() > 3 {
12917 return newErrorFormulaArg(formulaErrorVALUE, "WORKDAY requires at most 3 arguments")
12920 args.PushBack(argsList.Front().Value.(formulaArg))
12921 args.PushBack(argsList.Front().Next().Value.(formulaArg))
12922 args.PushBack(newNumberFormulaArg(1))
12923 if argsList.Len() == 3 {
12924 args.PushBack(argsList.Back().Value.(formulaArg))
12926 return fn.WORKDAYdotINTL(args)
12929 // WORKDAYdotINTL function returns a date that is a supplied number of working
12930 // days (excluding weekends and holidays) ahead of a given start date. The
12931 // function allows the user to specify which days of the week are counted as
12932 // weekends. The syntax of the function is:
12934 // WORKDAY.INTL(start_date,days,[weekend],[holidays])
12935 func (fn *formulaFuncs) WORKDAYdotINTL(argsList *list.List) formulaArg {
12936 if argsList.Len() < 2 {
12937 return newErrorFormulaArg(formulaErrorVALUE, "WORKDAY.INTL requires at least 2 arguments")
12939 if argsList.Len() > 4 {
12940 return newErrorFormulaArg(formulaErrorVALUE, "WORKDAY.INTL requires at most 4 arguments")
12942 startDate := toExcelDateArg(argsList.Front().Value.(formulaArg))
12943 if startDate.Type != ArgNumber {
12946 days := argsList.Front().Next().Value.(formulaArg).ToNumber()
12947 if days.Type != ArgNumber {
12950 weekend := newNumberFormulaArg(1)
12951 if argsList.Len() > 2 {
12952 weekend = argsList.Front().Next().Next().Value.(formulaArg)
12955 if argsList.Len() == 4 {
12956 holidays = prepareHolidays(argsList.Back().Value.(formulaArg))
12957 sort.Ints(holidays)
12959 if days.Number == 0 {
12960 return newNumberFormulaArg(math.Ceil(startDate.Number))
12962 weekendMask, workdaysPerWeek := prepareWorkday(weekend)
12963 if workdaysPerWeek == 0 {
12964 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
12967 if days.Number < 0 {
12970 offset := int(days.Number) / workdaysPerWeek
12971 daysMod := int(days.Number) % workdaysPerWeek
12972 endDate := int(math.Ceil(startDate.Number)) + offset*7
12974 for !isWorkday(weekendMask, float64(endDate)) {
12980 if isWorkday(weekendMask, float64(endDate)) {
12989 return newNumberFormulaArg(float64(workdayIntl(endDate, sign, holidays, weekendMask, startDate.Number)))
12992 // YEAR function returns an integer representing the year of a supplied date.
12993 // The syntax of the function is:
12995 // YEAR(serial_number)
12996 func (fn *formulaFuncs) YEAR(argsList *list.List) formulaArg {
12997 if argsList.Len() != 1 {
12998 return newErrorFormulaArg(formulaErrorVALUE, "YEAR requires exactly 1 argument")
13000 arg := argsList.Front().Value.(formulaArg)
13001 num := arg.ToNumber()
13002 if num.Type != ArgNumber {
13003 dateString := strings.ToLower(arg.Value())
13004 if !isDateOnlyFmt(dateString) {
13005 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
13009 year, _, _, _, err := strToDate(dateString)
13010 if err.Type == ArgError {
13013 return newNumberFormulaArg(float64(year))
13015 if num.Number < 0 {
13016 return newErrorFormulaArg(formulaErrorNUM, "YEAR only accepts positive argument")
13018 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Year()))
13021 // yearFracBasisCond is an implementation of the yearFracBasis1.
13022 func yearFracBasisCond(sy, sm, sd, ey, em, ed int) bool {
13023 return (isLeapYear(sy) && (sm < 2 || (sm == 2 && sd <= 29))) || (isLeapYear(ey) && (em > 2 || (em == 2 && ed == 29)))
13026 // yearFracBasis0 function returns the fraction of a year that between two
13027 // supplied dates in US (NASD) 30/360 type of day.
13028 func yearFracBasis0(startDate, endDate float64) (dayDiff, daysInYear float64) {
13029 startTime, endTime := timeFromExcelTime(startDate, false), timeFromExcelTime(endDate, false)
13030 sy, smM, sd := startTime.Date()
13031 ey, emM, ed := endTime.Date()
13032 sm, em := int(smM), int(emM)
13036 if sd == 30 && ed == 31 {
13038 } else if leap := isLeapYear(sy); sm == 2 && ((leap && sd == 29) || (!leap && sd == 28)) {
13040 if leap := isLeapYear(ey); em == 2 && ((leap && ed == 29) || (!leap && ed == 28)) {
13044 dayDiff = float64((ey-sy)*360 + (em-sm)*30 + (ed - sd))
13049 // yearFracBasis1 function returns the fraction of a year that between two
13050 // supplied dates in actual type of day.
13051 func yearFracBasis1(startDate, endDate float64) (dayDiff, daysInYear float64) {
13052 startTime, endTime := timeFromExcelTime(startDate, false), timeFromExcelTime(endDate, false)
13053 sy, smM, sd := startTime.Date()
13054 ey, emM, ed := endTime.Date()
13055 sm, em := int(smM), int(emM)
13056 dayDiff = endDate - startDate
13057 isYearDifferent := sy != ey
13058 if isYearDifferent && (ey != sy+1 || sm < em || (sm == em && sd < ed)) {
13060 for y := sy; y <= ey; y++ {
13061 dayCount += getYearDays(y, 1)
13063 daysInYear = float64(dayCount) / float64(ey-sy+1)
13065 if !isYearDifferent && isLeapYear(sy) {
13068 if isYearDifferent && yearFracBasisCond(sy, sm, sd, ey, em, ed) {
13078 // yearFracBasis4 function returns the fraction of a year that between two
13079 // supplied dates in European 30/360 type of day.
13080 func yearFracBasis4(startDate, endDate float64) (dayDiff, daysInYear float64) {
13081 startTime, endTime := timeFromExcelTime(startDate, false), timeFromExcelTime(endDate, false)
13082 sy, smM, sd := startTime.Date()
13083 ey, emM, ed := endTime.Date()
13084 sm, em := int(smM), int(emM)
13091 dayDiff = float64((ey-sy)*360 + (em-sm)*30 + (ed - sd))
13096 // yearFrac is an implementation of the formula function YEARFRAC.
13097 func yearFrac(startDate, endDate float64, basis int) formulaArg {
13098 startTime, endTime := timeFromExcelTime(startDate, false), timeFromExcelTime(endDate, false)
13099 if startTime == endTime {
13100 return newNumberFormulaArg(0)
13102 var dayDiff, daysInYear float64
13105 dayDiff, daysInYear = yearFracBasis0(startDate, endDate)
13107 dayDiff, daysInYear = yearFracBasis1(startDate, endDate)
13109 dayDiff = endDate - startDate
13112 dayDiff = endDate - startDate
13115 dayDiff, daysInYear = yearFracBasis4(startDate, endDate)
13117 return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
13119 return newNumberFormulaArg(dayDiff / daysInYear)
13122 // getYearDays return days of the year with specifying the type of day count
13123 // basis to be used.
13124 func getYearDays(year, basis int) int {
13127 if isLeapYear(year) {
13138 // YEARFRAC function returns the fraction of a year that is represented by the
13139 // number of whole days between two supplied dates. The syntax of the
13142 // YEARFRAC(start_date,end_date,[basis])
13143 func (fn *formulaFuncs) YEARFRAC(argsList *list.List) formulaArg {
13144 if argsList.Len() != 2 && argsList.Len() != 3 {
13145 return newErrorFormulaArg(formulaErrorVALUE, "YEARFRAC requires 3 or 4 arguments")
13147 args := fn.prepareDataValueArgs(2, argsList)
13148 if args.Type != ArgList {
13151 start, end := args.List[0], args.List[1]
13152 basis := newNumberFormulaArg(0)
13153 if argsList.Len() == 3 {
13154 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
13158 return yearFrac(start.Number, end.Number, int(basis.Number))
13161 // NOW function returns the current date and time. The function receives no
13162 // arguments and therefore. The syntax of the function is:
13165 func (fn *formulaFuncs) NOW(argsList *list.List) formulaArg {
13166 if argsList.Len() != 0 {
13167 return newErrorFormulaArg(formulaErrorVALUE, "NOW accepts no arguments")
13170 _, offset := now.Zone()
13171 return newNumberFormulaArg(25569.0 + float64(now.Unix()+int64(offset))/86400)
13174 // SECOND function returns an integer representing the second component of a
13175 // supplied Excel time. The syntax of the function is:
13177 // SECOND(serial_number)
13178 func (fn *formulaFuncs) SECOND(argsList *list.List) formulaArg {
13179 if argsList.Len() != 1 {
13180 return newErrorFormulaArg(formulaErrorVALUE, "SECOND requires exactly 1 argument")
13182 date := argsList.Front().Value.(formulaArg)
13183 num := date.ToNumber()
13184 if num.Type != ArgNumber {
13185 timeString := strings.ToLower(date.Value())
13186 if !isTimeOnlyFmt(timeString) {
13187 _, _, _, _, err := strToDate(timeString)
13188 if err.Type == ArgError {
13192 _, _, s, _, _, err := strToTime(timeString)
13193 if err.Type == ArgError {
13196 return newNumberFormulaArg(float64(int(s) % 60))
13198 if num.Number < 0 {
13199 return newErrorFormulaArg(formulaErrorNUM, "SECOND only accepts positive argument")
13201 return newNumberFormulaArg(float64(timeFromExcelTime(num.Number, false).Second()))
13204 // TIME function accepts three integer arguments representing hours, minutes
13205 // and seconds, and returns an Excel time. I.e. the function returns the
13206 // decimal value that represents the time in Excel. The syntax of the
13209 // TIME(hour,minute,second)
13210 func (fn *formulaFuncs) TIME(argsList *list.List) formulaArg {
13211 if argsList.Len() != 3 {
13212 return newErrorFormulaArg(formulaErrorVALUE, "TIME requires 3 number arguments")
13214 h := argsList.Front().Value.(formulaArg).ToNumber()
13215 m := argsList.Front().Next().Value.(formulaArg).ToNumber()
13216 s := argsList.Back().Value.(formulaArg).ToNumber()
13217 if h.Type != ArgNumber || m.Type != ArgNumber || s.Type != ArgNumber {
13218 return newErrorFormulaArg(formulaErrorVALUE, "TIME requires 3 number arguments")
13220 t := (h.Number*3600 + m.Number*60 + s.Number) / 86400
13222 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
13224 return newNumberFormulaArg(t)
13227 // TIMEVALUE function converts a text representation of a time, into an Excel
13228 // time. The syntax of the function is:
13230 // TIMEVALUE(time_text)
13231 func (fn *formulaFuncs) TIMEVALUE(argsList *list.List) formulaArg {
13232 if argsList.Len() != 1 {
13233 return newErrorFormulaArg(formulaErrorVALUE, "TIMEVALUE requires exactly 1 argument")
13235 date := argsList.Front().Value.(formulaArg)
13236 timeString := strings.ToLower(date.Value())
13237 if !isTimeOnlyFmt(timeString) {
13238 _, _, _, _, err := strToDate(timeString)
13239 if err.Type == ArgError {
13243 h, m, s, pm, _, err := strToTime(timeString)
13244 if err.Type == ArgError {
13251 args.PushBack(newNumberFormulaArg(float64(h)))
13252 args.PushBack(newNumberFormulaArg(float64(m)))
13253 args.PushBack(newNumberFormulaArg(s))
13254 return fn.TIME(args)
13257 // TODAY function returns the current date. The function has no arguments and
13258 // therefore. The syntax of the function is:
13261 func (fn *formulaFuncs) TODAY(argsList *list.List) formulaArg {
13262 if argsList.Len() != 0 {
13263 return newErrorFormulaArg(formulaErrorVALUE, "TODAY accepts no arguments")
13266 _, offset := now.Zone()
13267 return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), now.Unix()+int64(offset)) + 1)
13270 // makeDate return date as a Unix time, the number of seconds elapsed since
13271 // January 1, 1970 UTC.
13272 func makeDate(y int, m time.Month, d int) int64 {
13273 if y == 1900 && int(m) <= 2 {
13276 date := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
13280 // daysBetween return time interval of the given start timestamp and end
13282 func daysBetween(startDate, endDate int64) float64 {
13283 return float64(int(0.5 + float64((endDate-startDate)/86400)))
13286 // WEEKDAY function returns an integer representing the day of the week for a
13287 // supplied date. The syntax of the function is:
13289 // WEEKDAY(serial_number,[return_type])
13290 func (fn *formulaFuncs) WEEKDAY(argsList *list.List) formulaArg {
13291 if argsList.Len() < 1 {
13292 return newErrorFormulaArg(formulaErrorVALUE, "WEEKDAY requires at least 1 argument")
13294 if argsList.Len() > 2 {
13295 return newErrorFormulaArg(formulaErrorVALUE, "WEEKDAY allows at most 2 arguments")
13297 sn := argsList.Front().Value.(formulaArg)
13298 num := sn.ToNumber()
13299 weekday, returnType := 0, 1
13300 if num.Type != ArgNumber {
13301 dateString := strings.ToLower(sn.Value())
13302 if !isDateOnlyFmt(dateString) {
13303 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
13307 y, m, d, _, err := strToDate(dateString)
13308 if err.Type == ArgError {
13311 weekday = int(time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location()).Weekday())
13313 if num.Number < 0 {
13314 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
13316 weekday = int(timeFromExcelTime(num.Number, false).Weekday())
13318 if argsList.Len() == 2 {
13319 returnTypeArg := argsList.Back().Value.(formulaArg).ToNumber()
13320 if returnTypeArg.Type != ArgNumber {
13321 return returnTypeArg
13323 returnType = int(returnTypeArg.Number)
13325 if returnType == 2 {
13329 if returnType == 1 {
13330 return newNumberFormulaArg(float64(weekday))
13332 if returnType == 3 {
13333 return newNumberFormulaArg(float64((weekday + 6 - 1) % 7))
13335 if returnType >= 11 && returnType <= 17 {
13336 return newNumberFormulaArg(float64((weekday+6-(returnType-10))%7 + 1))
13338 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13341 // weeknum is an implementation of the formula function WEEKNUM.
13342 func (fn *formulaFuncs) weeknum(snTime time.Time, returnType int) formulaArg {
13343 days := snTime.YearDay()
13344 weekMod, weekNum := days%7, math.Ceil(float64(days)/7)
13348 year := snTime.Year()
13349 firstWeekday := int(time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC).Weekday())
13351 switch returnType {
13356 case 12, 13, 14, 15, 16:
13357 offset = returnType - 10
13359 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
13361 padding := offset + 7 - firstWeekday
13365 if weekMod > padding {
13368 if returnType == 21 && (firstWeekday == 0 || firstWeekday > 4) {
13369 if weekNum--; weekNum < 1 {
13370 if weekNum = 52; int(time.Date(year-1, time.January, 1, 0, 0, 0, 0, time.UTC).Weekday()) < 4 {
13375 return newNumberFormulaArg(weekNum)
13378 // WEEKNUM function returns an integer representing the week number (from 1 to
13379 // 53) of the year. The syntax of the function is:
13381 // WEEKNUM(serial_number,[return_type])
13382 func (fn *formulaFuncs) WEEKNUM(argsList *list.List) formulaArg {
13383 if argsList.Len() < 1 {
13384 return newErrorFormulaArg(formulaErrorVALUE, "WEEKNUM requires at least 1 argument")
13386 if argsList.Len() > 2 {
13387 return newErrorFormulaArg(formulaErrorVALUE, "WEEKNUM allows at most 2 arguments")
13389 sn := argsList.Front().Value.(formulaArg)
13390 num, returnType := sn.ToNumber(), 1
13391 var snTime time.Time
13392 if num.Type != ArgNumber {
13393 dateString := strings.ToLower(sn.Value())
13394 if !isDateOnlyFmt(dateString) {
13395 if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
13399 y, m, d, _, err := strToDate(dateString)
13400 if err.Type == ArgError {
13403 snTime = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location())
13405 if num.Number < 0 {
13406 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
13408 snTime = timeFromExcelTime(num.Number, false)
13410 if argsList.Len() == 2 {
13411 returnTypeArg := argsList.Back().Value.(formulaArg).ToNumber()
13412 if returnTypeArg.Type != ArgNumber {
13413 return returnTypeArg
13415 returnType = int(returnTypeArg.Number)
13417 return fn.weeknum(snTime, returnType)
13422 // prepareToText checking and prepare arguments for the formula functions
13423 // ARRAYTOTEXT and VALUETOTEXT.
13424 func prepareToText(name string, argsList *list.List) formulaArg {
13425 if argsList.Len() < 1 {
13426 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
13428 if argsList.Len() > 2 {
13429 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 2 arguments", name))
13431 format := newNumberFormulaArg(0)
13432 if argsList.Len() == 2 {
13433 if format = argsList.Back().Value.(formulaArg).ToNumber(); format.Type != ArgNumber {
13437 if format.Number != 0 && format.Number != 1 {
13438 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13443 // ARRAYTOTEXT function returns an array of text values from any specified
13444 // range. It passes text values unchanged, and converts non-text values to
13445 // text. The syntax of the function is:
13447 // ARRAYTOTEXT(array,[format])
13448 func (fn *formulaFuncs) ARRAYTOTEXT(argsList *list.List) formulaArg {
13450 format := prepareToText("ARRAYTOTEXT", argsList)
13451 if format.Type != ArgNumber {
13454 for _, rows := range argsList.Front().Value.(formulaArg).Matrix {
13456 for _, cell := range rows {
13457 if num := cell.ToNumber(); num.Type != ArgNumber && format.Number == 1 {
13458 row = append(row, fmt.Sprintf("\"%s\"", cell.Value()))
13461 row = append(row, cell.Value())
13463 mtx = append(mtx, row)
13466 for _, row := range mtx {
13467 if format.Number == 1 {
13468 text = append(text, strings.Join(row, ","))
13471 text = append(text, strings.Join(row, ", "))
13473 if format.Number == 1 {
13474 return newStringFormulaArg(fmt.Sprintf("{%s}", strings.Join(text, ";")))
13476 return newStringFormulaArg(strings.Join(text, ", "))
13479 // CHAR function returns the character relating to a supplied character set
13480 // number (from 1 to 255). The syntax of the function is:
13483 func (fn *formulaFuncs) CHAR(argsList *list.List) formulaArg {
13484 if argsList.Len() != 1 {
13485 return newErrorFormulaArg(formulaErrorVALUE, "CHAR requires 1 argument")
13487 arg := argsList.Front().Value.(formulaArg).ToNumber()
13488 if arg.Type != ArgNumber {
13491 num := int(arg.Number)
13492 if num < 0 || num > MaxFieldLength {
13493 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13495 return newStringFormulaArg(fmt.Sprintf("%c", num))
13498 // CLEAN removes all non-printable characters from a supplied text string. The
13499 // syntax of the function is:
13502 func (fn *formulaFuncs) CLEAN(argsList *list.List) formulaArg {
13503 if argsList.Len() != 1 {
13504 return newErrorFormulaArg(formulaErrorVALUE, "CLEAN requires 1 argument")
13506 b := bytes.Buffer{}
13507 for _, c := range argsList.Front().Value.(formulaArg).Value() {
13512 return newStringFormulaArg(b.String())
13515 // CODE function converts the first character of a supplied text string into
13516 // the associated numeric character set code used by your computer. The
13517 // syntax of the function is:
13520 func (fn *formulaFuncs) CODE(argsList *list.List) formulaArg {
13521 return fn.code("CODE", argsList)
13524 // code is an implementation of the formula functions CODE and UNICODE.
13525 func (fn *formulaFuncs) code(name string, argsList *list.List) formulaArg {
13526 if argsList.Len() != 1 {
13527 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 1 argument", name))
13529 text := argsList.Front().Value.(formulaArg).Value()
13530 if len(text) == 0 {
13531 if name == "CODE" {
13532 return newNumberFormulaArg(0)
13534 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13536 return newNumberFormulaArg(float64(text[0]))
13539 // CONCAT function joins together a series of supplied text strings into one
13540 // combined text string.
13542 // CONCAT(text1,[text2],...)
13543 func (fn *formulaFuncs) CONCAT(argsList *list.List) formulaArg {
13544 return fn.concat("CONCAT", argsList)
13547 // CONCATENATE function joins together a series of supplied text strings into
13548 // one combined text string.
13550 // CONCATENATE(text1,[text2],...)
13551 func (fn *formulaFuncs) CONCATENATE(argsList *list.List) formulaArg {
13552 return fn.concat("CONCATENATE", argsList)
13555 // concat is an implementation of the formula functions CONCAT and
13557 func (fn *formulaFuncs) concat(name string, argsList *list.List) formulaArg {
13558 var buf bytes.Buffer
13559 for arg := argsList.Front(); arg != nil; arg = arg.Next() {
13560 for _, cell := range arg.Value.(formulaArg).ToList() {
13561 if cell.Type == ArgError {
13564 buf.WriteString(cell.Value())
13567 return newStringFormulaArg(buf.String())
13570 // DBCS converts half-width (single-byte) letters within a character string to
13571 // full-width (double-byte) characters. The syntax of the function is:
13574 func (fn *formulaFuncs) DBCS(argsList *list.List) formulaArg {
13575 if argsList.Len() != 1 {
13576 return newErrorFormulaArg(formulaErrorVALUE, "DBCS requires 1 argument")
13578 arg := argsList.Front().Value.(formulaArg)
13579 if arg.Type == ArgError {
13582 if fn.f.options.CultureInfo == CultureNameZhCN {
13584 for _, r := range arg.Value() {
13591 if (code < 32 || code > 126) && r != 165 && code < 65381 {
13592 chars = append(chars, string(code))
13594 chars = append(chars, string(r))
13597 return newStringFormulaArg(strings.Join(chars, ""))
13602 // EXACT function tests if two supplied text strings or values are exactly
13603 // equal and if so, returns TRUE; Otherwise, the function returns FALSE. The
13604 // function is case-sensitive. The syntax of the function is:
13606 // EXACT(text1,text2)
13607 func (fn *formulaFuncs) EXACT(argsList *list.List) formulaArg {
13608 if argsList.Len() != 2 {
13609 return newErrorFormulaArg(formulaErrorVALUE, "EXACT requires 2 arguments")
13611 text1 := argsList.Front().Value.(formulaArg).Value()
13612 text2 := argsList.Back().Value.(formulaArg).Value()
13613 return newBoolFormulaArg(text1 == text2)
13616 // FIXED function rounds a supplied number to a specified number of decimal
13617 // places and then converts this into text. The syntax of the function is:
13619 // FIXED(number,[decimals],[no_commas])
13620 func (fn *formulaFuncs) FIXED(argsList *list.List) formulaArg {
13621 if argsList.Len() < 1 {
13622 return newErrorFormulaArg(formulaErrorVALUE, "FIXED requires at least 1 argument")
13624 if argsList.Len() > 3 {
13625 return newErrorFormulaArg(formulaErrorVALUE, "FIXED allows at most 3 arguments")
13627 numArg := argsList.Front().Value.(formulaArg).ToNumber()
13628 if numArg.Type != ArgNumber {
13631 precision, decimals, noCommas := 0, 0, false
13632 s := strings.Split(argsList.Front().Value.(formulaArg).Value(), ".")
13633 if argsList.Len() == 1 && len(s) == 2 {
13634 precision = len(s[1])
13635 decimals = len(s[1])
13637 if argsList.Len() >= 2 {
13638 decimalsArg := argsList.Front().Next().Value.(formulaArg).ToNumber()
13639 if decimalsArg.Type != ArgNumber {
13642 decimals = int(decimalsArg.Number)
13644 if argsList.Len() == 3 {
13645 noCommasArg := argsList.Back().Value.(formulaArg).ToBool()
13646 if noCommasArg.Type == ArgError {
13649 noCommas = noCommasArg.Boolean
13651 n := math.Pow(10, float64(decimals))
13652 r := numArg.Number * n
13653 fixed := float64(int(r+math.Copysign(0.5, r))) / n
13655 precision = decimals
13658 return newStringFormulaArg(fmt.Sprintf(fmt.Sprintf("%%.%df", precision), fixed))
13660 p := message.NewPrinter(language.English)
13661 return newStringFormulaArg(p.Sprintf(fmt.Sprintf("%%.%df", precision), fixed))
13664 // FIND function returns the position of a specified character or sub-string
13665 // within a supplied text string. The function is case-sensitive. The syntax
13666 // of the function is:
13668 // FIND(find_text,within_text,[start_num])
13669 func (fn *formulaFuncs) FIND(argsList *list.List) formulaArg {
13670 return fn.find("FIND", argsList)
13673 // FINDB counts each double-byte character as 2 when you have enabled the
13674 // editing of a language that supports DBCS and then set it as the default
13675 // language. Otherwise, FINDB counts each character as 1. The syntax of the
13678 // FINDB(find_text,within_text,[start_num])
13679 func (fn *formulaFuncs) FINDB(argsList *list.List) formulaArg {
13680 return fn.find("FINDB", argsList)
13683 // prepareFindArgs checking and prepare arguments for the formula functions
13684 // FIND, FINDB, SEARCH and SEARCHB.
13685 func (fn *formulaFuncs) prepareFindArgs(name string, argsList *list.List) formulaArg {
13686 if argsList.Len() < 2 {
13687 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 2 arguments", name))
13689 if argsList.Len() > 3 {
13690 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 3 arguments", name))
13693 if argsList.Len() == 3 {
13694 numArg := argsList.Back().Value.(formulaArg).ToNumber()
13695 if numArg.Type != ArgNumber {
13698 if numArg.Number < 0 {
13699 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13701 startNum = int(numArg.Number)
13703 return newListFormulaArg([]formulaArg{newNumberFormulaArg(float64(startNum))})
13706 // find is an implementation of the formula functions FIND, FINDB, SEARCH and
13708 func (fn *formulaFuncs) find(name string, argsList *list.List) formulaArg {
13709 args := fn.prepareFindArgs(name, argsList)
13710 if args.Type != ArgList {
13713 findText := argsList.Front().Value.(formulaArg).Value()
13714 withinText := argsList.Front().Next().Value.(formulaArg).Value()
13715 startNum := int(args.List[0].Number)
13716 if findText == "" {
13717 return newNumberFormulaArg(float64(startNum))
13719 dbcs, search := name == "FINDB" || name == "SEARCHB", name == "SEARCH" || name == "SEARCHB"
13721 findText, withinText = strings.ToUpper(findText), strings.ToUpper(withinText)
13723 offset, ok := matchPattern(findText, withinText, dbcs, startNum)
13725 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13730 for idx := range withinText {
13740 return newNumberFormulaArg(float64(result))
13743 // LEFT function returns a specified number of characters from the start of a
13744 // supplied text string. The syntax of the function is:
13746 // LEFT(text,[num_chars])
13747 func (fn *formulaFuncs) LEFT(argsList *list.List) formulaArg {
13748 return fn.leftRight("LEFT", argsList)
13751 // LEFTB returns the first character or characters in a text string, based on
13752 // the number of bytes you specify. The syntax of the function is:
13754 // LEFTB(text,[num_bytes])
13755 func (fn *formulaFuncs) LEFTB(argsList *list.List) formulaArg {
13756 return fn.leftRight("LEFTB", argsList)
13759 // leftRight is an implementation of the formula functions LEFT, LEFTB, RIGHT,
13761 func (fn *formulaFuncs) leftRight(name string, argsList *list.List) formulaArg {
13762 if argsList.Len() < 1 {
13763 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
13765 if argsList.Len() > 2 {
13766 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 2 arguments", name))
13768 text, numChars := argsList.Front().Value.(formulaArg).Value(), 1
13769 if argsList.Len() == 2 {
13770 numArg := argsList.Back().Value.(formulaArg).ToNumber()
13771 if numArg.Type != ArgNumber {
13774 if numArg.Number < 0 {
13775 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13777 numChars = int(numArg.Number)
13779 if name == "LEFTB" || name == "RIGHTB" {
13780 if len(text) > numChars {
13781 if name == "LEFTB" {
13782 return newStringFormulaArg(text[:numChars])
13785 return newStringFormulaArg(text[len(text)-numChars:])
13787 return newStringFormulaArg(text)
13790 if utf8.RuneCountInString(text) > numChars {
13791 if name == "LEFT" {
13792 return newStringFormulaArg(string([]rune(text)[:numChars]))
13795 return newStringFormulaArg(string([]rune(text)[utf8.RuneCountInString(text)-numChars:]))
13797 return newStringFormulaArg(text)
13800 // LEN returns the length of a supplied text string. The syntax of the
13804 func (fn *formulaFuncs) LEN(argsList *list.List) formulaArg {
13805 if argsList.Len() != 1 {
13806 return newErrorFormulaArg(formulaErrorVALUE, "LEN requires 1 string argument")
13808 return newNumberFormulaArg(float64(utf8.RuneCountInString(argsList.Front().Value.(formulaArg).Value())))
13811 // LENB returns the number of bytes used to represent the characters in a text
13812 // string. LENB counts 2 bytes per character only when a DBCS language is set
13813 // as the default language. Otherwise LENB behaves the same as LEN, counting
13814 // 1 byte per character. The syntax of the function is:
13817 func (fn *formulaFuncs) LENB(argsList *list.List) formulaArg {
13818 if argsList.Len() != 1 {
13819 return newErrorFormulaArg(formulaErrorVALUE, "LENB requires 1 string argument")
13822 for _, r := range argsList.Front().Value.(formulaArg).Value() {
13823 b := utf8.RuneLen(r)
13830 return newNumberFormulaArg(float64(bytes))
13833 // LOWER converts all characters in a supplied text string to lower case. The
13834 // syntax of the function is:
13837 func (fn *formulaFuncs) LOWER(argsList *list.List) formulaArg {
13838 if argsList.Len() != 1 {
13839 return newErrorFormulaArg(formulaErrorVALUE, "LOWER requires 1 argument")
13841 return newStringFormulaArg(strings.ToLower(argsList.Front().Value.(formulaArg).Value()))
13844 // MID function returns a specified number of characters from the middle of a
13845 // supplied text string. The syntax of the function is:
13847 // MID(text,start_num,num_chars)
13848 func (fn *formulaFuncs) MID(argsList *list.List) formulaArg {
13849 return fn.mid("MID", argsList)
13852 // MIDB returns a specific number of characters from a text string, starting
13853 // at the position you specify, based on the number of bytes you specify. The
13854 // syntax of the function is:
13856 // MID(text,start_num,num_chars)
13857 func (fn *formulaFuncs) MIDB(argsList *list.List) formulaArg {
13858 return fn.mid("MIDB", argsList)
13861 // mid is an implementation of the formula functions MID and MIDB.
13862 func (fn *formulaFuncs) mid(name string, argsList *list.List) formulaArg {
13863 if argsList.Len() != 3 {
13864 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 arguments", name))
13866 text := argsList.Front().Value.(formulaArg).Value()
13867 startNumArg, numCharsArg := argsList.Front().Next().Value.(formulaArg).ToNumber(), argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
13868 if startNumArg.Type != ArgNumber {
13871 if numCharsArg.Type != ArgNumber {
13874 startNum := int(startNumArg.Number)
13875 if startNum < 1 || numCharsArg.Number < 0 {
13876 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13878 if name == "MIDB" {
13880 var cnt, offset int
13881 for _, char := range text {
13884 if utf8.RuneLen(char) > 1 {
13888 if cnt == int(numCharsArg.Number) {
13891 if offset+1 > startNum {
13893 if cnt+2 > int(numCharsArg.Number) {
13894 result += string(char)[:1]
13897 result += string(char)
13900 result += string(char)
13905 return newStringFormulaArg(result)
13908 textLen := utf8.RuneCountInString(text)
13909 if startNum > textLen {
13910 return newStringFormulaArg("")
13913 endNum := startNum + int(numCharsArg.Number)
13914 if endNum > textLen+1 {
13915 return newStringFormulaArg(string([]rune(text)[startNum:]))
13917 return newStringFormulaArg(string([]rune(text)[startNum:endNum]))
13920 // PROPER converts all characters in a supplied text string to proper case
13921 // (i.e. all letters that do not immediately follow another letter are set to
13922 // upper case and all other characters are lower case). The syntax of the
13926 func (fn *formulaFuncs) PROPER(argsList *list.List) formulaArg {
13927 if argsList.Len() != 1 {
13928 return newErrorFormulaArg(formulaErrorVALUE, "PROPER requires 1 argument")
13930 buf := bytes.Buffer{}
13932 for _, char := range argsList.Front().Value.(formulaArg).Value() {
13933 if !isLetter && unicode.IsLetter(char) {
13934 buf.WriteRune(unicode.ToUpper(char))
13936 buf.WriteRune(unicode.ToLower(char))
13938 isLetter = unicode.IsLetter(char)
13940 return newStringFormulaArg(buf.String())
13943 // REPLACE function replaces all or part of a text string with another string.
13944 // The syntax of the function is:
13946 // REPLACE(old_text,start_num,num_chars,new_text)
13947 func (fn *formulaFuncs) REPLACE(argsList *list.List) formulaArg {
13948 return fn.replace("REPLACE", argsList)
13951 // REPLACEB replaces part of a text string, based on the number of bytes you
13952 // specify, with a different text string.
13954 // REPLACEB(old_text,start_num,num_chars,new_text)
13955 func (fn *formulaFuncs) REPLACEB(argsList *list.List) formulaArg {
13956 return fn.replace("REPLACEB", argsList)
13959 // replace is an implementation of the formula functions REPLACE and REPLACEB.
13960 // TODO: support DBCS include Japanese, Chinese (Simplified), Chinese
13961 // (Traditional), and Korean.
13962 func (fn *formulaFuncs) replace(name string, argsList *list.List) formulaArg {
13963 if argsList.Len() != 4 {
13964 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 4 arguments", name))
13966 sourceText, targetText := argsList.Front().Value.(formulaArg).Value(), argsList.Back().Value.(formulaArg).Value()
13967 startNumArg, numCharsArg := argsList.Front().Next().Value.(formulaArg).ToNumber(), argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
13968 if startNumArg.Type != ArgNumber {
13971 if numCharsArg.Type != ArgNumber {
13974 sourceTextLen, startIdx := len(sourceText), int(startNumArg.Number)
13975 if startIdx > sourceTextLen {
13976 startIdx = sourceTextLen + 1
13978 endIdx := startIdx + int(numCharsArg.Number)
13979 if endIdx > sourceTextLen {
13980 endIdx = sourceTextLen + 1
13982 if startIdx < 1 || endIdx < 1 {
13983 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
13985 result := sourceText[:startIdx-1] + targetText + sourceText[endIdx-1:]
13986 return newStringFormulaArg(result)
13989 // REPT function returns a supplied text string, repeated a specified number
13990 // of times. The syntax of the function is:
13992 // REPT(text,number_times)
13993 func (fn *formulaFuncs) REPT(argsList *list.List) formulaArg {
13994 if argsList.Len() != 2 {
13995 return newErrorFormulaArg(formulaErrorVALUE, "REPT requires 2 arguments")
13997 text := argsList.Front().Value.(formulaArg)
13998 if text.Type != ArgString {
13999 return newErrorFormulaArg(formulaErrorVALUE, "REPT requires first argument to be a string")
14001 times := argsList.Back().Value.(formulaArg).ToNumber()
14002 if times.Type != ArgNumber {
14003 return newErrorFormulaArg(formulaErrorVALUE, "REPT requires second argument to be a number")
14005 if times.Number < 0 {
14006 return newErrorFormulaArg(formulaErrorVALUE, "REPT requires second argument to be >= 0")
14008 if times.Number == 0 {
14009 return newStringFormulaArg("")
14011 buf := bytes.Buffer{}
14012 for i := 0; i < int(times.Number); i++ {
14013 buf.WriteString(text.Value())
14015 return newStringFormulaArg(buf.String())
14018 // RIGHT function returns a specified number of characters from the end of a
14019 // supplied text string. The syntax of the function is:
14021 // RIGHT(text,[num_chars])
14022 func (fn *formulaFuncs) RIGHT(argsList *list.List) formulaArg {
14023 return fn.leftRight("RIGHT", argsList)
14026 // RIGHTB returns the last character or characters in a text string, based on
14027 // the number of bytes you specify. The syntax of the function is:
14029 // RIGHTB(text,[num_bytes])
14030 func (fn *formulaFuncs) RIGHTB(argsList *list.List) formulaArg {
14031 return fn.leftRight("RIGHTB", argsList)
14034 // SEARCH function returns the position of a specified character or sub-string
14035 // within a supplied text string. The syntax of the function is:
14037 // SEARCH(search_text,within_text,[start_num])
14038 func (fn *formulaFuncs) SEARCH(argsList *list.List) formulaArg {
14039 return fn.find("SEARCH", argsList)
14042 // SEARCHB functions locate one text string within a second text string, and
14043 // return the number of the starting position of the first text string from the
14044 // first character of the second text string. The syntax of the function is:
14046 // SEARCHB(search_text,within_text,[start_num])
14047 func (fn *formulaFuncs) SEARCHB(argsList *list.List) formulaArg {
14048 return fn.find("SEARCHB", argsList)
14051 // SUBSTITUTE function replaces one or more instances of a given text string,
14052 // within an original text string. The syntax of the function is:
14054 // SUBSTITUTE(text,old_text,new_text,[instance_num])
14055 func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg {
14056 if argsList.Len() != 3 && argsList.Len() != 4 {
14057 return newErrorFormulaArg(formulaErrorVALUE, "SUBSTITUTE requires 3 or 4 arguments")
14059 text, sourceText := argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg)
14060 targetText, instanceNum := argsList.Front().Next().Next().Value.(formulaArg), 0
14061 if argsList.Len() == 3 {
14062 return newStringFormulaArg(strings.ReplaceAll(text.Value(), sourceText.Value(), targetText.Value()))
14064 instanceNumArg := argsList.Back().Value.(formulaArg).ToNumber()
14065 if instanceNumArg.Type != ArgNumber {
14066 return instanceNumArg
14068 instanceNum = int(instanceNumArg.Number)
14069 if instanceNum < 1 {
14070 return newErrorFormulaArg(formulaErrorVALUE, "instance_num should be > 0")
14072 str, sourceTextLen, count, chars, pos := text.Value(), len(sourceText.Value()), instanceNum, 0, -1
14075 index := strings.Index(str, sourceText.Value())
14080 pos = index + chars
14084 idx := sourceTextLen + index
14090 return newStringFormulaArg(text.Value())
14092 pre, post := text.Value()[:pos], text.Value()[pos+sourceTextLen:]
14093 return newStringFormulaArg(pre + targetText.Value() + post)
14096 // TEXT function converts a supplied numeric value into text, in a
14097 // user-specified format. The syntax of the function is:
14099 // TEXT(value,format_text)
14100 func (fn *formulaFuncs) TEXT(argsList *list.List) formulaArg {
14101 if argsList.Len() != 2 {
14102 return newErrorFormulaArg(formulaErrorVALUE, "TEXT requires 2 arguments")
14104 value, fmtText := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
14105 if value.Type == ArgError {
14108 if fmtText.Type == ArgError {
14111 cellType := CellTypeNumber
14112 if num := value.ToNumber(); num.Type != ArgNumber {
14113 cellType = CellTypeSharedString
14115 return newStringFormulaArg(format(value.Value(), fmtText.Value(), false, cellType, nil))
14118 // prepareTextAfterBefore checking and prepare arguments for the formula
14119 // functions TEXTAFTER and TEXTBEFORE.
14120 func (fn *formulaFuncs) prepareTextAfterBefore(name string, argsList *list.List) formulaArg {
14121 argsLen := argsList.Len()
14123 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 2 arguments", name))
14126 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s accepts at most 6 arguments", name))
14128 text, delimiter := argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg)
14129 instanceNum, matchMode, matchEnd, ifNotFound := newNumberFormulaArg(1), newBoolFormulaArg(false), newBoolFormulaArg(false), newEmptyFormulaArg()
14131 instanceNum = argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
14132 if instanceNum.Type != ArgNumber {
14137 matchMode = argsList.Front().Next().Next().Next().Value.(formulaArg).ToBool()
14138 if matchMode.Type != ArgNumber {
14141 if matchMode.Number == 1 {
14142 text, delimiter = newStringFormulaArg(strings.ToLower(text.Value())), newStringFormulaArg(strings.ToLower(delimiter.Value()))
14146 matchEnd = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToBool()
14147 if matchEnd.Type != ArgNumber {
14152 ifNotFound = argsList.Back().Value.(formulaArg)
14154 if text.Value() == "" {
14155 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
14157 lenArgsList := list.New().Init()
14158 lenArgsList.PushBack(text)
14159 textLen := fn.LEN(lenArgsList)
14160 if instanceNum.Number == 0 || instanceNum.Number > textLen.Number {
14161 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14163 reverseSearch, startPos := instanceNum.Number < 0, 0.0
14165 startPos = textLen.Number
14167 return newListFormulaArg([]formulaArg{
14168 text, delimiter, instanceNum, matchMode, matchEnd, ifNotFound,
14169 textLen, newBoolFormulaArg(reverseSearch), newNumberFormulaArg(startPos),
14173 // textAfterBeforeSearch is an implementation of the formula functions TEXTAFTER
14175 func textAfterBeforeSearch(text string, delimiter []string, startPos int, reverseSearch bool) (int, string) {
14177 var modifiedDelimiter string
14178 for i := 0; i < len(delimiter); i++ {
14179 nextDelimiter := delimiter[i]
14180 nextIdx := strings.Index(text[startPos:], nextDelimiter)
14182 nextIdx += startPos
14185 nextIdx = strings.LastIndex(text[:startPos], nextDelimiter)
14187 if idx == -1 || (((nextIdx < idx && !reverseSearch) || (nextIdx > idx && reverseSearch)) && idx != -1) {
14189 modifiedDelimiter = nextDelimiter
14192 return idx, modifiedDelimiter
14195 // textAfterBeforeResult is an implementation of the formula functions TEXTAFTER
14197 func textAfterBeforeResult(name, modifiedDelimiter string, text []rune, foundIdx, repeatZero, textLen int, matchEndActive, matchEnd, reverseSearch bool) formulaArg {
14198 if name == "TEXTAFTER" {
14199 endPos := len(modifiedDelimiter)
14200 if (repeatZero > 1 || matchEndActive) && matchEnd && reverseSearch {
14203 if foundIdx+endPos >= textLen {
14204 return newEmptyFormulaArg()
14206 return newStringFormulaArg(string(text[foundIdx+endPos : textLen]))
14208 return newStringFormulaArg(string(text[:foundIdx]))
14211 // textAfterBefore is an implementation of the formula functions TEXTAFTER and
14213 func (fn *formulaFuncs) textAfterBefore(name string, argsList *list.List) formulaArg {
14214 args := fn.prepareTextAfterBefore(name, argsList)
14215 if args.Type != ArgList {
14219 text = []rune(argsList.Front().Value.(formulaArg).Value())
14220 modifiedText = args.List[0].Value()
14221 delimiter = []string{args.List[1].Value()}
14222 instanceNum = args.List[2].Number
14223 matchEnd = args.List[4].Number == 1
14224 ifNotFound = args.List[5]
14225 textLen = args.List[6]
14226 reverseSearch = args.List[7].Number == 1
14228 repeatZero, startPos int
14229 matchEndActive bool
14230 modifiedDelimiter string
14233 startPos = int(args.List[8].Number)
14235 for i := 0; i < int(math.Abs(instanceNum)); i++ {
14236 foundIdx, modifiedDelimiter = textAfterBeforeSearch(modifiedText, delimiter, startPos, reverseSearch)
14240 if foundIdx == -1 {
14241 if matchEnd && i == int(math.Abs(instanceNum))-1 {
14242 if foundIdx = int(textLen.Number); reverseSearch {
14245 matchEndActive = true
14249 if startPos = foundIdx + len(modifiedDelimiter); reverseSearch {
14250 startPos = foundIdx - len(modifiedDelimiter)
14253 if foundIdx == -1 {
14256 return textAfterBeforeResult(name, modifiedDelimiter, text, foundIdx, repeatZero, int(textLen.Number), matchEndActive, matchEnd, reverseSearch)
14259 // TEXTAFTER function returns the text that occurs after a given substring or
14260 // delimiter. The syntax of the function is:
14262 // TEXTAFTER(text,delimiter,[instance_num],[match_mode],[match_end],[if_not_found])
14263 func (fn *formulaFuncs) TEXTAFTER(argsList *list.List) formulaArg {
14264 return fn.textAfterBefore("TEXTAFTER", argsList)
14267 // TEXTBEFORE function returns text that occurs before a given character or
14268 // string. The syntax of the function is:
14270 // TEXTBEFORE(text,delimiter,[instance_num],[match_mode],[match_end],[if_not_found])
14271 func (fn *formulaFuncs) TEXTBEFORE(argsList *list.List) formulaArg {
14272 return fn.textAfterBefore("TEXTBEFORE", argsList)
14275 // TEXTJOIN function joins together a series of supplied text strings into one
14276 // combined text string. The user can specify a delimiter to add between the
14277 // individual text items, if required. The syntax of the function is:
14279 // TEXTJOIN([delimiter],[ignore_empty],text1,[text2],...)
14280 func (fn *formulaFuncs) TEXTJOIN(argsList *list.List) formulaArg {
14281 if argsList.Len() < 3 {
14282 return newErrorFormulaArg(formulaErrorVALUE, "TEXTJOIN requires at least 3 arguments")
14284 if argsList.Len() > 252 {
14285 return newErrorFormulaArg(formulaErrorVALUE, "TEXTJOIN accepts at most 252 arguments")
14287 delimiter := argsList.Front().Value.(formulaArg)
14288 ignoreEmpty := argsList.Front().Next().Value.(formulaArg)
14289 if ignoreEmpty.Type != ArgNumber || !ignoreEmpty.Boolean {
14290 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14292 args, ok := textJoin(argsList.Front().Next().Next(), []string{}, ignoreEmpty.Number != 0)
14293 if ok.Type != ArgNumber {
14296 result := strings.Join(args, delimiter.Value())
14297 if len(result) > TotalCellChars {
14298 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("TEXTJOIN function exceeds %d characters", TotalCellChars))
14300 return newStringFormulaArg(result)
14303 // textJoin is an implementation of the formula function TEXTJOIN.
14304 func textJoin(arg *list.Element, arr []string, ignoreEmpty bool) ([]string, formulaArg) {
14305 for arg.Next(); arg != nil; arg = arg.Next() {
14306 switch arg.Value.(formulaArg).Type {
14308 return arr, arg.Value.(formulaArg)
14309 case ArgString, ArgEmpty:
14310 val := arg.Value.(formulaArg).Value()
14311 if val != "" || !ignoreEmpty {
14312 arr = append(arr, val)
14315 arr = append(arr, arg.Value.(formulaArg).Value())
14317 for _, row := range arg.Value.(formulaArg).Matrix {
14318 argList := list.New().Init()
14319 for _, ele := range row {
14320 argList.PushBack(ele)
14322 if argList.Len() > 0 {
14323 args, _ := textJoin(argList.Front(), []string{}, ignoreEmpty)
14324 arr = append(arr, args...)
14329 return arr, newBoolFormulaArg(true)
14332 // TRIM removes extra spaces (i.e. all spaces except for single spaces between
14333 // words or characters) from a supplied text string. The syntax of the
14337 func (fn *formulaFuncs) TRIM(argsList *list.List) formulaArg {
14338 if argsList.Len() != 1 {
14339 return newErrorFormulaArg(formulaErrorVALUE, "TRIM requires 1 argument")
14341 return newStringFormulaArg(strings.TrimSpace(argsList.Front().Value.(formulaArg).Value()))
14344 // UNICHAR returns the Unicode character that is referenced by the given
14345 // numeric value. The syntax of the function is:
14348 func (fn *formulaFuncs) UNICHAR(argsList *list.List) formulaArg {
14349 if argsList.Len() != 1 {
14350 return newErrorFormulaArg(formulaErrorVALUE, "UNICHAR requires 1 argument")
14352 numArg := argsList.Front().Value.(formulaArg).ToNumber()
14353 if numArg.Type != ArgNumber {
14356 if numArg.Number <= 0 || numArg.Number > 55295 {
14357 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14359 return newStringFormulaArg(string(rune(numArg.Number)))
14362 // UNICODE function returns the code point for the first character of a
14363 // supplied text string. The syntax of the function is:
14366 func (fn *formulaFuncs) UNICODE(argsList *list.List) formulaArg {
14367 return fn.code("UNICODE", argsList)
14370 // UPPER converts all characters in a supplied text string to upper case. The
14371 // syntax of the function is:
14374 func (fn *formulaFuncs) UPPER(argsList *list.List) formulaArg {
14375 if argsList.Len() != 1 {
14376 return newErrorFormulaArg(formulaErrorVALUE, "UPPER requires 1 argument")
14378 return newStringFormulaArg(strings.ToUpper(argsList.Front().Value.(formulaArg).Value()))
14381 // VALUE function converts a text string into a numeric value. The syntax of
14382 // the function is:
14385 func (fn *formulaFuncs) VALUE(argsList *list.List) formulaArg {
14386 if argsList.Len() != 1 {
14387 return newErrorFormulaArg(formulaErrorVALUE, "VALUE requires 1 argument")
14389 text := strings.ReplaceAll(argsList.Front().Value.(formulaArg).Value(), ",", "")
14391 if strings.HasSuffix(text, "%") {
14392 percent, text = 0.01, strings.TrimSuffix(text, "%")
14394 decimal := big.Float{}
14395 if _, ok := decimal.SetString(text); ok {
14396 value, _ := decimal.Float64()
14397 return newNumberFormulaArg(value * percent)
14399 dateValue, timeValue, errTime, errDate := 0.0, 0.0, false, false
14400 if !isDateOnlyFmt(text) {
14401 h, m, s, _, _, err := strToTime(text)
14402 errTime = err.Type == ArgError
14404 timeValue = (float64(h)*3600 + float64(m)*60 + s) / 86400
14407 y, m, d, _, err := strToDate(text)
14408 errDate = err.Type == ArgError
14410 dateValue = daysBetween(excelMinTime1900.Unix(), makeDate(y, time.Month(m), d)) + 1
14412 if errTime && errDate {
14413 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14415 return newNumberFormulaArg(dateValue + timeValue)
14418 // VALUETOTEXT function returns text from any specified value. It passes text
14419 // values unchanged, and converts non-text values to text.
14421 // VALUETOTEXT(value,[format])
14422 func (fn *formulaFuncs) VALUETOTEXT(argsList *list.List) formulaArg {
14423 format := prepareToText("VALUETOTEXT", argsList)
14424 if format.Type != ArgNumber {
14427 cell := argsList.Front().Value.(formulaArg)
14428 if num := cell.ToNumber(); num.Type != ArgNumber && format.Number == 1 {
14429 return newStringFormulaArg(fmt.Sprintf("\"%s\"", cell.Value()))
14431 return newStringFormulaArg(cell.Value())
14434 // Conditional Functions
14436 // IF function tests a supplied condition and returns one result if the
14437 // condition evaluates to TRUE, and another result if the condition evaluates
14438 // to FALSE. The syntax of the function is:
14440 // IF(logical_test,value_if_true,value_if_false)
14441 func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
14442 if argsList.Len() == 0 {
14443 return newErrorFormulaArg(formulaErrorVALUE, "IF requires at least 1 argument")
14445 if argsList.Len() > 3 {
14446 return newErrorFormulaArg(formulaErrorVALUE, "IF accepts at most 3 arguments")
14448 token := argsList.Front().Value.(formulaArg)
14454 switch token.Type {
14456 if cond, err = strconv.ParseBool(token.Value()); err != nil {
14457 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
14460 cond = token.Number == 1
14463 if argsList.Len() == 1 {
14464 return newBoolFormulaArg(cond)
14467 value := argsList.Front().Next().Value.(formulaArg)
14468 switch value.Type {
14470 result = value.ToNumber()
14472 result = newStringFormulaArg(value.Value())
14476 if argsList.Len() == 3 {
14477 value := argsList.Back().Value.(formulaArg)
14478 switch value.Type {
14480 result = value.ToNumber()
14482 result = newStringFormulaArg(value.Value())
14488 // Lookup and Reference Functions
14490 // ADDRESS function takes a row and a column number and returns a cell
14491 // reference as a text string. The syntax of the function is:
14493 // ADDRESS(row_num,column_num,[abs_num],[a1],[sheet_text])
14494 func (fn *formulaFuncs) ADDRESS(argsList *list.List) formulaArg {
14495 if argsList.Len() < 2 {
14496 return newErrorFormulaArg(formulaErrorVALUE, "ADDRESS requires at least 2 arguments")
14498 if argsList.Len() > 5 {
14499 return newErrorFormulaArg(formulaErrorVALUE, "ADDRESS requires at most 5 arguments")
14501 rowNum := argsList.Front().Value.(formulaArg).ToNumber()
14502 if rowNum.Type != ArgNumber {
14503 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14505 if rowNum.Number > TotalRows {
14506 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14508 colNum := argsList.Front().Next().Value.(formulaArg).ToNumber()
14509 if colNum.Type != ArgNumber {
14510 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14512 absNum := newNumberFormulaArg(1)
14513 if argsList.Len() >= 3 {
14514 absNum = argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
14515 if absNum.Type != ArgNumber {
14516 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14519 if absNum.Number < 1 || absNum.Number > 4 {
14520 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
14522 a1 := newBoolFormulaArg(true)
14523 if argsList.Len() >= 4 {
14524 a1 = argsList.Front().Next().Next().Next().Value.(formulaArg).ToBool()
14525 if a1.Type != ArgNumber {
14526 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14529 var sheetText string
14530 if argsList.Len() == 5 {
14531 sheetText = fmt.Sprintf("%s!", argsList.Back().Value.(formulaArg).Value())
14533 formatter := addressFmtMaps[fmt.Sprintf("%d_%s", int(absNum.Number), a1.Value())]
14534 addr, err := formatter(int(colNum.Number), int(rowNum.Number))
14536 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14538 return newStringFormulaArg(fmt.Sprintf("%s%s", sheetText, addr))
14541 // ANCHORARRAY function returns the entire spilled range for the dynamic array
14542 // in cell. The syntax of the function is:
14544 // ANCHORARRAY(cell)
14545 func (fn *formulaFuncs) ANCHORARRAY(argsList *list.List) formulaArg {
14546 if argsList.Len() != 1 {
14547 return newErrorFormulaArg(formulaErrorVALUE, "ANCHORARRAY requires 1 numeric argument")
14549 ws, err := fn.f.workSheetReader(fn.sheet)
14551 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
14553 ref := argsList.Front().Value.(formulaArg).cellRefs.Front().Value.(cellRef)
14554 cell := ws.SheetData.Row[ref.Row-1].C[ref.Col-1]
14556 return newEmptyFormulaArg()
14558 coordinates, err := rangeRefToCoordinates(cell.F.Ref)
14560 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
14562 _ = sortCoordinates(coordinates)
14563 var mtx [][]formulaArg
14564 for c := coordinates[0]; c <= coordinates[2]; c++ {
14565 var row []formulaArg
14566 for r := coordinates[1]; r <= coordinates[3]; r++ {
14567 cellName, _ := CoordinatesToCellName(c, r)
14568 result, err := fn.f.CalcCellValue(ref.Sheet, cellName, Options{RawCellValue: true})
14570 return newErrorFormulaArg(formulaErrorVALUE, err.Error())
14572 arg := newStringFormulaArg(result)
14573 if num := arg.ToNumber(); num.Type == ArgNumber {
14576 row = append(row, arg)
14578 mtx = append(mtx, row)
14580 return newMatrixFormulaArg(mtx)
14583 // CHOOSE function returns a value from an array, that corresponds to a
14584 // supplied index number (position). The syntax of the function is:
14586 // CHOOSE(index_num,value1,[value2],...)
14587 func (fn *formulaFuncs) CHOOSE(argsList *list.List) formulaArg {
14588 if argsList.Len() < 2 {
14589 return newErrorFormulaArg(formulaErrorVALUE, "CHOOSE requires 2 arguments")
14591 idx, err := strconv.Atoi(argsList.Front().Value.(formulaArg).Value())
14593 return newErrorFormulaArg(formulaErrorVALUE, "CHOOSE requires first argument of type number")
14595 if argsList.Len() <= idx {
14596 return newErrorFormulaArg(formulaErrorVALUE, "index_num should be <= to the number of values")
14598 arg := argsList.Front()
14599 for i := 0; i < idx; i++ {
14602 return arg.Value.(formulaArg)
14605 // matchPatternToRegExp convert find text pattern to regular expression.
14606 func matchPatternToRegExp(findText string, dbcs bool) (string, bool) {
14613 mark = "(?:(?:[\\x00-\\x0081])|(?:[\\xFF61-\\xFFA0])|(?:[\\xF8F1-\\xF8F4])|[0-9A-Za-z])"
14615 for _, char := range findText {
14616 if strings.ContainsAny(string(char), ".+$^[](){}|/") {
14617 exp += fmt.Sprintf("\\%s", string(char))
14630 exp += string(char)
14632 return fmt.Sprintf("^%s", exp), wildCard
14635 // matchPattern finds whether the text matches or satisfies the pattern
14636 // string. The pattern supports '*' and '?' wildcards in the pattern string.
14637 func matchPattern(findText, withinText string, dbcs bool, startNum int) (int, bool) {
14638 exp, wildCard := matchPatternToRegExp(findText, dbcs)
14640 for idx := range withinText {
14641 if offset < startNum {
14646 if ok, _ := regexp.MatchString(exp, withinText[idx:]); ok {
14650 if strings.Index(withinText[idx:], findText) == 0 {
14655 return offset, utf8.RuneCountInString(withinText) != offset-1
14658 // compareFormulaArg compares the left-hand sides and the right-hand sides'
14659 // formula arguments by given conditions such as case-sensitive, if exact
14660 // match, and make compare result as formula criteria condition type.
14661 func compareFormulaArg(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte {
14662 if lhs.Type != rhs.Type {
14667 if lhs.Number == rhs.Number {
14670 if lhs.Number < rhs.Number {
14675 ls, rs := lhs.Value(), rhs.Value()
14676 if !caseSensitive {
14677 ls, rs = strings.ToLower(ls), strings.ToLower(rs)
14679 if matchMode.Number == matchModeWildcard {
14680 if _, ok := matchPattern(rs, ls, false, 0); ok {
14684 return map[int]byte{1: criteriaG, -1: criteriaL, 0: criteriaEq}[strings.Compare(ls, rs)]
14688 return compareFormulaArgList(lhs, rhs, matchMode, caseSensitive)
14690 return compareFormulaArgMatrix(lhs, rhs, matchMode, caseSensitive)
14696 // compareFormulaArgList compares the left-hand sides and the right-hand sides
14697 // list type formula arguments.
14698 func compareFormulaArgList(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte {
14699 if len(lhs.List) < len(rhs.List) {
14702 if len(lhs.List) > len(rhs.List) {
14705 for arg := range lhs.List {
14706 criteria := compareFormulaArg(lhs.List[arg], rhs.List[arg], matchMode, caseSensitive)
14707 if criteria != criteriaEq {
14714 // compareFormulaArgMatrix compares the left-hand sides and the right-hand sides'
14715 // matrix type formula arguments.
14716 func compareFormulaArgMatrix(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte {
14717 if len(lhs.Matrix) < len(rhs.Matrix) {
14720 if len(lhs.Matrix) > len(rhs.Matrix) {
14723 for i := range lhs.Matrix {
14724 left, right := lhs.Matrix[i], rhs.Matrix[i]
14725 if len(left) < len(right) {
14728 if len(left) > len(right) {
14731 for arg := range left {
14732 criteria := compareFormulaArg(left[arg], right[arg], matchMode, caseSensitive)
14733 if criteria != criteriaEq {
14741 // COLUMN function returns the first column number within a supplied reference
14742 // or the number of the current column. The syntax of the function is:
14744 // COLUMN([reference])
14745 func (fn *formulaFuncs) COLUMN(argsList *list.List) formulaArg {
14746 if argsList.Len() > 1 {
14747 return newErrorFormulaArg(formulaErrorVALUE, "COLUMN requires at most 1 argument")
14749 if argsList.Len() == 1 {
14750 if argsList.Front().Value.(formulaArg).cellRanges != nil && argsList.Front().Value.(formulaArg).cellRanges.Len() > 0 {
14751 return newNumberFormulaArg(float64(argsList.Front().Value.(formulaArg).cellRanges.Front().Value.(cellRange).From.Col))
14753 if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
14754 return newNumberFormulaArg(float64(argsList.Front().Value.(formulaArg).cellRefs.Front().Value.(cellRef).Col))
14756 return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
14758 col, _, _ := CellNameToCoordinates(fn.cell)
14759 return newNumberFormulaArg(float64(col))
14762 // calcColsRowsMinMax calculation min and max value for given formula arguments
14763 // sequence of the formula functions COLUMNS and ROWS.
14764 func calcColsRowsMinMax(cols bool, argsList *list.List) (min, max int) {
14765 getVal := func(cols bool, cell cellRef) int {
14771 if argsList.Front().Value.(formulaArg).cellRanges != nil && argsList.Front().Value.(formulaArg).cellRanges.Len() > 0 {
14772 crs := argsList.Front().Value.(formulaArg).cellRanges
14773 for cr := crs.Front(); cr != nil; cr = cr.Next() {
14775 min = getVal(cols, cr.Value.(cellRange).From)
14777 if max < getVal(cols, cr.Value.(cellRange).To) {
14778 max = getVal(cols, cr.Value.(cellRange).To)
14782 if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
14783 cr := argsList.Front().Value.(formulaArg).cellRefs
14784 for refs := cr.Front(); refs != nil; refs = refs.Next() {
14786 min = getVal(cols, refs.Value.(cellRef))
14788 if max < getVal(cols, refs.Value.(cellRef)) {
14789 max = getVal(cols, refs.Value.(cellRef))
14796 // COLUMNS function receives an Excel range and returns the number of columns
14797 // that are contained within the range. The syntax of the function is:
14800 func (fn *formulaFuncs) COLUMNS(argsList *list.List) formulaArg {
14801 if argsList.Len() != 1 {
14802 return newErrorFormulaArg(formulaErrorVALUE, "COLUMNS requires 1 argument")
14804 min, max := calcColsRowsMinMax(true, argsList)
14805 if max == MaxColumns {
14806 return newNumberFormulaArg(float64(MaxColumns))
14808 result := max - min + 1
14811 return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
14813 return newNumberFormulaArg(float64(1))
14815 return newNumberFormulaArg(float64(result))
14818 // FORMULATEXT function returns a formula as a text string. The syntax of the
14821 // FORMULATEXT(reference)
14822 func (fn *formulaFuncs) FORMULATEXT(argsList *list.List) formulaArg {
14823 if argsList.Len() != 1 {
14824 return newErrorFormulaArg(formulaErrorVALUE, "FORMULATEXT requires 1 argument")
14826 refs := argsList.Front().Value.(formulaArg).cellRefs
14828 if refs != nil && refs.Len() > 0 {
14829 col, row = refs.Front().Value.(cellRef).Col, refs.Front().Value.(cellRef).Row
14831 ranges := argsList.Front().Value.(formulaArg).cellRanges
14832 if ranges != nil && ranges.Len() > 0 {
14833 col, row = ranges.Front().Value.(cellRange).From.Col, ranges.Front().Value.(cellRange).From.Row
14835 cell, err := CoordinatesToCellName(col, row)
14837 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14839 formula, _ := fn.f.GetCellFormula(fn.sheet, cell)
14840 return newStringFormulaArg(formula)
14843 // checkHVLookupArgs checking arguments, prepare extract mode, lookup value,
14844 // and data for the formula functions HLOOKUP and VLOOKUP.
14845 func checkHVLookupArgs(name string, argsList *list.List) (idx int, lookupValue, tableArray, matchMode, errArg formulaArg) {
14846 unit := map[string]string{
14850 if argsList.Len() < 3 {
14851 errArg = newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 3 arguments", name))
14854 if argsList.Len() > 4 {
14855 errArg = newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at most 4 arguments", name))
14858 lookupValue = argsList.Front().Value.(formulaArg)
14859 tableArray = argsList.Front().Next().Value.(formulaArg)
14860 if tableArray.Type != ArgMatrix {
14861 errArg = newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires second argument of table array", name))
14864 arg := argsList.Front().Next().Next().Value.(formulaArg)
14865 if arg.Type != ArgNumber || arg.Boolean {
14866 errArg = newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires numeric %s argument", name, unit))
14869 idx, matchMode = int(arg.Number)-1, newNumberFormulaArg(matchModeMaxLess)
14870 if argsList.Len() == 4 {
14871 rangeLookup := argsList.Back().Value.(formulaArg).ToBool()
14872 if rangeLookup.Type == ArgError {
14873 errArg = rangeLookup
14876 if rangeLookup.Number == 0 {
14877 matchMode = newNumberFormulaArg(matchModeWildcard)
14883 // HLOOKUP function 'looks up' a given value in the top row of a data array
14884 // (or table), and returns the corresponding value from another row of the
14885 // array. The syntax of the function is:
14887 // HLOOKUP(lookup_value,table_array,row_index_num,[range_lookup])
14888 func (fn *formulaFuncs) HLOOKUP(argsList *list.List) formulaArg {
14889 rowIdx, lookupValue, tableArray, matchMode, errArg := checkHVLookupArgs("HLOOKUP", argsList)
14890 if errArg.Type == ArgError {
14895 if matchMode.Number == matchModeWildcard || len(tableArray.Matrix) == TotalRows {
14896 matchIdx, wasExact = lookupLinearSearch(false, lookupValue, tableArray, matchMode, newNumberFormulaArg(searchModeLinear))
14898 matchIdx, wasExact = lookupBinarySearch(false, lookupValue, tableArray, matchMode, newNumberFormulaArg(searchModeAscBinary))
14900 if matchIdx == -1 {
14901 return newErrorFormulaArg(formulaErrorNA, "HLOOKUP no result found")
14903 if rowIdx < 0 || rowIdx >= len(tableArray.Matrix) {
14904 return newErrorFormulaArg(formulaErrorNA, "HLOOKUP has invalid row index")
14906 row := tableArray.Matrix[rowIdx]
14907 if wasExact || matchMode.Number == matchModeWildcard {
14908 return row[matchIdx]
14910 return newErrorFormulaArg(formulaErrorNA, "HLOOKUP no result found")
14913 // HYPERLINK function creates a hyperlink to a specified location. The syntax
14914 // of the function is:
14916 // HYPERLINK(link_location,[friendly_name])
14917 func (fn *formulaFuncs) HYPERLINK(argsList *list.List) formulaArg {
14918 if argsList.Len() < 1 {
14919 return newErrorFormulaArg(formulaErrorVALUE, "HYPERLINK requires at least 1 argument")
14921 if argsList.Len() > 2 {
14922 return newErrorFormulaArg(formulaErrorVALUE, "HYPERLINK allows at most 2 arguments")
14924 return newStringFormulaArg(argsList.Back().Value.(formulaArg).Value())
14927 // calcMatch returns the position of the value by given match type, criteria
14928 // and lookup array for the formula function MATCH.
14929 func calcMatch(matchType int, criteria *formulaCriteria, lookupArray []formulaArg) formulaArg {
14933 for i, arg := range lookupArray {
14934 if ok, _ := formulaCriteriaEval(arg, criteria); ok {
14935 return newNumberFormulaArg(float64(i + 1))
14939 for i, arg := range lookupArray {
14940 if ok, _ := formulaCriteriaEval(arg, &formulaCriteria{
14941 Type: criteriaGe, Condition: criteria.Condition,
14946 if criteria.Condition.Type == ArgNumber {
14951 for i, arg := range lookupArray {
14952 if ok, _ := formulaCriteriaEval(arg, &formulaCriteria{
14953 Type: criteriaLe, Condition: criteria.Condition,
14958 if criteria.Condition.Type == ArgNumber {
14964 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
14966 return newNumberFormulaArg(float64(idx + 1))
14969 // MATCH function looks up a value in an array, and returns the position of
14970 // the value within the array. The user can specify that the function should
14971 // only return a result if an exact match is found, or that the function
14972 // should return the position of the closest match (above or below), if an
14973 // exact match is not found. The syntax of the Match function is:
14975 // MATCH(lookup_value,lookup_array,[match_type])
14976 func (fn *formulaFuncs) MATCH(argsList *list.List) formulaArg {
14977 if argsList.Len() != 2 && argsList.Len() != 3 {
14978 return newErrorFormulaArg(formulaErrorVALUE, "MATCH requires 1 or 2 arguments")
14982 lookupArray []formulaArg
14983 lookupArrayArg = argsList.Front().Next().Value.(formulaArg)
14984 lookupArrayErr = "MATCH arguments lookup_array should be one-dimensional array"
14986 if argsList.Len() == 3 {
14987 matchTypeArg := argsList.Back().Value.(formulaArg).ToNumber()
14988 if matchTypeArg.Type != ArgNumber {
14989 return newErrorFormulaArg(formulaErrorVALUE, "MATCH requires numeric match_type argument")
14991 if matchTypeArg.Number == -1 || matchTypeArg.Number == 0 {
14992 matchType = int(matchTypeArg.Number)
14995 switch lookupArrayArg.Type {
14997 if len(lookupArrayArg.Matrix) != 1 && len(lookupArrayArg.Matrix[0]) != 1 {
14998 return newErrorFormulaArg(formulaErrorNA, lookupArrayErr)
15000 lookupArray = lookupArrayArg.ToList()
15002 return newErrorFormulaArg(formulaErrorNA, lookupArrayErr)
15004 return calcMatch(matchType, formulaCriteriaParser(argsList.Front().Value.(formulaArg)), lookupArray)
15007 // TRANSPOSE function 'transposes' an array of cells (i.e. the function copies
15008 // a horizontal range of cells into a vertical range and vice versa). The
15009 // syntax of the function is:
15011 // TRANSPOSE(array)
15012 func (fn *formulaFuncs) TRANSPOSE(argsList *list.List) formulaArg {
15013 if argsList.Len() != 1 {
15014 return newErrorFormulaArg(formulaErrorVALUE, "TRANSPOSE requires 1 argument")
15016 args := argsList.Back().Value.(formulaArg).ToList()
15017 rmin, rmax := calcColsRowsMinMax(false, argsList)
15018 cmin, cmax := calcColsRowsMinMax(true, argsList)
15019 cols, rows := cmax-cmin+1, rmax-rmin+1
15020 src := make([][]formulaArg, 0)
15021 for i := 0; i < len(args); i += cols {
15022 src = append(src, args[i:i+cols])
15024 mtx := make([][]formulaArg, cols)
15025 for r, row := range src {
15027 for c, cell := range row {
15029 if len(mtx[rowIdx]) == 0 {
15030 mtx[rowIdx] = make([]formulaArg, rows)
15032 mtx[rowIdx][colIdx] = cell
15035 return newMatrixFormulaArg(mtx)
15038 // lookupLinearSearch sequentially checks each look value of the lookup array until
15039 // a match is found or the whole list has been searched.
15040 func lookupLinearSearch(vertical bool, lookupValue, lookupArray, matchMode, searchMode formulaArg) (int, bool) {
15041 var tableArray []formulaArg
15043 for _, row := range lookupArray.Matrix {
15044 tableArray = append(tableArray, row[0])
15047 tableArray = lookupArray.Matrix[0]
15049 matchIdx, wasExact := -1, false
15051 for i, cell := range tableArray {
15053 if lookupValue.Type == ArgNumber {
15054 if lhs = cell.ToNumber(); lhs.Type == ArgError {
15057 } else if lookupValue.Type == ArgMatrix {
15059 } else if lookupArray.Type == ArgString {
15060 lhs = newStringFormulaArg(cell.Value())
15062 if compareFormulaArg(lhs, lookupValue, matchMode, false) == criteriaEq {
15065 if searchMode.Number == searchModeLinear {
15069 if matchMode.Number == matchModeMinGreater || matchMode.Number == matchModeMaxLess {
15070 matchIdx = int(calcMatch(int(matchMode.Number), formulaCriteriaParser(lookupValue), tableArray).Number)
15074 return matchIdx, wasExact
15077 // VLOOKUP function 'looks up' a given value in the left-hand column of a
15078 // data array (or table), and returns the corresponding value from another
15079 // column of the array. The syntax of the function is:
15081 // VLOOKUP(lookup_value,table_array,col_index_num,[range_lookup])
15082 func (fn *formulaFuncs) VLOOKUP(argsList *list.List) formulaArg {
15083 colIdx, lookupValue, tableArray, matchMode, errArg := checkHVLookupArgs("VLOOKUP", argsList)
15084 if errArg.Type == ArgError {
15089 if matchMode.Number == matchModeWildcard || len(tableArray.Matrix) == TotalRows {
15090 matchIdx, wasExact = lookupLinearSearch(true, lookupValue, tableArray, matchMode, newNumberFormulaArg(searchModeLinear))
15092 matchIdx, wasExact = lookupBinarySearch(true, lookupValue, tableArray, matchMode, newNumberFormulaArg(searchModeAscBinary))
15094 if matchIdx == -1 {
15095 return newErrorFormulaArg(formulaErrorNA, "VLOOKUP no result found")
15097 mtx := tableArray.Matrix[matchIdx]
15098 if colIdx < 0 || colIdx >= len(mtx) {
15099 return newErrorFormulaArg(formulaErrorNA, "VLOOKUP has invalid column index")
15101 if wasExact || matchMode.Number == matchModeWildcard {
15104 return newErrorFormulaArg(formulaErrorNA, "VLOOKUP no result found")
15107 // lookupBinarySearch finds the position of a target value when range lookup
15108 // is TRUE, if the data of table array can't guarantee be sorted, it will
15109 // return wrong result.
15110 func lookupBinarySearch(vertical bool, lookupValue, lookupArray, matchMode, searchMode formulaArg) (matchIdx int, wasExact bool) {
15111 var tableArray []formulaArg
15113 for _, row := range lookupArray.Matrix {
15114 tableArray = append(tableArray, row[0])
15117 tableArray = lookupArray.Matrix[0]
15119 low, high, lastMatchIdx := 0, len(tableArray)-1, -1
15122 mid := low + (high-low)/2
15123 cell := tableArray[mid]
15125 if lookupValue.Type == ArgNumber {
15126 if lhs = cell.ToNumber(); lhs.Type == ArgError {
15129 } else if lookupValue.Type == ArgMatrix && vertical {
15131 } else if lookupValue.Type == ArgString {
15132 lhs = newStringFormulaArg(cell.Value())
15134 result := compareFormulaArg(lhs, lookupValue, matchMode, false)
15135 if result == criteriaEq {
15136 matchIdx, wasExact = mid, true
15137 if searchMode.Number == searchModeDescBinary {
15138 matchIdx = count - matchIdx
15141 } else if result == criteriaG {
15143 } else if result == criteriaL {
15145 if cell.Type != ArgEmpty {
15146 lastMatchIdx = matchIdx
15153 matchIdx, wasExact = lastMatchIdx, true
15157 // checkLookupArgs checking arguments, prepare lookup value, and data for the
15158 // formula function LOOKUP.
15159 func checkLookupArgs(argsList *list.List) (arrayForm bool, lookupValue, lookupVector, errArg formulaArg) {
15160 if argsList.Len() < 2 {
15161 errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at least 2 arguments")
15164 if argsList.Len() > 3 {
15165 errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at most 3 arguments")
15168 lookupValue = newStringFormulaArg(argsList.Front().Value.(formulaArg).Value())
15169 lookupVector = argsList.Front().Next().Value.(formulaArg)
15170 if lookupVector.Type != ArgMatrix && lookupVector.Type != ArgList {
15171 errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires second argument of table array")
15174 arrayForm = lookupVector.Type == ArgMatrix
15175 if arrayForm && len(lookupVector.Matrix) == 0 {
15176 errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires not empty range as second argument")
15181 // iterateLookupArgs iterate arguments to extract columns and calculate match
15182 // index for the formula function LOOKUP.
15183 func iterateLookupArgs(lookupValue, lookupVector formulaArg) ([]formulaArg, int, bool) {
15184 cols, matchIdx, ok := lookupCol(lookupVector, 0), -1, false
15185 for idx, col := range cols {
15189 lhs = lhs.ToNumber()
15191 if lhs.Type == ArgError {
15196 compare := compareFormulaArg(lhs, col, newNumberFormulaArg(matchModeMaxLess), false)
15197 // Find exact match
15198 if compare == criteriaEq {
15202 // Find the nearest match if lookup value is more than or equal to the first value in lookup vector
15204 ok = compare == criteriaG
15205 } else if ok && compare == criteriaL && matchIdx == -1 {
15209 return cols, matchIdx, ok
15212 // index is an implementation of the formula function INDEX.
15213 func (fn *formulaFuncs) index(array formulaArg, rowIdx, colIdx int) formulaArg {
15214 var cells []formulaArg
15215 if array.Type == ArgMatrix {
15216 cellMatrix := array.Matrix
15217 if rowIdx < -1 || rowIdx >= len(cellMatrix) {
15218 return newErrorFormulaArg(formulaErrorREF, "INDEX row_num out of range")
15221 if colIdx >= len(cellMatrix[0]) {
15222 return newErrorFormulaArg(formulaErrorREF, "INDEX col_num out of range")
15224 var column [][]formulaArg
15225 for _, cells = range cellMatrix {
15226 column = append(column, []formulaArg{cells[colIdx]})
15228 return newMatrixFormulaArg(column)
15230 cells = cellMatrix[rowIdx]
15232 if colIdx < -1 || colIdx >= len(cells) {
15233 return newErrorFormulaArg(formulaErrorREF, "INDEX col_num out of range")
15235 return newListFormulaArg(cells)
15238 // validateMatchMode check the number of match mode if be equal to 0, 1, -1 or
15240 func validateMatchMode(mode float64) bool {
15241 return mode == matchModeExact || mode == matchModeMinGreater || mode == matchModeMaxLess || mode == matchModeWildcard
15244 // validateSearchMode check the number of search mode if be equal to 1, -1, 2
15246 func validateSearchMode(mode float64) bool {
15247 return mode == searchModeLinear || mode == searchModeReverseLinear || mode == searchModeAscBinary || mode == searchModeDescBinary
15250 // prepareXlookupArgs checking and prepare arguments for the formula function
15252 func (fn *formulaFuncs) prepareXlookupArgs(argsList *list.List) formulaArg {
15253 if argsList.Len() < 3 {
15254 return newErrorFormulaArg(formulaErrorVALUE, "XLOOKUP requires at least 3 arguments")
15256 if argsList.Len() > 6 {
15257 return newErrorFormulaArg(formulaErrorVALUE, "XLOOKUP allows at most 6 arguments")
15259 lookupValue := argsList.Front().Value.(formulaArg)
15260 lookupArray := argsList.Front().Next().Value.(formulaArg)
15261 returnArray := argsList.Front().Next().Next().Value.(formulaArg)
15262 ifNotFond := newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
15263 matchMode, searchMode := newNumberFormulaArg(matchModeExact), newNumberFormulaArg(searchModeLinear)
15264 if argsList.Len() > 3 {
15265 ifNotFond = argsList.Front().Next().Next().Next().Value.(formulaArg)
15267 if argsList.Len() > 4 {
15268 if matchMode = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); matchMode.Type != ArgNumber {
15272 if argsList.Len() > 5 {
15273 if searchMode = argsList.Back().Value.(formulaArg).ToNumber(); searchMode.Type != ArgNumber {
15277 if lookupArray.Type != ArgMatrix || returnArray.Type != ArgMatrix {
15278 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
15280 if !validateMatchMode(matchMode.Number) || !validateSearchMode(searchMode.Number) {
15281 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15283 return newListFormulaArg([]formulaArg{lookupValue, lookupArray, returnArray, ifNotFond, matchMode, searchMode})
15286 // xlookup is an implementation of the formula function XLOOKUP.
15287 func (fn *formulaFuncs) xlookup(lookupRows, lookupCols, returnArrayRows, returnArrayCols, matchIdx int,
15288 condition1, condition2, condition3, condition4 bool, returnArray formulaArg,
15290 var result [][]formulaArg
15291 for rowIdx, row := range returnArray.Matrix {
15292 for colIdx, cell := range row {
15295 result = append(result, []formulaArg{cell})
15298 if returnArrayRows > 1 && returnArrayCols > 1 {
15299 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15303 if returnArrayCols != lookupCols {
15304 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15306 if colIdx == matchIdx {
15307 result = append(result, []formulaArg{cell})
15312 if returnArrayRows != lookupRows {
15313 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15315 if rowIdx == matchIdx {
15316 if len(result) == 0 {
15317 result = append(result, []formulaArg{cell})
15320 result[0] = append(result[0], cell)
15325 array := newMatrixFormulaArg(result)
15326 cells := array.ToList()
15327 if len(cells) == 1 {
15333 // XLOOKUP function searches a range or an array, and then returns the item
15334 // corresponding to the first match it finds. If no match exists, then
15335 // XLOOKUP can return the closest (approximate) match. The syntax of the
15338 // XLOOKUP(lookup_value,lookup_array,return_array,[if_not_found],[match_mode],[search_mode])
15339 func (fn *formulaFuncs) XLOOKUP(argsList *list.List) formulaArg {
15340 args := fn.prepareXlookupArgs(argsList)
15341 if args.Type != ArgList {
15344 lookupValue, lookupArray, returnArray, ifNotFond, matchMode, searchMode := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5]
15345 lookupRows, lookupCols := len(lookupArray.Matrix), 0
15346 if lookupRows > 0 {
15347 lookupCols = len(lookupArray.Matrix[0])
15349 if lookupRows != 1 && lookupCols != 1 {
15350 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15352 verticalLookup := lookupRows >= lookupCols
15354 switch searchMode.Number {
15355 case searchModeLinear, searchModeReverseLinear:
15356 matchIdx, _ = lookupLinearSearch(verticalLookup, lookupValue, lookupArray, matchMode, searchMode)
15358 matchIdx, _ = lookupBinarySearch(verticalLookup, lookupValue, lookupArray, matchMode, searchMode)
15360 if matchIdx == -1 {
15363 returnArrayRows, returnArrayCols := len(returnArray.Matrix), len(returnArray.Matrix[0])
15364 condition1 := lookupRows == 1 && lookupCols == 1
15365 condition2 := returnArrayRows == 1 || returnArrayCols == 1
15366 condition3 := lookupRows == 1 && lookupCols > 1
15367 condition4 := lookupRows > 1 && lookupCols == 1
15368 return fn.xlookup(lookupRows, lookupCols, returnArrayRows, returnArrayCols, matchIdx, condition1, condition2, condition3, condition4, returnArray)
15371 // INDEX function returns a reference to a cell that lies in a specified row
15372 // and column of a range of cells. The syntax of the function is:
15374 // INDEX(array,row_num,[col_num])
15375 func (fn *formulaFuncs) INDEX(argsList *list.List) formulaArg {
15376 if argsList.Len() < 2 || argsList.Len() > 3 {
15377 return newErrorFormulaArg(formulaErrorVALUE, "INDEX requires 2 or 3 arguments")
15379 array := argsList.Front().Value.(formulaArg)
15380 if array.Type != ArgMatrix && array.Type != ArgList {
15381 array = newMatrixFormulaArg([][]formulaArg{{array}})
15383 rowArg := argsList.Front().Next().Value.(formulaArg).ToNumber()
15384 if rowArg.Type != ArgNumber {
15387 rowIdx, colIdx := int(rowArg.Number)-1, -1
15388 if argsList.Len() == 3 {
15389 colArg := argsList.Back().Value.(formulaArg).ToNumber()
15390 if colArg.Type != ArgNumber {
15393 colIdx = int(colArg.Number) - 1
15395 if rowIdx == -1 && colIdx == -1 {
15396 if len(array.ToList()) != 1 {
15397 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15399 return array.ToList()[0]
15401 cells := fn.index(array, rowIdx, colIdx)
15402 if cells.Type != ArgList {
15406 return newMatrixFormulaArg([][]formulaArg{cells.List})
15408 return cells.List[colIdx]
15411 // INDIRECT function converts a text string into a cell reference. The syntax
15412 // of the Indirect function is:
15414 // INDIRECT(ref_text,[a1])
15415 func (fn *formulaFuncs) INDIRECT(argsList *list.List) formulaArg {
15416 if argsList.Len() != 1 && argsList.Len() != 2 {
15417 return newErrorFormulaArg(formulaErrorVALUE, "INDIRECT requires 1 or 2 arguments")
15419 refText := argsList.Front().Value.(formulaArg).Value()
15420 a1 := newBoolFormulaArg(true)
15421 if argsList.Len() == 2 {
15422 if a1 = argsList.Back().Value.(formulaArg).ToBool(); a1.Type != ArgNumber {
15423 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15426 R1C1ToA1 := func(ref string) (cell string, err error) {
15427 parts := strings.Split(strings.TrimLeft(ref, "R"), "C")
15428 if len(parts) != 2 {
15431 row, err := strconv.Atoi(parts[0])
15435 col, err := strconv.Atoi(parts[1])
15439 cell, err = CoordinatesToCellName(col, row)
15442 refs := strings.Split(refText, ":")
15443 fromRef, toRef := refs[0], ""
15444 if len(refs) == 2 {
15447 if a1.Number == 0 {
15448 from, err := R1C1ToA1(refs[0])
15450 return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
15453 if len(refs) == 2 {
15454 to, err := R1C1ToA1(refs[1])
15456 return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
15461 if len(refs) == 1 {
15462 value, err := fn.f.GetCellValue(fn.sheet, fromRef)
15464 return newErrorFormulaArg(formulaErrorREF, formulaErrorREF)
15466 return newStringFormulaArg(value)
15468 arg, _ := fn.f.parseReference(fn.ctx, fn.sheet, fromRef+":"+toRef)
15472 // LOOKUP function performs an approximate match lookup in a one-column or
15473 // one-row range, and returns the corresponding value from another one-column
15474 // or one-row range. The syntax of the function is:
15476 // LOOKUP(lookup_value,lookup_vector,[result_vector])
15477 func (fn *formulaFuncs) LOOKUP(argsList *list.List) formulaArg {
15478 arrayForm, lookupValue, lookupVector, errArg := checkLookupArgs(argsList)
15479 if errArg.Type == ArgError {
15482 cols, matchIdx, ok := iterateLookupArgs(lookupValue, lookupVector)
15483 if ok && matchIdx == -1 {
15484 matchIdx = len(cols) - 1
15486 var column []formulaArg
15487 if argsList.Len() == 3 {
15488 column = lookupCol(argsList.Back().Value.(formulaArg), 0)
15489 } else if arrayForm && len(lookupVector.Matrix[0]) > 1 {
15490 column = lookupCol(lookupVector, 1)
15494 if matchIdx < 0 || matchIdx >= len(column) {
15495 return newErrorFormulaArg(formulaErrorNA, "LOOKUP no result found")
15497 return column[matchIdx]
15500 // lookupCol extract columns for LOOKUP.
15501 func lookupCol(arr formulaArg, idx int) []formulaArg {
15503 if arr.Type == ArgMatrix {
15505 for _, r := range arr.Matrix {
15507 col = append(col, r[idx])
15510 col = append(col, newEmptyFormulaArg())
15516 // ROW function returns the first row number within a supplied reference or
15517 // the number of the current row. The syntax of the function is:
15519 // ROW([reference])
15520 func (fn *formulaFuncs) ROW(argsList *list.List) formulaArg {
15521 if argsList.Len() > 1 {
15522 return newErrorFormulaArg(formulaErrorVALUE, "ROW requires at most 1 argument")
15524 if argsList.Len() == 1 {
15525 if argsList.Front().Value.(formulaArg).cellRanges != nil && argsList.Front().Value.(formulaArg).cellRanges.Len() > 0 {
15526 return newNumberFormulaArg(float64(argsList.Front().Value.(formulaArg).cellRanges.Front().Value.(cellRange).From.Row))
15528 if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
15529 return newNumberFormulaArg(float64(argsList.Front().Value.(formulaArg).cellRefs.Front().Value.(cellRef).Row))
15531 return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
15533 _, row, _ := CellNameToCoordinates(fn.cell)
15534 return newNumberFormulaArg(float64(row))
15537 // ROWS function takes an Excel range and returns the number of rows that are
15538 // contained within the range. The syntax of the function is:
15541 func (fn *formulaFuncs) ROWS(argsList *list.List) formulaArg {
15542 if argsList.Len() != 1 {
15543 return newErrorFormulaArg(formulaErrorVALUE, "ROWS requires 1 argument")
15545 min, max := calcColsRowsMinMax(false, argsList)
15546 if max == TotalRows {
15547 return newNumberFormulaArg(TotalRows)
15549 result := max - min + 1
15552 return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
15554 return newNumberFormulaArg(float64(1))
15556 return newNumberFormulaArg(float64(result))
15561 // ENCODEURL function returns a URL-encoded string, replacing certain
15562 // non-alphanumeric characters with the percentage symbol (%) and a
15563 // hexadecimal number. The syntax of the function is:
15566 func (fn *formulaFuncs) ENCODEURL(argsList *list.List) formulaArg {
15567 if argsList.Len() != 1 {
15568 return newErrorFormulaArg(formulaErrorVALUE, "ENCODEURL requires 1 argument")
15570 token := argsList.Front().Value.(formulaArg).Value()
15571 return newStringFormulaArg(strings.ReplaceAll(url.QueryEscape(token), "+", "%20"))
15574 // Financial Functions
15576 // validateFrequency check the number of coupon payments per year if be equal to 1, 2 or 4.
15577 func validateFrequency(freq float64) bool {
15578 return freq == 1 || freq == 2 || freq == 4
15581 // ACCRINT function returns the accrued interest in a security that pays
15582 // periodic interest. The syntax of the function is:
15584 // ACCRINT(issue,first_interest,settlement,rate,par,frequency,[basis],[calc_method])
15585 func (fn *formulaFuncs) ACCRINT(argsList *list.List) formulaArg {
15586 if argsList.Len() < 6 {
15587 return newErrorFormulaArg(formulaErrorVALUE, "ACCRINT requires at least 6 arguments")
15589 if argsList.Len() > 8 {
15590 return newErrorFormulaArg(formulaErrorVALUE, "ACCRINT allows at most 8 arguments")
15592 args := fn.prepareDataValueArgs(3, argsList)
15593 if args.Type != ArgList {
15596 issue, settlement := args.List[0], args.List[2]
15597 rate := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
15598 par := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
15599 frequency := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
15600 if rate.Type != ArgNumber || par.Type != ArgNumber || frequency.Type != ArgNumber {
15601 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15603 if !validateFrequency(frequency.Number) {
15604 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15606 basis := newNumberFormulaArg(0)
15607 if argsList.Len() >= 7 {
15608 if basis = argsList.Front().Next().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
15609 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15612 if argsList.Len() == 8 {
15613 if cm := argsList.Back().Value.(formulaArg).ToBool(); cm.Type != ArgNumber {
15614 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15617 frac1 := yearFrac(issue.Number, settlement.Number, int(basis.Number))
15618 if frac1.Type != ArgNumber {
15621 return newNumberFormulaArg(par.Number * rate.Number * frac1.Number)
15624 // ACCRINTM function returns the accrued interest in a security that pays
15625 // interest at maturity. The syntax of the function is:
15627 // ACCRINTM(issue,settlement,rate,[par],[basis])
15628 func (fn *formulaFuncs) ACCRINTM(argsList *list.List) formulaArg {
15629 if argsList.Len() != 4 && argsList.Len() != 5 {
15630 return newErrorFormulaArg(formulaErrorVALUE, "ACCRINTM requires 4 or 5 arguments")
15632 args := fn.prepareDataValueArgs(2, argsList)
15633 if args.Type != ArgList {
15636 issue, settlement := args.List[0], args.List[1]
15637 if settlement.Number < issue.Number {
15638 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15640 rate := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
15641 par := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
15642 if rate.Type != ArgNumber || par.Type != ArgNumber {
15643 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15645 if par.Number <= 0 {
15646 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15648 basis := newNumberFormulaArg(0)
15649 if argsList.Len() == 5 {
15650 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
15651 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15654 frac := yearFrac(issue.Number, settlement.Number, int(basis.Number))
15655 if frac.Type != ArgNumber {
15658 return newNumberFormulaArg(frac.Number * rate.Number * par.Number)
15661 // prepareAmorArgs checking and prepare arguments for the formula functions
15662 // AMORDEGRC and AMORLINC.
15663 func (fn *formulaFuncs) prepareAmorArgs(name string, argsList *list.List) formulaArg {
15664 cost := argsList.Front().Value.(formulaArg).ToNumber()
15665 if cost.Type != ArgNumber {
15666 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires cost to be number argument", name))
15668 if cost.Number < 0 {
15669 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires cost >= 0", name))
15671 args := list.New().Init()
15672 args.PushBack(argsList.Front().Next().Value.(formulaArg))
15673 datePurchased := fn.DATEVALUE(args)
15674 if datePurchased.Type != ArgNumber {
15675 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15678 args.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
15679 firstPeriod := fn.DATEVALUE(args)
15680 if firstPeriod.Type != ArgNumber {
15681 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15683 if firstPeriod.Number < datePurchased.Number {
15684 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15686 salvage := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
15687 if salvage.Type != ArgNumber {
15688 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15690 if salvage.Number < 0 || salvage.Number > cost.Number {
15691 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15693 period := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
15694 if period.Type != ArgNumber || period.Number < 0 {
15695 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15697 rate := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
15698 if rate.Type != ArgNumber || rate.Number < 0 {
15699 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15701 basis := newNumberFormulaArg(0)
15702 if argsList.Len() == 7 {
15703 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
15704 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15707 return newListFormulaArg([]formulaArg{cost, datePurchased, firstPeriod, salvage, period, rate, basis})
15710 // AMORDEGRC function is provided for users of the French accounting system.
15711 // The function calculates the prorated linear depreciation of an asset for a
15712 // specified accounting period. The syntax of the function is:
15714 // AMORDEGRC(cost,date_purchased,first_period,salvage,period,rate,[basis])
15715 func (fn *formulaFuncs) AMORDEGRC(argsList *list.List) formulaArg {
15716 if argsList.Len() != 6 && argsList.Len() != 7 {
15717 return newErrorFormulaArg(formulaErrorVALUE, "AMORDEGRC requires 6 or 7 arguments")
15719 args := fn.prepareAmorArgs("AMORDEGRC", argsList)
15720 if args.Type != ArgList {
15723 cost, datePurchased, firstPeriod, salvage, period, rate, basis := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6]
15724 if rate.Number >= 0.5 {
15725 return newErrorFormulaArg(formulaErrorNUM, "AMORDEGRC requires rate to be < 0.5")
15727 assetsLife, amorCoeff := 1/rate.Number, 2.5
15728 if assetsLife < 3 {
15730 } else if assetsLife < 5 {
15732 } else if assetsLife <= 6 {
15735 rate.Number *= amorCoeff
15736 frac := yearFrac(datePurchased.Number, firstPeriod.Number, int(basis.Number))
15737 if frac.Type != ArgNumber {
15740 nRate := float64(int((frac.Number * cost.Number * rate.Number) + 0.5))
15741 cost.Number -= nRate
15742 rest := cost.Number - salvage.Number
15743 for n := 0; n < int(period.Number); n++ {
15744 nRate = float64(int((cost.Number * rate.Number) + 0.5))
15747 switch int(period.Number) - n {
15750 return newNumberFormulaArg(float64(int((cost.Number * 0.5) + 0.5)))
15752 return newNumberFormulaArg(0)
15755 cost.Number -= nRate
15757 return newNumberFormulaArg(nRate)
15760 // AMORLINC function is provided for users of the French accounting system.
15761 // The function calculates the prorated linear depreciation of an asset for a
15762 // specified accounting period. The syntax of the function is:
15764 // AMORLINC(cost,date_purchased,first_period,salvage,period,rate,[basis])
15765 func (fn *formulaFuncs) AMORLINC(argsList *list.List) formulaArg {
15766 if argsList.Len() != 6 && argsList.Len() != 7 {
15767 return newErrorFormulaArg(formulaErrorVALUE, "AMORLINC requires 6 or 7 arguments")
15769 args := fn.prepareAmorArgs("AMORLINC", argsList)
15770 if args.Type != ArgList {
15773 cost, datePurchased, firstPeriod, salvage, period, rate, basis := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6]
15774 frac := yearFrac(datePurchased.Number, firstPeriod.Number, int(basis.Number))
15775 if frac.Type != ArgNumber {
15778 rate1 := frac.Number * cost.Number * rate.Number
15779 if period.Number == 0 {
15780 return newNumberFormulaArg(rate1)
15782 rate2 := cost.Number * rate.Number
15783 delta := cost.Number - salvage.Number
15784 periods := int((delta - rate1) / rate2)
15785 if int(period.Number) <= periods {
15786 return newNumberFormulaArg(rate2)
15787 } else if int(period.Number)-1 == periods {
15788 return newNumberFormulaArg(delta - rate2*float64(periods) - math.Nextafter(rate1, rate1))
15790 return newNumberFormulaArg(0)
15793 // prepareCouponArgs checking and prepare arguments for the formula functions
15794 // COUPDAYBS, COUPDAYS, COUPDAYSNC, COUPPCD, COUPNUM and COUPNCD.
15795 func (fn *formulaFuncs) prepareCouponArgs(name string, argsList *list.List) formulaArg {
15796 if argsList.Len() != 3 && argsList.Len() != 4 {
15797 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 or 4 arguments", name))
15799 args := fn.prepareDataValueArgs(2, argsList)
15800 if args.Type != ArgList {
15803 settlement, maturity := args.List[0], args.List[1]
15804 if settlement.Number >= maturity.Number {
15805 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > settlement", name))
15807 frequency := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
15808 if frequency.Type != ArgNumber {
15809 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
15811 if !validateFrequency(frequency.Number) {
15812 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15814 basis := newNumberFormulaArg(0)
15815 if argsList.Len() == 4 {
15816 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
15817 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
15820 return newListFormulaArg([]formulaArg{settlement, maturity, frequency, basis})
15823 // is30BasisMethod determine if the financial day count basis rules is 30/360
15825 func is30BasisMethod(basis int) bool {
15826 return basis == 0 || basis == 4
15829 // getDaysInMonthRange return the day by given year, month range and day count
15831 func getDaysInMonthRange(fromMonth, toMonth int) int {
15832 if fromMonth > toMonth {
15835 return (toMonth - fromMonth + 1) * 30
15838 // getDayOnBasis returns the day by given date and day count basis.
15839 func getDayOnBasis(y, m, d, basis int) int {
15840 if !is30BasisMethod(basis) {
15844 dim := getDaysInMonth(y, m)
15845 if day > 30 || d >= dim || day >= dim {
15851 // coupdays returns the number of days that base on date range and the day
15852 // count basis to be used.
15853 func coupdays(from, to time.Time, basis int) float64 {
15855 fromY, fromM, fromD := from.Date()
15856 toY, toM, toD := to.Date()
15857 fromDay, toDay := getDayOnBasis(fromY, int(fromM), fromD, basis), getDayOnBasis(toY, int(toM), toD, basis)
15858 if !is30BasisMethod(basis) {
15859 return (daysBetween(excelMinTime1900.Unix(), makeDate(toY, toM, toDay)) + 1) - (daysBetween(excelMinTime1900.Unix(), makeDate(fromY, fromM, fromDay)) + 1)
15862 if (int(fromM) == 2 || fromDay < 30) && toD == 31 {
15866 if int(fromM) == 2 && fromDay == 30 {
15867 fromDay = getDaysInMonth(fromY, 2)
15869 if int(toM) == 2 && toDay == 30 {
15870 toDay = getDaysInMonth(toY, 2)
15873 if fromY < toY || (fromY == toY && int(fromM) < int(toM)) {
15874 days = 30 - fromDay + 1
15877 date := time.Date(fromY, fromM, fromD, 0, 0, 0, 0, time.UTC).AddDate(0, 1, 0)
15878 if date.Year() < toY {
15879 days += getDaysInMonthRange(int(date.Month()), 12)
15880 date = date.AddDate(0, 13-int(date.Month()), 0)
15882 days += getDaysInMonthRange(int(date.Month()), int(toM)-1)
15884 if days += toDay - fromDay; days > 0 {
15885 return float64(days)
15890 // COUPDAYBS function calculates the number of days from the beginning of a
15891 // coupon's period to the settlement date. The syntax of the function is:
15893 // COUPDAYBS(settlement,maturity,frequency,[basis])
15894 func (fn *formulaFuncs) COUPDAYBS(argsList *list.List) formulaArg {
15895 args := fn.prepareCouponArgs("COUPDAYBS", argsList)
15896 if args.Type != ArgList {
15899 settlement := timeFromExcelTime(args.List[0].Number, false)
15900 pcd := timeFromExcelTime(fn.COUPPCD(argsList).Number, false)
15901 return newNumberFormulaArg(coupdays(pcd, settlement, int(args.List[3].Number)))
15904 // COUPDAYS function calculates the number of days in a coupon period that
15905 // contains the settlement date. The syntax of the function is:
15907 // COUPDAYS(settlement,maturity,frequency,[basis])
15908 func (fn *formulaFuncs) COUPDAYS(argsList *list.List) formulaArg {
15909 args := fn.prepareCouponArgs("COUPDAYS", argsList)
15910 if args.Type != ArgList {
15913 freq := args.List[2].Number
15914 basis := int(args.List[3].Number)
15916 pcd := timeFromExcelTime(fn.COUPPCD(argsList).Number, false)
15917 next := pcd.AddDate(0, 12/int(freq), 0)
15918 return newNumberFormulaArg(coupdays(pcd, next, basis))
15920 return newNumberFormulaArg(float64(getYearDays(0, basis)) / freq)
15923 // COUPDAYSNC function calculates the number of days from the settlement date
15924 // to the next coupon date. The syntax of the function is:
15926 // COUPDAYSNC(settlement,maturity,frequency,[basis])
15927 func (fn *formulaFuncs) COUPDAYSNC(argsList *list.List) formulaArg {
15928 args := fn.prepareCouponArgs("COUPDAYSNC", argsList)
15929 if args.Type != ArgList {
15932 settlement := timeFromExcelTime(args.List[0].Number, false)
15933 basis := int(args.List[3].Number)
15934 ncd := timeFromExcelTime(fn.COUPNCD(argsList).Number, false)
15935 return newNumberFormulaArg(coupdays(settlement, ncd, basis))
15938 // coupons is an implementation of the formula functions COUPNCD and COUPPCD.
15939 func (fn *formulaFuncs) coupons(name string, arg formulaArg) formulaArg {
15940 settlement := timeFromExcelTime(arg.List[0].Number, false)
15941 maturity := timeFromExcelTime(arg.List[1].Number, false)
15942 maturityDays := (maturity.Year()-settlement.Year())*12 + (int(maturity.Month()) - int(settlement.Month()))
15943 coupon := 12 / int(arg.List[2].Number)
15944 mod := maturityDays % coupon
15945 year := settlement.Year()
15946 month := int(settlement.Month())
15947 if mod == 0 && settlement.Day() >= maturity.Day() {
15952 if name != "COUPNCD" {
15958 } else if month < 0 {
15962 day, lastDay := maturity.Day(), time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
15963 days := getDaysInMonth(lastDay.Year(), int(lastDay.Month()))
15964 if getDaysInMonth(maturity.Year(), int(maturity.Month())) == maturity.Day() {
15966 } else if day > 27 && day > days {
15969 return newNumberFormulaArg(daysBetween(excelMinTime1900.Unix(), makeDate(year, time.Month(month), day)) + 1)
15972 // COUPNCD function calculates the number of coupons payable, between a
15973 // security's settlement date and maturity date, rounded up to the nearest
15974 // whole coupon. The syntax of the function is:
15976 // COUPNCD(settlement,maturity,frequency,[basis])
15977 func (fn *formulaFuncs) COUPNCD(argsList *list.List) formulaArg {
15978 args := fn.prepareCouponArgs("COUPNCD", argsList)
15979 if args.Type != ArgList {
15982 return fn.coupons("COUPNCD", args)
15985 // COUPNUM function calculates the number of coupons payable, between a
15986 // security's settlement date and maturity date, rounded up to the nearest
15987 // whole coupon. The syntax of the function is:
15989 // COUPNUM(settlement,maturity,frequency,[basis])
15990 func (fn *formulaFuncs) COUPNUM(argsList *list.List) formulaArg {
15991 args := fn.prepareCouponArgs("COUPNUM", argsList)
15992 if args.Type != ArgList {
15995 frac := yearFrac(args.List[0].Number, args.List[1].Number, 0)
15996 return newNumberFormulaArg(math.Ceil(frac.Number * args.List[2].Number))
15999 // COUPPCD function returns the previous coupon date, before the settlement
16000 // date for a security. The syntax of the function is:
16002 // COUPPCD(settlement,maturity,frequency,[basis])
16003 func (fn *formulaFuncs) COUPPCD(argsList *list.List) formulaArg {
16004 args := fn.prepareCouponArgs("COUPPCD", argsList)
16005 if args.Type != ArgList {
16008 return fn.coupons("COUPPCD", args)
16011 // CUMIPMT function calculates the cumulative interest paid on a loan or
16012 // investment, between two specified periods. The syntax of the function is:
16014 // CUMIPMT(rate,nper,pv,start_period,end_period,type)
16015 func (fn *formulaFuncs) CUMIPMT(argsList *list.List) formulaArg {
16016 return fn.cumip("CUMIPMT", argsList)
16019 // CUMPRINC function calculates the cumulative payment on the principal of a
16020 // loan or investment, between two specified periods. The syntax of the
16023 // CUMPRINC(rate,nper,pv,start_period,end_period,type)
16024 func (fn *formulaFuncs) CUMPRINC(argsList *list.List) formulaArg {
16025 return fn.cumip("CUMPRINC", argsList)
16028 // cumip is an implementation of the formula functions CUMIPMT and CUMPRINC.
16029 func (fn *formulaFuncs) cumip(name string, argsList *list.List) formulaArg {
16030 if argsList.Len() != 6 {
16031 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 6 arguments", name))
16033 rate := argsList.Front().Value.(formulaArg).ToNumber()
16034 if rate.Type != ArgNumber {
16037 nper := argsList.Front().Next().Value.(formulaArg).ToNumber()
16038 if nper.Type != ArgNumber {
16041 pv := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16042 if pv.Type != ArgNumber {
16045 start := argsList.Back().Prev().Prev().Value.(formulaArg).ToNumber()
16046 if start.Type != ArgNumber {
16049 end := argsList.Back().Prev().Value.(formulaArg).ToNumber()
16050 if end.Type != ArgNumber {
16053 typ := argsList.Back().Value.(formulaArg).ToNumber()
16054 if typ.Type != ArgNumber {
16057 if typ.Number != 0 && typ.Number != 1 {
16058 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16060 if start.Number < 1 || start.Number > end.Number {
16061 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16064 for per := start.Number; per <= end.Number; per++ {
16065 args := list.New().Init()
16066 args.PushBack(rate)
16067 args.PushBack(newNumberFormulaArg(per))
16068 args.PushBack(nper)
16070 args.PushBack(newNumberFormulaArg(0))
16072 if name == "CUMIPMT" {
16073 num += fn.IPMT(args).Number
16076 num += fn.PPMT(args).Number
16078 return newNumberFormulaArg(num)
16081 // calcDbArgsCompare implements common arguments' comparison for DB and DDB.
16082 func calcDbArgsCompare(cost, salvage, life, period formulaArg) bool {
16083 return (cost.Number <= 0) || ((salvage.Number / cost.Number) < 0) || (life.Number <= 0) || (period.Number < 1)
16086 // DB function calculates the depreciation of an asset, using the Fixed
16087 // Declining Balance Method, for each period of the asset's lifetime. The
16088 // syntax of the function is:
16090 // DB(cost,salvage,life,period,[month])
16091 func (fn *formulaFuncs) DB(argsList *list.List) formulaArg {
16092 if argsList.Len() < 4 {
16093 return newErrorFormulaArg(formulaErrorVALUE, "DB requires at least 4 arguments")
16095 if argsList.Len() > 5 {
16096 return newErrorFormulaArg(formulaErrorVALUE, "DB allows at most 5 arguments")
16098 cost := argsList.Front().Value.(formulaArg).ToNumber()
16099 if cost.Type != ArgNumber {
16102 salvage := argsList.Front().Next().Value.(formulaArg).ToNumber()
16103 if salvage.Type != ArgNumber {
16106 life := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16107 if life.Type != ArgNumber {
16110 period := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
16111 if period.Type != ArgNumber {
16114 month := newNumberFormulaArg(12)
16115 if argsList.Len() == 5 {
16116 if month = argsList.Back().Value.(formulaArg).ToNumber(); month.Type != ArgNumber {
16120 if cost.Number == 0 {
16121 return newNumberFormulaArg(0)
16123 if calcDbArgsCompare(cost, salvage, life, period) || (month.Number < 1) {
16124 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16126 dr := 1 - math.Pow(salvage.Number/cost.Number, 1/life.Number)
16127 dr = math.Round(dr*1000) / 1000
16128 pd, depreciation := 0.0, 0.0
16129 for per := 1; per <= int(period.Number); per++ {
16131 depreciation = cost.Number * dr * month.Number / 12
16132 } else if per == int(life.Number+1) {
16133 depreciation = (cost.Number - pd) * dr * (12 - month.Number) / 12
16135 depreciation = (cost.Number - pd) * dr
16139 return newNumberFormulaArg(depreciation)
16142 // DDB function calculates the depreciation of an asset, using the Double
16143 // Declining Balance Method, or another specified depreciation rate. The
16144 // syntax of the function is:
16146 // DDB(cost,salvage,life,period,[factor])
16147 func (fn *formulaFuncs) DDB(argsList *list.List) formulaArg {
16148 if argsList.Len() < 4 {
16149 return newErrorFormulaArg(formulaErrorVALUE, "DDB requires at least 4 arguments")
16151 if argsList.Len() > 5 {
16152 return newErrorFormulaArg(formulaErrorVALUE, "DDB allows at most 5 arguments")
16154 cost := argsList.Front().Value.(formulaArg).ToNumber()
16155 if cost.Type != ArgNumber {
16158 salvage := argsList.Front().Next().Value.(formulaArg).ToNumber()
16159 if salvage.Type != ArgNumber {
16162 life := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16163 if life.Type != ArgNumber {
16166 period := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
16167 if period.Type != ArgNumber {
16170 factor := newNumberFormulaArg(2)
16171 if argsList.Len() == 5 {
16172 if factor = argsList.Back().Value.(formulaArg).ToNumber(); factor.Type != ArgNumber {
16176 if cost.Number == 0 {
16177 return newNumberFormulaArg(0)
16179 if calcDbArgsCompare(cost, salvage, life, period) || (factor.Number <= 0.0) || (period.Number > life.Number) {
16180 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16182 pd, depreciation := 0.0, 0.0
16183 for per := 1; per <= int(period.Number); per++ {
16184 depreciation = math.Min((cost.Number-pd)*(factor.Number/life.Number), cost.Number-salvage.Number-pd)
16187 return newNumberFormulaArg(depreciation)
16190 // prepareDataValueArgs convert first N arguments to data value for the
16191 // formula functions.
16192 func (fn *formulaFuncs) prepareDataValueArgs(n int, argsList *list.List) formulaArg {
16194 var dataValues []formulaArg
16195 getDateValue := func(arg formulaArg, l *list.List) formulaArg {
16200 num := arg.ToNumber()
16201 if num.Type == ArgNumber {
16207 arg = fn.DATEVALUE(l)
16208 if arg.Type == ArgError {
16209 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16212 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16216 for i, arg := 0, argsList.Front(); i < n; arg = arg.Next() {
16217 dataValue := getDateValue(arg.Value.(formulaArg), l)
16218 if dataValue.Type != ArgNumber {
16221 dataValues = append(dataValues, dataValue)
16224 return newListFormulaArg(dataValues)
16227 // discIntrate is an implementation of the formula functions DISC and INTRATE.
16228 func (fn *formulaFuncs) discIntrate(name string, argsList *list.List) formulaArg {
16229 if argsList.Len() != 4 && argsList.Len() != 5 {
16230 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 4 or 5 arguments", name))
16232 args := fn.prepareDataValueArgs(2, argsList)
16233 if args.Type != ArgList {
16236 settlement, maturity, argName := args.List[0], args.List[1], "pr"
16237 if maturity.Number <= settlement.Number {
16238 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > settlement", name))
16240 prInvestment := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16241 if prInvestment.Type != ArgNumber {
16242 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16244 if prInvestment.Number <= 0 {
16245 if name == "INTRATE" {
16246 argName = "investment"
16248 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires %s > 0", name, argName))
16250 redemption := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
16251 if redemption.Type != ArgNumber {
16252 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16254 if redemption.Number <= 0 {
16255 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires redemption > 0", name))
16257 basis := newNumberFormulaArg(0)
16258 if argsList.Len() == 5 {
16259 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
16260 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16263 frac := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
16264 if frac.Type != ArgNumber {
16267 if name == "INTRATE" {
16268 return newNumberFormulaArg((redemption.Number - prInvestment.Number) / prInvestment.Number / frac.Number)
16270 return newNumberFormulaArg((redemption.Number - prInvestment.Number) / redemption.Number / frac.Number)
16273 // DISC function calculates the Discount Rate for a security. The syntax of
16274 // the function is:
16276 // DISC(settlement,maturity,pr,redemption,[basis])
16277 func (fn *formulaFuncs) DISC(argsList *list.List) formulaArg {
16278 return fn.discIntrate("DISC", argsList)
16281 // DOLLARDE function converts a dollar value in fractional notation, into a
16282 // dollar value expressed as a decimal. The syntax of the function is:
16284 // DOLLARDE(fractional_dollar,fraction)
16285 func (fn *formulaFuncs) DOLLARDE(argsList *list.List) formulaArg {
16286 return fn.dollar("DOLLARDE", argsList)
16289 // DOLLARFR function converts a dollar value in decimal notation, into a
16290 // dollar value that is expressed in fractional notation. The syntax of the
16293 // DOLLARFR(decimal_dollar,fraction)
16294 func (fn *formulaFuncs) DOLLARFR(argsList *list.List) formulaArg {
16295 return fn.dollar("DOLLARFR", argsList)
16298 // dollar is an implementation of the formula functions DOLLARDE and DOLLARFR.
16299 func (fn *formulaFuncs) dollar(name string, argsList *list.List) formulaArg {
16300 if argsList.Len() != 2 {
16301 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 arguments", name))
16303 dollar := argsList.Front().Value.(formulaArg).ToNumber()
16304 if dollar.Type != ArgNumber {
16307 frac := argsList.Back().Value.(formulaArg).ToNumber()
16308 if frac.Type != ArgNumber {
16311 if frac.Number < 0 {
16312 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16314 if frac.Number == 0 {
16315 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
16317 cents := math.Mod(dollar.Number, 1)
16318 if name == "DOLLARDE" {
16319 cents /= frac.Number
16320 cents *= math.Pow(10, math.Ceil(math.Log10(frac.Number)))
16322 cents *= frac.Number
16323 cents *= math.Pow(10, -math.Ceil(math.Log10(frac.Number)))
16325 return newNumberFormulaArg(math.Floor(dollar.Number) + cents)
16328 // prepareDurationArgs checking and prepare arguments for the formula
16329 // functions DURATION and MDURATION.
16330 func (fn *formulaFuncs) prepareDurationArgs(name string, argsList *list.List) formulaArg {
16331 if argsList.Len() != 5 && argsList.Len() != 6 {
16332 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 5 or 6 arguments", name))
16334 args := fn.prepareDataValueArgs(2, argsList)
16335 if args.Type != ArgList {
16338 settlement, maturity := args.List[0], args.List[1]
16339 if settlement.Number >= maturity.Number {
16340 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > settlement", name))
16342 coupon := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16343 if coupon.Type != ArgNumber {
16346 if coupon.Number < 0 {
16347 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires coupon >= 0", name))
16349 yld := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
16350 if yld.Type != ArgNumber {
16353 if yld.Number < 0 {
16354 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires yld >= 0", name))
16356 frequency := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
16357 if frequency.Type != ArgNumber {
16360 if !validateFrequency(frequency.Number) {
16361 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16363 basis := newNumberFormulaArg(0)
16364 if argsList.Len() == 6 {
16365 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
16366 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16369 return newListFormulaArg([]formulaArg{settlement, maturity, coupon, yld, frequency, basis})
16372 // duration is an implementation of the formula function DURATION.
16373 func (fn *formulaFuncs) duration(settlement, maturity, coupon, yld, frequency, basis formulaArg) formulaArg {
16374 frac := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
16375 if frac.Type != ArgNumber {
16378 argumments := list.New().Init()
16379 argumments.PushBack(settlement)
16380 argumments.PushBack(maturity)
16381 argumments.PushBack(frequency)
16382 argumments.PushBack(basis)
16383 coups := fn.COUPNUM(argumments)
16386 coupon.Number *= 100 / frequency.Number
16387 yld.Number /= frequency.Number
16389 diff := frac.Number*frequency.Number - coups.Number
16390 for t := 1.0; t < coups.Number; t++ {
16392 add := coupon.Number / math.Pow(yld.Number, tDiff)
16394 duration += tDiff * add
16396 add := (coupon.Number + 100) / math.Pow(yld.Number, coups.Number+diff)
16398 duration += (coups.Number + diff) * add
16400 duration /= frequency.Number
16401 return newNumberFormulaArg(duration)
16404 // DURATION function calculates the Duration (specifically, the Macaulay
16405 // Duration) of a security that pays periodic interest, assuming a par value
16406 // of $100. The syntax of the function is:
16408 // DURATION(settlement,maturity,coupon,yld,frequency,[basis])
16409 func (fn *formulaFuncs) DURATION(argsList *list.List) formulaArg {
16410 args := fn.prepareDurationArgs("DURATION", argsList)
16411 if args.Type != ArgList {
16414 return fn.duration(args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5])
16417 // EFFECT function returns the effective annual interest rate for a given
16418 // nominal interest rate and number of compounding periods per year. The
16419 // syntax of the function is:
16421 // EFFECT(nominal_rate,npery)
16422 func (fn *formulaFuncs) EFFECT(argsList *list.List) formulaArg {
16423 if argsList.Len() != 2 {
16424 return newErrorFormulaArg(formulaErrorVALUE, "EFFECT requires 2 arguments")
16426 rate := argsList.Front().Value.(formulaArg).ToNumber()
16427 if rate.Type != ArgNumber {
16430 npery := argsList.Back().Value.(formulaArg).ToNumber()
16431 if npery.Type != ArgNumber {
16434 if rate.Number <= 0 || npery.Number < 1 {
16435 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16437 return newNumberFormulaArg(math.Pow(1+rate.Number/npery.Number, npery.Number) - 1)
16440 // EUROCONVERT function convert a number to euro or from euro to a
16441 // participating currency. You can also use it to convert a number from one
16442 // participating currency to another by using the euro as an intermediary
16443 // (triangulation). The syntax of the function is:
16445 // EUROCONVERT(number,sourcecurrency,targetcurrency[,fullprecision,triangulationprecision])
16446 func (fn *formulaFuncs) EUROCONVERT(argsList *list.List) formulaArg {
16447 if argsList.Len() < 3 {
16448 return newErrorFormulaArg(formulaErrorVALUE, "EUROCONVERT requires at least 3 arguments")
16450 if argsList.Len() > 5 {
16451 return newErrorFormulaArg(formulaErrorVALUE, "EUROCONVERT allows at most 5 arguments")
16453 number := argsList.Front().Value.(formulaArg).ToNumber()
16454 if number.Type != ArgNumber {
16457 sourceCurrency := argsList.Front().Next().Value.(formulaArg).Value()
16458 targetCurrency := argsList.Front().Next().Next().Value.(formulaArg).Value()
16459 fullPrec, triangulationPrec := newBoolFormulaArg(false), newNumberFormulaArg(0)
16460 if argsList.Len() >= 4 {
16461 if fullPrec = argsList.Front().Next().Next().Next().Value.(formulaArg).ToBool(); fullPrec.Type != ArgNumber {
16465 if argsList.Len() == 5 {
16466 if triangulationPrec = argsList.Back().Value.(formulaArg).ToNumber(); triangulationPrec.Type != ArgNumber {
16467 return triangulationPrec
16470 convertTable := map[string][]float64{
16472 "ATS": {13.7603, 2},
16473 "BEF": {40.3399, 0},
16474 "DEM": {1.95583, 2},
16475 "ESP": {166.386, 0},
16476 "FIM": {5.94573, 2},
16477 "FRF": {6.55957, 2},
16478 "IEP": {0.787564, 2},
16479 "ITL": {1936.27, 0},
16480 "LUF": {40.3399, 0},
16481 "NLG": {2.20371, 2},
16482 "PTE": {200.482, 2},
16483 "GRD": {340.750, 2},
16484 "SIT": {239.640, 2},
16485 "MTL": {0.429300, 2},
16486 "CYP": {0.585274, 2},
16487 "SKK": {30.1260, 2},
16488 "EEK": {15.6466, 2},
16489 "LVL": {0.702804, 2},
16490 "LTL": {3.45280, 2},
16492 source, ok := convertTable[sourceCurrency]
16494 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16496 target, ok := convertTable[targetCurrency]
16498 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
16500 if sourceCurrency == targetCurrency {
16504 if sourceCurrency == "EUR" {
16505 res = number.Number * target[0]
16507 intermediate := number.Number / source[0]
16508 if triangulationPrec.Number != 0 {
16509 ratio := math.Pow(10, triangulationPrec.Number)
16510 intermediate = math.Round(intermediate*ratio) / ratio
16512 res = intermediate * target[0]
16514 if fullPrec.Number != 1 {
16515 ratio := math.Pow(10, target[1])
16516 res = math.Round(res*ratio) / ratio
16518 return newNumberFormulaArg(res)
16521 // FV function calculates the Future Value of an investment with periodic
16522 // constant payments and a constant interest rate. The syntax of the function
16525 // FV(rate,nper,[pmt],[pv],[type])
16526 func (fn *formulaFuncs) FV(argsList *list.List) formulaArg {
16527 if argsList.Len() < 3 {
16528 return newErrorFormulaArg(formulaErrorVALUE, "FV requires at least 3 arguments")
16530 if argsList.Len() > 5 {
16531 return newErrorFormulaArg(formulaErrorVALUE, "FV allows at most 5 arguments")
16533 rate := argsList.Front().Value.(formulaArg).ToNumber()
16534 if rate.Type != ArgNumber {
16537 nper := argsList.Front().Next().Value.(formulaArg).ToNumber()
16538 if nper.Type != ArgNumber {
16541 pmt := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16542 if pmt.Type != ArgNumber {
16545 pv, typ := newNumberFormulaArg(0), newNumberFormulaArg(0)
16546 if argsList.Len() >= 4 {
16547 if pv = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); pv.Type != ArgNumber {
16551 if argsList.Len() == 5 {
16552 if typ = argsList.Back().Value.(formulaArg).ToNumber(); typ.Type != ArgNumber {
16556 if typ.Number != 0 && typ.Number != 1 {
16557 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16559 if rate.Number != 0 {
16560 return newNumberFormulaArg(-pv.Number*math.Pow(1+rate.Number, nper.Number) - pmt.Number*(1+rate.Number*typ.Number)*(math.Pow(1+rate.Number, nper.Number)-1)/rate.Number)
16562 return newNumberFormulaArg(-pv.Number - pmt.Number*nper.Number)
16565 // FVSCHEDULE function calculates the Future Value of an investment with a
16566 // variable interest rate. The syntax of the function is:
16568 // FVSCHEDULE(principal,schedule)
16569 func (fn *formulaFuncs) FVSCHEDULE(argsList *list.List) formulaArg {
16570 if argsList.Len() != 2 {
16571 return newErrorFormulaArg(formulaErrorVALUE, "FVSCHEDULE requires 2 arguments")
16573 pri := argsList.Front().Value.(formulaArg).ToNumber()
16574 if pri.Type != ArgNumber {
16577 principal := pri.Number
16578 for _, arg := range argsList.Back().Value.(formulaArg).ToList() {
16579 if arg.Value() == "" {
16582 rate := arg.ToNumber()
16583 if rate.Type != ArgNumber {
16586 principal *= 1 + rate.Number
16588 return newNumberFormulaArg(principal)
16591 // INTRATE function calculates the interest rate for a fully invested
16592 // security. The syntax of the function is:
16594 // INTRATE(settlement,maturity,investment,redemption,[basis])
16595 func (fn *formulaFuncs) INTRATE(argsList *list.List) formulaArg {
16596 return fn.discIntrate("INTRATE", argsList)
16599 // IPMT function calculates the interest payment, during a specific period of a
16600 // loan or investment that is paid in constant periodic payments, with a
16601 // constant interest rate. The syntax of the function is:
16603 // IPMT(rate,per,nper,pv,[fv],[type])
16604 func (fn *formulaFuncs) IPMT(argsList *list.List) formulaArg {
16605 return fn.ipmt("IPMT", argsList)
16608 // calcIpmt is part of the implementation ipmt.
16609 func calcIpmt(name string, typ, per, pmt, pv, rate formulaArg) formulaArg {
16610 capital, interest, principal := pv.Number, 0.0, 0.0
16611 for i := 1; i <= int(per.Number); i++ {
16612 if typ.Number != 0 && i == 1 {
16615 interest = -capital * rate.Number
16617 principal = pmt.Number - interest
16618 capital += principal
16620 if name == "IPMT" {
16621 return newNumberFormulaArg(interest)
16623 return newNumberFormulaArg(principal)
16626 // ipmt is an implementation of the formula functions IPMT and PPMT.
16627 func (fn *formulaFuncs) ipmt(name string, argsList *list.List) formulaArg {
16628 if argsList.Len() < 4 {
16629 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 4 arguments", name))
16631 if argsList.Len() > 6 {
16632 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 6 arguments", name))
16634 rate := argsList.Front().Value.(formulaArg).ToNumber()
16635 if rate.Type != ArgNumber {
16638 per := argsList.Front().Next().Value.(formulaArg).ToNumber()
16639 if per.Type != ArgNumber {
16642 nper := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16643 if nper.Type != ArgNumber {
16646 pv := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
16647 if pv.Type != ArgNumber {
16650 fv, typ := newNumberFormulaArg(0), newNumberFormulaArg(0)
16651 if argsList.Len() >= 5 {
16652 if fv = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); fv.Type != ArgNumber {
16656 if argsList.Len() == 6 {
16657 if typ = argsList.Back().Value.(formulaArg).ToNumber(); typ.Type != ArgNumber {
16661 if typ.Number != 0 && typ.Number != 1 {
16662 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16664 if per.Number <= 0 || per.Number > nper.Number {
16665 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16667 args := list.New().Init()
16668 args.PushBack(rate)
16669 args.PushBack(nper)
16673 pmt := fn.PMT(args)
16674 return calcIpmt(name, typ, per, pmt, pv, rate)
16677 // IRR function returns the Internal Rate of Return for a supplied series of
16678 // periodic cash flows (i.e. an initial investment value and a series of net
16679 // income values). The syntax of the function is:
16681 // IRR(values,[guess])
16682 func (fn *formulaFuncs) IRR(argsList *list.List) formulaArg {
16683 if argsList.Len() < 1 {
16684 return newErrorFormulaArg(formulaErrorVALUE, "IRR requires at least 1 argument")
16686 if argsList.Len() > 2 {
16687 return newErrorFormulaArg(formulaErrorVALUE, "IRR allows at most 2 arguments")
16689 values, guess := argsList.Front().Value.(formulaArg).ToList(), newNumberFormulaArg(0.1)
16690 if argsList.Len() > 1 {
16691 if guess = argsList.Back().Value.(formulaArg).ToNumber(); guess.Type != ArgNumber {
16695 x1, x2 := newNumberFormulaArg(0), guess
16696 args := list.New().Init()
16698 for _, v := range values {
16702 args.Front().Value = x2
16704 for i := 0; i < maxFinancialIterations; i++ {
16705 if f1.Number*f2.Number < 0 {
16708 if math.Abs(f1.Number) < math.Abs(f2.Number) {
16709 x1.Number += 1.6 * (x1.Number - x2.Number)
16710 args.Front().Value = x1
16714 x2.Number += 1.6 * (x2.Number - x1.Number)
16715 args.Front().Value = x2
16718 if f1.Number*f2.Number > 0 {
16719 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16721 args.Front().Value = x1
16723 var rtb, dx, xMid, fMid float64
16726 dx = x2.Number - x1.Number
16729 dx = x1.Number - x2.Number
16731 for i := 0; i < maxFinancialIterations; i++ {
16734 args.Front().Value = newNumberFormulaArg(xMid)
16735 fMid = fn.NPV(args).Number
16739 if math.Abs(fMid) < financialPrecision || math.Abs(dx) < financialPrecision {
16743 return newNumberFormulaArg(xMid)
16746 // ISPMT function calculates the interest paid during a specific period of a
16747 // loan or investment. The syntax of the function is:
16749 // ISPMT(rate,per,nper,pv)
16750 func (fn *formulaFuncs) ISPMT(argsList *list.List) formulaArg {
16751 if argsList.Len() != 4 {
16752 return newErrorFormulaArg(formulaErrorVALUE, "ISPMT requires 4 arguments")
16754 rate := argsList.Front().Value.(formulaArg).ToNumber()
16755 if rate.Type != ArgNumber {
16758 per := argsList.Front().Next().Value.(formulaArg).ToNumber()
16759 if per.Type != ArgNumber {
16762 nper := argsList.Back().Prev().Value.(formulaArg).ToNumber()
16763 if nper.Type != ArgNumber {
16766 pv := argsList.Back().Value.(formulaArg).ToNumber()
16767 if pv.Type != ArgNumber {
16770 pr, payment, num := pv.Number, pv.Number/nper.Number, 0.0
16771 for i := 0; i <= int(per.Number); i++ {
16772 num = rate.Number * pr * -1
16774 if i == int(nper.Number) {
16778 return newNumberFormulaArg(num)
16781 // MDURATION function calculates the Modified Macaulay Duration of a security
16782 // that pays periodic interest, assuming a par value of $100. The syntax of
16783 // the function is:
16785 // MDURATION(settlement,maturity,coupon,yld,frequency,[basis])
16786 func (fn *formulaFuncs) MDURATION(argsList *list.List) formulaArg {
16787 args := fn.prepareDurationArgs("MDURATION", argsList)
16788 if args.Type != ArgList {
16791 duration := fn.duration(args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5])
16792 if duration.Type != ArgNumber {
16795 return newNumberFormulaArg(duration.Number / (1 + args.List[3].Number/args.List[4].Number))
16798 // MIRR function returns the Modified Internal Rate of Return for a supplied
16799 // series of periodic cash flows (i.e. a set of values, which includes an
16800 // initial investment value and a series of net income values). The syntax of
16801 // the function is:
16803 // MIRR(values,finance_rate,reinvest_rate)
16804 func (fn *formulaFuncs) MIRR(argsList *list.List) formulaArg {
16805 if argsList.Len() != 3 {
16806 return newErrorFormulaArg(formulaErrorVALUE, "MIRR requires 3 arguments")
16808 values := argsList.Front().Value.(formulaArg).ToList()
16809 financeRate := argsList.Front().Next().Value.(formulaArg).ToNumber()
16810 if financeRate.Type != ArgNumber {
16813 reinvestRate := argsList.Back().Value.(formulaArg).ToNumber()
16814 if reinvestRate.Type != ArgNumber {
16815 return reinvestRate
16817 n, fr, rr, npvPos, npvNeg := len(values), 1+financeRate.Number, 1+reinvestRate.Number, 0.0, 0.0
16818 for i, v := range values {
16819 val := v.ToNumber()
16820 if val.Number >= 0 {
16821 npvPos += val.Number / math.Pow(rr, float64(i))
16824 npvNeg += val.Number / math.Pow(fr, float64(i))
16826 if npvNeg == 0 || npvPos == 0 || reinvestRate.Number <= -1 {
16827 return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
16829 return newNumberFormulaArg(math.Pow(-npvPos*math.Pow(rr, float64(n))/(npvNeg*rr), 1/(float64(n)-1)) - 1)
16832 // NOMINAL function returns the nominal interest rate for a given effective
16833 // interest rate and number of compounding periods per year. The syntax of
16834 // the function is:
16836 // NOMINAL(effect_rate,npery)
16837 func (fn *formulaFuncs) NOMINAL(argsList *list.List) formulaArg {
16838 if argsList.Len() != 2 {
16839 return newErrorFormulaArg(formulaErrorVALUE, "NOMINAL requires 2 arguments")
16841 rate := argsList.Front().Value.(formulaArg).ToNumber()
16842 if rate.Type != ArgNumber {
16845 npery := argsList.Back().Value.(formulaArg).ToNumber()
16846 if npery.Type != ArgNumber {
16849 if rate.Number <= 0 || npery.Number < 1 {
16850 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16852 return newNumberFormulaArg(npery.Number * (math.Pow(rate.Number+1, 1/npery.Number) - 1))
16855 // NPER function calculates the number of periods required to pay off a loan,
16856 // for a constant periodic payment and a constant interest rate. The syntax
16857 // of the function is:
16859 // NPER(rate,pmt,pv,[fv],[type])
16860 func (fn *formulaFuncs) NPER(argsList *list.List) formulaArg {
16861 if argsList.Len() < 3 {
16862 return newErrorFormulaArg(formulaErrorVALUE, "NPER requires at least 3 arguments")
16864 if argsList.Len() > 5 {
16865 return newErrorFormulaArg(formulaErrorVALUE, "NPER allows at most 5 arguments")
16867 rate := argsList.Front().Value.(formulaArg).ToNumber()
16868 if rate.Type != ArgNumber {
16871 pmt := argsList.Front().Next().Value.(formulaArg).ToNumber()
16872 if pmt.Type != ArgNumber {
16875 pv := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
16876 if pv.Type != ArgNumber {
16879 fv, typ := newNumberFormulaArg(0), newNumberFormulaArg(0)
16880 if argsList.Len() >= 4 {
16881 if fv = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); fv.Type != ArgNumber {
16885 if argsList.Len() == 5 {
16886 if typ = argsList.Back().Value.(formulaArg).ToNumber(); typ.Type != ArgNumber {
16890 if typ.Number != 0 && typ.Number != 1 {
16891 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
16893 if pmt.Number == 0 {
16894 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
16896 if rate.Number != 0 {
16897 p := math.Log((pmt.Number*(1+rate.Number*typ.Number)/rate.Number-fv.Number)/(pv.Number+pmt.Number*(1+rate.Number*typ.Number)/rate.Number)) / math.Log(1+rate.Number)
16898 return newNumberFormulaArg(p)
16900 return newNumberFormulaArg((-pv.Number - fv.Number) / pmt.Number)
16903 // NPV function calculates the Net Present Value of an investment, based on a
16904 // supplied discount rate, and a series of future payments and income. The
16905 // syntax of the function is:
16907 // NPV(rate,value1,[value2],[value3],...)
16908 func (fn *formulaFuncs) NPV(argsList *list.List) formulaArg {
16909 if argsList.Len() < 2 {
16910 return newErrorFormulaArg(formulaErrorVALUE, "NPV requires at least 2 arguments")
16912 rate := argsList.Front().Value.(formulaArg).ToNumber()
16913 if rate.Type != ArgNumber {
16917 for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
16918 num := arg.Value.(formulaArg).ToNumber()
16919 if num.Type != ArgNumber {
16922 val += num.Number / math.Pow(1+rate.Number, float64(i))
16925 return newNumberFormulaArg(val)
16928 // aggrBetween is a part of implementation of the formula function ODDFPRICE.
16929 func aggrBetween(startPeriod, endPeriod float64, initialValue []float64, f func(acc []float64, index float64) []float64) []float64 {
16931 if startPeriod <= endPeriod {
16932 for i := startPeriod; i <= endPeriod; i++ {
16936 for i := startPeriod; i >= endPeriod; i-- {
16940 return fold(f, initialValue, s)
16943 // fold is a part of implementation of the formula function ODDFPRICE.
16944 func fold(f func(acc []float64, index float64) []float64, state []float64, source []float64) []float64 {
16945 length, value := len(source), state
16946 for index := 0; length > index; index++ {
16947 value = f(value, source[index])
16952 // changeMonth is a part of implementation of the formula function ODDFPRICE.
16953 func changeMonth(date time.Time, numMonths float64, returnLastMonth bool) time.Time {
16955 if returnLastMonth && date.Day() == getDaysInMonth(date.Year(), int(date.Month())) {
16958 newDate := date.AddDate(0, int(numMonths), offsetDay)
16959 if returnLastMonth {
16960 lastDay := getDaysInMonth(newDate.Year(), int(newDate.Month()))
16961 return timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), makeDate(newDate.Year(), newDate.Month(), lastDay))+1, false)
16966 // datesAggregate is a part of implementation of the formula function
16968 func datesAggregate(startDate, endDate time.Time, numMonths float64, f func(pcd, ncd time.Time) float64, acc float64, returnLastMonth bool) (time.Time, time.Time, float64) {
16969 frontDate, trailingDate := startDate, endDate
16970 s1 := frontDate.After(endDate) || frontDate.Equal(endDate)
16971 s2 := endDate.After(frontDate) || endDate.Equal(frontDate)
16977 trailingDate = frontDate
16978 frontDate = changeMonth(frontDate, numMonths, returnLastMonth)
16979 fn := f(frontDate, trailingDate)
16981 s1 = frontDate.After(endDate) || frontDate.Equal(endDate)
16982 s2 = endDate.After(frontDate) || endDate.Equal(frontDate)
16988 return frontDate, trailingDate, acc
16991 // coupNumber is a part of implementation of the formula function ODDFPRICE.
16992 func coupNumber(maturity, settlement, numMonths float64) float64 {
16993 maturityTime, settlementTime := timeFromExcelTime(maturity, false), timeFromExcelTime(settlement, false)
16994 my, mm, md := maturityTime.Year(), maturityTime.Month(), maturityTime.Day()
16995 sy, sm, sd := settlementTime.Year(), settlementTime.Month(), settlementTime.Day()
16996 couponsTemp, endOfMonthTemp := 0.0, getDaysInMonth(my, int(mm)) == md
16997 endOfMonth := endOfMonthTemp
16998 if !endOfMonthTemp && mm != 2 && md > 28 && md < getDaysInMonth(my, int(mm)) {
16999 endOfMonth = getDaysInMonth(sy, int(sm)) == sd
17001 startDate := changeMonth(settlementTime, 0, endOfMonth)
17002 coupons := couponsTemp
17003 if startDate.After(settlementTime) {
17006 date := changeMonth(startDate, numMonths, endOfMonth)
17007 f := func(pcd, ncd time.Time) float64 {
17010 _, _, result := datesAggregate(date, maturityTime, numMonths, f, coupons, endOfMonth)
17014 // prepareOddYldOrPrArg checking and prepare yield or price arguments for the
17015 // formula functions ODDFPRICE, ODDFYIELD, ODDLPRICE and ODDLYIELD.
17016 func prepareOddYldOrPrArg(name string, arg formulaArg) formulaArg {
17017 yldOrPr := arg.ToNumber()
17018 if yldOrPr.Type != ArgNumber {
17021 if (name == "ODDFPRICE" || name == "ODDLPRICE") && yldOrPr.Number < 0 {
17022 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires yld >= 0", name))
17024 if (name == "ODDFYIELD" || name == "ODDLYIELD") && yldOrPr.Number <= 0 {
17025 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires pr > 0", name))
17030 // prepareOddfArgs checking and prepare arguments for the formula
17031 // functions ODDFPRICE and ODDFYIELD.
17032 func (fn *formulaFuncs) prepareOddfArgs(name string, argsList *list.List) formulaArg {
17033 dateValues := fn.prepareDataValueArgs(4, argsList)
17034 if dateValues.Type != ArgList {
17037 settlement, maturity, issue, firstCoupon := dateValues.List[0], dateValues.List[1], dateValues.List[2], dateValues.List[3]
17038 if issue.Number >= settlement.Number {
17039 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires settlement > issue", name))
17041 if settlement.Number >= firstCoupon.Number {
17042 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires first_coupon > settlement", name))
17044 if firstCoupon.Number >= maturity.Number {
17045 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > first_coupon", name))
17047 rate := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17048 if rate.Type != ArgNumber {
17051 if rate.Number < 0 {
17052 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires rate >= 0", name))
17054 yldOrPr := prepareOddYldOrPrArg(name, argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg))
17055 if yldOrPr.Type != ArgNumber {
17058 redemption := argsList.Front().Next().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17059 if redemption.Type != ArgNumber {
17062 if redemption.Number <= 0 {
17063 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires redemption > 0", name))
17065 frequency := argsList.Front().Next().Next().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17066 if frequency.Type != ArgNumber {
17069 if !validateFrequency(frequency.Number) {
17070 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17072 basis := newNumberFormulaArg(0)
17073 if argsList.Len() == 9 {
17074 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17075 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17078 return newListFormulaArg([]formulaArg{settlement, maturity, issue, firstCoupon, rate, yldOrPr, redemption, frequency, basis})
17081 // ODDFPRICE function calculates the price per $100 face value of a security
17082 // with an odd (short or long) first period. The syntax of the function is:
17084 // ODDFPRICE(settlement,maturity,issue,first_coupon,rate,yld,redemption,frequency,[basis])
17085 func (fn *formulaFuncs) ODDFPRICE(argsList *list.List) formulaArg {
17086 if argsList.Len() != 8 && argsList.Len() != 9 {
17087 return newErrorFormulaArg(formulaErrorVALUE, "ODDFPRICE requires 8 or 9 arguments")
17089 args := fn.prepareOddfArgs("ODDFPRICE", argsList)
17090 if args.Type != ArgList {
17093 settlement, maturity, issue, firstCoupon, rate, yld, redemption, frequency, basisArg := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6], args.List[7], args.List[8]
17094 if basisArg.Number < 0 || basisArg.Number > 4 {
17095 return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
17097 issueTime := timeFromExcelTime(issue.Number, false)
17098 settlementTime := timeFromExcelTime(settlement.Number, false)
17099 maturityTime := timeFromExcelTime(maturity.Number, false)
17100 firstCouponTime := timeFromExcelTime(firstCoupon.Number, false)
17101 basis := int(basisArg.Number)
17102 monthDays := getDaysInMonth(maturityTime.Year(), int(maturityTime.Month()))
17103 returnLastMonth := monthDays == maturityTime.Day()
17104 numMonths := 12 / frequency.Number
17105 numMonthsNeg := -numMonths
17106 mat := changeMonth(maturityTime, numMonthsNeg, returnLastMonth)
17107 pcd, _, _ := datesAggregate(mat, firstCouponTime, numMonthsNeg, func(d1, d2 time.Time) float64 {
17109 }, 0, returnLastMonth)
17110 if !pcd.Equal(firstCouponTime) {
17111 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17113 fnArgs := list.New().Init()
17114 fnArgs.PushBack(settlement)
17115 fnArgs.PushBack(maturity)
17116 fnArgs.PushBack(frequency)
17117 fnArgs.PushBack(basisArg)
17118 e := fn.COUPDAYS(fnArgs)
17119 n := fn.COUPNUM(fnArgs)
17120 m := frequency.Number
17121 dfc := coupdays(issueTime, firstCouponTime, basis)
17122 if dfc < e.Number {
17123 dsc := coupdays(settlementTime, firstCouponTime, basis)
17124 a := coupdays(issueTime, settlementTime, basis)
17125 x := yld.Number/m + 1
17126 y := dsc / e.Number
17128 p3 := math.Pow(p1, n.Number-1+y)
17129 term1 := redemption.Number / p3
17130 term2 := 100 * rate.Number / m * dfc / e.Number / math.Pow(p1, y)
17131 f := func(acc []float64, index float64) []float64 {
17132 return []float64{acc[0] + 100*rate.Number/m/math.Pow(p1, index-1+y)}
17134 term3 := aggrBetween(2, math.Floor(n.Number), []float64{0}, f)
17135 p2 := rate.Number / m
17136 term4 := a / e.Number * p2 * 100
17137 return newNumberFormulaArg(term1 + term2 + term3[0] - term4)
17140 fnArgs.PushBack(issue)
17141 fnArgs.PushBack(firstCoupon)
17142 fnArgs.PushBack(frequency)
17143 nc := fn.COUPNUM(fnArgs)
17144 lastCoupon := firstCoupon.Number
17145 aggrFunc := func(acc []float64, index float64) []float64 {
17146 lastCouponTime := timeFromExcelTime(lastCoupon, false)
17147 earlyCoupon := daysBetween(excelMinTime1900.Unix(), makeDate(lastCouponTime.Year(), time.Month(float64(lastCouponTime.Month())+numMonthsNeg), lastCouponTime.Day())) + 1
17148 earlyCouponTime := timeFromExcelTime(earlyCoupon, false)
17151 nl = coupdays(earlyCouponTime, lastCouponTime, basis)
17153 dci := coupdays(issueTime, lastCouponTime, basis)
17157 startDate := earlyCoupon
17158 if issue.Number > earlyCoupon {
17159 startDate = issue.Number
17161 endDate := lastCoupon
17162 if settlement.Number < lastCoupon {
17163 endDate = settlement.Number
17165 startDateTime := timeFromExcelTime(startDate, false)
17166 endDateTime := timeFromExcelTime(endDate, false)
17167 a := coupdays(startDateTime, endDateTime, basis)
17168 lastCoupon = earlyCoupon
17171 return []float64{dcnl + dci/nl, anl + a/nl}
17173 ag := aggrBetween(math.Floor(nc.Number), 1, []float64{0, 0}, aggrFunc)
17174 dcnl, anl := ag[0], ag[1]
17177 fnArgs.PushBack(settlement)
17178 fnArgs.PushBack(firstCoupon)
17179 fnArgs.PushBack(frequency)
17180 if basis == 2 || basis == 3 {
17181 d := timeFromExcelTime(fn.COUPNCD(fnArgs).Number, false)
17182 dsc = coupdays(settlementTime, d, basis)
17184 d := timeFromExcelTime(fn.COUPPCD(fnArgs).Number, false)
17185 a := coupdays(d, settlementTime, basis)
17188 nq := coupNumber(firstCoupon.Number, settlement.Number, numMonths)
17190 fnArgs.PushBack(firstCoupon)
17191 fnArgs.PushBack(maturity)
17192 fnArgs.PushBack(frequency)
17193 fnArgs.PushBack(basisArg)
17194 n = fn.COUPNUM(fnArgs)
17195 x := yld.Number/m + 1
17196 y := dsc / e.Number
17198 p3 := math.Pow(p1, y+nq+n.Number)
17199 term1 := redemption.Number / p3
17200 term2 := 100 * rate.Number / m * dcnl / math.Pow(p1, nq+y)
17201 f := func(acc []float64, index float64) []float64 {
17202 return []float64{acc[0] + 100*rate.Number/m/math.Pow(p1, index+nq+y)}
17204 term3 := aggrBetween(1, math.Floor(n.Number), []float64{0}, f)
17205 term4 := 100 * rate.Number / m * anl
17206 return newNumberFormulaArg(term1 + term2 + term3[0] - term4)
17209 // getODDFPRICE is a part of implementation of the formula function ODDFPRICE.
17210 func getODDFPRICE(f func(yld float64) float64, x, cnt, prec float64) float64 {
17211 const maxCnt = 20.0
17212 d := func(f func(yld float64) float64, x float64) float64 {
17213 return (f(x+prec) - f(x-prec)) / (2 * prec)
17215 fx, Fx := f(x), d(f, x)
17216 newX := x - (fx / Fx)
17217 if math.Abs(newX-x) < prec {
17219 } else if cnt > maxCnt {
17222 return getODDFPRICE(f, newX, cnt+1, prec)
17225 // ODDFYIELD function calculates the yield of a security with an odd (short or
17226 // long) first period. The syntax of the function is:
17228 // ODDFYIELD(settlement,maturity,issue,first_coupon,rate,pr,redemption,frequency,[basis])
17229 func (fn *formulaFuncs) ODDFYIELD(argsList *list.List) formulaArg {
17230 if argsList.Len() != 8 && argsList.Len() != 9 {
17231 return newErrorFormulaArg(formulaErrorVALUE, "ODDFYIELD requires 8 or 9 arguments")
17233 args := fn.prepareOddfArgs("ODDFYIELD", argsList)
17234 if args.Type != ArgList {
17237 settlement, maturity, issue, firstCoupon, rate, pr, redemption, frequency, basisArg := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6], args.List[7], args.List[8]
17238 if basisArg.Number < 0 || basisArg.Number > 4 {
17239 return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
17241 settlementTime := timeFromExcelTime(settlement.Number, false)
17242 maturityTime := timeFromExcelTime(maturity.Number, false)
17243 years := coupdays(settlementTime, maturityTime, int(basisArg.Number))
17244 px := pr.Number - 100
17245 num := rate.Number*years*100 - px
17246 denum := px/4 + years*px/2 + years*100
17247 guess := num / denum
17248 f := func(yld float64) float64 {
17249 fnArgs := list.New().Init()
17250 fnArgs.PushBack(settlement)
17251 fnArgs.PushBack(maturity)
17252 fnArgs.PushBack(issue)
17253 fnArgs.PushBack(firstCoupon)
17254 fnArgs.PushBack(rate)
17255 fnArgs.PushBack(newNumberFormulaArg(yld))
17256 fnArgs.PushBack(redemption)
17257 fnArgs.PushBack(frequency)
17258 fnArgs.PushBack(basisArg)
17259 return pr.Number - fn.ODDFPRICE(fnArgs).Number
17261 if result := getODDFPRICE(f, guess, 0, 1e-7); !math.IsInf(result, 0) {
17262 return newNumberFormulaArg(result)
17264 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17267 // prepareOddlArgs checking and prepare arguments for the formula
17268 // functions ODDLPRICE and ODDLYIELD.
17269 func (fn *formulaFuncs) prepareOddlArgs(name string, argsList *list.List) formulaArg {
17270 dateValues := fn.prepareDataValueArgs(3, argsList)
17271 if dateValues.Type != ArgList {
17274 settlement, maturity, lastInterest := dateValues.List[0], dateValues.List[1], dateValues.List[2]
17275 if lastInterest.Number >= settlement.Number {
17276 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires settlement > last_interest", name))
17278 if settlement.Number >= maturity.Number {
17279 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > settlement", name))
17281 rate := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
17282 if rate.Type != ArgNumber {
17285 if rate.Number < 0 {
17286 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires rate >= 0", name))
17288 yldOrPr := prepareOddYldOrPrArg(name, argsList.Front().Next().Next().Next().Next().Value.(formulaArg))
17289 if yldOrPr.Type != ArgNumber {
17292 redemption := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17293 if redemption.Type != ArgNumber {
17296 if redemption.Number <= 0 {
17297 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires redemption > 0", name))
17299 frequency := argsList.Front().Next().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17300 if frequency.Type != ArgNumber {
17303 if !validateFrequency(frequency.Number) {
17304 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17306 basis := newNumberFormulaArg(0)
17307 if argsList.Len() == 8 {
17308 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17309 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17312 return newListFormulaArg([]formulaArg{settlement, maturity, lastInterest, rate, yldOrPr, redemption, frequency, basis})
17315 // oddl is an implementation of the formula functions ODDLPRICE and ODDLYIELD.
17316 func (fn *formulaFuncs) oddl(name string, argsList *list.List) formulaArg {
17317 if argsList.Len() != 7 && argsList.Len() != 8 {
17318 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 7 or 8 arguments", name))
17320 args := fn.prepareOddlArgs(name, argsList)
17321 if args.Type != ArgList {
17324 settlement, maturity, lastInterest, rate, prOrYld, redemption, frequency, basisArg := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5], args.List[6], args.List[7]
17325 if basisArg.Number < 0 || basisArg.Number > 4 {
17326 return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
17328 settlementTime := timeFromExcelTime(settlement.Number, false)
17329 maturityTime := timeFromExcelTime(maturity.Number, false)
17330 basis := int(basisArg.Number)
17331 numMonths := 12 / frequency.Number
17332 fnArgs := list.New().Init()
17333 fnArgs.PushBack(lastInterest)
17334 fnArgs.PushBack(maturity)
17335 fnArgs.PushBack(frequency)
17336 fnArgs.PushBack(basisArg)
17337 nc := fn.COUPNUM(fnArgs)
17338 earlyCoupon := lastInterest.Number
17339 aggrFunc := func(acc []float64, index float64) []float64 {
17340 earlyCouponTime := timeFromExcelTime(earlyCoupon, false)
17341 lateCouponTime := changeMonth(earlyCouponTime, numMonths, false)
17342 lateCoupon, _ := timeToExcelTime(lateCouponTime, false)
17343 nl := coupdays(earlyCouponTime, lateCouponTime, basis)
17344 dci := coupdays(earlyCouponTime, maturityTime, basis)
17345 if index < nc.Number {
17349 if lateCoupon < settlement.Number {
17351 } else if earlyCoupon < settlement.Number {
17352 a = coupdays(earlyCouponTime, settlementTime, basis)
17354 startDate := earlyCoupon
17355 if settlement.Number > earlyCoupon {
17356 startDate = settlement.Number
17358 endDate := lateCoupon
17359 if maturity.Number < lateCoupon {
17360 endDate = maturity.Number
17362 startDateTime := timeFromExcelTime(startDate, false)
17363 endDateTime := timeFromExcelTime(endDate, false)
17364 dsc := coupdays(startDateTime, endDateTime, basis)
17365 earlyCoupon = lateCoupon
17369 return []float64{dcnl + dci/nl, anl + a/nl, dscnl + dsc/nl}
17371 ag := aggrBetween(1, math.Floor(nc.Number), []float64{0, 0, 0}, aggrFunc)
17372 dcnl, anl, dscnl := ag[0], ag[1], ag[2]
17373 x := 100.0 * rate.Number / frequency.Number
17374 term1 := dcnl*x + redemption.Number
17375 if name == "ODDLPRICE" {
17376 term2 := dscnl*prOrYld.Number/frequency.Number + 1
17378 return newNumberFormulaArg(term1/term2 - term3)
17380 term2 := anl*x + prOrYld.Number
17381 term3 := frequency.Number / dscnl
17382 return newNumberFormulaArg((term1 - term2) / term2 * term3)
17385 // ODDLPRICE function calculates the price per $100 face value of a security
17386 // with an odd (short or long) last period. The syntax of the function is:
17388 // ODDLPRICE(settlement,maturity,last_interest,rate,yld,redemption,frequency,[basis])
17389 func (fn *formulaFuncs) ODDLPRICE(argsList *list.List) formulaArg {
17390 return fn.oddl("ODDLPRICE", argsList)
17393 // ODDLYIELD function calculates the yield of a security with an odd (short or
17394 // long) last period. The syntax of the function is:
17396 // ODDLYIELD(settlement,maturity,last_interest,rate,pr,redemption,frequency,[basis])
17397 func (fn *formulaFuncs) ODDLYIELD(argsList *list.List) formulaArg {
17398 return fn.oddl("ODDLYIELD", argsList)
17401 // PDURATION function calculates the number of periods required for an
17402 // investment to reach a specified future value. The syntax of the function
17405 // PDURATION(rate,pv,fv)
17406 func (fn *formulaFuncs) PDURATION(argsList *list.List) formulaArg {
17407 if argsList.Len() != 3 {
17408 return newErrorFormulaArg(formulaErrorVALUE, "PDURATION requires 3 arguments")
17410 rate := argsList.Front().Value.(formulaArg).ToNumber()
17411 if rate.Type != ArgNumber {
17414 pv := argsList.Front().Next().Value.(formulaArg).ToNumber()
17415 if pv.Type != ArgNumber {
17418 fv := argsList.Back().Value.(formulaArg).ToNumber()
17419 if fv.Type != ArgNumber {
17422 if rate.Number <= 0 || pv.Number <= 0 || fv.Number <= 0 {
17423 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17425 return newNumberFormulaArg((math.Log(fv.Number) - math.Log(pv.Number)) / math.Log(1+rate.Number))
17428 // PMT function calculates the constant periodic payment required to pay off
17429 // (or partially pay off) a loan or investment, with a constant interest
17430 // rate, over a specified period. The syntax of the function is:
17432 // PMT(rate,nper,pv,[fv],[type])
17433 func (fn *formulaFuncs) PMT(argsList *list.List) formulaArg {
17434 if argsList.Len() < 3 {
17435 return newErrorFormulaArg(formulaErrorVALUE, "PMT requires at least 3 arguments")
17437 if argsList.Len() > 5 {
17438 return newErrorFormulaArg(formulaErrorVALUE, "PMT allows at most 5 arguments")
17440 rate := argsList.Front().Value.(formulaArg).ToNumber()
17441 if rate.Type != ArgNumber {
17444 nper := argsList.Front().Next().Value.(formulaArg).ToNumber()
17445 if nper.Type != ArgNumber {
17448 pv := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17449 if pv.Type != ArgNumber {
17452 fv, typ := newNumberFormulaArg(0), newNumberFormulaArg(0)
17453 if argsList.Len() >= 4 {
17454 if fv = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); fv.Type != ArgNumber {
17458 if argsList.Len() == 5 {
17459 if typ = argsList.Back().Value.(formulaArg).ToNumber(); typ.Type != ArgNumber {
17463 if typ.Number != 0 && typ.Number != 1 {
17464 return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
17466 if rate.Number != 0 {
17467 p := (-fv.Number - pv.Number*math.Pow(1+rate.Number, nper.Number)) / (1 + rate.Number*typ.Number) / ((math.Pow(1+rate.Number, nper.Number) - 1) / rate.Number)
17468 return newNumberFormulaArg(p)
17470 return newNumberFormulaArg((-pv.Number - fv.Number) / nper.Number)
17473 // PPMT function calculates the payment on the principal, during a specific
17474 // period of a loan or investment that is paid in constant periodic payments,
17475 // with a constant interest rate. The syntax of the function is:
17477 // PPMT(rate,per,nper,pv,[fv],[type])
17478 func (fn *formulaFuncs) PPMT(argsList *list.List) formulaArg {
17479 return fn.ipmt("PPMT", argsList)
17482 // price is an implementation of the formula function PRICE.
17483 func (fn *formulaFuncs) price(settlement, maturity, rate, yld, redemption, frequency, basis formulaArg) formulaArg {
17484 if basis.Number < 0 || basis.Number > 4 {
17485 return newErrorFormulaArg(formulaErrorNUM, "invalid basis")
17487 argsList := list.New().Init()
17488 argsList.PushBack(settlement)
17489 argsList.PushBack(maturity)
17490 argsList.PushBack(frequency)
17491 argsList.PushBack(basis)
17492 e := fn.COUPDAYS(argsList)
17493 dsc := fn.COUPDAYSNC(argsList).Number / e.Number
17494 n := fn.COUPNUM(argsList)
17495 a := fn.COUPDAYBS(argsList)
17498 ret = redemption.Number / math.Pow(1+yld.Number/frequency.Number, n.Number-1+dsc)
17499 ret -= 100 * rate.Number / frequency.Number * a.Number / e.Number
17500 t1 := 100 * rate.Number / frequency.Number
17501 t2 := 1 + yld.Number/frequency.Number
17502 for k := 0.0; k < n.Number; k++ {
17503 ret += t1 / math.Pow(t2, k+dsc)
17506 dsc = e.Number - a.Number
17507 t1 := 100*(rate.Number/frequency.Number) + redemption.Number
17508 t2 := (yld.Number/frequency.Number)*(dsc/e.Number) + 1
17509 t3 := 100 * (rate.Number / frequency.Number) * (a.Number / e.Number)
17512 return newNumberFormulaArg(ret)
17515 // checkPriceYieldArgs checking and prepare arguments for the formula functions
17516 // PRICE and YIELD.
17517 func checkPriceYieldArgs(name string, rate, prYld, redemption, frequency formulaArg) formulaArg {
17518 if rate.Type != ArgNumber {
17521 if rate.Number < 0 {
17522 return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires rate >= 0", name))
17524 if prYld.Type != ArgNumber {
17527 if redemption.Type != ArgNumber {
17530 if name == "PRICE" {
17531 if prYld.Number < 0 {
17532 return newErrorFormulaArg(formulaErrorNUM, "PRICE requires yld >= 0")
17534 if redemption.Number <= 0 {
17535 return newErrorFormulaArg(formulaErrorNUM, "PRICE requires redemption > 0")
17538 if name == "YIELD" {
17539 if prYld.Number <= 0 {
17540 return newErrorFormulaArg(formulaErrorNUM, "YIELD requires pr > 0")
17542 if redemption.Number < 0 {
17543 return newErrorFormulaArg(formulaErrorNUM, "YIELD requires redemption >= 0")
17546 if frequency.Type != ArgNumber {
17549 if !validateFrequency(frequency.Number) {
17550 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17552 return newEmptyFormulaArg()
17555 // priceYield is an implementation of the formula functions PRICE and YIELD.
17556 func (fn *formulaFuncs) priceYield(name string, argsList *list.List) formulaArg {
17557 if argsList.Len() != 6 && argsList.Len() != 7 {
17558 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 6 or 7 arguments", name))
17560 args := fn.prepareDataValueArgs(2, argsList)
17561 if args.Type != ArgList {
17564 settlement, maturity := args.List[0], args.List[1]
17565 rate := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17566 prYld := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
17567 redemption := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17568 frequency := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17569 if arg := checkPriceYieldArgs(name, rate, prYld, redemption, frequency); arg.Type != ArgEmpty {
17572 basis := newNumberFormulaArg(0)
17573 if argsList.Len() == 7 {
17574 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17575 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17578 if name == "PRICE" {
17579 return fn.price(settlement, maturity, rate, prYld, redemption, frequency, basis)
17581 return fn.yield(settlement, maturity, rate, prYld, redemption, frequency, basis)
17584 // PRICE function calculates the price, per $100 face value of a security that
17585 // pays periodic interest. The syntax of the function is:
17587 // PRICE(settlement,maturity,rate,yld,redemption,frequency,[basis])
17588 func (fn *formulaFuncs) PRICE(argsList *list.List) formulaArg {
17589 return fn.priceYield("PRICE", argsList)
17592 // PRICEDISC function calculates the price, per $100 face value of a
17593 // discounted security. The syntax of the function is:
17595 // PRICEDISC(settlement,maturity,discount,redemption,[basis])
17596 func (fn *formulaFuncs) PRICEDISC(argsList *list.List) formulaArg {
17597 if argsList.Len() != 4 && argsList.Len() != 5 {
17598 return newErrorFormulaArg(formulaErrorVALUE, "PRICEDISC requires 4 or 5 arguments")
17600 args := fn.prepareDataValueArgs(2, argsList)
17601 if args.Type != ArgList {
17604 settlement, maturity := args.List[0], args.List[1]
17605 if maturity.Number <= settlement.Number {
17606 return newErrorFormulaArg(formulaErrorNUM, "PRICEDISC requires maturity > settlement")
17608 discount := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17609 if discount.Type != ArgNumber {
17610 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
17612 if discount.Number <= 0 {
17613 return newErrorFormulaArg(formulaErrorNUM, "PRICEDISC requires discount > 0")
17615 redemption := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
17616 if redemption.Type != ArgNumber {
17617 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
17619 if redemption.Number <= 0 {
17620 return newErrorFormulaArg(formulaErrorNUM, "PRICEDISC requires redemption > 0")
17622 basis := newNumberFormulaArg(0)
17623 if argsList.Len() == 5 {
17624 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17625 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17628 frac := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
17629 if frac.Type != ArgNumber {
17632 return newNumberFormulaArg(redemption.Number * (1 - discount.Number*frac.Number))
17635 // PRICEMAT function calculates the price, per $100 face value of a security
17636 // that pays interest at maturity. The syntax of the function is:
17638 // PRICEMAT(settlement,maturity,issue,rate,yld,[basis])
17639 func (fn *formulaFuncs) PRICEMAT(argsList *list.List) formulaArg {
17640 if argsList.Len() != 5 && argsList.Len() != 6 {
17641 return newErrorFormulaArg(formulaErrorVALUE, "PRICEMAT requires 5 or 6 arguments")
17643 args := fn.prepareDataValueArgs(3, argsList)
17644 if args.Type != ArgList {
17647 settlement, maturity, issue := args.List[0], args.List[1], args.List[2]
17648 if settlement.Number >= maturity.Number {
17649 return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires maturity > settlement")
17651 if issue.Number >= settlement.Number {
17652 return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires settlement > issue")
17654 rate := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
17655 if rate.Type != ArgNumber {
17658 if rate.Number < 0 {
17659 return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires rate >= 0")
17661 yld := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
17662 if yld.Type != ArgNumber {
17665 if yld.Number < 0 {
17666 return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires yld >= 0")
17668 basis := newNumberFormulaArg(0)
17669 if argsList.Len() == 6 {
17670 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17671 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17674 dsm := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
17675 if dsm.Type != ArgNumber {
17678 dis := yearFrac(issue.Number, settlement.Number, int(basis.Number))
17679 dim := yearFrac(issue.Number, maturity.Number, int(basis.Number))
17680 return newNumberFormulaArg(((1+dim.Number*rate.Number)/(1+dsm.Number*yld.Number) - dis.Number*rate.Number) * 100)
17683 // PV function calculates the Present Value of an investment, based on a
17684 // series of future payments. The syntax of the function is:
17686 // PV(rate,nper,pmt,[fv],[type])
17687 func (fn *formulaFuncs) PV(argsList *list.List) formulaArg {
17688 if argsList.Len() < 3 {
17689 return newErrorFormulaArg(formulaErrorVALUE, "PV requires at least 3 arguments")
17691 if argsList.Len() > 5 {
17692 return newErrorFormulaArg(formulaErrorVALUE, "PV allows at most 5 arguments")
17694 rate := argsList.Front().Value.(formulaArg).ToNumber()
17695 if rate.Type != ArgNumber {
17698 nper := argsList.Front().Next().Value.(formulaArg).ToNumber()
17699 if nper.Type != ArgNumber {
17702 pmt := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17703 if pmt.Type != ArgNumber {
17706 fv := newNumberFormulaArg(0)
17707 if argsList.Len() >= 4 {
17708 if fv = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); fv.Type != ArgNumber {
17712 t := newNumberFormulaArg(0)
17713 if argsList.Len() == 5 {
17714 if t = argsList.Back().Value.(formulaArg).ToNumber(); t.Type != ArgNumber {
17721 if rate.Number == 0 {
17722 return newNumberFormulaArg(-pmt.Number*nper.Number - fv.Number)
17724 return newNumberFormulaArg((((1-math.Pow(1+rate.Number, nper.Number))/rate.Number)*pmt.Number*(1+rate.Number*t.Number) - fv.Number) / math.Pow(1+rate.Number, nper.Number))
17727 // rate is an implementation of the formula function RATE.
17728 func (fn *formulaFuncs) rate(nper, pmt, pv, fv, t, guess formulaArg) formulaArg {
17729 maxIter, iter, isClose, epsMax, rate := 100, 0, false, 1e-6, guess.Number
17730 for iter < maxIter && !isClose {
17731 t1 := math.Pow(rate+1, nper.Number)
17732 t2 := math.Pow(rate+1, nper.Number-1)
17733 rt := rate*t.Number + 1
17734 p0 := pmt.Number * (t1 - 1)
17735 f1 := fv.Number + t1*pv.Number + p0*rt/rate
17736 n1 := nper.Number * t2 * pv.Number
17737 n2 := p0 * rt / math.Pow(rate, 2)
17738 f2 := math.Nextafter(n1, n1) - math.Nextafter(n2, n2)
17739 f3 := (nper.Number*pmt.Number*t2*rt + p0*t.Number) / rate
17740 delta := f1 / (f2 + f3)
17741 if math.Abs(delta) < epsMax {
17747 return newNumberFormulaArg(rate)
17750 // RATE function calculates the interest rate required to pay off a specified
17751 // amount of a loan, or to reach a target amount on an investment, over a
17752 // given period. The syntax of the function is:
17754 // RATE(nper,pmt,pv,[fv],[type],[guess])
17755 func (fn *formulaFuncs) RATE(argsList *list.List) formulaArg {
17756 if argsList.Len() < 3 {
17757 return newErrorFormulaArg(formulaErrorVALUE, "RATE requires at least 3 arguments")
17759 if argsList.Len() > 6 {
17760 return newErrorFormulaArg(formulaErrorVALUE, "RATE allows at most 6 arguments")
17762 nper := argsList.Front().Value.(formulaArg).ToNumber()
17763 if nper.Type != ArgNumber {
17766 pmt := argsList.Front().Next().Value.(formulaArg).ToNumber()
17767 if pmt.Type != ArgNumber {
17770 pv := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17771 if pv.Type != ArgNumber {
17774 fv := newNumberFormulaArg(0)
17775 if argsList.Len() >= 4 {
17776 if fv = argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber(); fv.Type != ArgNumber {
17780 t := newNumberFormulaArg(0)
17781 if argsList.Len() >= 5 {
17782 if t = argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); t.Type != ArgNumber {
17789 guess := newNumberFormulaArg(0.1)
17790 if argsList.Len() == 6 {
17791 if guess = argsList.Back().Value.(formulaArg).ToNumber(); guess.Type != ArgNumber {
17795 return fn.rate(nper, pmt, pv, fv, t, guess)
17798 // RECEIVED function calculates the amount received at maturity for a fully
17799 // invested security. The syntax of the function is:
17801 // RECEIVED(settlement,maturity,investment,discount,[basis])
17802 func (fn *formulaFuncs) RECEIVED(argsList *list.List) formulaArg {
17803 if argsList.Len() < 4 {
17804 return newErrorFormulaArg(formulaErrorVALUE, "RECEIVED requires at least 4 arguments")
17806 if argsList.Len() > 5 {
17807 return newErrorFormulaArg(formulaErrorVALUE, "RECEIVED allows at most 5 arguments")
17809 args := fn.prepareDataValueArgs(2, argsList)
17810 if args.Type != ArgList {
17813 settlement, maturity := args.List[0], args.List[1]
17814 investment := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
17815 if investment.Type != ArgNumber {
17818 discount := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
17819 if discount.Type != ArgNumber {
17822 if discount.Number <= 0 {
17823 return newErrorFormulaArg(formulaErrorNUM, "RECEIVED requires discount > 0")
17825 basis := newNumberFormulaArg(0)
17826 if argsList.Len() == 5 {
17827 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
17828 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17831 frac := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
17832 if frac.Type != ArgNumber {
17835 return newNumberFormulaArg(investment.Number / (1 - discount.Number*frac.Number))
17838 // RRI function calculates the equivalent interest rate for an investment with
17839 // specified present value, future value and duration. The syntax of the
17843 func (fn *formulaFuncs) RRI(argsList *list.List) formulaArg {
17844 if argsList.Len() != 3 {
17845 return newErrorFormulaArg(formulaErrorVALUE, "RRI requires 3 arguments")
17847 nper := argsList.Front().Value.(formulaArg).ToNumber()
17848 pv := argsList.Front().Next().Value.(formulaArg).ToNumber()
17849 fv := argsList.Back().Value.(formulaArg).ToNumber()
17850 if nper.Type != ArgNumber || pv.Type != ArgNumber || fv.Type != ArgNumber {
17851 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17853 if nper.Number <= 0 {
17854 return newErrorFormulaArg(formulaErrorNUM, "RRI requires nper argument to be > 0")
17856 if pv.Number <= 0 {
17857 return newErrorFormulaArg(formulaErrorNUM, "RRI requires pv argument to be > 0")
17860 return newErrorFormulaArg(formulaErrorNUM, "RRI requires fv argument to be >= 0")
17862 return newNumberFormulaArg(math.Pow(fv.Number/pv.Number, 1/nper.Number) - 1)
17865 // SLN function calculates the straight line depreciation of an asset for one
17866 // period. The syntax of the function is:
17868 // SLN(cost,salvage,life)
17869 func (fn *formulaFuncs) SLN(argsList *list.List) formulaArg {
17870 if argsList.Len() != 3 {
17871 return newErrorFormulaArg(formulaErrorVALUE, "SLN requires 3 arguments")
17873 cost := argsList.Front().Value.(formulaArg).ToNumber()
17874 salvage := argsList.Front().Next().Value.(formulaArg).ToNumber()
17875 life := argsList.Back().Value.(formulaArg).ToNumber()
17876 if cost.Type != ArgNumber || salvage.Type != ArgNumber || life.Type != ArgNumber {
17877 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17879 if life.Number == 0 {
17880 return newErrorFormulaArg(formulaErrorNUM, "SLN requires life argument to be > 0")
17882 return newNumberFormulaArg((cost.Number - salvage.Number) / life.Number)
17885 // SYD function calculates the sum-of-years' digits depreciation for a
17886 // specified period in the lifetime of an asset. The syntax of the function
17889 // SYD(cost,salvage,life,per)
17890 func (fn *formulaFuncs) SYD(argsList *list.List) formulaArg {
17891 if argsList.Len() != 4 {
17892 return newErrorFormulaArg(formulaErrorVALUE, "SYD requires 4 arguments")
17894 cost := argsList.Front().Value.(formulaArg).ToNumber()
17895 salvage := argsList.Front().Next().Value.(formulaArg).ToNumber()
17896 life := argsList.Back().Prev().Value.(formulaArg).ToNumber()
17897 per := argsList.Back().Value.(formulaArg).ToNumber()
17898 if cost.Type != ArgNumber || salvage.Type != ArgNumber || life.Type != ArgNumber || per.Type != ArgNumber {
17899 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17901 if life.Number <= 0 {
17902 return newErrorFormulaArg(formulaErrorNUM, "SYD requires life argument to be > 0")
17904 if per.Number <= 0 {
17905 return newErrorFormulaArg(formulaErrorNUM, "SYD requires per argument to be > 0")
17907 if per.Number > life.Number {
17908 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17910 return newNumberFormulaArg(((cost.Number - salvage.Number) * (life.Number - per.Number + 1) * 2) / (life.Number * (life.Number + 1)))
17913 // TBILLEQ function calculates the bond-equivalent yield for a Treasury Bill.
17914 // The syntax of the function is:
17916 // TBILLEQ(settlement,maturity,discount)
17917 func (fn *formulaFuncs) TBILLEQ(argsList *list.List) formulaArg {
17918 if argsList.Len() != 3 {
17919 return newErrorFormulaArg(formulaErrorVALUE, "TBILLEQ requires 3 arguments")
17921 args := fn.prepareDataValueArgs(2, argsList)
17922 if args.Type != ArgList {
17925 settlement, maturity := args.List[0], args.List[1]
17926 dsm := maturity.Number - settlement.Number
17927 if dsm > 365 || maturity.Number <= settlement.Number {
17928 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17930 discount := argsList.Back().Value.(formulaArg).ToNumber()
17931 if discount.Type != ArgNumber {
17932 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
17934 if discount.Number <= 0 {
17935 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17937 return newNumberFormulaArg((365 * discount.Number) / (360 - discount.Number*dsm))
17940 // TBILLPRICE function returns the price, per $100 face value, of a Treasury
17941 // Bill. The syntax of the function is:
17943 // TBILLPRICE(settlement,maturity,discount)
17944 func (fn *formulaFuncs) TBILLPRICE(argsList *list.List) formulaArg {
17945 if argsList.Len() != 3 {
17946 return newErrorFormulaArg(formulaErrorVALUE, "TBILLPRICE requires 3 arguments")
17948 args := fn.prepareDataValueArgs(2, argsList)
17949 if args.Type != ArgList {
17952 settlement, maturity := args.List[0], args.List[1]
17953 dsm := maturity.Number - settlement.Number
17954 if dsm > 365 || maturity.Number <= settlement.Number {
17955 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17957 discount := argsList.Back().Value.(formulaArg).ToNumber()
17958 if discount.Type != ArgNumber {
17959 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
17961 if discount.Number <= 0 {
17962 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17964 return newNumberFormulaArg(100 * (1 - discount.Number*dsm/360))
17967 // TBILLYIELD function calculates the yield of a Treasury Bill. The syntax of
17968 // the function is:
17970 // TBILLYIELD(settlement,maturity,pr)
17971 func (fn *formulaFuncs) TBILLYIELD(argsList *list.List) formulaArg {
17972 if argsList.Len() != 3 {
17973 return newErrorFormulaArg(formulaErrorVALUE, "TBILLYIELD requires 3 arguments")
17975 args := fn.prepareDataValueArgs(2, argsList)
17976 if args.Type != ArgList {
17979 settlement, maturity := args.List[0], args.List[1]
17980 dsm := maturity.Number - settlement.Number
17981 if dsm > 365 || maturity.Number <= settlement.Number {
17982 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17984 pr := argsList.Back().Value.(formulaArg).ToNumber()
17985 if pr.Type != ArgNumber {
17986 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
17988 if pr.Number <= 0 {
17989 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
17991 return newNumberFormulaArg(((100 - pr.Number) / pr.Number) * (360 / dsm))
17994 // prepareVdbArgs checking and prepare arguments for the formula function
17996 func (fn *formulaFuncs) prepareVdbArgs(argsList *list.List) formulaArg {
17997 cost := argsList.Front().Value.(formulaArg).ToNumber()
17998 if cost.Type != ArgNumber {
18001 if cost.Number < 0 {
18002 return newErrorFormulaArg(formulaErrorNUM, "VDB requires cost >= 0")
18004 salvage := argsList.Front().Next().Value.(formulaArg).ToNumber()
18005 if salvage.Type != ArgNumber {
18008 if salvage.Number < 0 {
18009 return newErrorFormulaArg(formulaErrorNUM, "VDB requires salvage >= 0")
18011 life := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
18012 if life.Type != ArgNumber {
18015 if life.Number <= 0 {
18016 return newErrorFormulaArg(formulaErrorNUM, "VDB requires life > 0")
18018 startPeriod := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
18019 if startPeriod.Type != ArgNumber {
18022 if startPeriod.Number < 0 {
18023 return newErrorFormulaArg(formulaErrorNUM, "VDB requires start_period > 0")
18025 endPeriod := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
18026 if endPeriod.Type != ArgNumber {
18029 if startPeriod.Number > endPeriod.Number {
18030 return newErrorFormulaArg(formulaErrorNUM, "VDB requires start_period <= end_period")
18032 if endPeriod.Number > life.Number {
18033 return newErrorFormulaArg(formulaErrorNUM, "VDB requires end_period <= life")
18035 factor := newNumberFormulaArg(2)
18036 if argsList.Len() > 5 {
18037 if factor = argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber(); factor.Type != ArgNumber {
18038 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18040 if factor.Number < 0 {
18041 return newErrorFormulaArg(formulaErrorVALUE, "VDB requires factor >= 0")
18044 return newListFormulaArg([]formulaArg{cost, salvage, life, startPeriod, endPeriod, factor})
18047 // vdb is a part of implementation of the formula function VDB.
18048 func (fn *formulaFuncs) vdb(cost, salvage, life, life1, period, factor formulaArg) formulaArg {
18049 var ddb, vdb, sln, term float64
18050 endInt, cs, nowSln := math.Ceil(period.Number), cost.Number-salvage.Number, false
18051 ddbArgs := list.New()
18052 for i := 1.0; i <= endInt; i++ {
18055 ddbArgs.PushBack(cost)
18056 ddbArgs.PushBack(salvage)
18057 ddbArgs.PushBack(life)
18058 ddbArgs.PushBack(newNumberFormulaArg(i))
18059 ddbArgs.PushBack(factor)
18060 ddb = fn.DDB(ddbArgs).Number
18061 sln = cs / (life1.Number - i + 1)
18073 term *= period.Number + 1 - endInt
18077 return newNumberFormulaArg(vdb)
18080 // VDB function calculates the depreciation of an asset, using the Double
18081 // Declining Balance Method, or another specified depreciation rate, for a
18082 // specified period (including partial periods). The syntax of the function
18085 // VDB(cost,salvage,life,start_period,end_period,[factor],[no_switch])
18086 func (fn *formulaFuncs) VDB(argsList *list.List) formulaArg {
18087 if argsList.Len() < 5 || argsList.Len() > 7 {
18088 return newErrorFormulaArg(formulaErrorVALUE, "VDB requires 5 or 7 arguments")
18090 args := fn.prepareVdbArgs(argsList)
18091 if args.Type != ArgList {
18094 cost, salvage, life, startPeriod, endPeriod, factor := args.List[0], args.List[1], args.List[2], args.List[3], args.List[4], args.List[5]
18095 noSwitch := newBoolFormulaArg(false)
18096 if argsList.Len() > 6 {
18097 if noSwitch = argsList.Back().Value.(formulaArg).ToBool(); noSwitch.Type != ArgNumber {
18098 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18101 startInt, endInt, vdb, ddbArgs := math.Floor(startPeriod.Number), math.Ceil(endPeriod.Number), newNumberFormulaArg(0), list.New()
18102 if noSwitch.Number == 1 {
18103 for i := startInt + 1; i <= endInt; i++ {
18105 ddbArgs.PushBack(cost)
18106 ddbArgs.PushBack(salvage)
18107 ddbArgs.PushBack(life)
18108 ddbArgs.PushBack(newNumberFormulaArg(i))
18109 ddbArgs.PushBack(factor)
18110 term := fn.DDB(ddbArgs)
18111 if i == startInt+1 {
18112 term.Number *= math.Min(endPeriod.Number, startInt+1) - startPeriod.Number
18113 } else if i == endInt {
18114 term.Number *= endPeriod.Number + 1 - endInt
18116 vdb.Number += term.Number
18120 life1, part := life, 0.0
18121 if startPeriod.Number != math.Floor(startPeriod.Number) && factor.Number > 1.0 && startPeriod.Number >= life.Number/2.0 {
18122 part = startPeriod.Number - life.Number/2.0
18123 startPeriod.Number = life.Number / 2.0
18124 endPeriod.Number -= part
18126 cost.Number -= fn.vdb(cost, salvage, life, life1, startPeriod, factor).Number
18127 return fn.vdb(cost, salvage, life, newNumberFormulaArg(life.Number-startPeriod.Number), newNumberFormulaArg(endPeriod.Number-startPeriod.Number), factor)
18130 // prepareXArgs prepare arguments for the formula function XIRR and XNPV.
18131 func (fn *formulaFuncs) prepareXArgs(values, dates formulaArg) (valuesArg, datesArg []float64, err formulaArg) {
18132 for _, arg := range values.ToList() {
18133 if numArg := arg.ToNumber(); numArg.Type == ArgNumber {
18134 valuesArg = append(valuesArg, numArg.Number)
18137 err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18140 if len(valuesArg) < 2 {
18141 err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18144 args, date := list.New(), 0.0
18145 for _, arg := range dates.ToList() {
18148 dateValue := fn.DATEVALUE(args)
18149 if dateValue.Type != ArgNumber {
18150 err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18153 if dateValue.Number < date {
18154 err = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18157 datesArg = append(datesArg, dateValue.Number)
18158 date = dateValue.Number
18160 if len(valuesArg) != len(datesArg) {
18161 err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18164 err = newEmptyFormulaArg()
18168 // xirr is an implementation of the formula function XIRR.
18169 func (fn *formulaFuncs) xirr(values, dates []float64, guess float64) formulaArg {
18170 positive, negative := false, false
18171 for i := 0; i < len(values); i++ {
18179 if !positive || !negative {
18180 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18182 result, epsMax, count, maxIterate, err := guess, 1e-10, 0, 50, false
18184 resultValue := xirrPart1(values, dates, result)
18185 newRate := result - resultValue/xirrPart2(values, dates, result)
18186 epsRate := math.Abs(newRate - result)
18189 if epsRate <= epsMax || math.Abs(resultValue) <= epsMax {
18192 if count > maxIterate {
18197 if err || math.IsNaN(result) || math.IsInf(result, 0) {
18198 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18200 return newNumberFormulaArg(result)
18203 // xirrPart1 is a part of implementation of the formula function XIRR.
18204 func xirrPart1(values, dates []float64, rate float64) float64 {
18206 result := values[0]
18207 vlen := len(values)
18208 firstDate := dates[0]
18209 for i := 1; i < vlen; i++ {
18210 result += values[i] / math.Pow(r, (dates[i]-firstDate)/365)
18215 // xirrPart2 is a part of implementation of the formula function XIRR.
18216 func xirrPart2(values, dates []float64, rate float64) float64 {
18219 vlen := len(values)
18220 firstDate := dates[0]
18221 for i := 1; i < vlen; i++ {
18222 frac := (dates[i] - firstDate) / 365
18223 result -= frac * values[i] / math.Pow(r, frac+1)
18228 // XIRR function returns the Internal Rate of Return for a supplied series of
18229 // cash flows (i.e. a set of values, which includes an initial investment
18230 // value and a series of net income values) occurring at a series of supplied
18231 // dates. The syntax of the function is:
18233 // XIRR(values,dates,[guess])
18234 func (fn *formulaFuncs) XIRR(argsList *list.List) formulaArg {
18235 if argsList.Len() != 2 && argsList.Len() != 3 {
18236 return newErrorFormulaArg(formulaErrorVALUE, "XIRR requires 2 or 3 arguments")
18238 values, dates, err := fn.prepareXArgs(argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg))
18239 if err.Type != ArgEmpty {
18242 guess := newNumberFormulaArg(0)
18243 if argsList.Len() == 3 {
18244 if guess = argsList.Back().Value.(formulaArg).ToNumber(); guess.Type != ArgNumber {
18245 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18247 if guess.Number <= -1 {
18248 return newErrorFormulaArg(formulaErrorVALUE, "XIRR requires guess > -1")
18251 return fn.xirr(values, dates, guess.Number)
18254 // XNPV function calculates the Net Present Value for a schedule of cash flows
18255 // that is not necessarily periodic. The syntax of the function is:
18257 // XNPV(rate,values,dates)
18258 func (fn *formulaFuncs) XNPV(argsList *list.List) formulaArg {
18259 if argsList.Len() != 3 {
18260 return newErrorFormulaArg(formulaErrorVALUE, "XNPV requires 3 arguments")
18262 rate := argsList.Front().Value.(formulaArg).ToNumber()
18263 if rate.Type != ArgNumber {
18266 if rate.Number <= 0 {
18267 return newErrorFormulaArg(formulaErrorVALUE, "XNPV requires rate > 0")
18269 values, dates, err := fn.prepareXArgs(argsList.Front().Next().Value.(formulaArg), argsList.Back().Value.(formulaArg))
18270 if err.Type != ArgEmpty {
18273 date1, xnpv := dates[0], 0.0
18274 for idx, value := range values {
18275 xnpv += value / math.Pow(1+rate.Number, (dates[idx]-date1)/365)
18277 return newNumberFormulaArg(xnpv)
18280 // yield is an implementation of the formula function YIELD.
18281 func (fn *formulaFuncs) yield(settlement, maturity, rate, pr, redemption, frequency, basis formulaArg) formulaArg {
18282 priceN, yield1, yield2 := newNumberFormulaArg(0), newNumberFormulaArg(0), newNumberFormulaArg(1)
18283 price1 := fn.price(settlement, maturity, rate, yield1, redemption, frequency, basis)
18284 if price1.Type != ArgNumber {
18287 price2 := fn.price(settlement, maturity, rate, yield2, redemption, frequency, basis)
18288 yieldN := newNumberFormulaArg((yield2.Number - yield1.Number) * 0.5)
18289 for iter := 0; iter < 100 && priceN.Number != pr.Number; iter++ {
18290 priceN = fn.price(settlement, maturity, rate, yieldN, redemption, frequency, basis)
18291 if pr.Number == price1.Number {
18293 } else if pr.Number == price2.Number {
18295 } else if pr.Number == priceN.Number {
18297 } else if pr.Number < price2.Number {
18298 yield2.Number *= 2.0
18299 price2 = fn.price(settlement, maturity, rate, yield2, redemption, frequency, basis)
18300 yieldN.Number = (yield2.Number - yield1.Number) * 0.5
18302 if pr.Number < priceN.Number {
18309 f1 := (yield2.Number - yield1.Number) * ((pr.Number - price2.Number) / (price1.Number - price2.Number))
18310 yieldN.Number = yield2.Number - math.Nextafter(f1, f1)
18316 // YIELD function calculates the Yield of a security that pays periodic
18317 // interest. The syntax of the function is:
18319 // YIELD(settlement,maturity,rate,pr,redemption,frequency,[basis])
18320 func (fn *formulaFuncs) YIELD(argsList *list.List) formulaArg {
18321 return fn.priceYield("YIELD", argsList)
18324 // YIELDDISC function calculates the annual yield of a discounted security.
18325 // The syntax of the function is:
18327 // YIELDDISC(settlement,maturity,pr,redemption,[basis])
18328 func (fn *formulaFuncs) YIELDDISC(argsList *list.List) formulaArg {
18329 if argsList.Len() != 4 && argsList.Len() != 5 {
18330 return newErrorFormulaArg(formulaErrorVALUE, "YIELDDISC requires 4 or 5 arguments")
18332 args := fn.prepareDataValueArgs(2, argsList)
18333 if args.Type != ArgList {
18336 settlement, maturity := args.List[0], args.List[1]
18337 pr := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
18338 if pr.Type != ArgNumber {
18339 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18341 if pr.Number <= 0 {
18342 return newErrorFormulaArg(formulaErrorNUM, "YIELDDISC requires pr > 0")
18344 redemption := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
18345 if redemption.Type != ArgNumber {
18346 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18348 if redemption.Number <= 0 {
18349 return newErrorFormulaArg(formulaErrorNUM, "YIELDDISC requires redemption > 0")
18351 basis := newNumberFormulaArg(0)
18352 if argsList.Len() == 5 {
18353 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
18354 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18357 frac := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
18358 if frac.Type != ArgNumber {
18361 return newNumberFormulaArg((redemption.Number/pr.Number - 1) / frac.Number)
18364 // YIELDMAT function calculates the annual yield of a security that pays
18365 // interest at maturity. The syntax of the function is:
18367 // YIELDMAT(settlement,maturity,issue,rate,pr,[basis])
18368 func (fn *formulaFuncs) YIELDMAT(argsList *list.List) formulaArg {
18369 if argsList.Len() != 5 && argsList.Len() != 6 {
18370 return newErrorFormulaArg(formulaErrorVALUE, "YIELDMAT requires 5 or 6 arguments")
18372 args := fn.prepareDataValueArgs(2, argsList)
18373 if args.Type != ArgList {
18376 settlement, maturity := args.List[0], args.List[1]
18377 arg := list.New().Init()
18378 issue := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
18379 if issue.Type != ArgNumber {
18380 arg.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
18381 issue = fn.DATEVALUE(arg)
18382 if issue.Type != ArgNumber {
18383 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18386 if issue.Number >= settlement.Number {
18387 return newErrorFormulaArg(formulaErrorNUM, "YIELDMAT requires settlement > issue")
18389 rate := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
18390 if rate.Type != ArgNumber {
18393 if rate.Number < 0 {
18394 return newErrorFormulaArg(formulaErrorNUM, "YIELDMAT requires rate >= 0")
18396 pr := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
18397 if pr.Type != ArgNumber {
18400 if pr.Number <= 0 {
18401 return newErrorFormulaArg(formulaErrorNUM, "YIELDMAT requires pr > 0")
18403 basis := newNumberFormulaArg(0)
18404 if argsList.Len() == 6 {
18405 if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
18406 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18409 dim := yearFrac(issue.Number, maturity.Number, int(basis.Number))
18410 if dim.Type != ArgNumber {
18413 dis := yearFrac(issue.Number, settlement.Number, int(basis.Number))
18414 dsm := yearFrac(settlement.Number, maturity.Number, int(basis.Number))
18415 f1 := dim.Number * rate.Number
18416 result := 1 + math.Nextafter(f1, f1)
18417 result /= pr.Number/100 + dis.Number*rate.Number
18419 result /= dsm.Number
18420 return newNumberFormulaArg(result)
18423 // Database Functions
18425 // calcDatabase defines the structure for formula database.
18426 type calcDatabase struct {
18428 indexMap map[int]int
18429 database [][]formulaArg
18430 criteria [][]formulaArg
18433 // newCalcDatabase function returns formula database by given data range of
18434 // cells containing the database, field and criteria range.
18435 func newCalcDatabase(database, field, criteria formulaArg) *calcDatabase {
18436 db := calcDatabase{
18437 indexMap: make(map[int]int),
18438 database: database.Matrix,
18439 criteria: criteria.Matrix,
18441 exp := len(database.Matrix) < 2 || len(database.Matrix[0]) < 1 ||
18442 len(criteria.Matrix) < 2 || len(criteria.Matrix[0]) < 1
18443 if field.Type != ArgEmpty {
18444 if db.col = db.columnIndex(database.Matrix, field); exp || db.col < 0 || len(db.database[0]) <= db.col {
18449 if db.col = -1; exp {
18455 // columnIndex return index by specifies column field within the database for
18456 // which user want to return the count of non-blank cells.
18457 func (db *calcDatabase) columnIndex(database [][]formulaArg, field formulaArg) int {
18458 num := field.ToNumber()
18459 if num.Type != ArgNumber && len(database) > 0 {
18460 for i := 0; i < len(database[0]); i++ {
18461 if title := database[0][i]; strings.EqualFold(title.Value(), field.Value()) {
18467 return int(num.Number - 1)
18470 // criteriaEval evaluate formula criteria expression.
18471 func (db *calcDatabase) criteriaEval() bool {
18473 columns, rows = len(db.criteria[0]), len(db.criteria)
18474 criteria = db.criteria
18478 if len(db.indexMap) == 0 {
18479 fields := criteria[0]
18480 for j := 0; j < columns; j++ {
18481 if k = db.columnIndex(db.database, fields[j]); k < 0 {
18487 for i := 1; !matched && i < rows; i++ {
18489 for j := 0; matched && j < columns; j++ {
18490 criteriaExp := db.criteria[i][j]
18491 if criteriaExp.Value() == "" {
18494 criteria := formulaCriteriaParser(criteriaExp)
18495 cell := db.database[db.row][db.indexMap[j]]
18496 matched, _ = formulaCriteriaEval(cell, criteria)
18502 // value returns the current cell value.
18503 func (db *calcDatabase) value() formulaArg {
18505 return db.database[db.row][len(db.database[db.row])-1]
18507 return db.database[db.row][db.col]
18510 // next will return true if find the matched cell in the database.
18511 func (db *calcDatabase) next() bool {
18512 matched, rows := false, len(db.database)
18513 for !matched && db.row < rows {
18514 if db.row++; db.row < rows {
18515 matched = db.criteriaEval()
18521 // database is an implementation of the formula functions DAVERAGE, DMAX and DMIN.
18522 func (fn *formulaFuncs) database(name string, argsList *list.List) formulaArg {
18523 if argsList.Len() != 3 {
18524 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 arguments", name))
18526 database := argsList.Front().Value.(formulaArg)
18527 field := argsList.Front().Next().Value.(formulaArg)
18528 criteria := argsList.Back().Value.(formulaArg)
18529 db := newCalcDatabase(database, field, criteria)
18531 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18535 args.PushBack(db.value())
18539 return fn.MAX(args)
18541 return fn.MIN(args)
18543 return fn.PRODUCT(args)
18545 return fn.STDEV(args)
18547 return fn.STDEVP(args)
18549 return fn.SUM(args)
18551 return fn.VAR(args)
18553 return fn.VARP(args)
18555 return fn.AVERAGE(args)
18559 // DAVERAGE function calculates the average (statistical mean) of values in a
18560 // field (column) in a database for selected records, that satisfy
18561 // user-specified criteria. The syntax of the function is:
18563 // DAVERAGE(database,field,criteria)
18564 func (fn *formulaFuncs) DAVERAGE(argsList *list.List) formulaArg {
18565 return fn.database("DAVERAGE", argsList)
18568 // dcount is an implementation of the formula functions DCOUNT and DCOUNTA.
18569 func (fn *formulaFuncs) dcount(name string, argsList *list.List) formulaArg {
18570 if argsList.Len() < 2 {
18571 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 2 arguments", name))
18573 if argsList.Len() > 3 {
18574 return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 3 arguments", name))
18576 field := newEmptyFormulaArg()
18577 criteria := argsList.Back().Value.(formulaArg)
18578 if argsList.Len() > 2 {
18579 field = argsList.Front().Next().Value.(formulaArg)
18581 database := argsList.Front().Value.(formulaArg)
18582 db := newCalcDatabase(database, field, criteria)
18584 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18588 args.PushBack(db.value())
18590 if name == "DCOUNT" {
18591 return fn.COUNT(args)
18593 return fn.COUNTA(args)
18596 // DCOUNT function returns the number of cells containing numeric values, in a
18597 // field (column) of a database for selected records only. The records to be
18598 // included in the count are those that satisfy a set of one or more
18599 // user-specified criteria. The syntax of the function is:
18601 // DCOUNT(database,[field],criteria)
18602 func (fn *formulaFuncs) DCOUNT(argsList *list.List) formulaArg {
18603 return fn.dcount("DCOUNT", argsList)
18606 // DCOUNTA function returns the number of non-blank cells, in a field
18607 // (column) of a database for selected records only. The records to be
18608 // included in the count are those that satisfy a set of one or more
18609 // user-specified criteria. The syntax of the function is:
18611 // DCOUNTA(database,[field],criteria)
18612 func (fn *formulaFuncs) DCOUNTA(argsList *list.List) formulaArg {
18613 return fn.dcount("DCOUNTA", argsList)
18616 // DGET function returns a single value from a column of a database. The record
18617 // is selected via a set of one or more user-specified criteria. The syntax of
18618 // the function is:
18620 // DGET(database,field,criteria)
18621 func (fn *formulaFuncs) DGET(argsList *list.List) formulaArg {
18622 if argsList.Len() != 3 {
18623 return newErrorFormulaArg(formulaErrorVALUE, "DGET requires 3 arguments")
18625 database := argsList.Front().Value.(formulaArg)
18626 field := argsList.Front().Next().Value.(formulaArg)
18627 criteria := argsList.Back().Value.(formulaArg)
18628 db := newCalcDatabase(database, field, criteria)
18630 return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18632 value := newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
18634 if value = db.value(); db.next() {
18635 return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
18641 // DMAX function finds the maximum value in a field (column) in a database for
18642 // selected records only. The records to be included in the calculation are
18643 // defined by a set of one or more user-specified criteria. The syntax of the
18646 // DMAX(database,field,criteria)
18647 func (fn *formulaFuncs) DMAX(argsList *list.List) formulaArg {
18648 return fn.database("DMAX", argsList)
18651 // DMIN function finds the minimum value in a field (column) in a database for
18652 // selected records only. The records to be included in the calculation are
18653 // defined by a set of one or more user-specified criteria. The syntax of the
18656 // DMIN(database,field,criteria)
18657 func (fn *formulaFuncs) DMIN(argsList *list.List) formulaArg {
18658 return fn.database("DMIN", argsList)
18661 // DPRODUCT function calculates the product of a field (column) in a database
18662 // for selected records, that satisfy user-specified criteria. The syntax of
18663 // the function is:
18665 // DPRODUCT(database,field,criteria)
18666 func (fn *formulaFuncs) DPRODUCT(argsList *list.List) formulaArg {
18667 return fn.database("DPRODUCT", argsList)
18670 // DSTDEV function calculates the sample standard deviation of a field
18671 // (column) in a database for selected records only. The records to be
18672 // included in the calculation are defined by a set of one or more
18673 // user-specified criteria. The syntax of the function is:
18675 // DSTDEV(database,field,criteria)
18676 func (fn *formulaFuncs) DSTDEV(argsList *list.List) formulaArg {
18677 return fn.database("DSTDEV", argsList)
18680 // DSTDEVP function calculates the standard deviation of a field (column) in a
18681 // database for selected records only. The records to be included in the
18682 // calculation are defined by a set of one or more user-specified criteria.
18683 // The syntax of the function is:
18685 // DSTDEVP(database,field,criteria)
18686 func (fn *formulaFuncs) DSTDEVP(argsList *list.List) formulaArg {
18687 return fn.database("DSTDEVP", argsList)
18690 // DSUM function calculates the sum of a field (column) in a database for
18691 // selected records, that satisfy user-specified criteria. The syntax of the
18694 // DSUM(database,field,criteria)
18695 func (fn *formulaFuncs) DSUM(argsList *list.List) formulaArg {
18696 return fn.database("DSUM", argsList)
18699 // DVAR function calculates the sample variance of a field (column) in a
18700 // database for selected records only. The records to be included in the
18701 // calculation are defined by a set of one or more user-specified criteria.
18702 // The syntax of the function is:
18704 // DVAR(database,field,criteria)
18705 func (fn *formulaFuncs) DVAR(argsList *list.List) formulaArg {
18706 return fn.database("DVAR", argsList)
18709 // DVARP function calculates the variance (for an entire population), of the
18710 // values in a field (column) in a database for selected records only. The
18711 // records to be included in the calculation are defined by a set of one or
18712 // more user-specified criteria. The syntax of the function is:
18714 // DVARP(database,field,criteria)
18715 func (fn *formulaFuncs) DVARP(argsList *list.List) formulaArg {
18716 return fn.database("DVARP", argsList)
18719 // DISPIMG function calculates the Kingsoft WPS Office embedded image ID. The
18720 // syntax of the function is:
18722 // DISPIMG(picture_name,display_mode)
18723 func (fn *formulaFuncs) DISPIMG(argsList *list.List) formulaArg {
18724 if argsList.Len() != 2 {
18725 return newErrorFormulaArg(formulaErrorVALUE, "DISPIMG requires 2 numeric arguments")
18727 return argsList.Front().Value.(formulaArg)