diff options
-rw-r--r-- | calc.go | 35 | ||||
-rw-r--r-- | calc_test.go | 7 | ||||
-rw-r--r-- | styles.go | 4 | ||||
-rw-r--r-- | xmlStyles.go | 4 |
4 files changed, 46 insertions, 4 deletions
@@ -282,6 +282,7 @@ var tokenPriority = map[string]int{ // GAMMA // GAMMALN // GCD +// HARMEAN // HEX2BIN // HEX2DEC // HEX2OCT @@ -3927,6 +3928,40 @@ func (fn *formulaFuncs) GAMMALN(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "GAMMALN requires 1 numeric argument") } +// HARMEAN function calculates the harmonic mean of a supplied set of values. +// The syntax of the function is: +// +// HARMEAN(number1,[number2],...) +// +func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg { + if argsList.Len() < 1 { + return newErrorFormulaArg(formulaErrorVALUE, "HARMEAN requires at least 1 argument") + } + if min := fn.MIN(argsList); min.Number < 0 { + return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) + } + number, val, cnt := 0.0, 0.0, 0.0 + for token := argsList.Front(); token != nil; token = token.Next() { + arg := token.Value.(formulaArg) + switch arg.Type { + case ArgString: + num := arg.ToNumber() + if num.Type != ArgNumber { + continue + } + number = num.Number + case ArgNumber: + number = arg.Number + } + if number <= 0 { + return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) + } + val += (1 / number) + cnt++ + } + return newNumberFormulaArg(1 / (val / cnt)) +} + // KURT function calculates the kurtosis of a supplied set of values. The // syntax of the function is: // diff --git a/calc_test.go b/calc_test.go index f8397e7..65f7ce1 100644 --- a/calc_test.go +++ b/calc_test.go @@ -605,6 +605,9 @@ func TestCalcCellValue(t *testing.T) { // GAMMALN "=GAMMALN(4.5)": "2.453736570842443", "=GAMMALN(INT(1))": "0", + // HARMEAN + "=HARMEAN(2.5,3,0.5,1,3)": "1.229508196721312", + "=HARMEAN(\"2.5\",3,0.5,1,INT(3),\"\")": "1.229508196721312", // KURT "=KURT(F1:F9)": "-1.033503502551368", "=KURT(F1,F2:F9)": "-1.033503502551368", @@ -1393,6 +1396,10 @@ func TestCalcCellValue(t *testing.T) { "=GAMMALN(F1)": "GAMMALN requires 1 numeric argument", "=GAMMALN(0)": "#N/A", "=GAMMALN(INT(0))": "#N/A", + // HARMEAN + "=HARMEAN()": "HARMEAN requires at least 1 argument", + "=HARMEAN(-1)": "#N/A", + "=HARMEAN(0)": "#N/A", // KURT "=KURT()": "KURT requires at least 1 argument", "=KURT(F1,INT(1))": "#DIV/0!", @@ -2472,8 +2472,8 @@ func newAlignment(style *Style) *xlsxAlignment { func newProtection(style *Style) *xlsxProtection { var protection xlsxProtection if style.Protection != nil { - protection.Hidden = style.Protection.Hidden - protection.Locked = style.Protection.Locked + protection.Hidden = &style.Protection.Hidden + protection.Locked = &style.Protection.Locked } return &protection } diff --git a/xmlStyles.go b/xmlStyles.go index db85b15..0670b59 100644 --- a/xmlStyles.go +++ b/xmlStyles.go @@ -49,8 +49,8 @@ type xlsxAlignment struct { // set. The cell protection properties do not take effect unless the sheet has // been protected. type xlsxProtection struct { - Hidden bool `xml:"hidden,attr"` - Locked bool `xml:"locked,attr"` + Hidden *bool `xml:"hidden,attr"` + Locked *bool `xml:"locked,attr"` } // xlsxLine expresses a single set of cell border. |