This commit is contained in:
parent
363fa940ac
commit
ad90cea78b
44
calc.go
44
calc.go
|
@ -197,8 +197,10 @@ var (
|
|||
// calcContext defines the formula execution context.
|
||||
type calcContext struct {
|
||||
sync.Mutex
|
||||
entry string
|
||||
iterations map[string]uint
|
||||
entry string
|
||||
maxCalcIterations uint
|
||||
iterations map[string]uint
|
||||
iterationsCache map[string]formulaArg
|
||||
}
|
||||
|
||||
// cellRef defines the structure of a cell reference.
|
||||
|
@ -774,8 +776,10 @@ func (f *File) CalcCellValue(sheet, cell string, opts ...Options) (result string
|
|||
token formulaArg
|
||||
)
|
||||
if token, err = f.calcCellValue(&calcContext{
|
||||
entry: fmt.Sprintf("%s!%s", sheet, cell),
|
||||
iterations: make(map[string]uint),
|
||||
entry: fmt.Sprintf("%s!%s", sheet, cell),
|
||||
maxCalcIterations: getOptions(opts...).MaxCalcIterations,
|
||||
iterations: make(map[string]uint),
|
||||
iterationsCache: make(map[string]formulaArg),
|
||||
}, sheet, cell); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -1527,17 +1531,6 @@ func (f *File) cellResolver(ctx *calcContext, sheet, cell string) (formulaArg, e
|
|||
value string
|
||||
err error
|
||||
)
|
||||
ref := fmt.Sprintf("%s!%s", sheet, cell)
|
||||
if formula, _ := f.GetCellFormula(sheet, cell); len(formula) != 0 {
|
||||
ctx.Lock()
|
||||
if ctx.entry != ref && ctx.iterations[ref] <= f.options.MaxCalcIterations {
|
||||
ctx.iterations[ref]++
|
||||
ctx.Unlock()
|
||||
arg, _ = f.calcCellValue(ctx, sheet, cell)
|
||||
return arg, nil
|
||||
}
|
||||
ctx.Unlock()
|
||||
}
|
||||
if value, err = f.GetCellValue(sheet, cell, Options{RawCellValue: true}); err != nil {
|
||||
return arg, err
|
||||
}
|
||||
|
@ -1551,8 +1544,25 @@ func (f *File) cellResolver(ctx *calcContext, sheet, cell string) (formulaArg, e
|
|||
return newEmptyFormulaArg(), err
|
||||
}
|
||||
return arg.ToNumber(), err
|
||||
default:
|
||||
case CellTypeInlineString, CellTypeSharedString:
|
||||
return arg, err
|
||||
case CellTypeFormula:
|
||||
ref := fmt.Sprintf("%s!%s", sheet, cell)
|
||||
if ctx.entry != ref {
|
||||
ctx.Lock()
|
||||
if ctx.iterations[ref] <= ctx.maxCalcIterations {
|
||||
ctx.iterations[ref]++
|
||||
ctx.Unlock()
|
||||
arg, _ = f.calcCellValue(ctx, sheet, cell)
|
||||
ctx.iterationsCache[ref] = arg
|
||||
return arg, nil
|
||||
}
|
||||
ctx.Unlock()
|
||||
return ctx.iterationsCache[ref], nil
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
return newEmptyFormulaArg(), err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7746,7 +7756,7 @@ func (fn *formulaFuncs) COUNTBLANK(argsList *list.List) formulaArg {
|
|||
}
|
||||
var count float64
|
||||
for _, cell := range argsList.Front().Value.(formulaArg).ToList() {
|
||||
if cell.Value() == "" {
|
||||
if cell.Type == ArgEmpty {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
|
19
calc_test.go
19
calc_test.go
|
@ -1023,7 +1023,7 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=COUNTBLANK(MUNIT(1))": "0",
|
||||
"=COUNTBLANK(1)": "0",
|
||||
"=COUNTBLANK(B1:C1)": "1",
|
||||
"=COUNTBLANK(C1)": "1",
|
||||
"=COUNTBLANK(C1)": "0",
|
||||
// COUNTIF
|
||||
"=COUNTIF(D1:D9,\"Jan\")": "4",
|
||||
"=COUNTIF(D1:D9,\"<>Jan\")": "5",
|
||||
|
@ -5871,3 +5871,20 @@ func TestCalcColRowQRDecomposition(t *testing.T) {
|
|||
assert.False(t, calcRowQRDecomposition([][]float64{{0, 0}, {0, 0}}, []float64{0, 0}, 1, 0))
|
||||
assert.False(t, calcColQRDecomposition([][]float64{{0, 0}, {0, 0}}, []float64{0, 0}, 1, 0))
|
||||
}
|
||||
|
||||
func TestCalcCellResolver(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test reference a cell multiple times in a formula
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "A1", "VALUE1"))
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A2", "=A1"))
|
||||
for formula, expected := range map[string]string{
|
||||
"=CONCATENATE(A1,\"_\",A1)": "VALUE1_VALUE1",
|
||||
"=CONCATENATE(A1,\"_\",A2)": "VALUE1_VALUE1",
|
||||
"=CONCATENATE(A2,\"_\",A2)": "VALUE1_VALUE1",
|
||||
} {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A3", formula))
|
||||
result, err := f.CalcCellValue("Sheet1", "A3")
|
||||
assert.NoError(t, err, formula)
|
||||
assert.Equal(t, expected, result, formula)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue