未验证 提交 7b4da390 编写于 作者: 岳晨旭 提交者: GitHub

This closes #1819, closes #1827, formula function ISNUMBER, OR and FIND...

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
上级 bb603b37
......@@ -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
......
......@@ -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
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
}
if idx-pre > 1 {
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()))
}
pre = idx
mtx = append(mtx, array)
}
return newMatrixFormulaArg(mtx)
}
return newNumberFormulaArg(float64(result))
return find(findTextArg.Value())
}
// LEFT function returns a specified number of characters from the start of a
......
......@@ -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)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册