Skip to content

Commit 9b8f1a1

Browse files
committed
ref #65, new formula functions: MODE.MULT and MODE.SNGL
1 parent 5bf4bce commit 9b8f1a1

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

calc.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,8 @@ type formulaFuncs struct {
550550
// MIRR
551551
// MOD
552552
// MODE
553+
// MODE.MULT
554+
// MODE.SNGL
553555
// MONTH
554556
// MROUND
555557
// MULTINOMIAL
@@ -8021,6 +8023,67 @@ func (fn *formulaFuncs) MODE(argsList *list.List) formulaArg {
80218023
return newNumberFormulaArg(mode)
80228024
}
80238025

8026+
// MODEdotMULT function returns a vertical array of the statistical modes
8027+
// (the most frequently occurring values) within a list of supplied numbers.
8028+
// The syntax of the function is:
8029+
//
8030+
// MODE.MULT(number1,[number2],...)
8031+
//
8032+
func (fn *formulaFuncs) MODEdotMULT(argsList *list.List) formulaArg {
8033+
if argsList.Len() < 1 {
8034+
return newErrorFormulaArg(formulaErrorVALUE, "MODE.MULT requires at least 1 argument")
8035+
}
8036+
var values []float64
8037+
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
8038+
cells := arg.Value.(formulaArg)
8039+
if cells.Type != ArgMatrix && cells.ToNumber().Type != ArgNumber {
8040+
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
8041+
}
8042+
for _, cell := range cells.ToList() {
8043+
if num := cell.ToNumber(); num.Type == ArgNumber {
8044+
values = append(values, num.Number)
8045+
}
8046+
}
8047+
}
8048+
sort.Float64s(values)
8049+
cnt := len(values)
8050+
var count, modeCnt int
8051+
var mtx [][]formulaArg
8052+
for i := 0; i < cnt; i++ {
8053+
count = 0
8054+
for j := i + 1; j < cnt; j++ {
8055+
if values[i] == values[j] {
8056+
count++
8057+
}
8058+
}
8059+
if count > modeCnt {
8060+
modeCnt = count
8061+
mtx = [][]formulaArg{}
8062+
mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
8063+
} else if count == modeCnt {
8064+
mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
8065+
}
8066+
}
8067+
if modeCnt == 0 {
8068+
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
8069+
}
8070+
return newMatrixFormulaArg(mtx)
8071+
}
8072+
8073+
// MODEdotSNGL function returns the statistical mode (the most frequently
8074+
// occurring value) within a list of supplied numbers. If there are 2 or more
8075+
// most frequently occurring values in the supplied data, the function returns
8076+
// the lowest of these values. The syntax of the function is:
8077+
//
8078+
// MODE.SNGL(number1,[number2],...)
8079+
//
8080+
func (fn *formulaFuncs) MODEdotSNGL(argsList *list.List) formulaArg {
8081+
if argsList.Len() < 1 {
8082+
return newErrorFormulaArg(formulaErrorVALUE, "MODE.SNGL requires at least 1 argument")
8083+
}
8084+
return fn.MODE(argsList)
8085+
}
8086+
80248087
// NEGBINOMdotDIST function calculates the probability mass function or the
80258088
// cumulative distribution function for the Negative Binomial Distribution.
80268089
// This gives the probability that there will be a given number of failures

calc_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4880,8 +4880,11 @@ func TestCalcMODE(t *testing.T) {
48804880
}
48814881
f := prepareCalcData(cellData)
48824882
formulaList := map[string]string{
4883-
"=MODE(A1:A10)": "3",
4884-
"=MODE(B1:B6)": "2",
4883+
"=MODE(A1:A10)": "3",
4884+
"=MODE(B1:B6)": "2",
4885+
"=MODE.MULT(A1:A10)": "",
4886+
"=MODE.SNGL(A1:A10)": "3",
4887+
"=MODE.SNGL(B1:B6)": "2",
48854888
}
48864889
for formula, expected := range formulaList {
48874890
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
@@ -4890,9 +4893,15 @@ func TestCalcMODE(t *testing.T) {
48904893
assert.Equal(t, expected, result, formula)
48914894
}
48924895
calcError := map[string]string{
4893-
"=MODE()": "MODE requires at least 1 argument",
4894-
"=MODE(0,\"\")": "#VALUE!",
4895-
"=MODE(D1:D3)": "#N/A",
4896+
"=MODE()": "MODE requires at least 1 argument",
4897+
"=MODE(0,\"\")": "#VALUE!",
4898+
"=MODE(D1:D3)": "#N/A",
4899+
"=MODE.MULT()": "MODE.MULT requires at least 1 argument",
4900+
"=MODE.MULT(0,\"\")": "#VALUE!",
4901+
"=MODE.MULT(D1:D3)": "#N/A",
4902+
"=MODE.SNGL()": "MODE.SNGL requires at least 1 argument",
4903+
"=MODE.SNGL(0,\"\")": "#VALUE!",
4904+
"=MODE.SNGL(D1:D3)": "#N/A",
48964905
}
48974906
for formula, expected := range calcError {
48984907
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))

0 commit comments

Comments
 (0)