This closes #1819, closes #1827, formula function ISNUMBER, OR and FIND support matrix arguments (#1829)
- Keep minimum column and row number in formula operand when deleting columns and rows - Update unit tests
This commit is contained in:
parent
bb603b37d0
commit
7b4da3906d
10
adjust.go
10
adjust.go
|
@ -320,7 +320,9 @@ func adjustFormulaColumnName(name, operand string, abs, keepRelative bool, dir a
|
|||
return "", operand, false, err
|
||||
}
|
||||
if dir == columns && col >= num {
|
||||
col += offset
|
||||
if col += offset; col < 1 {
|
||||
col = 1
|
||||
}
|
||||
colName, err := ColumnNumberToName(col)
|
||||
return "", operand + colName, false, err
|
||||
}
|
||||
|
@ -334,8 +336,10 @@ func adjustFormulaRowNumber(name, operand string, abs, keepRelative bool, dir ad
|
|||
}
|
||||
row, _ := strconv.Atoi(name)
|
||||
if dir == rows && row >= num {
|
||||
row += offset
|
||||
if row <= 0 || row > TotalRows {
|
||||
if row += offset; row < 1 {
|
||||
row = 1
|
||||
}
|
||||
if row > TotalRows {
|
||||
return "", operand + name, false, ErrMaxRows
|
||||
}
|
||||
return "", operand + strconv.Itoa(row), false, nil
|
||||
|
|
86
calc.go
86
calc.go
|
@ -11602,7 +11602,22 @@ func (fn *formulaFuncs) ISNUMBER(argsList *list.List) formulaArg {
|
|||
if argsList.Len() != 1 {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, "ISNUMBER requires 1 argument")
|
||||
}
|
||||
if argsList.Front().Value.(formulaArg).Type == ArgNumber {
|
||||
arg := argsList.Front().Value.(formulaArg)
|
||||
if arg.Type == ArgMatrix {
|
||||
var mtx [][]formulaArg
|
||||
for _, row := range arg.Matrix {
|
||||
var array []formulaArg
|
||||
for _, val := range row {
|
||||
if val.Type == ArgNumber {
|
||||
array = append(array, newBoolFormulaArg(true))
|
||||
}
|
||||
array = append(array, newBoolFormulaArg(false))
|
||||
}
|
||||
mtx = append(mtx, array)
|
||||
}
|
||||
return newMatrixFormulaArg(mtx)
|
||||
}
|
||||
if arg.Type == ArgNumber {
|
||||
return newBoolFormulaArg(true)
|
||||
}
|
||||
return newBoolFormulaArg(false)
|
||||
|
@ -11951,11 +11966,14 @@ func (fn *formulaFuncs) OR(argsList *list.List) formulaArg {
|
|||
return newStringFormulaArg(strings.ToUpper(strconv.FormatBool(or)))
|
||||
}
|
||||
case ArgMatrix:
|
||||
// TODO
|
||||
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||
args := list.New()
|
||||
for _, arg := range token.ToList() {
|
||||
args.PushBack(arg)
|
||||
}
|
||||
return fn.OR(args)
|
||||
}
|
||||
}
|
||||
return newStringFormulaArg(strings.ToUpper(strconv.FormatBool(or)))
|
||||
return newBoolFormulaArg(or)
|
||||
}
|
||||
|
||||
// SWITCH function compares a number of supplied values to a supplied test
|
||||
|
@ -13741,34 +13759,48 @@ func (fn *formulaFuncs) find(name string, argsList *list.List) formulaArg {
|
|||
if args.Type != ArgList {
|
||||
return args
|
||||
}
|
||||
findText := argsList.Front().Value.(formulaArg).Value()
|
||||
findTextArg := argsList.Front().Value.(formulaArg)
|
||||
withinText := argsList.Front().Next().Value.(formulaArg).Value()
|
||||
startNum := int(args.List[0].Number)
|
||||
if findText == "" {
|
||||
return newNumberFormulaArg(float64(startNum))
|
||||
}
|
||||
dbcs, search := name == "FINDB" || name == "SEARCHB", name == "SEARCH" || name == "SEARCHB"
|
||||
if search {
|
||||
findText, withinText = strings.ToUpper(findText), strings.ToUpper(withinText)
|
||||
}
|
||||
offset, ok := matchPattern(findText, withinText, dbcs, startNum)
|
||||
if !ok {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||
}
|
||||
result := offset
|
||||
if dbcs {
|
||||
var pre int
|
||||
for idx := range withinText {
|
||||
if pre > offset {
|
||||
break
|
||||
}
|
||||
if idx-pre > 1 {
|
||||
result++
|
||||
}
|
||||
pre = idx
|
||||
find := func(findText string) formulaArg {
|
||||
if findText == "" {
|
||||
return newNumberFormulaArg(float64(startNum))
|
||||
}
|
||||
if search {
|
||||
findText, withinText = strings.ToUpper(findText), strings.ToUpper(withinText)
|
||||
}
|
||||
offset, ok := matchPattern(findText, withinText, dbcs, startNum)
|
||||
if !ok {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||
}
|
||||
result := offset
|
||||
if dbcs {
|
||||
var pre int
|
||||
for idx := range withinText {
|
||||
if pre > offset {
|
||||
break
|
||||
}
|
||||
if idx-pre > 1 {
|
||||
result++
|
||||
}
|
||||
pre = idx
|
||||
}
|
||||
}
|
||||
return newNumberFormulaArg(float64(result))
|
||||
}
|
||||
return newNumberFormulaArg(float64(result))
|
||||
if findTextArg.Type == ArgMatrix {
|
||||
var mtx [][]formulaArg
|
||||
for _, row := range findTextArg.Matrix {
|
||||
var array []formulaArg
|
||||
for _, findText := range row {
|
||||
array = append(array, find(findText.Value()))
|
||||
}
|
||||
mtx = append(mtx, array)
|
||||
}
|
||||
return newMatrixFormulaArg(mtx)
|
||||
}
|
||||
return find(findTextArg.Value())
|
||||
}
|
||||
|
||||
// LEFT function returns a specified number of characters from the start of a
|
||||
|
|
10
calc_test.go
10
calc_test.go
|
@ -1451,8 +1451,9 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=ISNONTEXT(\"Excelize\")": "FALSE",
|
||||
"=ISNONTEXT(NA())": "TRUE",
|
||||
// ISNUMBER
|
||||
"=ISNUMBER(A1)": "TRUE",
|
||||
"=ISNUMBER(D1)": "FALSE",
|
||||
"=ISNUMBER(A1)": "TRUE",
|
||||
"=ISNUMBER(D1)": "FALSE",
|
||||
"=ISNUMBER(A1:B1)": "TRUE",
|
||||
// ISODD
|
||||
"=ISODD(A1)": "TRUE",
|
||||
"=ISODD(A2)": "FALSE",
|
||||
|
@ -1526,6 +1527,7 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=OR(1=2,2=3)": "FALSE",
|
||||
"=OR(1=1,2=3)": "TRUE",
|
||||
"=OR(\"TRUE\",\"FALSE\")": "TRUE",
|
||||
"=OR(A1:B1)": "TRUE",
|
||||
// SWITCH
|
||||
"=SWITCH(1,1,\"A\",2,\"B\",3,\"C\",\"N\")": "A",
|
||||
"=SWITCH(3,1,\"A\",2,\"B\",3,\"C\",\"N\")": "C",
|
||||
|
@ -1748,6 +1750,7 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=FIND(\"\",\"Original Text\")": "1",
|
||||
"=FIND(\"\",\"Original Text\",2)": "2",
|
||||
"=FIND(\"s\",\"Sales\",2)": "5",
|
||||
"=FIND(D1:E2,\"Month\")": "1",
|
||||
// FINDB
|
||||
"=FINDB(\"T\",\"Original Text\")": "10",
|
||||
"=FINDB(\"t\",\"Original Text\")": "13",
|
||||
|
@ -3663,7 +3666,6 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=NOT(\"\")": {"#VALUE!", "NOT expects 1 boolean or numeric argument"},
|
||||
// OR
|
||||
"=OR(\"text\")": {"#VALUE!", "#VALUE!"},
|
||||
"=OR(A1:B1)": {"#VALUE!", "#VALUE!"},
|
||||
"=OR(\"1\",\"TRUE\",\"FALSE\")": {"#VALUE!", "#VALUE!"},
|
||||
"=OR()": {"#VALUE!", "OR requires at least 1 argument"},
|
||||
"=OR(1" + strings.Repeat(",1", 30) + ")": {"#VALUE!", "OR accepts at most 30 arguments"},
|
||||
|
@ -4773,7 +4775,7 @@ func TestCalcOR(t *testing.T) {
|
|||
})
|
||||
fn := formulaFuncs{}
|
||||
result := fn.OR(argsList)
|
||||
assert.Equal(t, result.String, "FALSE")
|
||||
assert.Equal(t, result.Value(), "FALSE")
|
||||
assert.Empty(t, result.Error)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue