@@ -93,21 +93,36 @@ type formulaArg struct {
9393// formulaFuncs is the type of the formula functions.
9494type formulaFuncs struct {}
9595
96+ // tokenPriority defined basic arithmetic operator priority.
97+ var tokenPriority = map [string ]int {
98+ "^" : 5 ,
99+ "*" : 4 ,
100+ "/" : 4 ,
101+ "+" : 3 ,
102+ "-" : 3 ,
103+ "=" : 2 ,
104+ "<" : 2 ,
105+ "<=" : 2 ,
106+ ">" : 2 ,
107+ ">=" : 2 ,
108+ "&" : 1 ,
109+ }
110+
96111// CalcCellValue provides a function to get calculated cell value. This
97112// feature is currently in working processing. Array formula, table formula
98113// and some other formulas are not supported currently.
99114//
100115// Supported formulas:
101116//
102- // ABS, ACOS, ACOSH, ACOT, ACOTH, ARABIC, ASIN, ASINH, ATAN2, ATANH, BASE ,
103- // CEILING, CEILING.MATH, CEILING.PRECISE, COMBIN, COMBINA, COS, COSH, COT ,
104- // COTH, COUNTA, CSC, CSCH, DECIMAL, DEGREES, EVEN, EXP, FACT, FACTDOUBLE ,
105- // FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT, ISBLANK, ISERR, ISERROR ,
106- // ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING, ISODD, LCM, LN, LOG ,
107- // LOG10, MDETERM, MEDIAN, MOD, MROUND, MULTINOMIAL, MUNIT, NA, ODD, PI ,
108- // POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN, ROUND, ROUNDDOWN ,
109- // ROUNDUP, SEC, SECH, SIGN, SIN, SINH, SQRT, SQRTPI, SUM, SUMIF, SUMSQ ,
110- // TAN, TANH, TRUNC
117+ // ABS, ACOS, ACOSH, ACOT, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN2, ATANH,
118+ // BASE, CEILING, CEILING.MATH, CEILING.PRECISE, COMBIN, COMBINA, COS,
119+ // COSH, COT, COTH, COUNTA, CSC, CSCH, DECIMAL, DEGREES, EVEN, EXP, FACT,
120+ // FACTDOUBLE, FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT, ISBLANK, ISERR,
121+ // ISERROR, ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING, ISODD, LCM,
122+ // LN, LOG, LOG10, MDETERM, MEDIAN, MOD, MROUND, MULTINOMIAL, MUNIT, NA,
123+ // ODD, OR, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN,
124+ // ROUND, ROUNDDOWN, ROUNDUP, SEC, SECH, SIGN, SIN, SINH, SQRT, SQRTPI,
125+ // SUM, SUMIF, SUMSQ, TAN, TANH, TRUNC
111126//
112127func (f * File ) CalcCellValue (sheet , cell string ) (result string , err error ) {
113128 var (
@@ -131,15 +146,9 @@ func (f *File) CalcCellValue(sheet, cell string) (result string, err error) {
131146
132147// getPriority calculate arithmetic operator priority.
133148func getPriority (token efp.Token ) (pri int ) {
134- var priority = map [string ]int {
135- "*" : 2 ,
136- "/" : 2 ,
137- "+" : 1 ,
138- "-" : 1 ,
139- }
140- pri , _ = priority [token .TValue ]
149+ pri , _ = tokenPriority [token .TValue ]
141150 if token .TValue == "-" && token .TType == efp .TokenTypeOperatorPrefix {
142- pri = 3
151+ pri = 6
143152 }
144153 if token .TSubType == efp .TokenSubTypeStart && token .TType == efp .TokenTypeSubexpression { // (
145154 pri = 0
@@ -306,18 +315,96 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error)
306315 return opdStack .Peek ().(efp.Token ), err
307316}
308317
309- // calcAdd evaluate addition arithmetic operations.
310- func calcAdd (opdStack * Stack ) error {
311- if opdStack .Len () < 2 {
312- return errors .New ("formula not valid" )
318+ // calcPow evaluate exponentiation arithmetic operations.
319+ func calcPow (rOpd , lOpd string , opdStack * Stack ) error {
320+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
321+ if err != nil {
322+ return err
323+ }
324+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
325+ if err != nil {
326+ return err
327+ }
328+ result := math .Pow (lOpdVal , rOpdVal )
329+ opdStack .Push (efp.Token {TValue : fmt .Sprintf ("%g" , result ), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
330+ return nil
331+ }
332+
333+ // calcEq evaluate equal arithmetic operations.
334+ func calcEq (rOpd , lOpd string , opdStack * Stack ) error {
335+ opdStack .Push (efp.Token {TValue : strings .ToUpper (strconv .FormatBool (rOpd == lOpd )), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
336+ return nil
337+ }
338+
339+ // calcL evaluate less than arithmetic operations.
340+ func calcL (rOpd , lOpd string , opdStack * Stack ) error {
341+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
342+ if err != nil {
343+ return err
344+ }
345+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
346+ if err != nil {
347+ return err
348+ }
349+ opdStack .Push (efp.Token {TValue : strings .ToUpper (strconv .FormatBool (rOpdVal > lOpdVal )), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
350+ return nil
351+ }
352+
353+ // calcLe evaluate less than or equal arithmetic operations.
354+ func calcLe (rOpd , lOpd string , opdStack * Stack ) error {
355+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
356+ if err != nil {
357+ return err
358+ }
359+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
360+ if err != nil {
361+ return err
313362 }
314- rOpd := opdStack .Pop ().(efp.Token )
315- lOpd := opdStack .Pop ().(efp.Token )
316- lOpdVal , err := strconv .ParseFloat (lOpd .TValue , 64 )
363+ opdStack .Push (efp.Token {TValue : strings .ToUpper (strconv .FormatBool (rOpdVal >= lOpdVal )), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
364+ return nil
365+ }
366+
367+ // calcG evaluate greater than or equal arithmetic operations.
368+ func calcG (rOpd , lOpd string , opdStack * Stack ) error {
369+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
370+ if err != nil {
371+ return err
372+ }
373+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
374+ if err != nil {
375+ return err
376+ }
377+ opdStack .Push (efp.Token {TValue : strings .ToUpper (strconv .FormatBool (rOpdVal < lOpdVal )), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
378+ return nil
379+ }
380+
381+ // calcGe evaluate greater than or equal arithmetic operations.
382+ func calcGe (rOpd , lOpd string , opdStack * Stack ) error {
383+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
317384 if err != nil {
318385 return err
319386 }
320- rOpdVal , err := strconv .ParseFloat (rOpd .TValue , 64 )
387+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
388+ if err != nil {
389+ return err
390+ }
391+ opdStack .Push (efp.Token {TValue : strings .ToUpper (strconv .FormatBool (rOpdVal <= lOpdVal )), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
392+ return nil
393+ }
394+
395+ // calcSplice evaluate splice '&' operations.
396+ func calcSplice (rOpd , lOpd string , opdStack * Stack ) error {
397+ opdStack .Push (efp.Token {TValue : lOpd + rOpd , TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
398+ return nil
399+ }
400+
401+ // calcAdd evaluate addition arithmetic operations.
402+ func calcAdd (rOpd , lOpd string , opdStack * Stack ) error {
403+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
404+ if err != nil {
405+ return err
406+ }
407+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
321408 if err != nil {
322409 return err
323410 }
@@ -327,17 +414,12 @@ func calcAdd(opdStack *Stack) error {
327414}
328415
329416// calcSubtract evaluate subtraction arithmetic operations.
330- func calcSubtract (opdStack * Stack ) error {
331- if opdStack .Len () < 2 {
332- return errors .New ("formula not valid" )
333- }
334- rOpd := opdStack .Pop ().(efp.Token )
335- lOpd := opdStack .Pop ().(efp.Token )
336- lOpdVal , err := strconv .ParseFloat (lOpd .TValue , 64 )
417+ func calcSubtract (rOpd , lOpd string , opdStack * Stack ) error {
418+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
337419 if err != nil {
338420 return err
339421 }
340- rOpdVal , err := strconv .ParseFloat (rOpd . TValue , 64 )
422+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
341423 if err != nil {
342424 return err
343425 }
@@ -347,17 +429,12 @@ func calcSubtract(opdStack *Stack) error {
347429}
348430
349431// calcMultiply evaluate multiplication arithmetic operations.
350- func calcMultiply (opdStack * Stack ) error {
351- if opdStack .Len () < 2 {
352- return errors .New ("formula not valid" )
353- }
354- rOpd := opdStack .Pop ().(efp.Token )
355- lOpd := opdStack .Pop ().(efp.Token )
356- lOpdVal , err := strconv .ParseFloat (lOpd .TValue , 64 )
432+ func calcMultiply (rOpd , lOpd string , opdStack * Stack ) error {
433+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
357434 if err != nil {
358435 return err
359436 }
360- rOpdVal , err := strconv .ParseFloat (rOpd . TValue , 64 )
437+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
361438 if err != nil {
362439 return err
363440 }
@@ -366,18 +443,13 @@ func calcMultiply(opdStack *Stack) error {
366443 return nil
367444}
368445
369- // calcDivide evaluate division arithmetic operations.
370- func calcDivide (opdStack * Stack ) error {
371- if opdStack .Len () < 2 {
372- return errors .New ("formula not valid" )
373- }
374- rOpd := opdStack .Pop ().(efp.Token )
375- lOpd := opdStack .Pop ().(efp.Token )
376- lOpdVal , err := strconv .ParseFloat (lOpd .TValue , 64 )
446+ // calcDiv evaluate division arithmetic operations.
447+ func calcDiv (rOpd , lOpd string , opdStack * Stack ) error {
448+ lOpdVal , err := strconv .ParseFloat (lOpd , 64 )
377449 if err != nil {
378450 return err
379451 }
380- rOpdVal , err := strconv .ParseFloat (rOpd . TValue , 64 )
452+ rOpdVal , err := strconv .ParseFloat (rOpd , 64 )
381453 if err != nil {
382454 return err
383455 }
@@ -403,24 +475,36 @@ func calculate(opdStack *Stack, opt efp.Token) error {
403475 result := 0 - opdVal
404476 opdStack .Push (efp.Token {TValue : fmt .Sprintf ("%g" , result ), TType : efp .TokenTypeOperand , TSubType : efp .TokenSubTypeNumber })
405477 }
406-
407- if opt .TValue == "+" {
408- if err := calcAdd (opdStack ); err != nil {
409- return err
410- }
478+ tokenCalcFunc := map [string ]func (rOpd , lOpd string , opdStack * Stack ) error {
479+ "^" : calcPow ,
480+ "*" : calcMultiply ,
481+ "/" : calcDiv ,
482+ "+" : calcAdd ,
483+ "=" : calcEq ,
484+ "<" : calcL ,
485+ "<=" : calcLe ,
486+ ">" : calcG ,
487+ ">=" : calcGe ,
488+ "&" : calcSplice ,
411489 }
412490 if opt .TValue == "-" && opt .TType == efp .TokenTypeOperatorInfix {
413- if err := calcSubtract ( opdStack ); err != nil {
414- return err
491+ if opdStack . Len () < 2 {
492+ return errors . New ( "formula not valid" )
415493 }
416- }
417- if opt . TValue == "*" {
418- if err := calcMultiply ( opdStack ); err != nil {
494+ rOpd := opdStack . Pop ().(efp. Token )
495+ lOpd := opdStack . Pop ().(efp. Token )
496+ if err := calcSubtract ( rOpd . TValue , lOpd . TValue , opdStack ); err != nil {
419497 return err
420498 }
421499 }
422- if opt .TValue == "/" {
423- if err := calcDivide (opdStack ); err != nil {
500+ fn , ok := tokenCalcFunc [opt .TValue ]
501+ if ok {
502+ if opdStack .Len () < 2 {
503+ return errors .New ("formula not valid" )
504+ }
505+ rOpd := opdStack .Pop ().(efp.Token )
506+ lOpd := opdStack .Pop ().(efp.Token )
507+ if err := fn (rOpd .TValue , lOpd .TValue , opdStack ); err != nil {
424508 return err
425509 }
426510 }
@@ -459,8 +543,8 @@ func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token efp.Tok
459543// isOperatorPrefixToken determine if the token is parse operator prefix
460544// token.
461545func isOperatorPrefixToken (token efp.Token ) bool {
462- if ( token . TValue == "-" && token .TType == efp . TokenTypeOperatorPrefix ) ||
463- token . TValue == "+" || token .TValue == "-" || token .TValue == "*" || token . TValue == "/" {
546+ _ , ok := tokenPriority [ token .TValue ]
547+ if ( token .TValue == "-" && token .TType == efp . TokenTypeOperatorPrefix ) || ok {
464548 return true
465549 }
466550 return false
@@ -3140,3 +3224,87 @@ func (fn *formulaFuncs) NA(argsList *list.List) (result string, err error) {
31403224 result = formulaErrorNA
31413225 return
31423226}
3227+
3228+ // Logical Functions
3229+
3230+ // AND function tests a number of supplied conditions and returns TRUE or
3231+ // FALSE.
3232+ func (fn * formulaFuncs ) AND (argsList * list.List ) (result string , err error ) {
3233+ if argsList .Len () == 0 {
3234+ err = errors .New ("AND requires at least 1 argument" )
3235+ return
3236+ }
3237+ if argsList .Len () > 30 {
3238+ err = errors .New ("AND accepts at most 30 arguments" )
3239+ return
3240+ }
3241+ var and = true
3242+ var val float64
3243+ for arg := argsList .Front (); arg != nil ; arg = arg .Next () {
3244+ token := arg .Value .(formulaArg )
3245+ switch token .Type {
3246+ case ArgUnknown :
3247+ continue
3248+ case ArgString :
3249+ if token .String == "TRUE" {
3250+ continue
3251+ }
3252+ if token .String == "FALSE" {
3253+ result = token .String
3254+ return
3255+ }
3256+ if val , err = strconv .ParseFloat (token .String , 64 ); err != nil {
3257+ err = errors .New (formulaErrorVALUE )
3258+ return
3259+ }
3260+ and = and && (val != 0 )
3261+ case ArgMatrix :
3262+ // TODO
3263+ err = errors .New (formulaErrorVALUE )
3264+ return
3265+ }
3266+ }
3267+ result = strings .ToUpper (strconv .FormatBool (and ))
3268+ return
3269+ }
3270+
3271+ // OR function tests a number of supplied conditions and returns either TRUE
3272+ // or FALSE.
3273+ func (fn * formulaFuncs ) OR (argsList * list.List ) (result string , err error ) {
3274+ if argsList .Len () == 0 {
3275+ err = errors .New ("OR requires at least 1 argument" )
3276+ return
3277+ }
3278+ if argsList .Len () > 30 {
3279+ err = errors .New ("OR accepts at most 30 arguments" )
3280+ return
3281+ }
3282+ var or bool
3283+ var val float64
3284+ for arg := argsList .Front (); arg != nil ; arg = arg .Next () {
3285+ token := arg .Value .(formulaArg )
3286+ switch token .Type {
3287+ case ArgUnknown :
3288+ continue
3289+ case ArgString :
3290+ if token .String == "FALSE" {
3291+ continue
3292+ }
3293+ if token .String == "TRUE" {
3294+ or = true
3295+ continue
3296+ }
3297+ if val , err = strconv .ParseFloat (token .String , 64 ); err != nil {
3298+ err = errors .New (formulaErrorVALUE )
3299+ return
3300+ }
3301+ or = val != 0
3302+ case ArgMatrix :
3303+ // TODO
3304+ err = errors .New (formulaErrorVALUE )
3305+ return
3306+ }
3307+ }
3308+ result = strings .ToUpper (strconv .FormatBool (or ))
3309+ return
3310+ }
0 commit comments