Ver Fonte

Fix issue 665 (#666)

jaby há 5 anos atrás
pai
commit
5993a07422
3 ficheiros alterados com 44 adições e 1 exclusões
  1. 17 0
      calc.go
  2. 26 0
      calc_test.go
  3. 1 1
      sheet.go

+ 17 - 0
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)

+ 26 - 0
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")
 }

+ 1 - 1
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)