Vyacheslav Zgordan a5ef37c0bc
Spreadsheet formulas: Flattening files (#366)
* evaluation errors fixed
* allow underscores in sheet names
* allow wildcard in *LOOKUP functions
* horizontal and vertical ranges
* horizontal and vertical ranges for sheet references
* remove redundant recalculate
* caching
* fixed named ranges, made Evaluator more generic
* Memory usage shown in flatten example
* temporary file deleted
* ParseCellReference duplicate removed
* ISREF is fixed
2020-01-29 10:43:43 +00:00

55 lines
1.7 KiB
Go

// Copyright 2017 FoxyUtils ehf. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased on https://unidoc.io.
package formula
import "fmt"
// defEval is the default formula evaluator which implements the Evaluator interface.
type defEval struct {
evCache
lastEvalIsRef bool
}
// Eval evaluates and returns the result of a formula.
func (d *defEval) Eval(ctx Context, formula string) Result {
expr := ParseString(formula)
if expr != nil {
d.checkLastEvalIsRef(ctx, expr)
result := expr.Eval(ctx, d)
if result.Type == ResultTypeError {
d.lastEvalIsRef = false
}
return result
}
return MakeErrorResult(fmt.Sprintf("unable to parse formula %s", formula))
}
// LastEvalIsRef returns if last evaluation with the evaluator was a reference.
func (d *defEval) LastEvalIsRef() bool {
return d.lastEvalIsRef
}
// checkLastEvalIsRef adds information which is needed for some functions but is lost after evaluation. E.g. which arguments are actually references.
func (d *defEval) checkLastEvalIsRef(ctx Context, expr Expression) {
switch expr.(type) {
case FunctionCall:
switch expr.(FunctionCall).name {
case "ISREF":
for _, arg := range expr.(FunctionCall).args {
switch arg.(type) {
case CellRef, Range, HorizontalRange, VerticalRange, NamedRangeRef, PrefixExpr, PrefixRangeExpr, PrefixHorizontalRange, PrefixVerticalRange:
evResult := arg.Eval(ctx, d)
d.lastEvalIsRef = !(evResult.Type == ResultTypeError && evResult.ValueString == "#NAME?")
default:
d.lastEvalIsRef = false
}
}
}
}
}