forked from p30928647/excelize
parent
4834a058aa
commit
b812e9a1a8
52
calc.go
52
calc.go
|
@ -116,11 +116,11 @@ var tokenPriority = map[string]int{
|
|||
//
|
||||
// ABS, ACOS, ACOSH, ACOT, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN2, ATANH,
|
||||
// BASE, CEILING, CEILING.MATH, CEILING.PRECISE, COMBIN, COMBINA, COS,
|
||||
// COSH, COT, COTH, COUNTA, CSC, CSCH, DECIMAL, DEGREES, EVEN, EXP, FACT,
|
||||
// FACTDOUBLE, FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT, ISBLANK, ISERR,
|
||||
// ISERROR, ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING, ISODD, LCM,
|
||||
// LN, LOG, LOG10, MDETERM, MEDIAN, MOD, MROUND, MULTINOMIAL, MUNIT, NA,
|
||||
// ODD, OR, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN,
|
||||
// COSH, COT, COTH, COUNTA, CSC, CSCH, DATE, DECIMAL, DEGREES, EVEN, EXP,
|
||||
// FACT, FACTDOUBLE, FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT, ISBLANK,
|
||||
// ISERR, ISERROR, ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING, ISODD,
|
||||
// LCM, LN, LOG, LOG10, MDETERM, MEDIAN, MOD, MROUND, MULTINOMIAL, MUNIT,
|
||||
// NA, ODD, OR, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN,
|
||||
// ROUND, ROUNDDOWN, ROUNDUP, SEC, SECH, SIGN, SIN, SINH, SQRT, SQRTPI,
|
||||
// SUM, SUMIF, SUMSQ, TAN, TANH, TRUNC
|
||||
//
|
||||
|
@ -3308,3 +3308,45 @@ func (fn *formulaFuncs) OR(argsList *list.List) (result string, err error) {
|
|||
result = strings.ToUpper(strconv.FormatBool(or))
|
||||
return
|
||||
}
|
||||
|
||||
// Date and Time Functions
|
||||
|
||||
// DATE returns a date, from a user-supplied year, month and day.
|
||||
func (fn *formulaFuncs) DATE(argsList *list.List) (result string, err error) {
|
||||
if argsList.Len() != 3 {
|
||||
err = errors.New("DATE requires 3 number arguments")
|
||||
return
|
||||
}
|
||||
var year, month, day int
|
||||
if year, err = strconv.Atoi(argsList.Front().Value.(formulaArg).String); err != nil {
|
||||
err = errors.New("DATE requires 3 number arguments")
|
||||
return
|
||||
}
|
||||
if month, err = strconv.Atoi(argsList.Front().Next().Value.(formulaArg).String); err != nil {
|
||||
err = errors.New("DATE requires 3 number arguments")
|
||||
return
|
||||
}
|
||||
if day, err = strconv.Atoi(argsList.Back().Value.(formulaArg).String); err != nil {
|
||||
err = errors.New("DATE requires 3 number arguments")
|
||||
return
|
||||
}
|
||||
d := makeDate(year, time.Month(month), day)
|
||||
result = timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), d)+1, false).String()
|
||||
return
|
||||
}
|
||||
|
||||
// makeDate return date as a Unix time, the number of seconds elapsed since
|
||||
// January 1, 1970 UTC.
|
||||
func makeDate(y int, m time.Month, d int) int64 {
|
||||
if y == 1900 && int(m) <= 2 {
|
||||
d--
|
||||
}
|
||||
date := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
|
||||
return date.Unix()
|
||||
}
|
||||
|
||||
// daysBetween return time interval of the given start timestamp and end
|
||||
// timestamp.
|
||||
func daysBetween(startDate, endDate int64) float64 {
|
||||
return float64(int(0.5 + float64((endDate-startDate)/86400)))
|
||||
}
|
||||
|
|
20
calc_test.go
20
calc_test.go
|
@ -407,14 +407,14 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=TRUNC(99.999,-1)": "90",
|
||||
"=TRUNC(-99.999,2)": "-99.99",
|
||||
"=TRUNC(-99.999,-1)": "-90",
|
||||
// Statistical functions
|
||||
// Statistical Functions
|
||||
// COUNTA
|
||||
`=COUNTA()`: "0",
|
||||
`=COUNTA(A1:A5,B2:B5,"text",1,2)`: "8",
|
||||
// MEDIAN
|
||||
"=MEDIAN(A1:A5,12)": "2",
|
||||
"=MEDIAN(A1:A5)": "1.5",
|
||||
// Information functions
|
||||
// Information Functions
|
||||
// ISBLANK
|
||||
"=ISBLANK(A1)": "FALSE",
|
||||
"=ISBLANK(A5)": "TRUE",
|
||||
|
@ -443,6 +443,7 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=ISODD(A2)": "FALSE",
|
||||
// NA
|
||||
"=NA()": "#N/A",
|
||||
// Logical Functions
|
||||
// AND
|
||||
"=AND(0)": "FALSE",
|
||||
"=AND(1)": "TRUE",
|
||||
|
@ -457,6 +458,10 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=OR(0)": "FALSE",
|
||||
"=OR(1=2,2=2)": "TRUE",
|
||||
"=OR(1=2,2=3)": "FALSE",
|
||||
// Date and Time Functions
|
||||
// DATE
|
||||
"=DATE(2020,10,21)": "2020-10-21 00:00:00 +0000 UTC",
|
||||
"=DATE(1900,1,1)": "1899-12-31 00:00:00 +0000 UTC",
|
||||
}
|
||||
for formula, expected := range mathCalc {
|
||||
f := prepareData()
|
||||
|
@ -732,10 +737,10 @@ func TestCalcCellValue(t *testing.T) {
|
|||
"=TRUNC()": "TRUNC requires at least 1 argument",
|
||||
`=TRUNC("X")`: "#VALUE!",
|
||||
`=TRUNC(1,"X")`: "#VALUE!",
|
||||
// Statistical functions
|
||||
// Statistical Functions
|
||||
// MEDIAN
|
||||
"=MEDIAN()": "MEDIAN requires at least 1 argument",
|
||||
// Information functions
|
||||
// Information Functions
|
||||
// ISBLANK
|
||||
"=ISBLANK(A1,A2)": "ISBLANK requires 1 argument",
|
||||
// ISERR
|
||||
|
@ -756,6 +761,7 @@ func TestCalcCellValue(t *testing.T) {
|
|||
`=ISODD("text")`: "#VALUE!",
|
||||
// NA
|
||||
"=NA(1)": "NA accepts no arguments",
|
||||
// Logical Functions
|
||||
// AND
|
||||
`=AND("text")`: "#VALUE!",
|
||||
`=AND(A1:B1)`: "#VALUE!",
|
||||
|
@ -766,6 +772,12 @@ func TestCalcCellValue(t *testing.T) {
|
|||
`=OR(A1:B1)`: "#VALUE!",
|
||||
"=OR()": "OR requires at least 1 argument",
|
||||
"=OR(1" + strings.Repeat(",1", 30) + ")": "OR accepts at most 30 arguments",
|
||||
// Date and Time Functions
|
||||
// DATE
|
||||
"=DATE()": "DATE requires 3 number arguments",
|
||||
`=DATE("text",10,21)`: "DATE requires 3 number arguments",
|
||||
`=DATE(2020,"text",21)`: "DATE requires 3 number arguments",
|
||||
`=DATE(2020,10,"text")`: "DATE requires 3 number arguments",
|
||||
}
|
||||
for formula, expected := range mathCalcError {
|
||||
f := prepareData()
|
||||
|
|
8
sheet.go
8
sheet.go
|
@ -31,10 +31,10 @@ import (
|
|||
"github.com/mohae/deepcopy"
|
||||
)
|
||||
|
||||
// NewSheet provides function to create a new sheet by given worksheet name.
|
||||
// When creating a new spreadsheet file, the default worksheet will be
|
||||
// created. Returns the number of sheets in the workbook (file) after
|
||||
// appending the new sheet.
|
||||
// NewSheet provides the function to create a new sheet by given a worksheet
|
||||
// name and returns the index of the sheets in the workbook
|
||||
// (spreadsheet) after it appended. Note that when creating a new spreadsheet
|
||||
// file, the default worksheet named `Sheet1` will be created.
|
||||
func (f *File) NewSheet(name string) int {
|
||||
// Check if the worksheet already exists
|
||||
index := f.GetSheetIndex(name)
|
||||
|
|
Loading…
Reference in New Issue