@@ -951,9 +951,6 @@ func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.T
951
951
if err != nil {
952
952
return result, err
953
953
}
954
- if result.Type == ArgError {
955
- return result, errors.New(result.Error)
956
- }
957
954
opfdStack.Push(result)
958
955
continue
959
956
}
@@ -965,10 +962,7 @@ func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.T
965
962
}
966
963
result, err := f.parseReference(ctx, sheet, token.TValue)
967
964
if err != nil {
968
- return newEmptyFormulaArg(), err
969
- }
970
- if result.Type == ArgUnknown {
971
- return newEmptyFormulaArg(), errors.New(formulaErrorVALUE)
965
+ return result, err
972
966
}
973
967
// when current token is range, next token is argument and opfdStack not empty,
974
968
// should push value to opfdStack and continue
@@ -1442,74 +1436,99 @@ func (f *File) parseToken(ctx *calcContext, sheet string, token efp.Token, opdSt
1442
1436
return nil
1443
1437
}
1444
1438
1439
+ // parseRef parse reference for a cell, column name or row number.
1440
+ func (f *File) parseRef(ref string) (cellRef, bool, bool, error) {
1441
+ var (
1442
+ err, colErr, rowErr error
1443
+ cr cellRef
1444
+ cell = ref
1445
+ tokens = strings.Split(ref, "!")
1446
+ )
1447
+ if len(tokens) == 2 { // have a worksheet
1448
+ cr.Sheet, cell = tokens[0], tokens[1]
1449
+ }
1450
+ if cr.Col, cr.Row, err = CellNameToCoordinates(cell); err != nil {
1451
+ if cr.Col, colErr = ColumnNameToNumber(cell); colErr == nil { // cast to column
1452
+ return cr, true, false, nil
1453
+ }
1454
+ if cr.Row, rowErr = strconv.Atoi(cell); rowErr == nil { // cast to row
1455
+ return cr, false, true, nil
1456
+ }
1457
+ return cr, false, false, err
1458
+ }
1459
+ return cr, false, false, err
1460
+ }
1461
+
1462
+ // prepareCellRange checking and convert cell reference to a cell range.
1463
+ func (cr *cellRange) prepareCellRange(col, row bool, cellRef cellRef) error {
1464
+ if col {
1465
+ cellRef.Row = TotalRows
1466
+ }
1467
+ if row {
1468
+ cellRef.Col = MaxColumns
1469
+ }
1470
+ if cellRef.Sheet == "" {
1471
+ cellRef.Sheet = cr.From.Sheet
1472
+ }
1473
+ if cr.From.Sheet != cellRef.Sheet || cr.To.Sheet != cellRef.Sheet {
1474
+ return errors.New("invalid reference")
1475
+ }
1476
+ if cr.From.Col > cellRef.Col {
1477
+ cr.From.Col = cellRef.Col
1478
+ }
1479
+ if cr.From.Row > cellRef.Row {
1480
+ cr.From.Row = cellRef.Row
1481
+ }
1482
+ if cr.To.Col < cellRef.Col {
1483
+ cr.To.Col = cellRef.Col
1484
+ }
1485
+ if cr.To.Row < cellRef.Row {
1486
+ cr.To.Row = cellRef.Row
1487
+ }
1488
+ return nil
1489
+ }
1490
+
1445
1491
// parseReference parse reference and extract values by given reference
1446
1492
// characters and default sheet name.
1447
- func (f *File) parseReference(ctx *calcContext, sheet, reference string) (arg formulaArg, err error) {
1493
+ func (f *File) parseReference(ctx *calcContext, sheet, reference string) (formulaArg, error) {
1448
1494
reference = strings.ReplaceAll(reference, "$", "")
1449
- refs, cellRanges, cellRefs := list.New(), list.New(), list.New()
1450
- for _, ref := range strings.Split(reference, ":") {
1451
- tokens := strings.Split(ref, "!")
1452
- cr := cellRef{}
1453
- if len(tokens) == 2 { // have a worksheet name
1454
- cr.Sheet = tokens[0]
1455
- // cast to cell reference
1456
- if cr.Col, cr.Row, err = CellNameToCoordinates(tokens[1]); err != nil {
1457
- // cast to column
1458
- if cr.Col, err = ColumnNameToNumber(tokens[1]); err != nil {
1459
- // cast to row
1460
- if cr.Row, err = strconv.Atoi(tokens[1]); err != nil {
1461
- err = newInvalidColumnNameError(tokens[1])
1462
- return
1463
- }
1464
- cr.Col = MaxColumns
1465
- }
1466
- }
1467
- if refs.Len() > 0 {
1468
- e := refs.Back()
1469
- cellRefs.PushBack(e.Value.(cellRef))
1470
- refs.Remove(e)
1495
+ ranges, cellRanges, cellRefs := strings.Split(reference, ":"), list.New(), list.New()
1496
+ if len(ranges) > 1 {
1497
+ var cr cellRange
1498
+ for i, ref := range ranges {
1499
+ cellRef, col, row, err := f.parseRef(ref)
1500
+ if err != nil {
1501
+ return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
1471
1502
}
1472
- refs.PushBack(cr)
1473
- continue
1474
- }
1475
- // cast to cell reference
1476
- if cr.Col, cr.Row, err = CellNameToCoordinates(tokens[0]); err != nil {
1477
- // cast to column
1478
- if cr.Col, err = ColumnNameToNumber(tokens[0]); err != nil {
1479
- // cast to row
1480
- if cr.Row, err = strconv.Atoi(tokens[0]); err != nil {
1481
- err = newInvalidColumnNameError(tokens[0])
1482
- return
1503
+ if i == 0 {
1504
+ if col {
1505
+ cellRef.Row = 1
1506
+ }
1507
+ if row {
1508
+ cellRef.Col = 1
1483
1509
}
1484
- cr.Col = MaxColumns
1510
+ if cellRef.Sheet == "" {
1511
+ cellRef.Sheet = sheet
1512
+ }
1513
+ cr.From, cr.To = cellRef, cellRef
1514
+ continue
1515
+ }
1516
+ if err := cr.prepareCellRange(col, row, cellRef); err != nil {
1517
+ return newErrorFormulaArg(formulaErrorNAME, err.Error()), err
1485
1518
}
1486
- cellRanges.PushBack(cellRange{
1487
- From: cellRef{Sheet: sheet, Col: cr.Col, Row: 1},
1488
- To: cellRef{Sheet: sheet, Col: cr.Col, Row: TotalRows},
1489
- })
1490
- cellRefs.Init()
1491
- arg, err = f.rangeResolver(ctx, cellRefs, cellRanges)
1492
- return
1493
- }
1494
- e := refs.Back()
1495
- if e == nil {
1496
- cr.Sheet = sheet
1497
- refs.PushBack(cr)
1498
- continue
1499
1519
}
1500
- cellRanges.PushBack(cellRange{
1501
- From: e.Value.(cellRef),
1502
- To: cr,
1503
- })
1504
- refs.Remove(e)
1520
+ cellRanges.PushBack(cr)
1521
+ return f.rangeResolver(ctx, cellRefs, cellRanges)
1505
1522
}
1506
- if refs.Len() > 0 {
1507
- e := refs.Back()
1508
- cellRefs.PushBack(e.Value.(cellRef))
1509
- refs.Remove(e)
1523
+ cellRef, _, _, err := f.parseRef(reference)
1524
+ if err != nil {
1525
+ return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
1510
1526
}
1511
- arg, err = f.rangeResolver(ctx, cellRefs, cellRanges)
1512
- return
1527
+ if cellRef.Sheet == "" {
1528
+ cellRef.Sheet = sheet
1529
+ }
1530
+ cellRefs.PushBack(cellRef)
1531
+ return f.rangeResolver(ctx, cellRefs, cellRanges)
1513
1532
}
1514
1533
1515
1534
// prepareValueRange prepare value range.
@@ -1598,9 +1617,6 @@ func (f *File) rangeResolver(ctx *calcContext, cellRefs, cellRanges *list.List)
1598
1617
// prepare value range
1599
1618
for temp := cellRanges.Front(); temp != nil; temp = temp.Next() {
1600
1619
cr := temp.Value.(cellRange)
1601
- if cr.From.Sheet != cr.To.Sheet {
1602
- err = errors.New(formulaErrorVALUE)
1603
- }
1604
1620
rng := []int{cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row}
1605
1621
_ = sortCoordinates(rng)
1606
1622
cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row = rng[0], rng[1], rng[2], rng[3]
@@ -14155,18 +14171,9 @@ func calcColumnsMinMax(argsList *list.List) (min, max int) {
14155
14171
if min == 0 {
14156
14172
min = cr.Value.(cellRange).From.Col
14157
14173
}
14158
- if min > cr.Value.(cellRange).From.Col {
14159
- min = cr.Value.(cellRange).From.Col
14160
- }
14161
- if min > cr.Value.(cellRange).To.Col {
14162
- min = cr.Value.(cellRange).To.Col
14163
- }
14164
14174
if max < cr.Value.(cellRange).To.Col {
14165
14175
max = cr.Value.(cellRange).To.Col
14166
14176
}
14167
- if max < cr.Value.(cellRange).From.Col {
14168
- max = cr.Value.(cellRange).From.Col
14169
- }
14170
14177
}
14171
14178
}
14172
14179
if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
@@ -14175,9 +14182,6 @@ func calcColumnsMinMax(argsList *list.List) (min, max int) {
14175
14182
if min == 0 {
14176
14183
min = refs.Value.(cellRef).Col
14177
14184
}
14178
- if min > refs.Value.(cellRef).Col {
14179
- min = refs.Value.(cellRef).Col
14180
- }
14181
14185
if max < refs.Value.(cellRef).Col {
14182
14186
max = refs.Value.(cellRef).Col
14183
14187
}
@@ -14936,18 +14940,9 @@ func calcRowsMinMax(argsList *list.List) (min, max int) {
14936
14940
if min == 0 {
14937
14941
min = cr.Value.(cellRange).From.Row
14938
14942
}
14939
- if min > cr.Value.(cellRange).From.Row {
14940
- min = cr.Value.(cellRange).From.Row
14941
- }
14942
- if min > cr.Value.(cellRange).To.Row {
14943
- min = cr.Value.(cellRange).To.Row
14944
- }
14945
14943
if max < cr.Value.(cellRange).To.Row {
14946
14944
max = cr.Value.(cellRange).To.Row
14947
14945
}
14948
- if max < cr.Value.(cellRange).From.Row {
14949
- max = cr.Value.(cellRange).From.Row
14950
- }
14951
14946
}
14952
14947
}
14953
14948
if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
@@ -14956,9 +14951,6 @@ func calcRowsMinMax(argsList *list.List) (min, max int) {
14956
14951
if min == 0 {
14957
14952
min = refs.Value.(cellRef).Row
14958
14953
}
14959
- if min > refs.Value.(cellRef).Row {
14960
- min = refs.Value.(cellRef).Row
14961
- }
14962
14954
if max < refs.Value.(cellRef).Row {
14963
14955
max = refs.Value.(cellRef).Row
14964
14956
}
0 commit comments