diff options
author | xuri <xuri.me@gmail.com> | 2021-02-19 00:03:51 +0800 |
---|---|---|
committer | xuri <xuri.me@gmail.com> | 2021-02-19 00:20:27 +0800 |
commit | 9154d500cf50621e15bf4a2bb9f6b5045d7b72d2 (patch) | |
tree | 102031d4b81c3d62a6d103d12544b96ea54d937c | |
parent | ae6f56b9531d6dce437a719523c1a9c67b97f776 (diff) |
ref: #756, set cell as blank when SetCellValue with nil #756, new formula fn: BITAND, BITLSHIFT, BITOR, BITRSHIFT, BITXOR
-rw-r--r-- | calc.go | 102 | ||||
-rw-r--r-- | calc_test.go | 53 | ||||
-rw-r--r-- | cell.go | 9 |
3 files changed, 141 insertions, 23 deletions
@@ -222,6 +222,11 @@ var tokenPriority = map[string]int{ // AVERAGE // AVERAGEA // BASE +// BITAND +// BITLSHIFT +// BITOR +// BITRSHIFT +// BITXOR // CEILING // CEILING.MATH // CEILING.PRECISE @@ -1146,18 +1151,82 @@ func formulaCriteriaEval(val string, criteria *formulaCriteria) (result bool, er // Engineering Functions +// BITAND function returns the bitwise 'AND' for two supplied integers. The +// syntax of the function is: +// +// BITAND(number1,number2) +// +func (fn *formulaFuncs) BITAND(argsList *list.List) formulaArg { + return fn.bitwise("BITAND", argsList) +} + +// BITLSHIFT function returns a supplied integer, shifted left by a specified +// number of bits. The syntax of the function is: +// +// BITLSHIFT(number1,shift_amount) +// +func (fn *formulaFuncs) BITLSHIFT(argsList *list.List) formulaArg { + return fn.bitwise("BITLSHIFT", argsList) +} + +// BITOR function returns the bitwise 'OR' for two supplied integers. The +// syntax of the function is: +// +// BITOR(number1,number2) +// +func (fn *formulaFuncs) BITOR(argsList *list.List) formulaArg { + return fn.bitwise("BITOR", argsList) +} + +// BITRSHIFT function returns a supplied integer, shifted right by a specified +// number of bits. The syntax of the function is: +// +// BITRSHIFT(number1,shift_amount) +// +func (fn *formulaFuncs) BITRSHIFT(argsList *list.List) formulaArg { + return fn.bitwise("BITRSHIFT", argsList) +} + +// BITXOR function returns the bitwise 'XOR' (exclusive 'OR') for two supplied +// integers. The syntax of the function is: +// +// BITXOR(number1,number2) +// +func (fn *formulaFuncs) BITXOR(argsList *list.List) formulaArg { + return fn.bitwise("BITXOR", argsList) +} + +// bitwise is an implementation of the formula function BITAND, BITLSHIFT, +// BITOR, BITRSHIFT and BITXOR. +func (fn *formulaFuncs) bitwise(name string, argsList *list.List) formulaArg { + if argsList.Len() != 2 { + return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 numeric arguments", name)) + } + num1, num2 := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber() + if num1.Type != ArgNumber || num2.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + max := math.Pow(2, 48) - 1 + if num1.Number < 0 || num1.Number > max || num2.Number < 0 || num2.Number > max { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + bitwiseFuncMap := map[string]func(a, b int) int{ + "BITAND": func(a, b int) int { return a & b }, + "BITLSHIFT": func(a, b int) int { return a << uint(b) }, + "BITOR": func(a, b int) int { return a | b }, + "BITRSHIFT": func(a, b int) int { return a >> uint(b) }, + "BITXOR": func(a, b int) int { return a ^ b }, + } + bitwiseFunc, _ := bitwiseFuncMap[name] + return newNumberFormulaArg(float64(bitwiseFunc(int(num1.Number), int(num2.Number)))) +} + // DEC2BIN function converts a decimal number into a Binary (Base 2) number. // The syntax of the function is: // // DEC2BIN(number,[places]) // func (fn *formulaFuncs) DEC2BIN(argsList *list.List) formulaArg { - if argsList.Len() < 1 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2BIN requires at least 1 argument") - } - if argsList.Len() > 2 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2BIN allows at most 2 arguments") - } return fn.dec2x("DEC2BIN", argsList) } @@ -1167,12 +1236,6 @@ func (fn *formulaFuncs) DEC2BIN(argsList *list.List) formulaArg { // DEC2HEX(number,[places]) // func (fn *formulaFuncs) DEC2HEX(argsList *list.List) formulaArg { - if argsList.Len() < 1 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2HEX requires at least 1 argument") - } - if argsList.Len() > 2 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2HEX allows at most 2 arguments") - } return fn.dec2x("DEC2HEX", argsList) } @@ -1182,17 +1245,18 @@ func (fn *formulaFuncs) DEC2HEX(argsList *list.List) formulaArg { // DEC2OCT(number,[places]) // func (fn *formulaFuncs) DEC2OCT(argsList *list.List) formulaArg { - if argsList.Len() < 1 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2OCT requires at least 1 argument") - } - if argsList.Len() > 2 { - return newErrorFormulaArg(formulaErrorVALUE, "DEC2OCT allows at most 2 arguments") - } return fn.dec2x("DEC2OCT", argsList) } -// dec2x is an implementation of the formula function DEC2BIN, DEC2HEX and DEC2OCT. +// dec2x is an implementation of the formula function DEC2BIN, DEC2HEX and +// DEC2OCT. func (fn *formulaFuncs) dec2x(name string, argsList *list.List) formulaArg { + if argsList.Len() < 1 { + return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name)) + } + if argsList.Len() > 2 { + return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s allows at most 2 arguments", name)) + } decimal := argsList.Front().Value.(formulaArg).ToNumber() if decimal.Type != ArgNumber { return newErrorFormulaArg(formulaErrorVALUE, decimal.Error) diff --git a/calc_test.go b/calc_test.go index 28ffb6c..04dce37 100644 --- a/calc_test.go +++ b/calc_test.go @@ -47,6 +47,19 @@ func TestCalcCellValue(t *testing.T) { "=2>=3": "FALSE", "=1&2": "12", // Engineering Functions + // BITAND + "=BITAND(13,14)": "12", + // BITLSHIFT + "=BITLSHIFT(5,2)": "20", + "=BITLSHIFT(3,5)": "96", + // BITOR + "=BITOR(9,12)": "13", + // BITRSHIFT + "=BITRSHIFT(20,2)": "5", + "=BITRSHIFT(52,4)": "3", + // BITXOR + "=BITXOR(5,6)": "3", + "=BITXOR(9,12)": "5", // DEC2BIN "=DEC2BIN(2)": "10", "=DEC2BIN(3)": "11", @@ -727,6 +740,46 @@ func TestCalcCellValue(t *testing.T) { mathCalcError := map[string]string{ "=1/0": "#DIV/0!", // Engineering Functions + // BITAND + "=BITAND()": "BITAND requires 2 numeric arguments", + "=BITAND(-1,2)": "#NUM!", + "=BITAND(2^48,2)": "#NUM!", + "=BITAND(1,-1)": "#NUM!", + "=BITAND(\"\",-1)": "#NUM!", + "=BITAND(1,\"\")": "#NUM!", + "=BITAND(1,2^48)": "#NUM!", + // BITLSHIFT + "=BITLSHIFT()": "BITLSHIFT requires 2 numeric arguments", + "=BITLSHIFT(-1,2)": "#NUM!", + "=BITLSHIFT(2^48,2)": "#NUM!", + "=BITLSHIFT(1,-1)": "#NUM!", + "=BITLSHIFT(\"\",-1)": "#NUM!", + "=BITLSHIFT(1,\"\")": "#NUM!", + "=BITLSHIFT(1,2^48)": "#NUM!", + // BITOR + "=BITOR()": "BITOR requires 2 numeric arguments", + "=BITOR(-1,2)": "#NUM!", + "=BITOR(2^48,2)": "#NUM!", + "=BITOR(1,-1)": "#NUM!", + "=BITOR(\"\",-1)": "#NUM!", + "=BITOR(1,\"\")": "#NUM!", + "=BITOR(1,2^48)": "#NUM!", + // BITRSHIFT + "=BITRSHIFT()": "BITRSHIFT requires 2 numeric arguments", + "=BITRSHIFT(-1,2)": "#NUM!", + "=BITRSHIFT(2^48,2)": "#NUM!", + "=BITRSHIFT(1,-1)": "#NUM!", + "=BITRSHIFT(\"\",-1)": "#NUM!", + "=BITRSHIFT(1,\"\")": "#NUM!", + "=BITRSHIFT(1,2^48)": "#NUM!", + // BITXOR + "=BITXOR()": "BITXOR requires 2 numeric arguments", + "=BITXOR(-1,2)": "#NUM!", + "=BITXOR(2^48,2)": "#NUM!", + "=BITXOR(1,-1)": "#NUM!", + "=BITXOR(\"\",-1)": "#NUM!", + "=BITXOR(1,\"\")": "#NUM!", + "=BITXOR(1,2^48)": "#NUM!", // DEC2BIN "=DEC2BIN()": "DEC2BIN requires at least 1 argument", "=DEC2BIN(1,1,1)": "DEC2BIN allows at most 2 arguments", @@ -1,4 +1,4 @@ -// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of +// Copyright 2016 - 2021 The excelize Authors. All rights reserved. Use of // this source code is governed by a BSD-style license that can be found in // the LICENSE file. // @@ -44,8 +44,9 @@ func (f *File) GetCellValue(sheet, axis string) (string, error) { } // SetCellValue provides a function to set value of a cell. The specified -// coordinates should not be in the first row of the table. The following -// shows the supported data types: +// coordinates should not be in the first row of the table, a complex number +// can be set with string text. The following shows the supported data +// types: // // int // int8 @@ -93,7 +94,7 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) error { case bool: err = f.SetCellBool(sheet, axis, v) case nil: - break + err = f.SetCellDefault(sheet, axis, "") default: err = f.SetCellStr(sheet, axis, fmt.Sprint(value)) } |