Skip to content

Commit 2499bf6

Browse files
committed
Support 5 new kinds of conditional formatting types
- New conditional formatting types: text, blanks, no blanks, errors, and no errors - Support calculate formula with multiple dash arithmetic symbol - Fix empty calculate result with numeric arguments in LEN, LOWER, PROPER, REPT, UPPER, and IF formula functions - Uniform double quote in calculation unit tests - Update unit tests
1 parent c7acf4f commit 2499bf6

File tree

5 files changed

+426
-238
lines changed

5 files changed

+426
-238
lines changed

calc.go

+30-15
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ func (f *File) calcCellValue(ctx *calcContext, sheet, cell string) (result formu
844844
ps := efp.ExcelParser()
845845
tokens := ps.Parse(formula)
846846
if tokens == nil {
847-
return
847+
return f.cellResolver(ctx, sheet, cell)
848848
}
849849
result, err = f.evalInfixExp(ctx, sheet, cell, tokens)
850850
return
@@ -1225,6 +1225,12 @@ func calcAdd(rOpd, lOpd formulaArg, opdStack *Stack) error {
12251225

12261226
// calcSubtract evaluate subtraction arithmetic operations.
12271227
func calcSubtract(rOpd, lOpd formulaArg, opdStack *Stack) error {
1228+
if rOpd.Value() == "" {
1229+
rOpd = newNumberFormulaArg(0)
1230+
}
1231+
if lOpd.Value() == "" {
1232+
lOpd = newNumberFormulaArg(0)
1233+
}
12281234
lOpdVal := lOpd.ToNumber()
12291235
if lOpdVal.Type != ArgNumber {
12301236
return errors.New(lOpdVal.Value())
@@ -1300,22 +1306,27 @@ func calculate(opdStack *Stack, opt efp.Token) error {
13001306
">=": calcGe,
13011307
"&": calcSplice,
13021308
}
1303-
fn, ok := tokenCalcFunc[opt.TValue]
1304-
if ok {
1309+
if fn, ok := tokenCalcFunc[opt.TValue]; ok {
13051310
if opdStack.Len() < 2 {
13061311
return ErrInvalidFormula
13071312
}
13081313
rOpd := opdStack.Pop().(formulaArg)
13091314
lOpd := opdStack.Pop().(formulaArg)
1315+
if opt.TValue != "&" {
1316+
if rOpd.Value() == "" {
1317+
rOpd = newNumberFormulaArg(0)
1318+
}
1319+
if lOpd.Value() == "" {
1320+
lOpd = newNumberFormulaArg(0)
1321+
}
1322+
}
13101323
if rOpd.Type == ArgError {
13111324
return errors.New(rOpd.Value())
13121325
}
13131326
if lOpd.Type == ArgError {
13141327
return errors.New(lOpd.Value())
13151328
}
1316-
if err := fn(rOpd, lOpd, opdStack); err != nil {
1317-
return err
1318-
}
1329+
return fn(rOpd, lOpd, opdStack)
13191330
}
13201331
return nil
13211332
}
@@ -1329,6 +1340,10 @@ func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token efp.Tok
13291340
tokenPriority := getPriority(token)
13301341
topOpt := optStack.Peek().(efp.Token)
13311342
topOptPriority := getPriority(topOpt)
1343+
if topOpt.TValue == "-" && topOpt.TType == efp.TokenTypeOperatorPrefix && token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix {
1344+
optStack.Pop()
1345+
return
1346+
}
13321347
if tokenPriority > topOptPriority {
13331348
optStack.Push(token)
13341349
return
@@ -13757,7 +13772,7 @@ func (fn *formulaFuncs) LEN(argsList *list.List) formulaArg {
1375713772
if argsList.Len() != 1 {
1375813773
return newErrorFormulaArg(formulaErrorVALUE, "LEN requires 1 string argument")
1375913774
}
13760-
return newNumberFormulaArg(float64(utf8.RuneCountInString(argsList.Front().Value.(formulaArg).String)))
13775+
return newNumberFormulaArg(float64(utf8.RuneCountInString(argsList.Front().Value.(formulaArg).Value())))
1376113776
}
1376213777

1376313778
// LENB returns the number of bytes used to represent the characters in a text
@@ -13790,7 +13805,7 @@ func (fn *formulaFuncs) LOWER(argsList *list.List) formulaArg {
1379013805
if argsList.Len() != 1 {
1379113806
return newErrorFormulaArg(formulaErrorVALUE, "LOWER requires 1 argument")
1379213807
}
13793-
return newStringFormulaArg(strings.ToLower(argsList.Front().Value.(formulaArg).String))
13808+
return newStringFormulaArg(strings.ToLower(argsList.Front().Value.(formulaArg).Value()))
1379413809
}
1379513810

1379613811
// MID function returns a specified number of characters from the middle of a
@@ -13881,7 +13896,7 @@ func (fn *formulaFuncs) PROPER(argsList *list.List) formulaArg {
1388113896
}
1388213897
buf := bytes.Buffer{}
1388313898
isLetter := false
13884-
for _, char := range argsList.Front().Value.(formulaArg).String {
13899+
for _, char := range argsList.Front().Value.(formulaArg).Value() {
1388513900
if !isLetter && unicode.IsLetter(char) {
1388613901
buf.WriteRune(unicode.ToUpper(char))
1388713902
} else {
@@ -13962,7 +13977,7 @@ func (fn *formulaFuncs) REPT(argsList *list.List) formulaArg {
1396213977
}
1396313978
buf := bytes.Buffer{}
1396413979
for i := 0; i < int(times.Number); i++ {
13965-
buf.WriteString(text.String)
13980+
buf.WriteString(text.Value())
1396613981
}
1396713982
return newStringFormulaArg(buf.String())
1396813983
}
@@ -14327,7 +14342,7 @@ func (fn *formulaFuncs) UPPER(argsList *list.List) formulaArg {
1432714342
if argsList.Len() != 1 {
1432814343
return newErrorFormulaArg(formulaErrorVALUE, "UPPER requires 1 argument")
1432914344
}
14330-
return newStringFormulaArg(strings.ToUpper(argsList.Front().Value.(formulaArg).String))
14345+
return newStringFormulaArg(strings.ToUpper(argsList.Front().Value.(formulaArg).Value()))
1433114346
}
1433214347

1433314348
// VALUE function converts a text string into a numeric value. The syntax of
@@ -14405,7 +14420,7 @@ func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
1440514420
)
1440614421
switch token.Type {
1440714422
case ArgString:
14408-
if cond, err = strconv.ParseBool(token.String); err != nil {
14423+
if cond, err = strconv.ParseBool(token.Value()); err != nil {
1440914424
return newErrorFormulaArg(formulaErrorVALUE, err.Error())
1441014425
}
1441114426
case ArgNumber:
@@ -14421,7 +14436,7 @@ func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
1442114436
case ArgNumber:
1442214437
result = value.ToNumber()
1442314438
default:
14424-
result = newStringFormulaArg(value.String)
14439+
result = newStringFormulaArg(value.Value())
1442514440
}
1442614441
return result
1442714442
}
@@ -14431,7 +14446,7 @@ func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
1443114446
case ArgNumber:
1443214447
result = value.ToNumber()
1443314448
default:
14434-
result = newStringFormulaArg(value.String)
14449+
result = newStringFormulaArg(value.Value())
1443514450
}
1443614451
}
1443714452
return result
@@ -14582,7 +14597,7 @@ func compareFormulaArg(lhs, rhs, matchMode formulaArg, caseSensitive bool) byte
1458214597
}
1458314598
return criteriaG
1458414599
case ArgString:
14585-
ls, rs := lhs.String, rhs.String
14600+
ls, rs := lhs.Value(), rhs.Value()
1458614601
if !caseSensitive {
1458714602
ls, rs = strings.ToLower(ls), strings.ToLower(rs)
1458814603
}

0 commit comments

Comments
 (0)