forked from p30928647/excelize
ref #65, new formula functions FORMULATEXT and TYPE
This commit is contained in:
parent
42a9665aa9
commit
1efa283887
67
calc.go
67
calc.go
|
@ -416,6 +416,7 @@ type formulaFuncs struct {
|
|||
// FLOOR
|
||||
// FLOOR.MATH
|
||||
// FLOOR.PRECISE
|
||||
// FORMULATEXT
|
||||
// FV
|
||||
// FVSCHEDULE
|
||||
// GAMMA
|
||||
|
@ -615,6 +616,7 @@ type formulaFuncs struct {
|
|||
// TRIMMEAN
|
||||
// TRUE
|
||||
// TRUNC
|
||||
// TYPE
|
||||
// UNICHAR
|
||||
// UNICODE
|
||||
// UPPER
|
||||
|
@ -6874,7 +6876,7 @@ func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
|
|||
return newErrorFormulaArg(formulaErrorVALUE, "ISERR requires 1 argument")
|
||||
}
|
||||
token := argsList.Front().Value.(formulaArg)
|
||||
result := "FALSE"
|
||||
result := false
|
||||
if token.Type == ArgError {
|
||||
for _, errType := range []string{
|
||||
formulaErrorDIV, formulaErrorNAME, formulaErrorNUM,
|
||||
|
@ -6882,11 +6884,11 @@ func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
|
|||
formulaErrorSPILL, formulaErrorCALC, formulaErrorGETTINGDATA,
|
||||
} {
|
||||
if errType == token.String {
|
||||
result = "TRUE"
|
||||
result = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return newStringFormulaArg(result)
|
||||
return newBoolFormulaArg(result)
|
||||
}
|
||||
|
||||
// ISERROR function tests if an initial supplied expression (or value) returns
|
||||
|
@ -6900,7 +6902,7 @@ func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
|
|||
return newErrorFormulaArg(formulaErrorVALUE, "ISERROR requires 1 argument")
|
||||
}
|
||||
token := argsList.Front().Value.(formulaArg)
|
||||
result := "FALSE"
|
||||
result := false
|
||||
if token.Type == ArgError {
|
||||
for _, errType := range []string{
|
||||
formulaErrorDIV, formulaErrorNAME, formulaErrorNA, formulaErrorNUM,
|
||||
|
@ -6908,11 +6910,11 @@ func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
|
|||
formulaErrorCALC, formulaErrorGETTINGDATA,
|
||||
} {
|
||||
if errType == token.String {
|
||||
result = "TRUE"
|
||||
result = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return newStringFormulaArg(result)
|
||||
return newBoolFormulaArg(result)
|
||||
}
|
||||
|
||||
// ISEVEN function tests if a supplied number (or numeric expression)
|
||||
|
@ -7190,6 +7192,32 @@ func (fn *formulaFuncs) SHEETS(argsList *list.List) formulaArg {
|
|||
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
|
||||
}
|
||||
|
||||
// TYPE function returns an integer that represents the value's data type. The
|
||||
// syntax of the function is:
|
||||
//
|
||||
// TYPE(value)
|
||||
//
|
||||
func (fn *formulaFuncs) TYPE(argsList *list.List) formulaArg {
|
||||
if argsList.Len() != 1 {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, "TYPE requires 1 argument")
|
||||
}
|
||||
token := argsList.Front().Value.(formulaArg)
|
||||
switch token.Type {
|
||||
case ArgError:
|
||||
return newNumberFormulaArg(16)
|
||||
case ArgMatrix:
|
||||
return newNumberFormulaArg(64)
|
||||
default:
|
||||
if arg := token.ToNumber(); arg.Type != ArgError || len(token.Value()) == 0 {
|
||||
return newNumberFormulaArg(1)
|
||||
}
|
||||
if arg := token.ToBool(); arg.Type != ArgError {
|
||||
return newNumberFormulaArg(4)
|
||||
}
|
||||
return newNumberFormulaArg(2)
|
||||
}
|
||||
}
|
||||
|
||||
// T function tests if a supplied value is text and if so, returns the
|
||||
// supplied text; Otherwise, the function returns an empty text string. The
|
||||
// syntax of the function is:
|
||||
|
@ -7343,7 +7371,6 @@ func (fn *formulaFuncs) NOT(argsList *list.List) formulaArg {
|
|||
case ArgNumber:
|
||||
return newBoolFormulaArg(!(token.Number != 0))
|
||||
case ArgError:
|
||||
|
||||
return token
|
||||
}
|
||||
return newErrorFormulaArg(formulaErrorVALUE, "NOT expects 1 boolean or numeric argument")
|
||||
|
@ -9415,6 +9442,32 @@ func (fn *formulaFuncs) COLUMNS(argsList *list.List) formulaArg {
|
|||
return newNumberFormulaArg(float64(result))
|
||||
}
|
||||
|
||||
// FORMULATEXT function returns a formula as a text string. The syntax of the
|
||||
// function is:
|
||||
//
|
||||
// FORMULATEXT(reference)
|
||||
//
|
||||
func (fn *formulaFuncs) FORMULATEXT(argsList *list.List) formulaArg {
|
||||
if argsList.Len() != 1 {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, "FORMULATEXT requires 1 argument")
|
||||
}
|
||||
refs := argsList.Front().Value.(formulaArg).cellRefs
|
||||
col, row := 0, 0
|
||||
if refs != nil && refs.Len() > 0 {
|
||||
col, row = refs.Front().Value.(cellRef).Col, refs.Front().Value.(cellRef).Row
|
||||
}
|
||||
ranges := argsList.Front().Value.(formulaArg).cellRanges
|
||||
if ranges != nil && ranges.Len() > 0 {
|
||||
col, row = ranges.Front().Value.(cellRange).From.Col, ranges.Front().Value.(cellRange).From.Row
|
||||
}
|
||||
cell, err := CoordinatesToCellName(col, row)
|
||||
if err != nil {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||
}
|
||||
formula, _ := fn.f.GetCellFormula(fn.sheet, cell)
|
||||
return newStringFormulaArg(formula)
|
||||
}
|
||||
|
||||
// checkHVLookupArgs checking arguments, prepare extract mode, lookup value,
|
||||
// and data for the formula functions HLOOKUP and VLOOKUP.
|
||||
func checkHVLookupArgs(name string, argsList *list.List) (idx int, lookupValue, tableArray, matchMode, errArg formulaArg) {
|
||||
|
|
29
calc_test.go
29
calc_test.go
|
@ -1005,8 +1005,9 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=ISERR(NA())": "FALSE",
|
||||
"=ISERR(POWER(0,-1)))": "TRUE",
|
||||
// ISERROR
|
||||
"=ISERROR(A1)": "FALSE",
|
||||
"=ISERROR(NA())": "TRUE",
|
||||
"=ISERROR(A1)": "FALSE",
|
||||
"=ISERROR(NA())": "TRUE",
|
||||
"=ISERROR(\"#VALUE!\")": "FALSE",
|
||||
// ISEVEN
|
||||
"=ISEVEN(A1)": "FALSE",
|
||||
"=ISEVEN(A2)": "TRUE",
|
||||
|
@ -1055,6 +1056,14 @@ func TestCalcCellValue(t *testing.T) {
|
|||
// SHEETS
|
||||
"=SHEETS()": "1",
|
||||
"=SHEETS(A1)": "1",
|
||||
// TYPE
|
||||
"=TYPE(2)": "1",
|
||||
"=TYPE(10/2)": "1",
|
||||
"=TYPE(C1)": "1",
|
||||
"=TYPE(\"text\")": "2",
|
||||
"=TYPE(TRUE)": "4",
|
||||
"=TYPE(NA())": "16",
|
||||
"=TYPE(MUNIT(2))": "64",
|
||||
// T
|
||||
"=T(\"text\")": "text",
|
||||
"=T(N(10))": "",
|
||||
|
@ -2536,6 +2545,8 @@ func TestCalcCellValue(t *testing.T) {
|
|||
// SHEETS
|
||||
"=SHEETS(\"\",\"\")": "SHEETS accepts at most 1 argument",
|
||||
"=SHEETS(\"Sheet1\")": "#N/A",
|
||||
// TYPE
|
||||
"=TYPE()": "TYPE requires 1 argument",
|
||||
// T
|
||||
"=T()": "T requires 1 argument",
|
||||
"=T(NA())": "#N/A",
|
||||
|
@ -2839,6 +2850,9 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=COLUMNS(Sheet1)": newInvalidColumnNameError("Sheet1").Error(),
|
||||
"=COLUMNS(Sheet1!A1!B1)": newInvalidColumnNameError("Sheet1").Error(),
|
||||
"=COLUMNS(Sheet1!Sheet1)": newInvalidColumnNameError("Sheet1").Error(),
|
||||
// FORMULATEXT
|
||||
"=FORMULATEXT()": "FORMULATEXT requires 1 argument",
|
||||
"=FORMULATEXT(1)": "#VALUE!",
|
||||
// HLOOKUP
|
||||
"=HLOOKUP()": "HLOOKUP requires at least 3 arguments",
|
||||
"=HLOOKUP(D2,D1,1,FALSE)": "HLOOKUP requires second argument of table array",
|
||||
|
@ -3693,6 +3707,17 @@ func TestCalcAVERAGEIF(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCalcFORMULATEXT(t *testing.T) {
|
||||
f, formulaText := NewFile(), "=SUM(B1:C1)"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", formulaText))
|
||||
for _, formula := range []string{"=FORMULATEXT(A1)", "=FORMULATEXT(A:A)", "=FORMULATEXT(A1:B1)"} {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "D1", formula), formula)
|
||||
result, err := f.CalcCellValue("Sheet1", "D1")
|
||||
assert.NoError(t, err, formula)
|
||||
assert.Equal(t, formulaText, result, formula)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalcHLOOKUP(t *testing.T) {
|
||||
cellData := [][]interface{}{
|
||||
{"Example Result Table"},
|
||||
|
|
Loading…
Reference in New Issue