summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaby <peter.de.velder@ilias-solutions.com>2020-07-14 17:05:43 +0200
committerGitHub <noreply@github.com>2020-07-14 23:05:43 +0800
commit5993a07422b6ace5230f562551f014180a83515a (patch)
tree2429c3a1d2b151fd40587807c75b7c110bb4fe75
parent0aa15106947965bdae9daae7571a4a3f569bf32d (diff)
Fix issue 665 (#666)
-rw-r--r--calc.go17
-rw-r--r--calc_test.go26
-rw-r--r--sheet.go2
3 files changed, 44 insertions, 1 deletions
diff --git a/calc.go b/calc.go
index 86f7cff..f86b12c 100644
--- a/calc.go
+++ b/calc.go
@@ -453,11 +453,28 @@ func isOperatorPrefixToken(token efp.Token) bool {
return false
}
+func (f *File) getDefinedNameRefTo(definedNameName string, currentSheet string) (refTo string) {
+ for _, definedName := range f.GetDefinedName() {
+ if definedName.Name == definedNameName {
+ refTo = definedName.RefersTo
+ // worksheet scope takes precedence over scope workbook when both definedNames exist
+ if definedName.Scope == currentSheet {
+ break
+ }
+ }
+ }
+ return refTo
+}
+
// parseToken parse basic arithmetic operator priority and evaluate based on
// operators and operands.
func (f *File) parseToken(sheet string, token efp.Token, opdStack, optStack *Stack) error {
// parse reference: must reference at here
if token.TSubType == efp.TokenSubTypeRange {
+ refTo := f.getDefinedNameRefTo(token.TValue, sheet)
+ if refTo != "" {
+ token.TValue = refTo
+ }
result, err := f.parseReference(sheet, token.TValue)
if err != nil {
return errors.New(formulaErrorNAME)
diff --git a/calc_test.go b/calc_test.go
index 283b9c2..4298aa7 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -790,4 +790,30 @@ func TestCalcCellValue(t *testing.T) {
_, err = f.CalcCellValue("Sheet1", "A1")
assert.EqualError(t, err, "not support UNSUPPORT function")
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCalcCellValue.xlsx")))
+
+}
+
+func TestCalcCellValueWithDefinedName(t *testing.T) {
+ cellData := [][]interface{}{
+ {"A1 value", "B1 value", nil},
+ }
+ prepareData := func() *File {
+ f := NewFile()
+ for r, row := range cellData {
+ for c, value := range row {
+ cell, _ := CoordinatesToCellName(c+1, r+1)
+ assert.NoError(t, f.SetCellValue("Sheet1", cell, value))
+ }
+ }
+ assert.NoError(t, f.SetDefinedName(&DefinedName{Name: "defined_name1", RefersTo: "Sheet1!A1", Scope: "Workbook"}))
+ assert.NoError(t, f.SetDefinedName(&DefinedName{Name: "defined_name1", RefersTo: "Sheet1!B1", Scope: "Sheet1"}))
+
+ return f
+ }
+ f := prepareData()
+ assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "=defined_name1"))
+ result, err := f.CalcCellValue("Sheet1", "C1")
+ assert.NoError(t, err)
+ // DefinedName with scope WorkSheet takes precedence over DefinedName with scope Workbook, so we should get B1 value
+ assert.Equal(t, "B1 value", result, "=defined_name1")
}
diff --git a/sheet.go b/sheet.go
index bbe84c2..20bf7c7 100644
--- a/sheet.go
+++ b/sheet.go
@@ -1421,7 +1421,7 @@ func (f *File) GetDefinedName() []DefinedName {
RefersTo: dn.Data,
Scope: "Workbook",
}
- if dn.LocalSheetID != nil {
+ if dn.LocalSheetID != nil && *dn.LocalSheetID >= 0 {
definedName.Scope = f.getSheetNameByID(*dn.LocalSheetID + 1)
}
definedNames = append(definedNames, definedName)