This closes #1989, fix incorrect result of formula functions XIRR and XNPV

- Require number data type instead of string
- Fix incorrect formula error type
This commit is contained in:
xuri 2024-09-08 12:19:58 +08:00
parent 8c0ef7f90d
commit ad8541790d
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
2 changed files with 32 additions and 34 deletions

26
calc.go
View File

@ -18197,28 +18197,26 @@ func (fn *formulaFuncs) prepareXArgs(values, dates formulaArg) (valuesArg, dates
valuesArg = append(valuesArg, numArg.Number)
continue
}
err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
err = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
return
}
if len(valuesArg) < 2 {
err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
return
}
args, date := list.New(), 0.0
date := 0.0
for _, arg := range dates.ToList() {
args.Init()
args.PushBack(arg)
dateValue := fn.DATEVALUE(args)
if dateValue.Type != ArgNumber {
err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
return
if arg.Type == ArgNumber {
datesArg = append(datesArg, arg.Number)
if arg.Number < date {
err = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
return
}
date = arg.Number
continue
}
if dateValue.Number < date {
err = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
return
}
datesArg = append(datesArg, dateValue.Number)
date = dateValue.Number
err = newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
return
}
if len(valuesArg) != len(datesArg) {
err = newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)

View File

@ -5562,13 +5562,13 @@ func TestCalcSUMIFSAndAVERAGEIFS(t *testing.T) {
func TestCalcXIRR(t *testing.T) {
cellData := [][]interface{}{
{-100.00, "01/01/2016"},
{20.00, "04/01/2016"},
{40.00, "10/01/2016"},
{25.00, "02/01/2017"},
{8.00, "03/01/2017"},
{15.00, "06/01/2017"},
{-1e-10, "09/01/2017"},
{-100.00, 42370},
{20.00, 42461},
{40.00, 42644},
{25.00, 42767},
{8.00, 42795},
{15.00, 42887},
{-1e-10, 42979},
}
f := prepareCalcData(cellData)
formulaList := map[string]string{
@ -5584,8 +5584,8 @@ func TestCalcXIRR(t *testing.T) {
calcError := map[string][]string{
"=XIRR()": {"#VALUE!", "XIRR requires 2 or 3 arguments"},
"=XIRR(A1:A4,B1:B4,-1)": {"#VALUE!", "XIRR requires guess > -1"},
"=XIRR(\"\",B1:B4)": {"#NUM!", "#NUM!"},
"=XIRR(A1:A4,\"\")": {"#NUM!", "#NUM!"},
"=XIRR(\"\",B1:B4)": {"#VALUE!", "#VALUE!"},
"=XIRR(A1:A4,\"\")": {"#VALUE!", "#VALUE!"},
"=XIRR(A1:A4,B1:B4,\"\")": {"#NUM!", "#NUM!"},
"=XIRR(A2:A6,B2:B6)": {"#NUM!", "#NUM!"},
"=XIRR(A2:A7,B2:B7)": {"#NUM!", "#NUM!"},
@ -5708,15 +5708,15 @@ func TestCalcXLOOKUP(t *testing.T) {
func TestCalcXNPV(t *testing.T) {
cellData := [][]interface{}{
{nil, 0.05},
{"01/01/2016", -10000, nil},
{"02/01/2016", 2000},
{"05/01/2016", 2400},
{"07/01/2016", 2900},
{"11/01/2016", 3500},
{"01/01/2017", 4100},
{42370, -10000, nil},
{42401, 2000},
{42491, 2400},
{42552, 2900},
{42675, 3500},
{42736, 4100},
{},
{"02/01/2016"},
{"01/01/2016"},
{42401},
{42370},
}
f := prepareCalcData(cellData)
formulaList := map[string]string{
@ -5732,9 +5732,9 @@ func TestCalcXNPV(t *testing.T) {
"=XNPV()": {"#VALUE!", "XNPV requires 3 arguments"},
"=XNPV(\"\",B2:B7,A2:A7)": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
"=XNPV(0,B2:B7,A2:A7)": {"#VALUE!", "XNPV requires rate > 0"},
"=XNPV(B1,\"\",A2:A7)": {"#NUM!", "#NUM!"},
"=XNPV(B1,B2:B7,\"\")": {"#NUM!", "#NUM!"},
"=XNPV(B1,B2:B7,C2:C7)": {"#NUM!", "#NUM!"},
"=XNPV(B1,\"\",A2:A7)": {"#VALUE!", "#VALUE!"},
"=XNPV(B1,B2:B7,\"\")": {"#VALUE!", "#VALUE!"},
"=XNPV(B1,B2:B7,C2:C7)": {"#VALUE!", "#VALUE!"},
"=XNPV(B1,B2,A2)": {"#NUM!", "#NUM!"},
"=XNPV(B1,B2:B3,A2:A5)": {"#NUM!", "#NUM!"},
"=XNPV(B1,B2:B3,A9:A10)": {"#VALUE!", "#VALUE!"},