summaryrefslogtreecommitdiff
path: root/calc.go
diff options
context:
space:
mode:
Diffstat (limited to 'calc.go')
-rw-r--r--calc.go92
1 files changed, 40 insertions, 52 deletions
diff --git a/calc.go b/calc.go
index 1fdaf6e..5661d7d 100644
--- a/calc.go
+++ b/calc.go
@@ -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
}