Skip to content

Commit

Permalink
Ref #65, new formula function DOLLAR (#1992)
Browse files Browse the repository at this point in the history
- Update unit tests
  • Loading branch information
ArcholSevier authored Sep 12, 2024
1 parent ad85417 commit 02189fb
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
44 changes: 44 additions & 0 deletions calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ type formulaFuncs struct {
// DISC
// DMAX
// DMIN
// DOLLAR
// DOLLARDE
// DOLLARFR
// DPRODUCT
Expand Down Expand Up @@ -16341,6 +16342,49 @@ func (fn *formulaFuncs) DISC(argsList *list.List) formulaArg {
return fn.discIntrate("DISC", argsList)
}

// DOLLAR function rounds a supplied number to a specified number of decimal
// places and then converts this into a text string with a currency format. The
// syntax of the function is:
//
// DOLLAR(number,[decimals])
func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "DOLLAR requires at least 1 argument")
}
if argsList.Len() > 2 {
return newErrorFormulaArg(formulaErrorVALUE, "DOLLAR requires 1 or 2 arguments")
}
numArg := argsList.Front().Value.(formulaArg)
n := numArg.ToNumber()
if n.Type != ArgNumber {
return n
}
decimals, dot, value := 2, ".", numArg.Value()
if argsList.Len() == 2 {
d := argsList.Back().Value.(formulaArg).ToNumber()
if d.Type != ArgNumber {
return d
}
if d.Number < 0 {
value = strconv.FormatFloat(fn.round(n.Number, d.Number, down), 'f', -1, 64)
}
if d.Number >= 128 {
return newErrorFormulaArg(formulaErrorVALUE, "decimal value should be less than 128")
}
if decimals = int(d.Number); decimals < 0 {
decimals, dot = 0, ""
}
}
symbol := map[CultureName]string{
CultureNameUnknown: "$",
CultureNameEnUS: "$",
CultureNameZhCN: "¥",
}[fn.f.options.CultureInfo]
numFmtCode := fmt.Sprintf("%s#,##0%s%s;(%s#,##0%s%s)",
symbol, dot, strings.Repeat("0", decimals), symbol, dot, strings.Repeat("0", decimals))
return newStringFormulaArg(format(value, numFmtCode, false, CellTypeNumber, nil))
}

// DOLLARDE function converts a dollar value in fractional notation, into a
// dollar value expressed as a decimal. The syntax of the function is:
//
Expand Down
16 changes: 16 additions & 0 deletions calc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,16 @@ func TestCalcCellValue(t *testing.T) {
"=DDB(10000,1000,5,5)": "296",
// DISC
"=DISC(\"04/01/2016\",\"03/31/2021\",95,100)": "0.01",
// DOLLAR
"=DOLLAR(1234.56)": "$1,234.56",
"=DOLLAR(1234.56,0)": "$1,235",
"=DOLLAR(1234.56,1)": "$1,234.6",
"=DOLLAR(1234.56,2)": "$1,234.56",
"=DOLLAR(1234.56,3)": "$1,234.560",
"=DOLLAR(1234.56,-2)": "$1,200",
"=DOLLAR(1234.56,-3)": "$1,000",
"=DOLLAR(-1234.56,3)": "($1,234.560)",
"=DOLLAR(-1234.56,-3)": "($1,000)",
// DOLLARDE
"=DOLLARDE(1.01,16)": "1.0625",
// DOLLARFR
Expand Down Expand Up @@ -4250,6 +4260,12 @@ func TestCalcCellValue(t *testing.T) {
"=DISC(\"04/01/2016\",\"03/31/2021\",0,100)": {"#NUM!", "DISC requires pr > 0"},
"=DISC(\"04/01/2016\",\"03/31/2021\",95,0)": {"#NUM!", "DISC requires redemption > 0"},
"=DISC(\"04/01/2016\",\"03/31/2021\",95,100,5)": {"#NUM!", "invalid basis"},
// DOLLAR
"DOLLAR()": {"#VALUE!", "DOLLAR requires at least 1 argument"},
"DOLLAR(0,0,0)": {"#VALUE!", "DOLLAR requires 1 or 2 arguments"},
"DOLLAR(\"\")": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
"DOLLAR(0,\"\")": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
"DOLLAR(1,200)": {"#VALUE!", "decimal value should be less than 128"},
// DOLLARDE
"=DOLLARDE()": {"#VALUE!", "DOLLARDE requires 2 arguments"},
"=DOLLARDE(\"\",0)": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
Expand Down

0 comments on commit 02189fb

Please sign in to comment.