forked from p30928647/excelize
ref: #756, set cell as blank when SetCellValue with nil #756, new formula fn: BITAND, BITLSHIFT, BITOR, BITRSHIFT, BITXOR
This commit is contained in:
parent
ae6f56b953
commit
9154d500cf
102
calc.go
102
calc.go
|
@ -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)
|
||||
|
|
53
calc_test.go
53
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",
|
||||
|
|
9
cell.go
9
cell.go
|
@ -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))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue