diff options
Diffstat (limited to 'calc.go')
-rw-r--r-- | calc.go | 92 |
1 files changed, 40 insertions, 52 deletions
@@ -777,57 +777,25 @@ func calcNEq(rOpd, lOpd string, opdStack *Stack) error { // calcL evaluate less than arithmetic operations. func calcL(rOpd, lOpd string, opdStack *Stack) error { - lOpdVal, err := strconv.ParseFloat(lOpd, 64) - if err != nil { - return err - } - rOpdVal, err := strconv.ParseFloat(rOpd, 64) - if err != nil { - return err - } - opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(rOpdVal > lOpdVal)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) + opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(strings.Compare(lOpd, rOpd) == -1)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) return nil } // calcLe evaluate less than or equal arithmetic operations. func calcLe(rOpd, lOpd string, opdStack *Stack) error { - lOpdVal, err := strconv.ParseFloat(lOpd, 64) - if err != nil { - return err - } - rOpdVal, err := strconv.ParseFloat(rOpd, 64) - if err != nil { - return err - } - opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(rOpdVal >= lOpdVal)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) + opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(strings.Compare(lOpd, rOpd) != 1)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) return nil } // calcG evaluate greater than or equal arithmetic operations. func calcG(rOpd, lOpd string, opdStack *Stack) error { - lOpdVal, err := strconv.ParseFloat(lOpd, 64) - if err != nil { - return err - } - rOpdVal, err := strconv.ParseFloat(rOpd, 64) - if err != nil { - return err - } - opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(rOpdVal < lOpdVal)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) + opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(strings.Compare(lOpd, rOpd) == 1)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) return nil } // calcGe evaluate greater than or equal arithmetic operations. func calcGe(rOpd, lOpd string, opdStack *Stack) error { - lOpdVal, err := strconv.ParseFloat(lOpd, 64) - if err != nil { - return err - } - rOpdVal, err := strconv.ParseFloat(rOpd, 64) - if err != nil { - return err - } - opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(rOpdVal <= lOpdVal)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) + opdStack.Push(efp.Token{TValue: strings.ToUpper(strconv.FormatBool(strings.Compare(lOpd, rOpd) != -1)), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) return nil } @@ -1214,7 +1182,7 @@ func (f *File) rangeResolver(cellRefs, cellRanges *list.List) (arg formulaArg, e if cell, err = CoordinatesToCellName(col, row); err != nil { return } - if value, err = f.GetCellValue(sheet, cell); err != nil { + if value, err = f.GetCellValue(sheet, cell, Options{RawCellValue: true}); err != nil { return } matrixRow = append(matrixRow, formulaArg{ @@ -1233,7 +1201,7 @@ func (f *File) rangeResolver(cellRefs, cellRanges *list.List) (arg formulaArg, e if cell, err = CoordinatesToCellName(cr.Col, cr.Row); err != nil { return } - if arg.String, err = f.GetCellValue(cr.Sheet, cell); err != nil { + if arg.String, err = f.GetCellValue(cr.Sheet, cell, Options{RawCellValue: true}); err != nil { return } arg.Type = ArgString @@ -7749,28 +7717,33 @@ func hlookupBinarySearch(row []formulaArg, lookupValue formulaArg) (matchIdx int return } -// LOOKUP function performs an approximate match lookup in a one-column or -// one-row range, and returns the corresponding value from another one-column -// or one-row range. The syntax of the function is: -// -// LOOKUP(lookup_value,lookup_vector,[result_vector]) -// -func (fn *formulaFuncs) LOOKUP(argsList *list.List) formulaArg { +// checkLookupArgs checking arguments, prepare lookup value, and data for the +// formula function LOOKUP. +func checkLookupArgs(argsList *list.List) (arrayForm bool, lookupValue, lookupVector, errArg formulaArg) { if argsList.Len() < 2 { - return newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at least 2 arguments") + errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at least 2 arguments") + return } if argsList.Len() > 3 { - return newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at most 3 arguments") + errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires at most 3 arguments") + return } - lookupValue := argsList.Front().Value.(formulaArg) - lookupVector := argsList.Front().Next().Value.(formulaArg) + lookupValue = argsList.Front().Value.(formulaArg) + lookupVector = argsList.Front().Next().Value.(formulaArg) if lookupVector.Type != ArgMatrix && lookupVector.Type != ArgList { - return newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires second argument of table array") + errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires second argument of table array") + return } - arrayForm := lookupVector.Type == ArgMatrix + arrayForm = lookupVector.Type == ArgMatrix if arrayForm && len(lookupVector.Matrix) == 0 { - return newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires not empty range as second argument") + errArg = newErrorFormulaArg(formulaErrorVALUE, "LOOKUP requires not empty range as second argument") } + return +} + +// iterateLookupArgs iterate arguments to extract columns and calculate match +// index for the formula function LOOKUP. +func iterateLookupArgs(lookupValue, lookupVector formulaArg) ([]formulaArg, int, bool) { cols, matchIdx, ok := lookupCol(lookupVector, 0), -1, false for idx, col := range cols { lhs := lookupValue @@ -7796,6 +7769,21 @@ func (fn *formulaFuncs) LOOKUP(argsList *list.List) formulaArg { matchIdx = idx - 1 } } + return cols, matchIdx, ok +} + +// LOOKUP function performs an approximate match lookup in a one-column or +// one-row range, and returns the corresponding value from another one-column +// or one-row range. The syntax of the function is: +// +// LOOKUP(lookup_value,lookup_vector,[result_vector]) +// +func (fn *formulaFuncs) LOOKUP(argsList *list.List) formulaArg { + arrayForm, lookupValue, lookupVector, errArg := checkLookupArgs(argsList) + if errArg.Type == ArgError { + return errArg + } + cols, matchIdx, ok := iterateLookupArgs(lookupValue, lookupVector) if ok && matchIdx == -1 { matchIdx = len(cols) - 1 } |