forked from p30928647/excelize
#65 fn: DEC2BIN, DEC2HEX, DEC2OCT
This commit is contained in:
parent
b3493c5416
commit
ae6f56b953
|
@ -9,6 +9,7 @@ go:
|
|||
- 1.13.x
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
|
101
calc.go
101
calc.go
|
@ -26,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"github.com/xuri/efp"
|
||||
)
|
||||
|
@ -240,6 +241,9 @@ var tokenPriority = map[string]int{
|
|||
// CSC
|
||||
// CSCH
|
||||
// DATE
|
||||
// DEC2BIN
|
||||
// DEC2HEX
|
||||
// DEC2OCT
|
||||
// DECIMAL
|
||||
// DEGREES
|
||||
// ENCODEURL
|
||||
|
@ -1140,7 +1144,100 @@ func formulaCriteriaEval(val string, criteria *formulaCriteria) (result bool, er
|
|||
return
|
||||
}
|
||||
|
||||
// Math and Trigonometric functions
|
||||
// Engineering Functions
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// DEC2HEX function converts a decimal number into a Hexadecimal (Base 16)
|
||||
// number. The syntax of the function is:
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
|
||||
// DEC2OCT function converts a decimal number into an Octal (Base 8) number.
|
||||
// The syntax of the function is:
|
||||
//
|
||||
// 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.
|
||||
func (fn *formulaFuncs) dec2x(name string, argsList *list.List) formulaArg {
|
||||
decimal := argsList.Front().Value.(formulaArg).ToNumber()
|
||||
if decimal.Type != ArgNumber {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, decimal.Error)
|
||||
}
|
||||
maxLimitMap := map[string]float64{
|
||||
"DEC2BIN": 511,
|
||||
"DEC2HEX": 549755813887,
|
||||
"DEC2OCT": 536870911,
|
||||
}
|
||||
minLimitMap := map[string]float64{
|
||||
"DEC2BIN": -512,
|
||||
"DEC2HEX": -549755813888,
|
||||
"DEC2OCT": -536870912,
|
||||
}
|
||||
baseMap := map[string]int{
|
||||
"DEC2BIN": 2,
|
||||
"DEC2HEX": 16,
|
||||
"DEC2OCT": 8,
|
||||
}
|
||||
maxLimit := maxLimitMap[name]
|
||||
minLimit := minLimitMap[name]
|
||||
base := baseMap[name]
|
||||
if decimal.Number < minLimit || decimal.Number > maxLimit {
|
||||
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
||||
}
|
||||
n := int64(decimal.Number)
|
||||
binary := strconv.FormatUint(*(*uint64)(unsafe.Pointer(&n)), base)
|
||||
if argsList.Len() == 2 {
|
||||
places := argsList.Back().Value.(formulaArg).ToNumber()
|
||||
if places.Type != ArgNumber {
|
||||
return newErrorFormulaArg(formulaErrorVALUE, places.Error)
|
||||
}
|
||||
binaryPlaces := len(binary)
|
||||
if places.Number < 0 || places.Number > 10 || binaryPlaces > int(places.Number) {
|
||||
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
||||
}
|
||||
return newStringFormulaArg(strings.ToUpper(fmt.Sprintf("%s%s", strings.Repeat("0", int(places.Number)-binaryPlaces), binary)))
|
||||
}
|
||||
if decimal.Number < 0 && len(binary) > 10 {
|
||||
return newStringFormulaArg(strings.ToUpper(binary[len(binary)-10:]))
|
||||
}
|
||||
return newStringFormulaArg(strings.ToUpper(binary))
|
||||
}
|
||||
|
||||
// Math and Trigonometric Functions
|
||||
|
||||
// ABS function returns the absolute value of any supplied number. The syntax
|
||||
// of the function is:
|
||||
|
@ -4357,7 +4454,7 @@ func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
|
|||
return newStringFormulaArg(result)
|
||||
}
|
||||
|
||||
// Excel Lookup and Reference Functions
|
||||
// Lookup and Reference Functions
|
||||
|
||||
// CHOOSE function returns a value from an array, that corresponds to a
|
||||
// supplied index number (position). The syntax of the function is:
|
||||
|
|
44
calc_test.go
44
calc_test.go
|
@ -46,6 +46,25 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=2>=1": "TRUE",
|
||||
"=2>=3": "FALSE",
|
||||
"=1&2": "12",
|
||||
// Engineering Functions
|
||||
// DEC2BIN
|
||||
"=DEC2BIN(2)": "10",
|
||||
"=DEC2BIN(3)": "11",
|
||||
"=DEC2BIN(2,10)": "0000000010",
|
||||
"=DEC2BIN(-2)": "1111111110",
|
||||
"=DEC2BIN(6)": "110",
|
||||
// DEC2HEX
|
||||
"=DEC2HEX(10)": "A",
|
||||
"=DEC2HEX(31)": "1F",
|
||||
"=DEC2HEX(16,10)": "0000000010",
|
||||
"=DEC2HEX(-16)": "FFFFFFFFF0",
|
||||
"=DEC2HEX(273)": "111",
|
||||
// DEC2OCT
|
||||
"=DEC2OCT(8)": "10",
|
||||
"=DEC2OCT(18)": "22",
|
||||
"=DEC2OCT(8,10)": "0000000010",
|
||||
"=DEC2OCT(-8)": "7777777770",
|
||||
"=DEC2OCT(237)": "355",
|
||||
// ABS
|
||||
"=ABS(-1)": "1",
|
||||
"=ABS(-6.5)": "6.5",
|
||||
|
@ -707,6 +726,31 @@ func TestCalcCellValue(t *testing.T) {
|
|||
}
|
||||
mathCalcError := map[string]string{
|
||||
"=1/0": "#DIV/0!",
|
||||
// Engineering Functions
|
||||
// DEC2BIN
|
||||
"=DEC2BIN()": "DEC2BIN requires at least 1 argument",
|
||||
"=DEC2BIN(1,1,1)": "DEC2BIN allows at most 2 arguments",
|
||||
"=DEC2BIN(\"\",1)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2BIN(1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2BIN(-513,10)": "#NUM!",
|
||||
"=DEC2BIN(1,-1)": "#NUM!",
|
||||
"=DEC2BIN(2,1)": "#NUM!",
|
||||
// DEC2HEX
|
||||
"=DEC2HEX()": "DEC2HEX requires at least 1 argument",
|
||||
"=DEC2HEX(1,1,1)": "DEC2HEX allows at most 2 arguments",
|
||||
"=DEC2HEX(\"\",1)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2HEX(1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2HEX(-549755813888,10)": "#NUM!",
|
||||
"=DEC2HEX(1,-1)": "#NUM!",
|
||||
"=DEC2HEX(31,1)": "#NUM!",
|
||||
// DEC2OCT
|
||||
"=DEC2OCT()": "DEC2OCT requires at least 1 argument",
|
||||
"=DEC2OCT(1,1,1)": "DEC2OCT allows at most 2 arguments",
|
||||
"=DEC2OCT(\"\",1)": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2OCT(1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||
"=DEC2OCT(-536870912 ,10)": "#NUM!",
|
||||
"=DEC2OCT(1,-1)": "#NUM!",
|
||||
"=DEC2OCT(8,1)": "#NUM!",
|
||||
// ABS
|
||||
"=ABS()": "ABS requires 1 numeric argument",
|
||||
`=ABS("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
|
||||
|
|
Loading…
Reference in New Issue