mirror of
https://github.com/unidoc/unioffice.git
synced 2025-04-25 13:48:53 +08:00
Financial functions: part 3 (#361)
* PMT, PPMT * PRICEDISC, fixed YEARFRAC * PV and handling empty arguments * RATE * RECEIVED * RRI * ODDLPRICE, ODDLYIELD * PRICE, PRICEMAT * SLN * SYD * TBILLEQ, TBILLPRICE, TBILLYIELD * VDB
This commit is contained in:
parent
dc34147325
commit
f4e59e2275
@ -31,7 +31,7 @@ func init() {
|
||||
RegisterFunction("TIMEVALUE", TimeValue)
|
||||
RegisterFunction("TODAY", Today)
|
||||
RegisterFunctionComplex("YEAR", Year)
|
||||
RegisterFunctionComplex("YEARFRAC", YearFrac)
|
||||
RegisterFunction("YEARFRAC", YearFrac)
|
||||
}
|
||||
|
||||
var date1900 int64 = makeDateS(1900, time.January, 1)
|
||||
@ -107,6 +107,8 @@ func initRegexpTime() {
|
||||
}
|
||||
}
|
||||
|
||||
var empty Result = MakeEmptyResult()
|
||||
|
||||
// Day is an implementation of the Excel DAY() function.
|
||||
func Day(args []Result) Result {
|
||||
if len(args) != 1 {
|
||||
@ -406,7 +408,7 @@ func dateValue(dateString string) (int, int, int, bool, Result) {
|
||||
if !validateDate(year, month, day) {
|
||||
return 0, 0, 0, false, MakeErrorResultType(ErrorTypeValue, dvErrMsg)
|
||||
}
|
||||
return year, month, day, timeIsEmpty, MakeEmptyResult()
|
||||
return year, month, day, timeIsEmpty, empty
|
||||
}
|
||||
|
||||
func validateDate(year, month, day int) bool {
|
||||
@ -743,7 +745,7 @@ func timeValue(timeString string) (int, int, float64, bool, bool, Result) {
|
||||
} else if hours >= 24 || seconds >= 10000 {
|
||||
return 0, 0, 0, false, false, MakeErrorResultType(ErrorTypeValue, tvErrMsg)
|
||||
}
|
||||
return hours, minutes, seconds, pm, dateIsEmpty, MakeEmptyResult()
|
||||
return hours, minutes, seconds, pm, dateIsEmpty, empty
|
||||
}
|
||||
|
||||
// Year is an implementation of the Excel YEAR() function.
|
||||
@ -760,73 +762,104 @@ func Year(ctx Context, ev Evaluator, args []Result) Result {
|
||||
}
|
||||
|
||||
// YearFrac is an implementation of the Excel YEARFRAC() function.
|
||||
func YearFrac(ctx Context, ev Evaluator, args []Result) Result {
|
||||
func YearFrac(args []Result) Result {
|
||||
argsNum := len(args)
|
||||
if (argsNum != 2 && argsNum != 3) || args[0].Type != ResultTypeNumber || args[1].Type != ResultTypeNumber {
|
||||
return MakeErrorResult("YEARFRAC requires two or three number arguments")
|
||||
}
|
||||
|
||||
basis := 0
|
||||
if argsNum == 3 {
|
||||
if argsNum == 3 && args[2].Type != ResultTypeEmpty {
|
||||
if args[2].Type != ResultTypeNumber {
|
||||
return MakeErrorResult("YEARFRAC requires two or three number arguments")
|
||||
}
|
||||
basis = int(args[2].ValueNumber)
|
||||
if !checkBasis(basis) {
|
||||
return MakeErrorResultType(ErrorTypeNum, "Incorrect basis argument for YEARFRAC")
|
||||
}
|
||||
}
|
||||
|
||||
epoch := ctx.GetEpoch()
|
||||
startDate, err := getValueAsTime(args[0].Value(), epoch)
|
||||
if err != nil {
|
||||
return MakeErrorResult("incorrect start date")
|
||||
if args[0].Type != ResultTypeNumber {
|
||||
return MakeErrorResult("YEARFRAC requires start date to be number argument")
|
||||
}
|
||||
endDate, err := getValueAsTime(args[1].Value(), epoch)
|
||||
if err != nil {
|
||||
return MakeErrorResult("incorrect end date")
|
||||
startDate := args[0].ValueNumber
|
||||
if args[1].Type != ResultTypeNumber {
|
||||
return MakeErrorResult("YEARFRAC requires end date to be number argument")
|
||||
}
|
||||
return yearFracFromTime(startDate, endDate, basis)
|
||||
endDate := args[1].ValueNumber
|
||||
yf, errResult := yearFrac(startDate, endDate, basis)
|
||||
if errResult.Type == ResultTypeError {
|
||||
return errResult
|
||||
}
|
||||
return MakeNumberResult(yf)
|
||||
}
|
||||
|
||||
func yearFrac(startDate, endDate float64, basis int) Result {
|
||||
return yearFracFromTime(dateFromDays(startDate), dateFromDays(endDate), basis)
|
||||
}
|
||||
|
||||
func yearFracFromTime(startDate, endDate time.Time, basis int) Result {
|
||||
// yearFrac returns float64 fraction of the year and Result value which can be of ResultTypeError type if an error occurs or ResultTypeEmpty if doesn't.
|
||||
func yearFrac(startDateF, endDateF float64, basis int) (float64, Result) {
|
||||
startDate, endDate := dateFromDays(startDateF), dateFromDays(endDateF)
|
||||
startDateS := startDate.Unix()
|
||||
endDateS := endDate.Unix()
|
||||
sy, sm, sd := startDate.Date()
|
||||
ey, em, ed := endDate.Date()
|
||||
|
||||
if startDateS == endDateS {
|
||||
return 0, empty
|
||||
}
|
||||
sy, smM, sd := startDate.Date()
|
||||
ey, emM, ed := endDate.Date()
|
||||
sm, em := int(smM), int(emM)
|
||||
var dayDiff, daysInYear float64
|
||||
switch basis {
|
||||
case 0:
|
||||
if sd == 31 && ed == 31 {
|
||||
sd = 30
|
||||
ed = 30
|
||||
} else if sd == 31 {
|
||||
sd = 30
|
||||
} else if sd == 30 && ed == 31 {
|
||||
ed = 30
|
||||
if sd == 31 {
|
||||
sd--
|
||||
}
|
||||
return MakeNumberResult(float64(((ed + int(em) * 30 + ey * 360) - (sd + int(sm) * 30 + sy * 360))) / 360)
|
||||
case 1:
|
||||
var ylength = 365.0
|
||||
if (sy == ey || ((sy + 1) == ey) && ((sm > em) || ((sm == em) && (sd >= ed)))) {
|
||||
if ((sy == ey && isLeapYear(sy)) || feb29Between(startDate, endDate) || (em == 1 && ed == 29)) {
|
||||
ylength = 366.0
|
||||
if sd == 30 && ed == 31 {
|
||||
ed--
|
||||
} else if leap := isLeapYear(sy); sm == 2 && ((leap && sd == 29) || (!leap && sd == 28)) {
|
||||
sd = 30
|
||||
if leap := isLeapYear(ey); em == 2 && ((leap && ed == 29) || (!leap && ed == 28)) {
|
||||
ed = 30
|
||||
}
|
||||
}
|
||||
dayDiff = float64((ey - sy) * 360 + (em - sm) * 30 + (ed - sd))
|
||||
daysInYear = 360
|
||||
case 1:
|
||||
dayDiff = endDateF - startDateF
|
||||
isYearDifferent := sy != ey
|
||||
if isYearDifferent && (ey != sy + 1 || sm < em || (sm == em && sd < ed)) {
|
||||
dayCount := 0
|
||||
for y := sy; y <= ey; y++ {
|
||||
dayCount += getDaysInYear(y, 1)
|
||||
}
|
||||
daysInYear = float64(dayCount) / float64(ey - sy + 1)
|
||||
} else {
|
||||
if !isYearDifferent && isLeapYear(sy) {
|
||||
daysInYear = 366
|
||||
} else {
|
||||
if isYearDifferent && ((isLeapYear(sy) && (sm < 2 || (sm == 2 && sd <= 29))) || (isLeapYear(ey) && (em > 2 || (em == 2 && ed == 29)))) {
|
||||
daysInYear = 366
|
||||
} else {
|
||||
daysInYear = 365
|
||||
}
|
||||
}
|
||||
return MakeNumberResult(daysBetween(startDateS, endDateS) / ylength)
|
||||
}
|
||||
var years = float64((ey - sy) + 1)
|
||||
var days = float64((makeDateS(ey + 1, time.January, 1) - makeDateS(sy, time.January, 1)) / 86400)
|
||||
var average = days / years
|
||||
return MakeNumberResult(daysBetween(startDateS, endDateS) / average)
|
||||
case 2:
|
||||
return MakeNumberResult(daysBetween(startDateS, endDateS) / 360.0)
|
||||
dayDiff = endDateF - startDateF
|
||||
daysInYear = 360
|
||||
case 3:
|
||||
return MakeNumberResult(daysBetween(startDateS, endDateS) / 365.0)
|
||||
case 4:
|
||||
return MakeNumberResult(float64(((ed + int(em) * 30 + ey * 360) - (sd + int(sm) * 30 + sy * 360))) / 360.0)
|
||||
dayDiff = endDateF - startDateF
|
||||
daysInYear = 365
|
||||
case 4:
|
||||
if sd == 31 {
|
||||
sd--
|
||||
}
|
||||
if ed == 31 {
|
||||
ed--
|
||||
}
|
||||
dayDiff = float64((ey - sy) * 360 + (em - sm) * 30 + (ed - sd))
|
||||
daysInYear = 360
|
||||
default:
|
||||
return 0, MakeErrorResultType(ErrorTypeNum, "Incorrect basis for YearFrac")
|
||||
}
|
||||
return MakeErrorResultType(ErrorTypeValue, "")
|
||||
return dayDiff / daysInYear, empty
|
||||
}
|
||||
|
||||
func getDaysInYear(year, basis int) int {
|
||||
@ -979,3 +1012,23 @@ func getDaysInYearRange(from, to, basis int) int {
|
||||
func basis30(basis int) bool {
|
||||
return basis == 0 || basis == 4
|
||||
}
|
||||
|
||||
func parseDate(arg Result, dateName, funcName string) (float64, Result) {
|
||||
var date float64
|
||||
switch arg.Type {
|
||||
case ResultTypeNumber:
|
||||
date = float64(int(arg.ValueNumber))
|
||||
case ResultTypeString:
|
||||
dateFromString := DateValue([]Result{arg})
|
||||
if dateFromString.Type == ResultTypeError {
|
||||
return 0, MakeErrorResult("Incorrect " + dateName + " date for " + funcName)
|
||||
}
|
||||
date = dateFromString.ValueNumber
|
||||
default:
|
||||
return 0, MakeErrorResult("Incorrect argument for " + funcName)
|
||||
}
|
||||
if date < 0 {
|
||||
return 0, MakeErrorResultType(ErrorTypeNum, dateName + " should be non negative")
|
||||
}
|
||||
return date, empty
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -98,7 +98,7 @@ func Index(args []Result) Result {
|
||||
}
|
||||
row := int(rowArg.ValueNumber) - 1
|
||||
col := -1
|
||||
if argsNum == 3 {
|
||||
if argsNum == 3 && args[2].Type != ResultTypeEmpty {
|
||||
colArg := args[2].AsNumber()
|
||||
if colArg.Type != ResultTypeNumber {
|
||||
return MakeErrorResult("INDEX requires numeric col argument")
|
||||
@ -192,7 +192,7 @@ func Match(args []Result) Result {
|
||||
}
|
||||
|
||||
matchType := 1
|
||||
if argsNum == 3 {
|
||||
if argsNum == 3 && args[2].Type != ResultTypeEmpty {
|
||||
if args[2].Type != ResultTypeNumber {
|
||||
return MakeErrorResult("MATCH requires the third argument to be a number")
|
||||
}
|
||||
@ -354,10 +354,11 @@ func Offset(ctx Context, ev Evaluator, args []Result) Result {
|
||||
// VLookup implements the VLOOKUP function that returns a matching value from a
|
||||
// column in an array.
|
||||
func VLookup(args []Result) Result {
|
||||
if len(args) < 3 {
|
||||
argsNum := len(args)
|
||||
if argsNum < 3 {
|
||||
return MakeErrorResult("VLOOKUP requires at least three arguments")
|
||||
}
|
||||
if len(args) > 4 {
|
||||
if argsNum > 4 {
|
||||
return MakeErrorResult("VLOOKUP requires at most four arguments")
|
||||
}
|
||||
lookupValue := args[0]
|
||||
@ -370,7 +371,7 @@ func VLookup(args []Result) Result {
|
||||
return MakeErrorResult("VLOOKUP requires numeric col argument")
|
||||
}
|
||||
exactMatch := false
|
||||
if len(args) == 4 {
|
||||
if argsNum == 4 && args[3].Type != ResultTypeEmpty {
|
||||
em := args[3].AsNumber()
|
||||
if em.Type != ResultTypeNumber {
|
||||
return MakeErrorResult("VLOOKUP requires numeric match argument")
|
||||
@ -547,7 +548,7 @@ func extractCol(arr Result) []Result {
|
||||
if len(r) > 0 {
|
||||
col = append(col, r[0])
|
||||
} else {
|
||||
col = append(col, MakeEmptyResult())
|
||||
col = append(col, empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1022,7 +1022,7 @@ func multinomial(args []Result) (float64, float64, Result) {
|
||||
return 0, 0, arg
|
||||
}
|
||||
}
|
||||
return num, denom, MakeEmptyResult()
|
||||
return num, denom, empty
|
||||
}
|
||||
|
||||
// Multinomial implements the excel MULTINOMIAL function.
|
||||
|
@ -284,7 +284,7 @@ func checkIfsRanges(args []Result, sumRange bool, fnName string) Result {
|
||||
i-- // after sumRange should go column 1, not 2
|
||||
}
|
||||
}
|
||||
return MakeEmptyResult()
|
||||
return empty
|
||||
}
|
||||
|
||||
//getIfsMatch returns an array of indexes of cells which meets all *IFS criterias
|
||||
|
@ -167,7 +167,8 @@ type parsedSearchObject struct {
|
||||
}
|
||||
|
||||
func parseSearchResults(fname string, args []Result) (*parsedSearchObject, Result) {
|
||||
if len(args) != 2 && len(args) != 3 {
|
||||
argsNum := len(args)
|
||||
if argsNum != 2 && argsNum != 3 {
|
||||
return nil, MakeErrorResult(fname + " requires two or three arguments")
|
||||
}
|
||||
findTextResult := args[0]
|
||||
@ -181,7 +182,7 @@ func parseSearchResults(fname string, args []Result) (*parsedSearchObject, Resul
|
||||
text := textResult.ValueString
|
||||
findText := findTextResult.ValueString
|
||||
position := 1
|
||||
if len(args) == 3 {
|
||||
if argsNum == 3 && args[2].Type != ResultTypeEmpty {
|
||||
positionResult := args[2]
|
||||
if positionResult.Type != ResultTypeNumber {
|
||||
return nil, MakeErrorResult("Position should be a number")
|
||||
@ -198,7 +199,7 @@ func parseSearchResults(fname string, args []Result) (*parsedSearchObject, Resul
|
||||
findText,
|
||||
text,
|
||||
position,
|
||||
}, MakeEmptyResult()
|
||||
}, empty
|
||||
}
|
||||
|
||||
// Find is an implementation of the Excel FIND().
|
||||
@ -543,7 +544,7 @@ func T(args []Result) Result {
|
||||
if s.Type == ResultTypeError || s.Type == ResultTypeString {
|
||||
return s
|
||||
}
|
||||
return MakeEmptyResult()
|
||||
return empty
|
||||
}
|
||||
|
||||
// Trim is an implementation of the Excel TRIM function that removes leading,
|
||||
@ -648,7 +649,7 @@ func parseReplaceResults(fname string, args []Result) (*parsedReplaceObject, Res
|
||||
startPos,
|
||||
length,
|
||||
textToReplace,
|
||||
}, MakeEmptyResult()
|
||||
}, empty
|
||||
}
|
||||
|
||||
// Replace is an implementation of the Excel REPLACE().
|
||||
|
@ -533,6 +533,7 @@ func TestMatch(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`MATCH("??ny",A1:A5)`, `2 ResultTypeNumber`},
|
||||
{`MATCH("*nny",A1:A5)`, `4 ResultTypeNumber`},
|
||||
{`MATCH("*nny",A1:A5,)`, `4 ResultTypeNumber`},
|
||||
{`=MATCH(5,B1:B5,1)`, `2 ResultTypeNumber`},
|
||||
{`=MATCH(5,C1:C5,-1)`, `3 ResultTypeNumber`},
|
||||
}
|
||||
@ -947,6 +948,7 @@ func TestFind(t *testing.T) {
|
||||
|
||||
td := []testStruct{
|
||||
{`FIND("",A1)`, `1 ResultTypeNumber`},
|
||||
{`FIND("",A1,)`, `1 ResultTypeNumber`},
|
||||
{`FIND(B1,A1)`, `2 ResultTypeNumber`},
|
||||
{`FIND(B2,A1,3)`, `3 ResultTypeNumber`},
|
||||
{`FIND(B2,A1,4)`, `#VALUE! ResultTypeError`},
|
||||
@ -975,6 +977,7 @@ func TestFindb(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`FINDB("",A1)`, `1 ResultTypeNumber`},
|
||||
{`FINDB(B1,A1)`, `2 ResultTypeNumber`},
|
||||
{`FINDB(B1,A1,)`, `2 ResultTypeNumber`},
|
||||
{`FINDB(B2,A1,3)`, `3 ResultTypeNumber`},
|
||||
{`FINDB(B2,A1,4)`, `#VALUE! ResultTypeError`},
|
||||
{`FINDB(D1,C1)`, `1 ResultTypeNumber`},
|
||||
@ -1002,6 +1005,7 @@ func TestSearch(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`SEARCH("",A1)`, `1 ResultTypeNumber`},
|
||||
{`SEARCH(B1,A1)`, `2 ResultTypeNumber`},
|
||||
{`SEARCH(B1,A1,)`, `2 ResultTypeNumber`},
|
||||
{`SEARCH(B2,A1,3)`, `3 ResultTypeNumber`},
|
||||
{`SEARCH(B2,A1,4)`, `#VALUE! ResultTypeError`},
|
||||
{`SEARCH(B3,A1,2)`, `2 ResultTypeNumber`},
|
||||
@ -1031,6 +1035,7 @@ func TestSearchb(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`SEARCHB("",A1)`, `1 ResultTypeNumber`},
|
||||
{`SEARCHB(B1,A1)`, `2 ResultTypeNumber`},
|
||||
{`SEARCHB(B1,A1,)`, `2 ResultTypeNumber`},
|
||||
{`SEARCHB(B2,A1,3)`, `3 ResultTypeNumber`},
|
||||
{`SEARCHB(B2,A1,4)`, `#VALUE! ResultTypeError`},
|
||||
{`SEARCHB(D1,C1)`, `1 ResultTypeNumber`},
|
||||
@ -1096,6 +1101,7 @@ func TestYearFrac(t *testing.T) {
|
||||
{`=YEARFRAC(A1,A2)`, `0.00277777777 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A3,A4)`, `0.16666666666 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A3,A5)`, `0.00277777777 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A3,A5,)`, `0.00277777777 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A1,A2,1)`, `0.00273972602 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A6,A7,1)`, `0.00273224043 ResultTypeNumber`},
|
||||
{`=YEARFRAC(A6,A8,1)`, `1 ResultTypeNumber`},
|
||||
@ -1307,6 +1313,8 @@ func TestDuration(t *testing.T) {
|
||||
sheet.Cell("A8").SetString("01/01/2048") // maturity date in string format
|
||||
|
||||
td := []testStruct{
|
||||
{`=DURATION(A1,A2,A3,A4,A5)`, `10.9191452815 ResultTypeNumber`},
|
||||
{`=DURATION(A1,A2,A3,A4,A5,)`, `10.9191452815 ResultTypeNumber`},
|
||||
{`=DURATION(A1,A2,A3,A4,A5,A6)`, `10.9191452815 ResultTypeNumber`},
|
||||
{`=DURATION(A7,A8,A3,A4,A5,A6)`, `10.9191452815 ResultTypeNumber`},
|
||||
{`=DURATION(A1,A2,A3,A4,A5,5)`, `#NUM! ResultTypeError`},
|
||||
@ -1331,6 +1339,8 @@ func TestMduration(t *testing.T) {
|
||||
sheet.Cell("A8").SetString("01/01/2016") // maturity date in string format
|
||||
|
||||
td := []testStruct{
|
||||
{`=MDURATION(A1,A2,A3,A4,A5)`, `5.73566981391 ResultTypeNumber`},
|
||||
{`=MDURATION(A1,A2,A3,A4,A5,)`, `5.73566981391 ResultTypeNumber`},
|
||||
{`=MDURATION(A1,A2,A3,A4,A5,A6)`, `5.73566981391 ResultTypeNumber`},
|
||||
{`=MDURATION(A7,A8,A3,A4,A5,A6)`, `5.73566981391 ResultTypeNumber`},
|
||||
{`=MDURATION(A1,A2,A3,A4,A5,5)`, `#NUM! ResultTypeError`},
|
||||
@ -1424,6 +1434,7 @@ func TestVlookup(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`=VLOOKUP(150,A1:B4,2)`, `value1 ResultTypeString`},
|
||||
{`=VLOOKUP(250,A1:B4,2)`, `value2 ResultTypeString`},
|
||||
{`=VLOOKUP(250,A1:B4,2,)`, `value2 ResultTypeString`},
|
||||
{`=VLOOKUP(250,A1:B4,2,FALSE)`, `#N/A ResultTypeError`},
|
||||
{`=VLOOKUP(300,A1:B4,2,FALSE)`, `value3 ResultTypeString`},
|
||||
}
|
||||
@ -1667,11 +1678,13 @@ func TestAccrintm(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,0))`, `20.5555555555 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,1))`, `20.4918032786 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,2))`, `20.8333333333 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,3))`, `20.5479452054 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,4))`, `20.5555555555 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000)`, `20.5555555555 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,)`, `20.5555555555 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,0)`, `20.5555555555 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,1)`, `20.4918032786 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,2)`, `20.8333333333 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,3)`, `20.5479452054 ResultTypeNumber`},
|
||||
{`=ACCRINTM(39539,39614,0.1,1000,4)`, `20.5555555555 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
@ -1684,6 +1697,9 @@ func TestAmordegrc(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=AMORDEGRC(2400,39679,39813,300,1,0.15)`, `776 ResultTypeNumber`},
|
||||
{`=AMORDEGRC(2400,39679,39813,300,1,0.15,)`, `776 ResultTypeNumber`},
|
||||
{`=AMORDEGRC(2400,39679,39813,300,1,0.15,0)`, `776 ResultTypeNumber`},
|
||||
{`=AMORDEGRC(2400,39679,39813,300,1,0.15,1)`, `776 ResultTypeNumber`},
|
||||
{`=AMORDEGRC(2400,39679,39813,300,1,0.15,2)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
@ -1698,6 +1714,9 @@ func TestAmorlinc(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=AMORLINC(2400,39679,39813,300,1,0.15)`, `360 ResultTypeNumber`},
|
||||
{`=AMORLINC(2400,39679,39813,300,1,0.15,)`, `360 ResultTypeNumber`},
|
||||
{`=AMORLINC(2400,39679,39813,300,1,0.15,0)`, `360 ResultTypeNumber`},
|
||||
{`=AMORLINC(2400,39679,39813,300,1,0.15,1)`, `360 ResultTypeNumber`},
|
||||
{`=AMORLINC(2400,39679,39813,300,1,0.15,2)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
@ -1712,6 +1731,8 @@ func TestCoupdaybs(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPDAYBS(40568,40862,2)`, `70 ResultTypeNumber`},
|
||||
{`=COUPDAYBS(40568,40862,2,)`, `70 ResultTypeNumber`},
|
||||
{`=COUPDAYBS(40568,40862,2,0)`, `70 ResultTypeNumber`},
|
||||
{`=COUPDAYBS(40568,40862,2,1)`, `71 ResultTypeNumber`},
|
||||
{`=COUPDAYBS(40568,40862,2,2)`, `71 ResultTypeNumber`},
|
||||
@ -1740,6 +1761,8 @@ func TestCoupdays(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPDAYS(40964,41228,1)`, `360 ResultTypeNumber`},
|
||||
{`=COUPDAYS(40964,41228,1,)`, `360 ResultTypeNumber`},
|
||||
{`=COUPDAYS(40964,41228,1,0)`, `360 ResultTypeNumber`},
|
||||
{`=COUPDAYS(40964,41228,1,1)`, `366 ResultTypeNumber`},
|
||||
{`=COUPDAYS(40964,41228,1,2)`, `360 ResultTypeNumber`},
|
||||
@ -1768,6 +1791,8 @@ func TestCoupdaysnc(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPDAYSNC(40933,41228,1)`, `290 ResultTypeNumber`},
|
||||
{`=COUPDAYSNC(40933,41228,1,)`, `290 ResultTypeNumber`},
|
||||
{`=COUPDAYSNC(40933,41228,1,0)`, `290 ResultTypeNumber`},
|
||||
{`=COUPDAYSNC(40933,41228,1,1)`, `295 ResultTypeNumber`},
|
||||
{`=COUPDAYSNC(40933,41228,1,2)`, `295 ResultTypeNumber`},
|
||||
@ -1796,6 +1821,9 @@ func TestCoupncd(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPNCD(40568,40862,1)`, `40862 ResultTypeNumber`},
|
||||
{`=COUPNCD(40568,40862,1,)`, `40862 ResultTypeNumber`},
|
||||
{`=COUPNCD(40568,40862,1,0)`, `40862 ResultTypeNumber`},
|
||||
{`=COUPNCD(40568,40862,1,1)`, `40862 ResultTypeNumber`},
|
||||
{`=COUPNCD(40568,40862,2,1)`, `40678 ResultTypeNumber`},
|
||||
{`=COUPNCD(40568,40862,4,1)`, `40589 ResultTypeNumber`},
|
||||
@ -1812,6 +1840,9 @@ func TestCouppcd(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPPCD(40568,40862,2)`, `40497 ResultTypeNumber`},
|
||||
{`=COUPPCD(40568,40862,2,)`, `40497 ResultTypeNumber`},
|
||||
{`=COUPPCD(40568,40862,2,0)`, `40497 ResultTypeNumber`},
|
||||
{`=COUPPCD(40568,40862,2,1)`, `40497 ResultTypeNumber`},
|
||||
{`=COUPPCD(40872,40568,2,1)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
@ -1826,6 +1857,9 @@ func TestCoupnum(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=COUPNUM(39107,39767,2)`, `4 ResultTypeNumber`},
|
||||
{`=COUPNUM(39107,39767,2,)`, `4 ResultTypeNumber`},
|
||||
{`=COUPNUM(39107,39767,2,0)`, `4 ResultTypeNumber`},
|
||||
{`=COUPNUM(39107,39767,2,1)`, `4 ResultTypeNumber`},
|
||||
{`=COUPNUM(39767,39107,2,1)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
@ -1925,6 +1959,8 @@ func TestDisc(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=DISC(A1,A2,A3,A4)`, `0.00068644067 ResultTypeNumber`},
|
||||
{`=DISC(A1,A2,A3,A4,)`, `0.00068644067 ResultTypeNumber`},
|
||||
{`=DISC(A1,A2,A3,A4,0)`, `0.00068644067 ResultTypeNumber`},
|
||||
{`=DISC(A1,A2,A3,A4,1)`, `0.00068638416 ResultTypeNumber`},
|
||||
{`=DISC(A1,A2,A3,A4,2)`, `0.00067650334 ResultTypeNumber`},
|
||||
@ -2028,6 +2064,8 @@ func TestIntrate(t *testing.T) {
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=INTRATE(A1,A2,A3,A4)`, `0.05768 ResultTypeNumber`},
|
||||
{`=INTRATE(A1,A2,A3,A4,)`, `0.05768 ResultTypeNumber`},
|
||||
{`=INTRATE(A1,A2,A3,A4,0)`, `0.05768 ResultTypeNumber`},
|
||||
{`=INTRATE(A1,A2,A3,A4,1)`, `0.05864133333 ResultTypeNumber`},
|
||||
{`=INTRATE(A1,A2,A3,A4,2)`, `0.05768 ResultTypeNumber`},
|
||||
@ -2165,7 +2203,12 @@ func TestNper(t *testing.T) {
|
||||
td := []testStruct{
|
||||
{`=NPER(A1/12,A2,A3,A4,1)`, `59.6738656742 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,A4)`, `60.0821228537 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,A4,)`, `60.0821228537 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,A4,0)`, `60.0821228537 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3)`, `-9.5785940398 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,,)`, `-9.5785940398 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,0,)`, `-9.5785940398 ResultTypeNumber`},
|
||||
{`=NPER(A1/12,A2,A3,,0)`, `-9.5785940398 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
@ -2192,3 +2235,377 @@ func TestNpv(t *testing.T) {
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPmt(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetNumber(0.08)
|
||||
sheet.Cell("A2").SetNumber(10)
|
||||
sheet.Cell("A3").SetNumber(10000)
|
||||
sheet.Cell("A4").SetNumber(0.06)
|
||||
sheet.Cell("A5").SetNumber(18)
|
||||
sheet.Cell("A6").SetNumber(50000)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PMT(A1/12,A2,A3)`, `-1037.0320893 ResultTypeNumber`},
|
||||
{`=PMT(A1/12,A2,A3,)`, `-1037.0320893 ResultTypeNumber`},
|
||||
{`=PMT(A1/12,A2,A3,0)`, `-1037.0320893 ResultTypeNumber`},
|
||||
{`=PMT(A1/12,A2,A3,1)`, `-1037.1291259 ResultTypeNumber`},
|
||||
{`=PMT(A4/12,A5*12,0,A6)`, `-129.08116086 ResultTypeNumber`},
|
||||
{`=PMT("A4/12",A5*12,0,A6)`, `#VALUE! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPpmt(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PPMT(0.1/12,1,2*12,2000)`, `-75.623186008 ResultTypeNumber`},
|
||||
{`=PPMT(0.08,10,10,200000)`, `-27598.053462 ResultTypeNumber`},
|
||||
{`=PPMT(0.08,11,10,200000)`, `#NUM! ResultTypeError`},
|
||||
{`=PPMT("0.08%",10,10,200000)`, `#VALUE! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPricedisc(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 2, 16, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 3, 1, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(0.0525)
|
||||
sheet.Cell("A4").SetNumber(100)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PRICEDISC(A1,A2,A3,A4)`, `99.78125 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,)`, `99.78125 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,0)`, `99.78125 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,1)`, `99.7991803278 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,2)`, `99.7958333333 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,3)`, `99.7986301369 ResultTypeNumber`},
|
||||
{`=PRICEDISC(A1,A2,A3,A4,4)`, `99.78125 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPv(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PV(0.08/12,20*12,500)`, `-59777.145851 ResultTypeNumber`},
|
||||
{`=PV(0.08/12,20*12,500,,)`, `-59777.145851 ResultTypeNumber`},
|
||||
{`=PV(0.08/12,20*12,500,0,)`, `-59777.145851 ResultTypeNumber`},
|
||||
{`=PV(0.08/12,20*12,500,,0)`, `-59777.145851 ResultTypeNumber`},
|
||||
{`=PV(0.08/12,20*12,500,0,0)`, `-59777.145851 ResultTypeNumber`},
|
||||
{`=PV(0.1/12,2*12,1000,10000)`, `-29864.950264 ResultTypeNumber`},
|
||||
{`=PV(0.1/12,2*12,1000,10000,)`, `-29864.950264 ResultTypeNumber`},
|
||||
{`=PV(0.1/12,2*12,1000,10000,0)`, `-29864.950264 ResultTypeNumber`},
|
||||
{`=PV(0.1/12,2*12,1000,10000,1)`, `-30045.540721 ResultTypeNumber`},
|
||||
{`=PV(0,2*12,1000,10000,1)`, `-34000 ResultTypeNumber`},
|
||||
{`=PV("hello world",2*12,1000,10000,1)`, `#VALUE! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestRate(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=RATE(2*12,-1000,-10000,100000)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,,)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,0,0.1)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,0,0.75)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,0,0.065)`, `0.06517891177 ResultTypeNumber`},
|
||||
{`=RATE(2*12,-1000,-10000,100000,1,0.1)`, `0.06323958 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestReceived(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 2, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 5, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(1000000)
|
||||
sheet.Cell("A4").SetNumber(0.0575)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=RECEIVED(A1,A2,A3,A4)`, `1014584.6544 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,)`, `1014584.6544 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,0)`, `1014584.6544 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,1)`, `1014342.13261 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,2)`, `1014584.6544 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,3)`, `1014381.99124 ResultTypeNumber`},
|
||||
{`=RECEIVED(A1,A2,A3,A4,4)`, `1014584.6544 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestRri(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=RRI(96,10000,11000)`, `0.00099330737 ResultTypeNumber`},
|
||||
{`=RRI(8,10000,11000)`, `0.01198502414 ResultTypeNumber`},
|
||||
{`=RRI(0,10000,11000)`, `#NUM! ResultTypeError`},
|
||||
{`=RRI(8,0,11000)`, `#NUM! ResultTypeError`},
|
||||
{`=RRI(8,10000,-0.000001)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestOddlprice(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 2, 7, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 6, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetDate(time.Date(2007, 10, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A4").SetNumber(0.0375)
|
||||
sheet.Cell("A5").SetNumber(0.0405)
|
||||
sheet.Cell("A6").SetNumber(100)
|
||||
sheet.Cell("A7").SetNumber(2)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=ODDLPRICE(A1,A2,A3,A4,A5,A6,A7,0)`, `99.8782860147 ResultTypeNumber`},
|
||||
{`=ODDLPRICE(A1,A2,A3,A4,A5,A6,A7,1)`, `99.8759395207 ResultTypeNumber`},
|
||||
{`=ODDLPRICE(A1,A2,A3,A4,A5,A6,A7,2)`, `99.8769016984 ResultTypeNumber`},
|
||||
{`=ODDLPRICE(A1,A2,A3,A4,A5,A6,A7,3)`, `99.8787957508 ResultTypeNumber`},
|
||||
{`=ODDLPRICE(A1,A2,A3,A4,A5,A6,A7,4)`, `99.8782860147 ResultTypeNumber`},
|
||||
{`=ODDLPRICE(A2,A1,A3,A4,A5,A6,A7,4)`, `#NUM! ResultTypeError`},
|
||||
{`=ODDLPRICE(A1,A3,A2,A4,A5,A6,A7,4)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestOddyield(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 4, 20, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 6, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetDate(time.Date(2007, 12, 24, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A4").SetNumber(0.0375)
|
||||
sheet.Cell("A5").SetNumber(99.875)
|
||||
sheet.Cell("A6").SetNumber(100)
|
||||
sheet.Cell("A7").SetNumber(2)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=ODDLYIELD(A1,A2,A3,A4,A5,A6,A7,0)`, `0.04519223562 ResultTypeNumber`},
|
||||
{`=ODDLYIELD(A1,A2,A3,A4,A5,A6,A7,1)`, `0.04517988549 ResultTypeNumber`},
|
||||
{`=ODDLYIELD(A1,A2,A3,A4,A5,A6,A7,2)`, `0.04503841511 ResultTypeNumber`},
|
||||
{`=ODDLYIELD(A1,A2,A3,A4,A5,A6,A7,3)`, `0.04515632373 ResultTypeNumber`},
|
||||
{`=ODDLYIELD(A1,A2,A3,A4,A5,A6,A7,4)`, `0.04519223562 ResultTypeNumber`},
|
||||
{`=ODDLYIELD(A2,A1,A3,A4,A5,A6,A7,4)`, `#NUM! ResultTypeError`},
|
||||
{`=ODDLYIELD(A1,A3,A2,A4,A5,A6,A7,4)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPrice(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 2, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2017, 11, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(0.0575)
|
||||
sheet.Cell("A4").SetNumber(0.065)
|
||||
sheet.Cell("A5").SetNumber(100)
|
||||
sheet.Cell("A6").SetNumber(2)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PRICE(A1,A2,A3,A4,A5,A6,0)`, `94.6343616213 ResultTypeNumber`},
|
||||
{`=PRICE(A1,A2,A3,A4,A5,A6,1)`, `94.6354492078 ResultTypeNumber`},
|
||||
{`=PRICE(A1,A2,A3,A4,A5,A6,2)`, `94.6024171768 ResultTypeNumber`},
|
||||
{`=PRICE(A1,A2,A3,A4,A5,A6,3)`, `94.6435945482 ResultTypeNumber`},
|
||||
{`=PRICE(A1,A2,A3,A4,A5,A6,4)`, `94.6343616213 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestPricemat(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 2, 15, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 4, 13, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetDate(time.Date(2007, 11, 11, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A4").SetNumber(0.061)
|
||||
sheet.Cell("A5").SetNumber(0.061)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=PRICEMAT(A1,A2,A3,A4,A5,0)`, `99.9844988755 ResultTypeNumber`},
|
||||
{`=PRICEMAT(A1,A2,A3,A4,A5,1)`, `99.9802978513 ResultTypeNumber`},
|
||||
{`=PRICEMAT(A1,A2,A3,A4,A5,2)`, `99.9841690643 ResultTypeNumber`},
|
||||
{`=PRICEMAT(A1,A2,A3,A4,A5,3)`, `99.9845977645 ResultTypeNumber`},
|
||||
{`=PRICEMAT(A1,A2,A3,A4,A5,4)`, `99.9844988755 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestSln(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=SLN(30000,7500,10)`, `2250 ResultTypeNumber`},
|
||||
{`=SLN(30000,7500,0)`, `#DIV/0! ResultTypeError`},
|
||||
{`=SLN("hello world",7500,10)`, `#VALUE! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestSyd(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=SYD(30000,7500,10,1)`, `4090.9090909 ResultTypeNumber`},
|
||||
{`=SYD(30000,7500,10,10)`, `409.09090909 ResultTypeNumber`},
|
||||
{`=SYD(30000,7500,10,11)`, `#NUM! ResultTypeError`},
|
||||
{`=SYD(30000,7500,0,0)`, `#NUM! ResultTypeError`},
|
||||
{`=SYD(30000,7500,10,0)`, `#NUM! ResultTypeError`},
|
||||
{`=SLN("hello world",7500,10,1)`, `#VALUE! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestTbilleq(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 3, 31, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 6, 1, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(0.0914)
|
||||
sheet.Cell("A4").SetDate(time.Date(2009, 4, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=TBILLEQ(A1,A2,A3)`, `0.09415149356 ResultTypeNumber`},
|
||||
{`=TBILLEQ("A1",A2,A3)`, `#VALUE! ResultTypeError`},
|
||||
{`=TBILLEQ(A1,A2,0)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLEQ(A2,A1,A3)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLEQ(A1,A4,A3)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestTbillprice(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 3, 31, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 6, 1, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(0.09)
|
||||
sheet.Cell("A4").SetDate(time.Date(2009, 4, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=TBILLPRICE(A1,A2,A3)`, `98.45 ResultTypeNumber`},
|
||||
{`=TBILLPRICE("A1",A2,A3)`, `#VALUE! ResultTypeError`},
|
||||
{`=TBILLPRICE(A1,A2,0)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLPRICE(A2,A1,A3)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLPRICE(A1,A4,A3)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestTbillyield(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetDate(time.Date(2008, 3, 31, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A2").SetDate(time.Date(2008, 6, 1, 0, 0, 0, 0, time.UTC))
|
||||
sheet.Cell("A3").SetNumber(98.45)
|
||||
sheet.Cell("A4").SetDate(time.Date(2009, 4, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=TBILLYIELD(A1,A2,A3)`, `0.09141696292 ResultTypeNumber`},
|
||||
{`=TBILLYIELD("A1",A2,A3)`, `#VALUE! ResultTypeError`},
|
||||
{`=TBILLYIELD(A1,A2,0)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLYIELD(A2,A1,A3)`, `#NUM! ResultTypeError`},
|
||||
{`=TBILLYIELD(A1,A4,A3)`, `#NUM! ResultTypeError`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
||||
func TestVdb(t *testing.T) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
|
||||
sheet.Cell("A1").SetNumber(2400)
|
||||
sheet.Cell("A2").SetNumber(300)
|
||||
sheet.Cell("A3").SetNumber(10)
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
td := []testStruct{
|
||||
{`=VDB(A1,A2,A3*365,0,1)`, `1.31506849315 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3*12,0,1)`, `40 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3,0,1)`, `480 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3*12,6,18)`, `396.306053264 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3*12,6,18,)`, `210 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3*12,6,18,,1)`, `0 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3*12,6,18,1.5)`, `311.808936658 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3,0,0.875,1.5)`, `315 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3,0,0.875,,)`, `183.75 ResultTypeNumber`},
|
||||
{`=VDB(A1,A2,A3,0,0.875,,1)`, `0 ResultTypeNumber`},
|
||||
}
|
||||
|
||||
runTests(t, ctx, td)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user