forked from p30928647/excelize
ref #65: new formula functions VALUE and WEEKDAY
This commit is contained in:
parent
ffc998941c
commit
5c4627a0c2
98
calc.go
98
calc.go
|
@ -17,6 +17,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"math/big"
|
||||||
"math/cmplx"
|
"math/cmplx"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -552,9 +553,11 @@ type formulaFuncs struct {
|
||||||
// UNICHAR
|
// UNICHAR
|
||||||
// UNICODE
|
// UNICODE
|
||||||
// UPPER
|
// UPPER
|
||||||
|
// VALUE
|
||||||
// VAR.P
|
// VAR.P
|
||||||
// VARP
|
// VARP
|
||||||
// VLOOKUP
|
// VLOOKUP
|
||||||
|
// WEEKDAY
|
||||||
// WEIBULL
|
// WEIBULL
|
||||||
// WEIBULL.DIST
|
// WEIBULL.DIST
|
||||||
// XOR
|
// XOR
|
||||||
|
@ -7187,6 +7190,63 @@ func daysBetween(startDate, endDate int64) float64 {
|
||||||
return float64(int(0.5 + float64((endDate-startDate)/86400)))
|
return float64(int(0.5 + float64((endDate-startDate)/86400)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WEEKDAY function returns an integer representing the day of the week for a
|
||||||
|
// supplied date. The syntax of the function is:
|
||||||
|
//
|
||||||
|
// WEEKDAY(serial_number,[return_type])
|
||||||
|
//
|
||||||
|
func (fn *formulaFuncs) WEEKDAY(argsList *list.List) formulaArg {
|
||||||
|
if argsList.Len() < 1 {
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, "WEEKDAY requires at least 1 argument")
|
||||||
|
}
|
||||||
|
if argsList.Len() > 2 {
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, "WEEKDAY allows at most 2 arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
sn := argsList.Front().Value.(formulaArg)
|
||||||
|
num := sn.ToNumber()
|
||||||
|
weekday, returnType := 0, 1
|
||||||
|
if num.Type != ArgNumber {
|
||||||
|
dateString := strings.ToLower(sn.Value())
|
||||||
|
if !isDateOnlyFmt(dateString) {
|
||||||
|
if _, _, _, _, _, err := strToTime(dateString); err.Type == ArgError {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y, m, d, _, err := strToDate(dateString)
|
||||||
|
if err.Type == ArgError {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
weekday = int(time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Now().Location()).Weekday())
|
||||||
|
} else {
|
||||||
|
if num.Number < 0 {
|
||||||
|
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
||||||
|
}
|
||||||
|
weekday = int(timeFromExcelTime(num.Number, false).Weekday())
|
||||||
|
}
|
||||||
|
if argsList.Len() == 2 {
|
||||||
|
returnTypeArg := argsList.Back().Value.(formulaArg).ToNumber()
|
||||||
|
if returnTypeArg.Type != ArgNumber {
|
||||||
|
return returnTypeArg
|
||||||
|
}
|
||||||
|
returnType = int(returnTypeArg.Number)
|
||||||
|
}
|
||||||
|
if returnType == 2 {
|
||||||
|
returnType = 11
|
||||||
|
}
|
||||||
|
weekday++
|
||||||
|
if returnType == 1 {
|
||||||
|
return newNumberFormulaArg(float64(weekday))
|
||||||
|
}
|
||||||
|
if returnType == 3 {
|
||||||
|
return newNumberFormulaArg(float64((weekday + 6 - 1) % 7))
|
||||||
|
}
|
||||||
|
if returnType >= 11 && returnType <= 17 {
|
||||||
|
return newNumberFormulaArg(float64((weekday+6-(returnType-10))%7 + 1))
|
||||||
|
}
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||||
|
}
|
||||||
|
|
||||||
// Text Functions
|
// Text Functions
|
||||||
|
|
||||||
// CHAR function returns the character relating to a supplied character set
|
// CHAR function returns the character relating to a supplied character set
|
||||||
|
@ -7831,6 +7891,44 @@ func (fn *formulaFuncs) UPPER(argsList *list.List) formulaArg {
|
||||||
return newStringFormulaArg(strings.ToUpper(argsList.Front().Value.(formulaArg).String))
|
return newStringFormulaArg(strings.ToUpper(argsList.Front().Value.(formulaArg).String))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VALUE function converts a text string into a numeric value. The syntax of
|
||||||
|
// the function is:
|
||||||
|
//
|
||||||
|
// VALUE(text)
|
||||||
|
//
|
||||||
|
func (fn *formulaFuncs) VALUE(argsList *list.List) formulaArg {
|
||||||
|
if argsList.Len() != 1 {
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, "VALUE requires 1 argument")
|
||||||
|
}
|
||||||
|
text := strings.ReplaceAll(argsList.Front().Value.(formulaArg).Value(), ",", "")
|
||||||
|
percent := 1.0
|
||||||
|
if strings.HasSuffix(text, "%") {
|
||||||
|
percent, text = 0.01, strings.TrimSuffix(text, "%")
|
||||||
|
}
|
||||||
|
decimal := big.Float{}
|
||||||
|
if _, ok := decimal.SetString(text); ok {
|
||||||
|
value, _ := decimal.Float64()
|
||||||
|
return newNumberFormulaArg(value * percent)
|
||||||
|
}
|
||||||
|
dateValue, timeValue, errTime, errDate := 0.0, 0.0, false, false
|
||||||
|
if !isDateOnlyFmt(text) {
|
||||||
|
h, m, s, _, _, err := strToTime(text)
|
||||||
|
errTime = err.Type == ArgError
|
||||||
|
if !errTime {
|
||||||
|
timeValue = (float64(h)*3600 + float64(m)*60 + s) / 86400
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y, m, d, _, err := strToDate(text)
|
||||||
|
errDate = err.Type == ArgError
|
||||||
|
if !errDate {
|
||||||
|
dateValue = daysBetween(excelMinTime1900.Unix(), makeDate(y, time.Month(m), d)) + 1
|
||||||
|
}
|
||||||
|
if errTime && errDate {
|
||||||
|
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
||||||
|
}
|
||||||
|
return newNumberFormulaArg(dateValue + timeValue)
|
||||||
|
}
|
||||||
|
|
||||||
// Conditional Functions
|
// Conditional Functions
|
||||||
|
|
||||||
// IF function tests a supplied condition and returns one result if the
|
// IF function tests a supplied condition and returns one result if the
|
||||||
|
|
32
calc_test.go
32
calc_test.go
|
@ -1052,6 +1052,20 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
"=TIME(5,44,32)": "0.239259259259259",
|
"=TIME(5,44,32)": "0.239259259259259",
|
||||||
"=TIME(\"5\",\"44\",\"32\")": "0.239259259259259",
|
"=TIME(\"5\",\"44\",\"32\")": "0.239259259259259",
|
||||||
"=TIME(0,0,73)": "0.000844907407407407",
|
"=TIME(0,0,73)": "0.000844907407407407",
|
||||||
|
// WEEKDAY
|
||||||
|
"=WEEKDAY(0)": "7",
|
||||||
|
"=WEEKDAY(47119)": "2",
|
||||||
|
"=WEEKDAY(\"12/25/2012\")": "3",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",1)": "3",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",2)": "2",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",3)": "1",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",11)": "2",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",12)": "1",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",13)": "7",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",14)": "6",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",15)": "5",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",16)": "4",
|
||||||
|
"=WEEKDAY(\"12/25/2012\",17)": "3",
|
||||||
// Text Functions
|
// Text Functions
|
||||||
// CHAR
|
// CHAR
|
||||||
"=CHAR(65)": "A",
|
"=CHAR(65)": "A",
|
||||||
|
@ -1194,6 +1208,13 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
"=UPPER(\"TEST\")": "TEST",
|
"=UPPER(\"TEST\")": "TEST",
|
||||||
"=UPPER(\"Test\")": "TEST",
|
"=UPPER(\"Test\")": "TEST",
|
||||||
"=UPPER(\"TEST 123\")": "TEST 123",
|
"=UPPER(\"TEST 123\")": "TEST 123",
|
||||||
|
// VALUE
|
||||||
|
"=VALUE(\"50\")": "50",
|
||||||
|
"=VALUE(\"1.0E-07\")": "1e-07",
|
||||||
|
"=VALUE(\"5,000\")": "5000",
|
||||||
|
"=VALUE(\"20%\")": "0.2",
|
||||||
|
"=VALUE(\"12:00:00\")": "0.5",
|
||||||
|
"=VALUE(\"01/02/2006 15:04:05\")": "38719.62783564815",
|
||||||
// Conditional Functions
|
// Conditional Functions
|
||||||
// IF
|
// IF
|
||||||
"=IF(1=1)": "TRUE",
|
"=IF(1=1)": "TRUE",
|
||||||
|
@ -2224,6 +2245,14 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
"=TIME(0,0,-1)": "#NUM!",
|
"=TIME(0,0,-1)": "#NUM!",
|
||||||
// TODAY
|
// TODAY
|
||||||
"=TODAY(A1)": "TODAY accepts no arguments",
|
"=TODAY(A1)": "TODAY accepts no arguments",
|
||||||
|
// WEEKDAY
|
||||||
|
"=WEEKDAY()": "WEEKDAY requires at least 1 argument",
|
||||||
|
"=WEEKDAY(0,1,0)": "WEEKDAY allows at most 2 arguments",
|
||||||
|
"=WEEKDAY(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
|
||||||
|
"=WEEKDAY(\"\",1)": "#VALUE!",
|
||||||
|
"=WEEKDAY(0,0)": "#VALUE!",
|
||||||
|
"=WEEKDAY(\"January 25, 100\")": "#VALUE!",
|
||||||
|
"=WEEKDAY(-1,1)": "#NUM!",
|
||||||
// Text Functions
|
// Text Functions
|
||||||
// CHAR
|
// CHAR
|
||||||
"=CHAR()": "CHAR requires 1 argument",
|
"=CHAR()": "CHAR requires 1 argument",
|
||||||
|
@ -2337,6 +2366,9 @@ func TestCalcCellValue(t *testing.T) {
|
||||||
// UNICODE
|
// UNICODE
|
||||||
"=UNICODE()": "UNICODE requires 1 argument",
|
"=UNICODE()": "UNICODE requires 1 argument",
|
||||||
"=UNICODE(\"\")": "#VALUE!",
|
"=UNICODE(\"\")": "#VALUE!",
|
||||||
|
// VALUE
|
||||||
|
"=VALUE()": "VALUE requires 1 argument",
|
||||||
|
"=VALUE(\"\")": "#VALUE!",
|
||||||
// UPPER
|
// UPPER
|
||||||
"=UPPER()": "UPPER requires 1 argument",
|
"=UPPER()": "UPPER requires 1 argument",
|
||||||
"=UPPER(1,2)": "UPPER requires 1 argument",
|
"=UPPER(1,2)": "UPPER requires 1 argument",
|
||||||
|
|
Loading…
Reference in New Issue