calc_test.go 62.4 KB
Newer Older
1 2 3
package excelize

import (
4
	"container/list"
xurime's avatar
xurime 已提交
5
	"path/filepath"
6
	"strings"
7 8 9
	"testing"

	"github.com/stretchr/testify/assert"
10
	"github.com/xuri/efp"
11 12
)

13 14 15 16 17
func prepareCalcData(cellData [][]interface{}) *File {
	f := NewFile()
	for r, row := range cellData {
		for c, value := range row {
			cell, _ := CoordinatesToCellName(c+1, r+1)
18
			_ = f.SetCellValue("Sheet1", cell, value)
19 20 21 22 23
		}
	}
	return f
}

24
func TestCalcCellValue(t *testing.T) {
xurime's avatar
xurime 已提交
25 26 27 28 29 30 31 32 33 34 35
	cellData := [][]interface{}{
		{1, 4, nil, "Month", "Team", "Sales"},
		{2, 5, nil, "Jan", "North 1", 36693},
		{3, nil, nil, "Jan", "North 2", 22100},
		{0, nil, nil, "Jan", "South 1", 53321},
		{nil, nil, nil, "Jan", "South 2", 34440},
		{nil, nil, nil, "Feb", "North 1", 29889},
		{nil, nil, nil, "Feb", "North 2", 50090},
		{nil, nil, nil, "Feb", "South 1", 32080},
		{nil, nil, nil, "Feb", "South 2", 45500},
	}
36
	mathCalc := map[string]string{
37 38 39 40 41 42 43 44 45 46 47 48
		"=2^3":  "8",
		"=1=1":  "TRUE",
		"=1=2":  "FALSE",
		"=1<2":  "TRUE",
		"=3<2":  "FALSE",
		"=2<=3": "TRUE",
		"=2<=1": "FALSE",
		"=2>1":  "TRUE",
		"=2>3":  "FALSE",
		"=2>=1": "TRUE",
		"=2>=3": "FALSE",
		"=1&2":  "12",
xurime's avatar
xurime 已提交
49
		// Engineering Functions
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
		// BIN2DEC
		"=BIN2DEC(\"10\")":         "2",
		"=BIN2DEC(\"11\")":         "3",
		"=BIN2DEC(\"0000000010\")": "2",
		"=BIN2DEC(\"1111111110\")": "-2",
		"=BIN2DEC(\"110\")":        "6",
		// BIN2HEX
		"=BIN2HEX(\"10\")":         "2",
		"=BIN2HEX(\"0000000001\")": "1",
		"=BIN2HEX(\"10\",10)":      "0000000002",
		"=BIN2HEX(\"1111111110\")": "FFFFFFFFFE",
		"=BIN2HEX(\"11101\")":      "1D",
		// BIN2OCT
		"=BIN2OCT(\"101\")":        "5",
		"=BIN2OCT(\"0000000001\")": "1",
		"=BIN2OCT(\"10\",10)":      "0000000002",
		"=BIN2OCT(\"1111111110\")": "7777777776",
		"=BIN2OCT(\"1110\")":       "16",
68 69 70 71 72 73 74 75 76 77 78 79 80
		// 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",
xurime's avatar
xurime 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
		// 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",
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
		// HEX2BIN
		"=HEX2BIN(\"2\")":          "10",
		"=HEX2BIN(\"0000000001\")": "1",
		"=HEX2BIN(\"2\",10)":       "0000000010",
		"=HEX2BIN(\"F0\")":         "11110000",
		"=HEX2BIN(\"1D\")":         "11101",
		// HEX2DEC
		"=HEX2DEC(\"A\")":          "10",
		"=HEX2DEC(\"1F\")":         "31",
		"=HEX2DEC(\"0000000010\")": "16",
		"=HEX2DEC(\"FFFFFFFFF0\")": "-16",
		"=HEX2DEC(\"111\")":        "273",
		"=HEX2DEC(\"\")":           "0",
		// HEX2OCT
		"=HEX2OCT(\"A\")":          "12",
		"=HEX2OCT(\"000000000F\")": "17",
		"=HEX2OCT(\"8\",10)":       "0000000010",
		"=HEX2OCT(\"FFFFFFFFF8\")": "7777777770",
		"=HEX2OCT(\"1F3\")":        "763",
		// OCT2BIN
		"=OCT2BIN(\"5\")":          "101",
		"=OCT2BIN(\"0000000001\")": "1",
		"=OCT2BIN(\"2\",10)":       "0000000010",
		"=OCT2BIN(\"7777777770\")": "1111111000",
		"=OCT2BIN(\"16\")":         "1110",
		// OCT2DEC
		"=OCT2DEC(\"10\")":         "8",
		"=OCT2DEC(\"22\")":         "18",
		"=OCT2DEC(\"0000000010\")": "8",
		"=OCT2DEC(\"7777777770\")": "-8",
		"=OCT2DEC(\"355\")":        "237",
		// OCT2HEX
		"=OCT2HEX(\"10\")":         "8",
		"=OCT2HEX(\"0000000007\")": "7",
		"=OCT2HEX(\"10\",10)":      "0000000008",
		"=OCT2HEX(\"7777777770\")": "FFFFFFFFF8",
		"=OCT2HEX(\"763\")":        "1F3",
		// Math and Trigonometric Functions
137
		// ABS
138 139 140 141 142 143
		"=ABS(-1)":      "1",
		"=ABS(-6.5)":    "6.5",
		"=ABS(6.5)":     "6.5",
		"=ABS(0)":       "0",
		"=ABS(2-4.5)":   "2.5",
		"=ABS(ABS(-1))": "1",
144
		// ACOS
145 146 147
		"=ACOS(-1)":     "3.141592653589793",
		"=ACOS(0)":      "1.570796326794897",
		"=ACOS(ABS(0))": "1.570796326794897",
148
		// ACOSH
149 150 151 152
		"=ACOSH(1)":        "0",
		"=ACOSH(2.5)":      "1.566799236972411",
		"=ACOSH(5)":        "2.292431669561178",
		"=ACOSH(ACOSH(5))": "1.471383321536679",
153
		// ACOT
154 155 156 157
		"=_xlfn.ACOT(1)":             "0.785398163397448",
		"=_xlfn.ACOT(-2)":            "2.677945044588987",
		"=_xlfn.ACOT(0)":             "1.570796326794897",
		"=_xlfn.ACOT(_xlfn.ACOT(0))": "0.566911504941009",
158
		// ACOTH
159 160 161 162
		"=_xlfn.ACOTH(-5)":      "-0.202732554054082",
		"=_xlfn.ACOTH(1.1)":     "1.522261218861711",
		"=_xlfn.ACOTH(2)":       "0.549306144334055",
		"=_xlfn.ACOTH(ABS(-2))": "0.549306144334055",
163 164 165 166 167 168
		// ARABIC
		`=_xlfn.ARABIC("IV")`:   "4",
		`=_xlfn.ARABIC("-IV")`:  "-4",
		`=_xlfn.ARABIC("MCXX")`: "1120",
		`=_xlfn.ARABIC("")`:     "0",
		// ASIN
169 170 171
		"=ASIN(-1)":      "-1.570796326794897",
		"=ASIN(0)":       "0",
		"=ASIN(ASIN(0))": "0",
172
		// ASINH
173 174 175 176
		"=ASINH(0)":        "0",
		"=ASINH(-0.5)":     "-0.481211825059604",
		"=ASINH(2)":        "1.44363547517881",
		"=ASINH(ASINH(0))": "0",
177
		// ATAN
178 179 180 181
		"=ATAN(-1)":      "-0.785398163397448",
		"=ATAN(0)":       "0",
		"=ATAN(1)":       "0.785398163397448",
		"=ATAN(ATAN(0))": "0",
182
		// ATANH
183 184 185 186
		"=ATANH(-0.8)":     "-1.09861228866811",
		"=ATANH(0)":        "0",
		"=ATANH(0.5)":      "0.549306144334055",
		"=ATANH(ATANH(0))": "0",
187
		// ATAN2
188 189 190 191
		"=ATAN2(1,1)":          "0.785398163397448",
		"=ATAN2(1,-1)":         "-0.785398163397448",
		"=ATAN2(4,0)":          "0",
		"=ATAN2(4,ATAN2(4,0))": "0",
192
		// BASE
193 194 195 196
		"=BASE(12,2)":          "1100",
		"=BASE(12,2,8)":        "00001100",
		"=BASE(100000,16)":     "186A0",
		"=BASE(BASE(12,2),16)": "44C",
xurime's avatar
xurime 已提交
197
		// CEILING
198 199 200 201 202 203 204 205 206 207
		"=CEILING(22.25,0.1)":              "22.3",
		"=CEILING(22.25,0.5)":              "22.5",
		"=CEILING(22.25,1)":                "23",
		"=CEILING(22.25,10)":               "30",
		"=CEILING(22.25,20)":               "40",
		"=CEILING(-22.25,-0.1)":            "-22.3",
		"=CEILING(-22.25,-1)":              "-23",
		"=CEILING(-22.25,-5)":              "-25",
		"=CEILING(22.25)":                  "23",
		"=CEILING(CEILING(22.25,0.1),0.1)": "22.3",
xurime's avatar
xurime 已提交
208
		// _xlfn.CEILING.MATH
209 210 211 212 213 214 215 216 217
		"=_xlfn.CEILING.MATH(15.25,1)":                       "16",
		"=_xlfn.CEILING.MATH(15.25,0.1)":                     "15.3",
		"=_xlfn.CEILING.MATH(15.25,5)":                       "20",
		"=_xlfn.CEILING.MATH(-15.25,1)":                      "-15",
		"=_xlfn.CEILING.MATH(-15.25,1,1)":                    "-15", // should be 16
		"=_xlfn.CEILING.MATH(-15.25,10)":                     "-10",
		"=_xlfn.CEILING.MATH(-15.25)":                        "-15",
		"=_xlfn.CEILING.MATH(-15.25,-5,-1)":                  "-10",
		"=_xlfn.CEILING.MATH(_xlfn.CEILING.MATH(15.25,1),1)": "16",
218
		// _xlfn.CEILING.PRECISE
219 220 221 222 223 224 225 226 227 228
		"=_xlfn.CEILING.PRECISE(22.25,0.1)":                          "22.3",
		"=_xlfn.CEILING.PRECISE(22.25,0.5)":                          "22.5",
		"=_xlfn.CEILING.PRECISE(22.25,1)":                            "23",
		"=_xlfn.CEILING.PRECISE(22.25)":                              "23",
		"=_xlfn.CEILING.PRECISE(22.25,10)":                           "30",
		"=_xlfn.CEILING.PRECISE(22.25,0)":                            "0",
		"=_xlfn.CEILING.PRECISE(-22.25,1)":                           "-22",
		"=_xlfn.CEILING.PRECISE(-22.25,-1)":                          "-22",
		"=_xlfn.CEILING.PRECISE(-22.25,5)":                           "-20",
		"=_xlfn.CEILING.PRECISE(_xlfn.CEILING.PRECISE(22.25,0.1),5)": "25",
229
		// COMBIN
230 231 232 233 234 235 236 237
		"=COMBIN(6,1)":           "6",
		"=COMBIN(6,2)":           "15",
		"=COMBIN(6,3)":           "20",
		"=COMBIN(6,4)":           "15",
		"=COMBIN(6,5)":           "6",
		"=COMBIN(6,6)":           "1",
		"=COMBIN(0,0)":           "1",
		"=COMBIN(6,COMBIN(0,0))": "6",
238
		// _xlfn.COMBINA
239 240 241 242 243 244 245 246
		"=_xlfn.COMBINA(6,1)":                  "6",
		"=_xlfn.COMBINA(6,2)":                  "21",
		"=_xlfn.COMBINA(6,3)":                  "56",
		"=_xlfn.COMBINA(6,4)":                  "126",
		"=_xlfn.COMBINA(6,5)":                  "252",
		"=_xlfn.COMBINA(6,6)":                  "462",
		"=_xlfn.COMBINA(0,0)":                  "0",
		"=_xlfn.COMBINA(0,_xlfn.COMBINA(0,0))": "0",
247 248 249
		// COS
		"=COS(0.785398163)": "0.707106781467586",
		"=COS(0)":           "1",
250
		"=COS(COS(0))":      "0.54030230586814",
251
		// COSH
252 253 254 255
		"=COSH(0)":       "1",
		"=COSH(0.5)":     "1.127625965206381",
		"=COSH(-2)":      "3.762195691083632",
		"=COSH(COSH(0))": "1.543080634815244",
256
		// _xlfn.COT
257 258
		"=_xlfn.COT(0.785398163397448)": "1.000000000000001",
		"=_xlfn.COT(_xlfn.COT(0.45))":   "-0.545473116787229",
259
		// _xlfn.COTH
260 261
		"=_xlfn.COTH(-3.14159265358979)": "-1.003741873197322",
		"=_xlfn.COTH(_xlfn.COTH(1))":     "1.156014018113954",
262
		// _xlfn.CSC
263
		"=_xlfn.CSC(-6)":              "3.578899547254406",
264
		"=_xlfn.CSC(1.5707963267949)": "1",
265
		"=_xlfn.CSC(_xlfn.CSC(1))":    "1.077851840310882",
266
		// _xlfn.CSCH
267
		"=_xlfn.CSCH(-3.14159265358979)": "-0.086589537530047",
xurime's avatar
xurime 已提交
268
		"=_xlfn.CSCH(_xlfn.CSCH(1))":     "1.044510103955183",
269
		// _xlfn.DECIMAL
xurime's avatar
xurime 已提交
270 271 272 273 274
		`=_xlfn.DECIMAL("1100",2)`:    "12",
		`=_xlfn.DECIMAL("186A0",16)`:  "100000",
		`=_xlfn.DECIMAL("31L0",32)`:   "100000",
		`=_xlfn.DECIMAL("70122",8)`:   "28754",
		`=_xlfn.DECIMAL("0x70122",8)`: "28754",
275
		// DEGREES
xurime's avatar
xurime 已提交
276 277 278
		"=DEGREES(1)":          "57.29577951308232",
		"=DEGREES(2.5)":        "143.2394487827058",
		"=DEGREES(DEGREES(1))": "3282.806350011744",
279 280 281 282 283 284 285
		// EVEN
		"=EVEN(23)":   "24",
		"=EVEN(2.22)": "4",
		"=EVEN(0)":    "0",
		"=EVEN(-0.3)": "-2",
		"=EVEN(-11)":  "-12",
		"=EVEN(-4)":   "-4",
xurime's avatar
xurime 已提交
286
		"=EVEN((0))":  "0",
287
		// EXP
xurime's avatar
xurime 已提交
288 289 290 291 292
		"=EXP(100)":    "2.6881171418161356E+43",
		"=EXP(0.1)":    "1.105170918075648",
		"=EXP(0)":      "1",
		"=EXP(-5)":     "0.006737946999085",
		"=EXP(EXP(0))": "2.718281828459045",
293
		// FACT
xurime's avatar
xurime 已提交
294 295
		"=FACT(3)":       "6",
		"=FACT(6)":       "720",
296
		"=FACT(10)":      "3.6288e+06",
xurime's avatar
xurime 已提交
297
		"=FACT(FACT(3))": "720",
298
		// FACTDOUBLE
xurime's avatar
xurime 已提交
299 300 301 302
		"=FACTDOUBLE(5)":             "15",
		"=FACTDOUBLE(8)":             "384",
		"=FACTDOUBLE(13)":            "135135",
		"=FACTDOUBLE(FACTDOUBLE(1))": "1",
303
		// FLOOR
xurime's avatar
xurime 已提交
304 305 306 307 308 309 310 311 312
		"=FLOOR(26.75,0.1)":        "26.700000000000003",
		"=FLOOR(26.75,0.5)":        "26.5",
		"=FLOOR(26.75,1)":          "26",
		"=FLOOR(26.75,10)":         "20",
		"=FLOOR(26.75,20)":         "20",
		"=FLOOR(-26.75,-0.1)":      "-26.700000000000003",
		"=FLOOR(-26.75,-1)":        "-26",
		"=FLOOR(-26.75,-5)":        "-25",
		"=FLOOR(FLOOR(26.75,1),1)": "26",
313
		// _xlfn.FLOOR.MATH
xurime's avatar
xurime 已提交
314 315 316 317 318 319 320 321 322
		"=_xlfn.FLOOR.MATH(58.55)":                  "58",
		"=_xlfn.FLOOR.MATH(58.55,0.1)":              "58.5",
		"=_xlfn.FLOOR.MATH(58.55,5)":                "55",
		"=_xlfn.FLOOR.MATH(58.55,1,1)":              "58",
		"=_xlfn.FLOOR.MATH(-58.55,1)":               "-59",
		"=_xlfn.FLOOR.MATH(-58.55,1,-1)":            "-58",
		"=_xlfn.FLOOR.MATH(-58.55,1,1)":             "-59", // should be -58
		"=_xlfn.FLOOR.MATH(-58.55,10)":              "-60",
		"=_xlfn.FLOOR.MATH(_xlfn.FLOOR.MATH(1),10)": "0",
323
		// _xlfn.FLOOR.PRECISE
xurime's avatar
xurime 已提交
324 325 326 327 328 329 330 331 332 333
		"=_xlfn.FLOOR.PRECISE(26.75,0.1)":                     "26.700000000000003",
		"=_xlfn.FLOOR.PRECISE(26.75,0.5)":                     "26.5",
		"=_xlfn.FLOOR.PRECISE(26.75,1)":                       "26",
		"=_xlfn.FLOOR.PRECISE(26.75)":                         "26",
		"=_xlfn.FLOOR.PRECISE(26.75,10)":                      "20",
		"=_xlfn.FLOOR.PRECISE(26.75,0)":                       "0",
		"=_xlfn.FLOOR.PRECISE(-26.75,1)":                      "-27",
		"=_xlfn.FLOOR.PRECISE(-26.75,-1)":                     "-27",
		"=_xlfn.FLOOR.PRECISE(-26.75,-5)":                     "-30",
		"=_xlfn.FLOOR.PRECISE(_xlfn.FLOOR.PRECISE(26.75),-5)": "25",
334
		// GCD
xurime's avatar
xurime 已提交
335 336
		"=GCD(0)":        "0",
		"=GCD(1,0)":      "1",
337 338 339 340
		"=GCD(1,5)":      "1",
		"=GCD(15,10,25)": "5",
		"=GCD(0,8,12)":   "4",
		"=GCD(7,2)":      "1",
xurime's avatar
xurime 已提交
341
		"=GCD(1,GCD(1))": "1",
342 343 344 345 346 347
		// INT
		"=INT(100.9)":  "100",
		"=INT(5.22)":   "5",
		"=INT(5.99)":   "5",
		"=INT(-6.1)":   "-7",
		"=INT(-100.9)": "-101",
xurime's avatar
xurime 已提交
348
		"=INT(INT(0))": "0",
349
		// ISO.CEILING
xurime's avatar
xurime 已提交
350 351 352 353 354 355 356 357 358
		"=ISO.CEILING(22.25)":              "23",
		"=ISO.CEILING(22.25,1)":            "23",
		"=ISO.CEILING(22.25,0.1)":          "22.3",
		"=ISO.CEILING(22.25,10)":           "30",
		"=ISO.CEILING(-22.25,1)":           "-22",
		"=ISO.CEILING(-22.25,0.1)":         "-22.200000000000003",
		"=ISO.CEILING(-22.25,5)":           "-20",
		"=ISO.CEILING(-22.25,0)":           "0",
		"=ISO.CEILING(1,ISO.CEILING(1,0))": "0",
359
		// LCM
xurime's avatar
xurime 已提交
360 361 362 363 364 365 366 367
		"=LCM(1,5)":        "5",
		"=LCM(15,10,25)":   "150",
		"=LCM(1,8,12)":     "24",
		"=LCM(7,2)":        "14",
		"=LCM(7)":          "7",
		`=LCM("",1)`:       "1",
		`=LCM(0,0)`:        "0",
		`=LCM(0,LCM(0,0))`: "0",
368
		// LN
xurime's avatar
xurime 已提交
369 370 371 372
		"=LN(1)":       "0",
		"=LN(100)":     "4.605170185988092",
		"=LN(0.5)":     "-0.693147180559945",
		"=LN(LN(100))": "1.527179625807901",
373
		// LOG
xurime's avatar
xurime 已提交
374 375 376 377 378
		"=LOG(64,2)":     "6",
		"=LOG(100)":      "2",
		"=LOG(4,0.5)":    "-2",
		"=LOG(500)":      "2.698970004336019",
		"=LOG(LOG(100))": "0.301029995663981",
379
		// LOG10
xurime's avatar
xurime 已提交
380 381 382 383 384
		"=LOG10(100)":        "2",
		"=LOG10(1000)":       "3",
		"=LOG10(0.001)":      "-3",
		"=LOG10(25)":         "1.397940008672038",
		"=LOG10(LOG10(100))": "0.301029995663981",
385
		// MOD
xurime's avatar
xurime 已提交
386 387 388 389 390 391
		"=MOD(6,4)":        "2",
		"=MOD(6,3)":        "0",
		"=MOD(6,2.5)":      "1",
		"=MOD(6,1.333)":    "0.668",
		"=MOD(-10.23,1)":   "0.77",
		"=MOD(MOD(1,1),1)": "0",
392
		// MROUND
xurime's avatar
xurime 已提交
393 394 395 396 397 398 399 400 401
		"=MROUND(333.7,0.5)":     "333.5",
		"=MROUND(333.8,1)":       "334",
		"=MROUND(333.3,2)":       "334",
		"=MROUND(555.3,400)":     "400",
		"=MROUND(555,1000)":      "1000",
		"=MROUND(-555.7,-1)":     "-556",
		"=MROUND(-555.4,-1)":     "-555",
		"=MROUND(-1555,-1000)":   "-2000",
		"=MROUND(MROUND(1,1),1)": "1",
402
		// MULTINOMIAL
xurime's avatar
xurime 已提交
403 404 405
		"=MULTINOMIAL(3,1,2,5)":        "27720",
		`=MULTINOMIAL("",3,1,2,5)`:     "27720",
		"=MULTINOMIAL(MULTINOMIAL(1))": "1",
406
		// _xlfn.MUNIT
407
		"=_xlfn.MUNIT(4)": "",
408 409 410 411 412 413 414 415
		// ODD
		"=ODD(22)":     "23",
		"=ODD(1.22)":   "3",
		"=ODD(1.22+4)": "7",
		"=ODD(0)":      "1",
		"=ODD(-1.3)":   "-3",
		"=ODD(-10)":    "-11",
		"=ODD(-3)":     "-3",
xurime's avatar
xurime 已提交
416
		"=ODD(ODD(1))": "1",
417 418
		// PI
		"=PI()": "3.141592653589793",
419
		// POWER
xurime's avatar
xurime 已提交
420 421
		"=POWER(4,2)":          "16",
		"=POWER(4,POWER(1,1))": "4",
422
		// PRODUCT
xurime's avatar
xurime 已提交
423 424 425
		"=PRODUCT(3,6)":            "18",
		`=PRODUCT("",3,6)`:         "18",
		`=PRODUCT(PRODUCT(1),3,6)`: "18",
426
		// QUOTIENT
xurime's avatar
xurime 已提交
427 428 429 430
		"=QUOTIENT(5,2)":             "2",
		"=QUOTIENT(4.5,3.1)":         "1",
		"=QUOTIENT(-10,3)":           "-3",
		"=QUOTIENT(QUOTIENT(1,2),3)": "0",
431
		// RADIANS
xurime's avatar
xurime 已提交
432 433 434 435 436
		"=RADIANS(50)":           "0.872664625997165",
		"=RADIANS(-180)":         "-3.141592653589793",
		"=RADIANS(180)":          "3.141592653589793",
		"=RADIANS(360)":          "6.283185307179586",
		"=RADIANS(RADIANS(360))": "0.109662271123215",
437
		// ROMAN
xurime's avatar
xurime 已提交
438 439 440 441 442 443 444 445 446
		"=ROMAN(499,0)":       "CDXCIX",
		"=ROMAN(1999,0)":      "MCMXCIX",
		"=ROMAN(1999,1)":      "MLMVLIV",
		"=ROMAN(1999,2)":      "MXMIX",
		"=ROMAN(1999,3)":      "MVMIV",
		"=ROMAN(1999,4)":      "MIM",
		"=ROMAN(1999,-1)":     "MCMXCIX",
		"=ROMAN(1999,5)":      "MIM",
		"=ROMAN(1999,ODD(1))": "MLMVLIV",
447
		// ROUND
xurime's avatar
xurime 已提交
448 449 450 451 452 453 454 455 456 457
		"=ROUND(100.319,1)":       "100.30000000000001",
		"=ROUND(5.28,1)":          "5.300000000000001",
		"=ROUND(5.9999,3)":        "6.000000000000002",
		"=ROUND(99.5,0)":          "100",
		"=ROUND(-6.3,0)":          "-6",
		"=ROUND(-100.5,0)":        "-101",
		"=ROUND(-22.45,1)":        "-22.5",
		"=ROUND(999,-1)":          "1000",
		"=ROUND(991,-1)":          "990",
		"=ROUND(ROUND(100,1),-1)": "100",
458
		// ROUNDDOWN
xurime's avatar
xurime 已提交
459 460 461 462 463 464 465
		"=ROUNDDOWN(99.999,1)":            "99.9",
		"=ROUNDDOWN(99.999,2)":            "99.99000000000002",
		"=ROUNDDOWN(99.999,0)":            "99",
		"=ROUNDDOWN(99.999,-1)":           "90",
		"=ROUNDDOWN(-99.999,2)":           "-99.99000000000002",
		"=ROUNDDOWN(-99.999,-1)":          "-90",
		"=ROUNDDOWN(ROUNDDOWN(100,1),-1)": "100",
466
		// ROUNDUP`
xurime's avatar
xurime 已提交
467 468 469 470 471 472 473
		"=ROUNDUP(11.111,1)":          "11.200000000000001",
		"=ROUNDUP(11.111,2)":          "11.120000000000003",
		"=ROUNDUP(11.111,0)":          "12",
		"=ROUNDUP(11.111,-1)":         "20",
		"=ROUNDUP(-11.111,2)":         "-11.120000000000003",
		"=ROUNDUP(-11.111,-1)":        "-20",
		"=ROUNDUP(ROUNDUP(100,1),-1)": "100",
474 475 476
		// SEC
		"=_xlfn.SEC(-3.14159265358979)": "-1",
		"=_xlfn.SEC(0)":                 "1",
xurime's avatar
xurime 已提交
477
		"=_xlfn.SEC(_xlfn.SEC(0))":      "0.54030230586814",
478
		// SECH
479
		"=_xlfn.SECH(-3.14159265358979)": "0.086266738334055",
480
		"=_xlfn.SECH(0)":                 "1",
xurime's avatar
xurime 已提交
481
		"=_xlfn.SECH(_xlfn.SECH(0))":     "0.648054273663886",
482 483 484 485 486 487
		// SIGN
		"=SIGN(9.5)":        "1",
		"=SIGN(-9.5)":       "-1",
		"=SIGN(0)":          "0",
		"=SIGN(0.00000001)": "1",
		"=SIGN(6-7)":        "-1",
xurime's avatar
xurime 已提交
488
		"=SIGN(SIGN(-1))":   "-1",
489
		// SIN
490
		"=SIN(0.785398163)": "0.707106780905509",
xurime's avatar
xurime 已提交
491
		"=SIN(SIN(1))":      "0.745624141665558",
492
		// SINH
xurime's avatar
xurime 已提交
493 494 495 496
		"=SINH(0)":       "0",
		"=SINH(0.5)":     "0.521095305493747",
		"=SINH(-2)":      "-3.626860407847019",
		"=SINH(SINH(0))": "0",
497
		// SQRT
xurime's avatar
xurime 已提交
498 499
		"=SQRT(4)":        "2",
		"=SQRT(SQRT(16))": "2",
500
		// SQRTPI
xurime's avatar
xurime 已提交
501 502 503 504 505
		"=SQRTPI(5)":         "3.963327297606011",
		"=SQRTPI(0.2)":       "0.792665459521202",
		"=SQRTPI(100)":       "17.72453850905516",
		"=SQRTPI(0)":         "0",
		"=SQRTPI(SQRTPI(0))": "0",
xurime's avatar
xurime 已提交
506 507 508 509 510 511 512 513 514
		// STDEV
		"=STDEV(F2:F9)":         "10724.978287523809",
		"=STDEV(MUNIT(2))":      "0.577350269189626",
		"=STDEV(0,INT(0))":      "0",
		"=STDEV(INT(1),INT(1))": "0",
		// STDEVA
		"=STDEVA(F2:F9)":    "10724.978287523809",
		"=STDEVA(MUNIT(2))": "0.577350269189626",
		"=STDEVA(0,INT(0))": "0",
515
		// SUM
516
		"=SUM(1,2)":                           "3",
xurime's avatar
xurime 已提交
517
		`=SUM("",1,2)`:                        "3",
518 519 520 521 522 523 524 525 526 527 528 529
		"=SUM(1,2+3)":                         "6",
		"=SUM(SUM(1,2),2)":                    "5",
		"=(-2-SUM(-4+7))*5":                   "-25",
		"SUM(1,2,3,4,5,6,7)":                  "28",
		"=SUM(1,2)+SUM(1,2)":                  "6",
		"=1+SUM(SUM(1,2*3),4)":                "12",
		"=1+SUM(SUM(1,-2*3),4)":               "0",
		"=(-2-SUM(-4*(7+7)))*5":               "270",
		"=SUM(SUM(1+2/1)*2-3/2,2)":            "6.5",
		"=((3+5*2)+3)/5+(-6)/4*2+3":           "3.2",
		"=1+SUM(SUM(1,2*3),4)*-4/2+5+(4+2)*3": "2",
		"=1+SUM(SUM(1,2*3),4)*4/3+5+(4+2)*3":  "38.666666666666664",
xurime's avatar
xurime 已提交
530
		// SUMIF
531 532 533 534 535
		`=SUMIF(F1:F5, "")`:             "0",
		`=SUMIF(A1:A5, "3")`:            "3",
		`=SUMIF(F1:F5, "=36693")`:       "36693",
		`=SUMIF(F1:F5, "<100")`:         "0",
		`=SUMIF(F1:F5, "<=36693")`:      "93233",
xurime's avatar
xurime 已提交
536
		`=SUMIF(F1:F5, ">100")`:         "146554",
537 538 539
		`=SUMIF(F1:F5, ">=100")`:        "146554",
		`=SUMIF(F1:F5, ">=text")`:       "0",
		`=SUMIF(F1:F5, "*Jan",F2:F5)`:   "0",
xurime's avatar
xurime 已提交
540 541 542 543
		`=SUMIF(D3:D7,"Jan",F2:F5)`:     "112114",
		`=SUMIF(D2:D9,"Feb",F2:F9)`:     "157559",
		`=SUMIF(E2:E9,"North 1",F2:F9)`: "66582",
		`=SUMIF(E2:E9,"North*",F2:F9)`:  "138772",
xurime's avatar
xurime 已提交
544
		// SUMSQ
xurime's avatar
xurime 已提交
545 546 547
		"=SUMSQ(A1:A4)":            "14",
		"=SUMSQ(A1,B1,A2,B2,6)":    "82",
		`=SUMSQ("",A1,B1,A2,B2,6)`: "82",
xurime's avatar
xurime 已提交
548
		`=SUMSQ(1,SUMSQ(1))`:       "2",
xurime's avatar
xurime 已提交
549
		"=SUMSQ(MUNIT(3))":         "0",
550 551 552
		// TAN
		"=TAN(1.047197551)": "1.732050806782486",
		"=TAN(0)":           "0",
xurime's avatar
xurime 已提交
553
		"=TAN(TAN(0))":      "0",
554
		// TANH
xurime's avatar
xurime 已提交
555 556 557 558
		"=TANH(0)":       "0",
		"=TANH(0.5)":     "0.46211715726001",
		"=TANH(-2)":      "-0.964027580075817",
		"=TANH(TANH(0))": "0",
559
		// TRUNC
xurime's avatar
xurime 已提交
560 561 562 563 564 565 566
		"=TRUNC(99.999,1)":    "99.9",
		"=TRUNC(99.999,2)":    "99.99",
		"=TRUNC(99.999)":      "99",
		"=TRUNC(99.999,-1)":   "90",
		"=TRUNC(-99.999,2)":   "-99.99",
		"=TRUNC(-99.999,-1)":  "-90",
		"=TRUNC(TRUNC(1),-1)": "0",
567
		// Statistical Functions
568 569 570 571 572 573 574 575 576 577 578 579 580
		// AVERAGE
		"=AVERAGE(INT(1))": "1",
		"=AVERAGE(A1)":     "1",
		"=AVERAGE(A1:A2)":  "1.5",
		"=AVERAGE(D2:F9)":  "38014.125",
		// AVERAGEA
		"=AVERAGEA(INT(1))": "1",
		"=AVERAGEA(A1)":     "1",
		"=AVERAGEA(A1:A2)":  "1.5",
		"=AVERAGEA(D2:F9)":  "12671.375",
		// COUNT
		"=COUNT()":                        "0",
		"=COUNT(E1:F2,\"text\",1,INT(2))": "3",
xurime's avatar
xurime 已提交
581
		// COUNTA
582 583 584 585 586 587 588 589
		"=COUNTA()":                              "0",
		"=COUNTA(A1:A5,B2:B5,\"text\",1,INT(2))": "8",
		"=COUNTA(COUNTA(1),MUNIT(1))":            "2",
		// COUNTBLANK
		"=COUNTBLANK(MUNIT(1))": "0",
		"=COUNTBLANK(1)":        "0",
		"=COUNTBLANK(B1:C1)":    "1",
		"=COUNTBLANK(C1)":       "1",
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
		// FISHER
		"=FISHER(-0.9)":   "-1.47221948958322",
		"=FISHER(-0.25)":  "-0.255412811882995",
		"=FISHER(0.8)":    "1.09861228866811",
		"=FISHER(INT(0))": "0",
		// FISHERINV
		"=FISHERINV(-0.2)":   "-0.197375320224904",
		"=FISHERINV(INT(0))": "0",
		"=FISHERINV(2.8)":    "0.992631520201128",
		// GAMMA
		"=GAMMA(0.1)":    "9.513507698668732",
		"=GAMMA(INT(1))": "1",
		"=GAMMA(1.5)":    "0.886226925452758",
		"=GAMMA(5.5)":    "52.34277778455352",
		// GAMMALN
		"=GAMMALN(4.5)":    "2.453736570842443",
		"=GAMMALN(INT(1))": "0",
xurime's avatar
xurime 已提交
607 608 609 610
		// KURT
		"=KURT(F1:F9)":           "-1.033503502551368",
		"=KURT(F1,F2:F9)":        "-1.033503502551368",
		"=KURT(INT(1),MUNIT(2))": "-3.333333333333336",
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
		// MAX
		"=MAX(1)":          "1",
		"=MAX(TRUE())":     "1",
		"=MAX(0.5,TRUE())": "1",
		"=MAX(FALSE())":    "0",
		"=MAX(MUNIT(2))":   "1",
		"=MAX(INT(1))":     "1",
		// MAXA
		"=MAXA(1)":          "1",
		"=MAXA(TRUE())":     "1",
		"=MAXA(0.5,TRUE())": "1",
		"=MAXA(FALSE())":    "0",
		"=MAXA(MUNIT(2))":   "1",
		"=MAXA(INT(1))":     "1",
		"=MAXA(A1:B4,MUNIT(1),INT(0),1,E1:F2,\"\")": "36693",
xurime's avatar
xurime 已提交
626
		// MEDIAN
xurime's avatar
xurime 已提交
627 628 629
		"=MEDIAN(A1:A5,12)":               "2",
		"=MEDIAN(A1:A5)":                  "1.5",
		"=MEDIAN(A1:A5,MEDIAN(A1:A5,12))": "2",
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
		// MIN
		"=MIN(1)":           "1",
		"=MIN(TRUE())":      "1",
		"=MIN(0.5,FALSE())": "0",
		"=MIN(FALSE())":     "0",
		"=MIN(MUNIT(2))":    "0",
		"=MIN(INT(1))":      "1",
		// MINA
		"=MINA(1)":           "1",
		"=MINA(TRUE())":      "1",
		"=MINA(0.5,FALSE())": "0",
		"=MINA(FALSE())":     "0",
		"=MINA(MUNIT(2))":    "0",
		"=MINA(INT(1))":      "1",
		"=MINA(A1:B4,MUNIT(1),INT(0),1,E1:F2,\"\")": "0",
		// PERMUT
		"=PERMUT(6,6)":  "720",
		"=PERMUT(7,6)":  "5040",
		"=PERMUT(10,6)": "151200",
649
		// Information Functions
650 651 652 653
		// ISBLANK
		"=ISBLANK(A1)": "FALSE",
		"=ISBLANK(A5)": "TRUE",
		// ISERR
654 655 656
		"=ISERR(A1)":           "FALSE",
		"=ISERR(NA())":         "FALSE",
		"=ISERR(POWER(0,-1)))": "TRUE",
657 658 659 660 661 662 663 664 665 666 667 668 669
		// ISERROR
		"=ISERROR(A1)":   "FALSE",
		"=ISERROR(NA())": "TRUE",
		// ISEVEN
		"=ISEVEN(A1)": "FALSE",
		"=ISEVEN(A2)": "TRUE",
		// ISNA
		"=ISNA(A1)":   "FALSE",
		"=ISNA(NA())": "TRUE",
		// ISNONTEXT
		"=ISNONTEXT(A1)":         "FALSE",
		"=ISNONTEXT(A5)":         "TRUE",
		`=ISNONTEXT("Excelize")`: "FALSE",
670
		"=ISNONTEXT(NA())":       "TRUE",
xurime's avatar
xurime 已提交
671 672 673
		// ISNUMBER
		"=ISNUMBER(A1)": "TRUE",
		"=ISNUMBER(D1)": "FALSE",
674 675 676
		// ISODD
		"=ISODD(A1)": "TRUE",
		"=ISODD(A2)": "FALSE",
677 678 679 680 681
		// ISTEXT
		"=ISTEXT(D1)": "TRUE",
		"=ISTEXT(A1)": "FALSE",
		// SHEET
		"SHEET()": "1",
682
		// Logical Functions
683 684 685 686 687 688 689 690 691
		// AND
		"=AND(0)":               "FALSE",
		"=AND(1)":               "TRUE",
		"=AND(1,0)":             "FALSE",
		"=AND(0,1)":             "FALSE",
		"=AND(1=1)":             "TRUE",
		"=AND(1<2)":             "TRUE",
		"=AND(1>2,2<3,2>0,3>1)": "FALSE",
		"=AND(1=1),1=1":         "TRUE",
692 693 694 695 696 697 698 699 700 701 702
		// FALSE
		"=FALSE()": "FALSE",
		// IFERROR
		"=IFERROR(1/2,0)":       "0.5",
		"=IFERROR(ISERROR(),0)": "0",
		"=IFERROR(1/0,0)":       "0",
		// NOT
		"=NOT(FALSE())":     "TRUE",
		"=NOT(\"false\")":   "TRUE",
		"=NOT(\"true\")":    "FALSE",
		"=NOT(ISBLANK(B1))": "TRUE",
703 704 705 706 707
		// OR
		"=OR(1)":       "TRUE",
		"=OR(0)":       "FALSE",
		"=OR(1=2,2=2)": "TRUE",
		"=OR(1=2,2=3)": "FALSE",
708 709
		// TRUE
		"=TRUE()": "TRUE",
710 711 712 713
		// 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",
714 715 716 717
		// Text Functions
		// CLEAN
		"=CLEAN(\"\u0009clean text\")": "clean text",
		"=CLEAN(0)":                    "0",
718 719 720 721
		// CONCAT
		"=CONCAT(TRUE(),1,FALSE(),\"0\",INT(2))": "TRUE1FALSE02",
		// CONCATENATE
		"=CONCATENATE(TRUE(),1,FALSE(),\"0\",INT(2))": "TRUE1FALSE02",
722 723 724 725
		// EXACT
		"=EXACT(1,\"1\")":     "TRUE",
		"=EXACT(1,1)":         "TRUE",
		"=EXACT(\"A\",\"a\")": "FALSE",
726 727 728
		// LEN
		"=LEN(\"\")": "0",
		"=LEN(D1)":   "5",
729 730 731
		// LENB
		"=LENB(\"\")": "0",
		"=LENB(D1)":   "5",
732 733 734
		// TRIM
		"=TRIM(\" trim text \")": "trim text",
		"=TRIM(0)":               "0",
735 736 737 738 739 740 741 742 743 744
		// LOWER
		"=LOWER(\"test\")":     "test",
		"=LOWER(\"TEST\")":     "test",
		"=LOWER(\"Test\")":     "test",
		"=LOWER(\"TEST 123\")": "test 123",
		// PROPER
		"=PROPER(\"this is a test sentence\")": "This Is A Test Sentence",
		"=PROPER(\"THIS IS A TEST SENTENCE\")": "This Is A Test Sentence",
		"=PROPER(\"123tEST teXT\")":            "123Test Text",
		"=PROPER(\"Mr. SMITH's address\")":     "Mr. Smith'S Address",
745 746 747 748
		// REPT
		"=REPT(\"*\",0)":  "",
		"=REPT(\"*\",1)":  "*",
		"=REPT(\"**\",2)": "****",
749 750 751 752 753
		// UPPER
		"=UPPER(\"test\")":     "TEST",
		"=UPPER(\"TEST\")":     "TEST",
		"=UPPER(\"Test\")":     "TEST",
		"=UPPER(\"TEST 123\")": "TEST 123",
754 755 756 757 758 759
		// Conditional Functions
		// IF
		"=IF(1=1)":                              "TRUE",
		"=IF(1<>1)":                             "FALSE",
		"=IF(5<0, \"negative\", \"positive\")":  "positive",
		"=IF(-2<0, \"negative\", \"positive\")": "negative",
760 761 762 763
		// Excel Lookup and Reference Functions
		// CHOOSE
		"=CHOOSE(4,\"red\",\"blue\",\"green\",\"brown\")": "brown",
		"=CHOOSE(1,\"red\",\"blue\",\"green\",\"brown\")": "red",
764
		"=SUM(CHOOSE(A2,A1,B1:B2,A1:A3,A1:A4))":           "9",
xurime's avatar
xurime 已提交
765
		// HLOOKUP
766 767 768 769
		"=HLOOKUP(D2,D2:D8,1,FALSE)":          "Jan",
		"=HLOOKUP(F3,F3:F8,3,FALSE)":          "34440",
		"=HLOOKUP(INT(F3),F3:F8,3,FALSE)":     "34440",
		"=HLOOKUP(MUNIT(1),MUNIT(1),1,FALSE)": "1",
xurime's avatar
xurime 已提交
770
		// VLOOKUP
771 772 773 774 775 776 777 778 779 780 781 782 783 784
		"=VLOOKUP(D2,D:D,1,FALSE)":            "Jan",
		"=VLOOKUP(D2,D1:D10,1)":               "Jan",
		"=VLOOKUP(D2,D1:D11,1)":               "Feb",
		"=VLOOKUP(D2,D1:D10,1,FALSE)":         "Jan",
		"=VLOOKUP(INT(36693),F2:F2,1,FALSE)":  "36693",
		"=VLOOKUP(INT(F2),F3:F9,1)":           "32080",
		"=VLOOKUP(INT(F2),F3:F9,1,TRUE)":      "32080",
		"=VLOOKUP(MUNIT(3),MUNIT(3),1)":       "0",
		"=VLOOKUP(A1,A3:B5,1)":                "0",
		"=VLOOKUP(MUNIT(1),MUNIT(1),1,FALSE)": "1",
		// LOOKUP
		"=LOOKUP(F8,F8:F9,F8:F9)":      "32080",
		"=LOOKUP(F8,F8:F9,D8:D9)":      "Feb",
		"=LOOKUP(1,MUNIT(1),MUNIT(1))": "1",
785 786 787
		// Web Functions
		// ENCODEURL
		"=ENCODEURL(\"https://xuri.me/excelize/en/?q=Save As\")": "https%3A%2F%2Fxuri.me%2Fexcelize%2Fen%2F%3Fq%3DSave%20As",
788 789
	}
	for formula, expected := range mathCalc {
790
		f := prepareCalcData(cellData)
791 792
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
		result, err := f.CalcCellValue("Sheet1", "C1")
xurime's avatar
xurime 已提交
793
		assert.NoError(t, err, formula)
xurime's avatar
xurime 已提交
794
		assert.Equal(t, expected, result, formula)
795 796
	}
	mathCalcError := map[string]string{
797
		"=1/0": "#DIV/0!",
xurime's avatar
xurime 已提交
798
		// Engineering Functions
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
		// BIN2DEC
		"=BIN2DEC()":     "BIN2DEC requires 1 numeric argument",
		"=BIN2DEC(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
		// BIN2HEX
		"=BIN2HEX()":               "BIN2HEX requires at least 1 argument",
		"=BIN2HEX(1,1,1)":          "BIN2HEX allows at most 2 arguments",
		"=BIN2HEX(\"\",1)":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=BIN2HEX(1,\"\")":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=BIN2HEX(12345678901,10)": "#NUM!",
		"=BIN2HEX(1,-1)":           "#NUM!",
		"=BIN2HEX(31,1)":           "#NUM!",
		// BIN2OCT
		"=BIN2OCT()":                 "BIN2OCT requires at least 1 argument",
		"=BIN2OCT(1,1,1)":            "BIN2OCT allows at most 2 arguments",
		"=BIN2OCT(\"\",1)":           "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=BIN2OCT(1,\"\")":           "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=BIN2OCT(-12345678901 ,10)": "#NUM!",
		"=BIN2OCT(1,-1)":             "#NUM!",
		"=BIN2OCT(8,1)":              "#NUM!",
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
		// 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!",
xurime's avatar
xurime 已提交
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
		// 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!",
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
		// HEX2BIN
		"=HEX2BIN()":        "HEX2BIN requires at least 1 argument",
		"=HEX2BIN(1,1,1)":   "HEX2BIN allows at most 2 arguments",
		"=HEX2BIN(\"X\",1)": "strconv.ParseInt: parsing \"X\": invalid syntax",
		"=HEX2BIN(1,\"\")":  "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=HEX2BIN(-513,10)": "strconv.ParseInt: parsing \"-\": invalid syntax",
		"=HEX2BIN(1,-1)":    "#NUM!",
		"=HEX2BIN(2,1)":     "#NUM!",
		// HEX2DEC
		"=HEX2DEC()":      "HEX2DEC requires 1 numeric argument",
		"=HEX2DEC(\"X\")": "strconv.ParseInt: parsing \"X\": invalid syntax",
		// HEX2OCT
		"=HEX2OCT()":        "HEX2OCT requires at least 1 argument",
		"=HEX2OCT(1,1,1)":   "HEX2OCT allows at most 2 arguments",
		"=HEX2OCT(\"X\",1)": "strconv.ParseInt: parsing \"X\": invalid syntax",
		"=HEX2OCT(1,\"\")":  "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=HEX2OCT(-513,10)": "strconv.ParseInt: parsing \"-\": invalid syntax",
		"=HEX2OCT(1,-1)":    "#NUM!",
		// OCT2BIN
		"=OCT2BIN()":               "OCT2BIN requires at least 1 argument",
		"=OCT2BIN(1,1,1)":          "OCT2BIN allows at most 2 arguments",
		"=OCT2BIN(\"\",1)":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=OCT2BIN(1,\"\")":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=OCT2BIN(-536870912 ,10)": "#NUM!",
		"=OCT2BIN(1,-1)":           "#NUM!",
		// OCT2DEC
		"=OCT2DEC()":     "OCT2DEC requires 1 numeric argument",
		"=OCT2DEC(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
		// OCT2HEX
		"=OCT2HEX()":               "OCT2HEX requires at least 1 argument",
		"=OCT2HEX(1,1,1)":          "OCT2HEX allows at most 2 arguments",
		"=OCT2HEX(\"\",1)":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=OCT2HEX(1,\"\")":         "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=OCT2HEX(-536870912 ,10)": "#NUM!",
		"=OCT2HEX(1,-1)":           "#NUM!",
		// Math and Trigonometric Functions
918
		// ABS
xurime's avatar
xurime 已提交
919
		"=ABS()":    "ABS requires 1 numeric argument",
920
		`=ABS("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
921
		"=ABS(~)":   `invalid column name "~"`,
922
		// ACOS
923 924 925
		"=ACOS()":        "ACOS requires 1 numeric argument",
		`=ACOS("X")`:     "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=ACOS(ACOS(0))": "#NUM!",
926
		// ACOSH
xurime's avatar
xurime 已提交
927
		"=ACOSH()":    "ACOSH requires 1 numeric argument",
928
		`=ACOSH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
929
		// _xlfn.ACOT
xurime's avatar
xurime 已提交
930
		"=_xlfn.ACOT()":    "ACOT requires 1 numeric argument",
931
		`=_xlfn.ACOT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
932
		// _xlfn.ACOTH
933 934 935
		"=_xlfn.ACOTH()":               "ACOTH requires 1 numeric argument",
		`=_xlfn.ACOTH("X")`:            "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=_xlfn.ACOTH(_xlfn.ACOTH(2))": "#NUM!",
xurime's avatar
xurime 已提交
936
		// _xlfn.ARABIC
937
		"=_xlfn.ARABIC()": "ARABIC requires 1 numeric argument",
938
		// ASIN
xurime's avatar
xurime 已提交
939
		"=ASIN()":    "ASIN requires 1 numeric argument",
940
		`=ASIN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
941
		// ASINH
xurime's avatar
xurime 已提交
942
		"=ASINH()":    "ASINH requires 1 numeric argument",
943
		`=ASINH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
944
		// ATAN
xurime's avatar
xurime 已提交
945
		"=ATAN()":    "ATAN requires 1 numeric argument",
946
		`=ATAN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
947
		// ATANH
xurime's avatar
xurime 已提交
948
		"=ATANH()":    "ATANH requires 1 numeric argument",
949
		`=ATANH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
950
		// ATAN2
xurime's avatar
xurime 已提交
951
		"=ATAN2()":      "ATAN2 requires 2 numeric arguments",
952 953
		`=ATAN2("X",0)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ATAN2(0,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
954 955 956
		// BASE
		"=BASE()":        "BASE requires at least 2 arguments",
		"=BASE(1,2,3,4)": "BASE allows at most 3 arguments",
957
		"=BASE(1,1)":     "radix must be an integer >= 2 and <= 36",
958
		`=BASE("X",2)`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
959
		`=BASE(1,"X")`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
960
		`=BASE(1,2,"X")`: "strconv.Atoi: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
961 962 963 964
		// CEILING
		"=CEILING()":      "CEILING requires at least 1 argument",
		"=CEILING(1,2,3)": "CEILING allows at most 2 arguments",
		"=CEILING(1,-1)":  "negative sig to CEILING invalid",
965 966
		`=CEILING("X",0)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=CEILING(0,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
967 968 969
		// _xlfn.CEILING.MATH
		"=_xlfn.CEILING.MATH()":        "CEILING.MATH requires at least 1 argument",
		"=_xlfn.CEILING.MATH(1,2,3,4)": "CEILING.MATH allows at most 3 arguments",
970 971 972
		`=_xlfn.CEILING.MATH("X")`:     "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.CEILING.MATH(1,"X")`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.CEILING.MATH(1,2,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
973 974 975
		// _xlfn.CEILING.PRECISE
		"=_xlfn.CEILING.PRECISE()":      "CEILING.PRECISE requires at least 1 argument",
		"=_xlfn.CEILING.PRECISE(1,2,3)": "CEILING.PRECISE allows at most 2 arguments",
976
		`=_xlfn.CEILING.PRECISE("X",2)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
977
		`=_xlfn.CEILING.PRECISE(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
978
		// COMBIN
xurime's avatar
xurime 已提交
979 980
		"=COMBIN()":       "COMBIN requires 2 argument",
		"=COMBIN(-1,1)":   "COMBIN requires number >= number_chosen",
981 982
		`=COMBIN("X",1)`:  "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=COMBIN(-1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
983
		// _xlfn.COMBINA
xurime's avatar
xurime 已提交
984 985 986
		"=_xlfn.COMBINA()":       "COMBINA requires 2 argument",
		"=_xlfn.COMBINA(-1,1)":   "COMBINA requires number > number_chosen",
		"=_xlfn.COMBINA(-1,-1)":  "COMBIN requires number >= number_chosen",
987 988
		`=_xlfn.COMBINA("X",1)`:  "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.COMBINA(-1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
989
		// COS
xurime's avatar
xurime 已提交
990
		"=COS()":    "COS requires 1 numeric argument",
991
		`=COS("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
992
		// COSH
xurime's avatar
xurime 已提交
993
		"=COSH()":    "COSH requires 1 numeric argument",
994
		`=COSH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
995
		// _xlfn.COT
xurime's avatar
xurime 已提交
996
		"=COT()":    "COT requires 1 numeric argument",
997
		`=COT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
998
		"=COT(0)":   "#DIV/0!",
999
		// _xlfn.COTH
xurime's avatar
xurime 已提交
1000
		"=COTH()":    "COTH requires 1 numeric argument",
1001
		`=COTH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1002
		"=COTH(0)":   "#DIV/0!",
1003
		// _xlfn.CSC
xurime's avatar
xurime 已提交
1004
		"=_xlfn.CSC()":    "CSC requires 1 numeric argument",
1005
		`=_xlfn.CSC("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1006
		"=_xlfn.CSC(0)":   "#DIV/0!",
1007
		// _xlfn.CSCH
xurime's avatar
xurime 已提交
1008
		"=_xlfn.CSCH()":    "CSCH requires 1 numeric argument",
1009
		`=_xlfn.CSCH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1010
		"=_xlfn.CSCH(0)":   "#DIV/0!",
1011 1012
		// _xlfn.DECIMAL
		"=_xlfn.DECIMAL()":          "DECIMAL requires 2 numeric arguments",
1013 1014
		`=_xlfn.DECIMAL("X", 2)`:    "strconv.ParseInt: parsing \"X\": invalid syntax",
		`=_xlfn.DECIMAL(2000, "X")`: "strconv.Atoi: parsing \"X\": invalid syntax",
1015
		// DEGREES
xurime's avatar
xurime 已提交
1016
		"=DEGREES()":    "DEGREES requires 1 numeric argument",
1017
		`=DEGREES("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1018
		"=DEGREES(0)":   "#DIV/0!",
1019
		// EVEN
xurime's avatar
xurime 已提交
1020
		"=EVEN()":    "EVEN requires 1 numeric argument",
1021
		`=EVEN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1022
		// EXP
xurime's avatar
xurime 已提交
1023
		"=EXP()":    "EXP requires 1 numeric argument",
1024
		`=EXP("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1025
		// FACT
xurime's avatar
xurime 已提交
1026
		"=FACT()":    "FACT requires 1 numeric argument",
1027
		`=FACT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1028
		"=FACT(-1)":  "#NUM!",
1029
		// FACTDOUBLE
xurime's avatar
xurime 已提交
1030
		"=FACTDOUBLE()":    "FACTDOUBLE requires 1 numeric argument",
1031
		`=FACTDOUBLE("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1032
		"=FACTDOUBLE(-1)":  "#NUM!",
1033
		// FLOOR
xurime's avatar
xurime 已提交
1034
		"=FLOOR()":       "FLOOR requires 2 numeric arguments",
1035 1036 1037
		`=FLOOR("X",-1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=FLOOR(1,"X")`:  "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=FLOOR(1,-1)":   "invalid arguments to FLOOR",
1038 1039 1040
		// _xlfn.FLOOR.MATH
		"=_xlfn.FLOOR.MATH()":        "FLOOR.MATH requires at least 1 argument",
		"=_xlfn.FLOOR.MATH(1,2,3,4)": "FLOOR.MATH allows at most 3 arguments",
1041 1042 1043
		`=_xlfn.FLOOR.MATH("X",2,3)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.FLOOR.MATH(1,"X",3)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.FLOOR.MATH(1,2,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1044 1045 1046
		// _xlfn.FLOOR.PRECISE
		"=_xlfn.FLOOR.PRECISE()":      "FLOOR.PRECISE requires at least 1 argument",
		"=_xlfn.FLOOR.PRECISE(1,2,3)": "FLOOR.PRECISE allows at most 2 arguments",
1047 1048
		`=_xlfn.FLOOR.PRECISE("X",2)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=_xlfn.FLOOR.PRECISE(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1049 1050
		// GCD
		"=GCD()":     "GCD requires at least 1 argument",
1051
		"=GCD(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
1052 1053
		"=GCD(-1)":   "GCD only accepts positive arguments",
		"=GCD(1,-1)": "GCD only accepts positive arguments",
1054
		`=GCD("X")`:  "strconv.ParseFloat: parsing \"X\": invalid syntax",
1055
		// INT
xurime's avatar
xurime 已提交
1056
		"=INT()":    "INT requires 1 numeric argument",
1057
		`=INT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1058 1059 1060
		// ISO.CEILING
		"=ISO.CEILING()":      "ISO.CEILING requires at least 1 argument",
		"=ISO.CEILING(1,2,3)": "ISO.CEILING allows at most 2 arguments",
1061 1062
		`=ISO.CEILING("X",2)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ISO.CEILING(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1063 1064 1065 1066
		// LCM
		"=LCM()":     "LCM requires at least 1 argument",
		"=LCM(-1)":   "LCM only accepts positive arguments",
		"=LCM(1,-1)": "LCM only accepts positive arguments",
1067
		`=LCM("X")`:  "strconv.ParseFloat: parsing \"X\": invalid syntax",
1068
		// LN
xurime's avatar
xurime 已提交
1069
		"=LN()":    "LN requires 1 numeric argument",
1070
		`=LN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1071 1072 1073
		// LOG
		"=LOG()":      "LOG requires at least 1 argument",
		"=LOG(1,2,3)": "LOG allows at most 2 arguments",
1074 1075 1076 1077
		`=LOG("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=LOG(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=LOG(0,0)":   "#DIV/0!",
		"=LOG(1,0)":   "#DIV/0!",
1078 1079
		"=LOG(1,1)":   "#DIV/0!",
		// LOG10
xurime's avatar
xurime 已提交
1080
		"=LOG10()":    "LOG10 requires 1 numeric argument",
1081
		`=LOG10("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1082 1083
		// MDETERM
		"MDETERM()": "MDETERM requires at least 1 argument",
1084
		// MOD
xurime's avatar
xurime 已提交
1085
		"=MOD()":      "MOD requires 2 numeric arguments",
1086 1087 1088
		"=MOD(6,0)":   "MOD divide by zero",
		`=MOD("X",0)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=MOD(6,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1089
		// MROUND
xurime's avatar
xurime 已提交
1090 1091 1092
		"=MROUND()":      "MROUND requires 2 numeric arguments",
		"=MROUND(1,0)":   "#NUM!",
		"=MROUND(1,-1)":  "#NUM!",
1093 1094
		`=MROUND("X",0)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=MROUND(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1095
		// MULTINOMIAL
1096
		`=MULTINOMIAL("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1097
		// _xlfn.MUNIT
1098 1099 1100
		"=_xlfn.MUNIT()":    "MUNIT requires 1 numeric argument",
		`=_xlfn.MUNIT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=_xlfn.MUNIT(-1)":  "",
1101
		// ODD
xurime's avatar
xurime 已提交
1102
		"=ODD()":    "ODD requires 1 numeric argument",
1103
		`=ODD("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1104 1105
		// PI
		"=PI(1)": "PI accepts no arguments",
1106
		// POWER
1107 1108
		`=POWER("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=POWER(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1109 1110 1111 1112
		"=POWER(0,0)":   "#NUM!",
		"=POWER(0,-1)":  "#DIV/0!",
		"=POWER(1)":     "POWER requires 2 numeric arguments",
		// PRODUCT
1113
		`=PRODUCT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1114
		// QUOTIENT
1115 1116
		`=QUOTIENT("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=QUOTIENT(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1117 1118
		"=QUOTIENT(1,0)":   "#DIV/0!",
		"=QUOTIENT(1)":     "QUOTIENT requires 2 numeric arguments",
1119
		// RADIANS
1120
		`=RADIANS("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1121
		"=RADIANS()":    "RADIANS requires 1 numeric argument",
1122 1123 1124
		// RAND
		"=RAND(1)": "RAND accepts no arguments",
		// RANDBETWEEN
xurime's avatar
xurime 已提交
1125 1126
		`=RANDBETWEEN("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=RANDBETWEEN(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1127 1128
		"=RANDBETWEEN()":      "RANDBETWEEN requires 2 numeric arguments",
		"=RANDBETWEEN(2,1)":   "#NUM!",
1129 1130 1131
		// ROMAN
		"=ROMAN()":      "ROMAN requires at least 1 argument",
		"=ROMAN(1,2,3)": "ROMAN allows at most 2 arguments",
1132 1133
		`=ROMAN("X")`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ROMAN("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1134
		// ROUND
xurime's avatar
xurime 已提交
1135
		"=ROUND()":      "ROUND requires 2 numeric arguments",
1136 1137
		`=ROUND("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ROUND(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1138
		// ROUNDDOWN
xurime's avatar
xurime 已提交
1139
		"=ROUNDDOWN()":      "ROUNDDOWN requires 2 numeric arguments",
1140 1141
		`=ROUNDDOWN("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ROUNDDOWN(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1142
		// ROUNDUP
xurime's avatar
xurime 已提交
1143
		"=ROUNDUP()":      "ROUNDUP requires 2 numeric arguments",
1144 1145
		`=ROUNDUP("X",1)`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=ROUNDUP(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1146
		// SEC
xurime's avatar
xurime 已提交
1147
		"=_xlfn.SEC()":    "SEC requires 1 numeric argument",
1148
		`=_xlfn.SEC("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1149
		// _xlfn.SECH
xurime's avatar
xurime 已提交
1150
		"=_xlfn.SECH()":    "SECH requires 1 numeric argument",
1151
		`=_xlfn.SECH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1152
		// SIGN
xurime's avatar
xurime 已提交
1153
		"=SIGN()":    "SIGN requires 1 numeric argument",
1154
		`=SIGN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1155
		// SIN
xurime's avatar
xurime 已提交
1156
		"=SIN()":    "SIN requires 1 numeric argument",
1157
		`=SIN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1158
		// SINH
xurime's avatar
xurime 已提交
1159
		"=SINH()":    "SINH requires 1 numeric argument",
1160
		`=SINH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1161
		// SQRT
xurime's avatar
xurime 已提交
1162
		"=SQRT()":    "SQRT requires 1 numeric argument",
xurime's avatar
xurime 已提交
1163
		`=SQRT("")`:  "strconv.ParseFloat: parsing \"\": invalid syntax",
1164
		`=SQRT("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1165
		"=SQRT(-1)":  "#NUM!",
1166
		// SQRTPI
xurime's avatar
xurime 已提交
1167
		"=SQRTPI()":    "SQRTPI requires 1 numeric argument",
1168
		`=SQRTPI("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
xurime's avatar
xurime 已提交
1169 1170 1171 1172 1173 1174
		// STDEV
		"=STDEV()":      "STDEV requires at least 1 argument",
		"=STDEV(E2:E9)": "#DIV/0!",
		// STDEVA
		"=STDEVA()":      "STDEVA requires at least 1 argument",
		"=STDEVA(E2:E9)": "#DIV/0!",
xurime's avatar
xurime 已提交
1175
		// SUM
xurime's avatar
xurime 已提交
1176 1177 1178 1179 1180 1181
		"=SUM((":   "formula not valid",
		"=SUM(-)":  "formula not valid",
		"=SUM(1+)": "formula not valid",
		"=SUM(1-)": "formula not valid",
		"=SUM(1*)": "formula not valid",
		"=SUM(1/)": "formula not valid",
xurime's avatar
xurime 已提交
1182 1183
		// SUMIF
		"=SUMIF()": "SUMIF requires at least 2 argument",
xurime's avatar
xurime 已提交
1184
		// SUMSQ
xurime's avatar
xurime 已提交
1185 1186
		`=SUMSQ("X")`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
		"=SUMSQ(C1:D2)": "strconv.ParseFloat: parsing \"Month\": invalid syntax",
1187
		// TAN
xurime's avatar
xurime 已提交
1188
		"=TAN()":    "TAN requires 1 numeric argument",
1189
		`=TAN("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1190
		// TANH
xurime's avatar
xurime 已提交
1191
		"=TANH()":    "TANH requires 1 numeric argument",
1192
		`=TANH("X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1193
		// TRUNC
xurime's avatar
xurime 已提交
1194
		"=TRUNC()":      "TRUNC requires at least 1 argument",
1195 1196
		`=TRUNC("X")`:   "strconv.ParseFloat: parsing \"X\": invalid syntax",
		`=TRUNC(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax",
1197
		// Statistical Functions
1198 1199 1200 1201 1202 1203 1204
		// AVERAGE
		"=AVERAGE(H1)": "AVERAGE divide by zero",
		// AVERAGE
		"=AVERAGEA(H1)": "AVERAGEA divide by zero",
		// COUNTBLANK
		"=COUNTBLANK()":    "COUNTBLANK requires 1 argument",
		"=COUNTBLANK(1,2)": "COUNTBLANK requires 1 argument",
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
		// FISHER
		"=FISHER()":         "FISHER requires 1 numeric argument",
		"=FISHER(2)":        "#N/A",
		"=FISHER(INT(-2)))": "#N/A",
		"=FISHER(F1)":       "FISHER requires 1 numeric argument",
		// FISHERINV
		"=FISHERINV()":   "FISHERINV requires 1 numeric argument",
		"=FISHERINV(F1)": "FISHERINV requires 1 numeric argument",
		// GAMMA
		"=GAMMA()":       "GAMMA requires 1 numeric argument",
		"=GAMMA(F1)":     "GAMMA requires 1 numeric argument",
		"=GAMMA(0)":      "#N/A",
		"=GAMMA(INT(0))": "#N/A",
		// GAMMALN
		"=GAMMALN()":       "GAMMALN requires 1 numeric argument",
		"=GAMMALN(F1)":     "GAMMALN requires 1 numeric argument",
		"=GAMMALN(0)":      "#N/A",
		"=GAMMALN(INT(0))": "#N/A",
xurime's avatar
xurime 已提交
1223 1224 1225
		// KURT
		"=KURT()":          "KURT requires at least 1 argument",
		"=KURT(F1,INT(1))": "#DIV/0!",
1226 1227 1228 1229 1230 1231
		// MAX
		"=MAX()":     "MAX requires at least 1 argument",
		"=MAX(NA())": "#N/A",
		// MAXA
		"=MAXA()":     "MAXA requires at least 1 argument",
		"=MAXA(NA())": "#N/A",
xurime's avatar
xurime 已提交
1232
		// MEDIAN
xurime's avatar
xurime 已提交
1233
		"=MEDIAN()":      "MEDIAN requires at least 1 argument",
1234
		"=MEDIAN(\"\")":  "strconv.ParseFloat: parsing \"\": invalid syntax",
xurime's avatar
xurime 已提交
1235
		"=MEDIAN(D1:D2)": "strconv.ParseFloat: parsing \"Month\": invalid syntax",
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
		// MIN
		"=MIN()":     "MIN requires at least 1 argument",
		"=MIN(NA())": "#N/A",
		// MINA
		"=MINA()":     "MINA requires at least 1 argument",
		"=MINA(NA())": "#N/A",
		// PERMUT
		"=PERMUT()":       "PERMUT requires 2 numeric arguments",
		"=PERMUT(\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=PERMUT(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
		"=PERMUT(6,8)":    "#N/A",
1247
		// Information Functions
1248 1249 1250 1251 1252 1253 1254
		// ISBLANK
		"=ISBLANK(A1,A2)": "ISBLANK requires 1 argument",
		// ISERR
		"=ISERR()": "ISERR requires 1 argument",
		// ISERROR
		"=ISERROR()": "ISERROR requires 1 argument",
		// ISEVEN
1255
		"=ISEVEN()":       "ISEVEN requires 1 argument",
1256
		`=ISEVEN("text")`: "strconv.Atoi: parsing \"text\": invalid syntax",
1257 1258 1259 1260
		// ISNA
		"=ISNA()": "ISNA requires 1 argument",
		// ISNONTEXT
		"=ISNONTEXT()": "ISNONTEXT requires 1 argument",
xurime's avatar
xurime 已提交
1261 1262
		// ISNUMBER
		"=ISNUMBER()": "ISNUMBER requires 1 argument",
1263
		// ISODD
1264
		"=ISODD()":       "ISODD requires 1 argument",
1265
		`=ISODD("text")`: "strconv.Atoi: parsing \"text\": invalid syntax",
1266 1267
		// ISTEXT
		"=ISTEXT()": "ISTEXT requires 1 argument",
1268
		// NA
1269
		"=NA()":  "#N/A",
1270
		"=NA(1)": "NA accepts no arguments",
1271 1272
		// SHEET
		"=SHEET(1)": "SHEET accepts no arguments",
1273
		// Logical Functions
1274
		// AND
1275
		`=AND("text")`: "strconv.ParseFloat: parsing \"text\": invalid syntax",
1276 1277 1278
		`=AND(A1:B1)`:  "#VALUE!",
		"=AND()":       "AND requires at least 1 argument",
		"=AND(1" + strings.Repeat(",1", 30) + ")": "AND accepts at most 30 arguments",
1279 1280 1281 1282 1283 1284 1285 1286
		// FALSE
		"=FALSE(A1)": "FALSE takes no arguments",
		// IFERROR
		"=IFERROR()": "IFERROR requires 2 arguments",
		// NOT
		"=NOT()":      "NOT requires 1 argument",
		"=NOT(NOT())": "NOT requires 1 argument",
		"=NOT(\"\")":  "NOT expects 1 boolean or numeric argument",
1287
		// OR
1288
		`=OR("text")`:                            "strconv.ParseFloat: parsing \"text\": invalid syntax",
1289 1290 1291
		`=OR(A1:B1)`:                             "#VALUE!",
		"=OR()":                                  "OR requires at least 1 argument",
		"=OR(1" + strings.Repeat(",1", 30) + ")": "OR accepts at most 30 arguments",
1292 1293
		// TRUE
		"=TRUE(A1)": "TRUE takes no arguments",
1294 1295 1296 1297 1298 1299
		// 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",
1300 1301 1302 1303
		// Text Functions
		// CLEAN
		"=CLEAN()":    "CLEAN requires 1 argument",
		"=CLEAN(1,2)": "CLEAN requires 1 argument",
1304 1305 1306 1307
		// CONCAT
		"=CONCAT(MUNIT(2))": "CONCAT requires arguments to be strings",
		// CONCATENATE
		"=CONCATENATE(MUNIT(2))": "CONCATENATE requires arguments to be strings",
1308 1309 1310
		// EXACT
		"=EXACT()":      "EXACT requires 2 arguments",
		"=EXACT(1,2,3)": "EXACT requires 2 arguments",
1311 1312
		// LEN
		"=LEN()": "LEN requires 1 string argument",
1313 1314
		// LENB
		"=LENB()": "LENB requires 1 string argument",
1315 1316 1317
		// TRIM
		"=TRIM()":    "TRIM requires 1 argument",
		"=TRIM(1,2)": "TRIM requires 1 argument",
1318 1319 1320 1321 1322 1323 1324 1325 1326
		// LOWER
		"=LOWER()":    "LOWER requires 1 argument",
		"=LOWER(1,2)": "LOWER requires 1 argument",
		// UPPER
		"=UPPER()":    "UPPER requires 1 argument",
		"=UPPER(1,2)": "UPPER requires 1 argument",
		// PROPER
		"=PROPER()":    "PROPER requires 1 argument",
		"=PROPER(1,2)": "PROPER requires 1 argument",
1327 1328 1329 1330 1331
		// REPT
		"=REPT()":            "REPT requires 2 arguments",
		"=REPT(INT(0),2)":    "REPT requires first argument to be a string",
		"=REPT(\"*\",\"*\")": "REPT requires second argument to be a number",
		"=REPT(\"*\",-1)":    "REPT requires second argument to be >= 0",
1332 1333 1334 1335
		// Conditional Functions
		// IF
		"=IF()":        "IF requires at least 1 argument",
		"=IF(0,1,2,3)": "IF accepts at most 3 arguments",
1336 1337 1338 1339 1340 1341
		"=IF(D1,1,2)":  "strconv.ParseBool: parsing \"Month\": invalid syntax",
		// Excel Lookup and Reference Functions
		// CHOOSE
		"=CHOOSE()":                "CHOOSE requires 2 arguments",
		"=CHOOSE(\"index_num\",0)": "CHOOSE requires first argument of type number",
		"=CHOOSE(2,0)":             "index_num should be <= to the number of values",
xurime's avatar
xurime 已提交
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
		// HLOOKUP
		"=HLOOKUP()":                     "HLOOKUP requires at least 3 arguments",
		"=HLOOKUP(D2,D1,1,FALSE)":        "HLOOKUP requires second argument of table array",
		"=HLOOKUP(D2,D:D,FALSE,FALSE)":   "HLOOKUP requires numeric row argument",
		"=HLOOKUP(D2,D:D,1,FALSE,FALSE)": "HLOOKUP requires at most 4 arguments",
		"=HLOOKUP(D2,D:D,1,2)":           "strconv.ParseBool: parsing \"2\": invalid syntax",
		"=HLOOKUP(D2,D10:D10,1,FALSE)":   "HLOOKUP no result found",
		"=HLOOKUP(D2,D2:D3,4,FALSE)":     "HLOOKUP has invalid row index",
		"=HLOOKUP(D2,C:C,1,FALSE)":       "HLOOKUP no result found",
		"=HLOOKUP(ISNUMBER(1),F3:F9,1)":  "HLOOKUP no result found",
		"=HLOOKUP(INT(1),E2:E9,1)":       "HLOOKUP no result found",
		"=HLOOKUP(MUNIT(2),MUNIT(3),1)":  "HLOOKUP no result found",
		"=HLOOKUP(A1:B2,B2:B3,1)":        "HLOOKUP no result found",
xurime's avatar
xurime 已提交
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
		// VLOOKUP
		"=VLOOKUP()":                     "VLOOKUP requires at least 3 arguments",
		"=VLOOKUP(D2,D1,1,FALSE)":        "VLOOKUP requires second argument of table array",
		"=VLOOKUP(D2,D:D,FALSE,FALSE)":   "VLOOKUP requires numeric col argument",
		"=VLOOKUP(D2,D:D,1,FALSE,FALSE)": "VLOOKUP requires at most 4 arguments",
		"=VLOOKUP(D2,D:D,1,2)":           "strconv.ParseBool: parsing \"2\": invalid syntax",
		"=VLOOKUP(D2,D10:D10,1,FALSE)":   "VLOOKUP no result found",
		"=VLOOKUP(D2,D:D,2,FALSE)":       "VLOOKUP has invalid column index",
		"=VLOOKUP(D2,C:C,1,FALSE)":       "VLOOKUP no result found",
		"=VLOOKUP(ISNUMBER(1),F3:F9,1)":  "VLOOKUP no result found",
		"=VLOOKUP(INT(1),E2:E9,1)":       "VLOOKUP no result found",
		"=VLOOKUP(MUNIT(2),MUNIT(3),1)":  "VLOOKUP no result found",
1367 1368 1369 1370 1371 1372
		"=VLOOKUP(1,G1:H2,1,FALSE)":      "VLOOKUP no result found",
		// LOOKUP
		"=LOOKUP()":                     "LOOKUP requires at least 2 arguments",
		"=LOOKUP(D2,D1,D2)":             "LOOKUP requires second argument of table array",
		"=LOOKUP(D2,D1,D2,FALSE)":       "LOOKUP requires at most 3 arguments",
		"=LOOKUP(D1,MUNIT(1),MUNIT(1))": "LOOKUP no result found",
1373 1374 1375
		// Web Functions
		// ENCODEURL
		"=ENCODEURL()": "ENCODEURL requires 1 argument",
1376 1377
	}
	for formula, expected := range mathCalcError {
1378
		f := prepareCalcData(cellData)
1379 1380
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
		result, err := f.CalcCellValue("Sheet1", "C1")
1381
		assert.EqualError(t, err, expected, formula)
xurime's avatar
xurime 已提交
1382
		assert.Equal(t, "", result, formula)
1383 1384 1385
	}

	referenceCalc := map[string]string{
1386 1387
		// MDETERM
		"=MDETERM(A1:B2)": "-3",
1388 1389 1390
		// PRODUCT
		"=PRODUCT(Sheet1!A1:Sheet1!A1:A2,A2)": "4",
		// SUM
1391
		"=A1/A3":                          "0.333333333333333",
1392 1393 1394 1395 1396
		"=SUM(A1:A2)":                     "3",
		"=SUM(Sheet1!A1,A2)":              "3",
		"=(-2-SUM(-4+A2))*5":              "0",
		"=SUM(Sheet1!A1:Sheet1!A1:A2,A2)": "5",
		"=SUM(A1,A2,A3)*SUM(2,3)":         "30",
1397 1398
		"=1+SUM(SUM(A1+A2/A3)*(2-3),2)":   "1.333333333333334",
		"=A1/A2/SUM(A1:A2:B1)":            "0.041666666666667",
xurime's avatar
xurime 已提交
1399
		"=A1/A2/SUM(A1:A2:B1)*A3":         "0.125",
xurime's avatar
xurime 已提交
1400 1401
		"=SUM(B1:D1)":                     "4",
		"=SUM(\"X\")":                     "0",
1402 1403
	}
	for formula, expected := range referenceCalc {
1404
		f := prepareCalcData(cellData)
1405 1406 1407
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
		result, err := f.CalcCellValue("Sheet1", "C1")
		assert.NoError(t, err)
xurime's avatar
xurime 已提交
1408
		assert.Equal(t, expected, result, formula)
1409 1410 1411
	}

	referenceCalcError := map[string]string{
1412 1413 1414
		// MDETERM
		"=MDETERM(A1:B3)": "#VALUE!",
		// SUM
1415 1416 1417
		"=1+SUM(SUM(A1+A2/A4)*(2-3),2)": "#DIV/0!",
	}
	for formula, expected := range referenceCalcError {
1418
		f := prepareCalcData(cellData)
1419 1420 1421
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
		result, err := f.CalcCellValue("Sheet1", "C1")
		assert.EqualError(t, err, expected)
xurime's avatar
xurime 已提交
1422
		assert.Equal(t, "", result, formula)
1423 1424
	}

xurime's avatar
xurime 已提交
1425 1426 1427 1428 1429
	volatileFuncs := []string{
		"=RAND()",
		"=RANDBETWEEN(1,2)",
	}
	for _, formula := range volatileFuncs {
1430
		f := prepareCalcData(cellData)
xurime's avatar
xurime 已提交
1431 1432 1433 1434 1435
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
		_, err := f.CalcCellValue("Sheet1", "C1")
		assert.NoError(t, err)
	}

1436
	// Test get calculated cell value on not formula cell.
1437
	f := prepareCalcData(cellData)
1438 1439 1440 1441
	result, err := f.CalcCellValue("Sheet1", "A1")
	assert.NoError(t, err)
	assert.Equal(t, "", result)
	// Test get calculated cell value on not exists worksheet.
1442
	f = prepareCalcData(cellData)
1443 1444 1445
	_, err = f.CalcCellValue("SheetN", "A1")
	assert.EqualError(t, err, "sheet SheetN is not exist")
	// Test get calculated cell value with not support formula.
1446
	f = prepareCalcData(cellData)
1447 1448 1449
	assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=UNSUPPORT(A1)"))
	_, err = f.CalcCellValue("Sheet1", "A1")
	assert.EqualError(t, err, "not support UNSUPPORT function")
xurime's avatar
xurime 已提交
1450
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCalcCellValue.xlsx")))
J
jaby 已提交
1451 1452 1453

}

1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
func TestCalculate(t *testing.T) {
	err := `strconv.ParseFloat: parsing "string": invalid syntax`
	opd := NewStack()
	opd.Push(efp.Token{TValue: "string"})
	opt := efp.Token{TValue: "-", TType: efp.TokenTypeOperatorPrefix}
	assert.EqualError(t, calculate(opd, opt), err)
	opd.Push(efp.Token{TValue: "string"})
	opd.Push(efp.Token{TValue: "string"})
	opt = efp.Token{TValue: "-", TType: efp.TokenTypeOperatorInfix}
	assert.EqualError(t, calculate(opd, opt), err)
}

1466
func TestCalcWithDefinedName(t *testing.T) {
J
jaby 已提交
1467 1468 1469
	cellData := [][]interface{}{
		{"A1 value", "B1 value", nil},
	}
1470 1471 1472
	f := prepareCalcData(cellData)
	assert.NoError(t, f.SetDefinedName(&DefinedName{Name: "defined_name1", RefersTo: "Sheet1!A1", Scope: "Workbook"}))
	assert.NoError(t, f.SetDefinedName(&DefinedName{Name: "defined_name1", RefersTo: "Sheet1!B1", Scope: "Sheet1"}))
J
jaby 已提交
1473 1474 1475 1476 1477
	assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "=defined_name1"))
	result, err := f.CalcCellValue("Sheet1", "C1")
	assert.NoError(t, err)
	// DefinedName with scope WorkSheet takes precedence over DefinedName with scope Workbook, so we should get B1 value
	assert.Equal(t, "B1 value", result, "=defined_name1")
1478
}
1479

1480
func TestCalcArithmeticOperations(t *testing.T) {
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
	err := `strconv.ParseFloat: parsing "text": invalid syntax`
	assert.EqualError(t, calcPow("1", "text", nil), err)
	assert.EqualError(t, calcPow("text", "1", nil), err)
	assert.EqualError(t, calcL("1", "text", nil), err)
	assert.EqualError(t, calcL("text", "1", nil), err)
	assert.EqualError(t, calcLe("1", "text", nil), err)
	assert.EqualError(t, calcLe("text", "1", nil), err)
	assert.EqualError(t, calcG("1", "text", nil), err)
	assert.EqualError(t, calcG("text", "1", nil), err)
	assert.EqualError(t, calcGe("1", "text", nil), err)
	assert.EqualError(t, calcGe("text", "1", nil), err)
	assert.EqualError(t, calcAdd("1", "text", nil), err)
	assert.EqualError(t, calcAdd("text", "1", nil), err)
	assert.EqualError(t, calcAdd("1", "text", nil), err)
	assert.EqualError(t, calcAdd("text", "1", nil), err)
	assert.EqualError(t, calcSubtract("1", "text", nil), err)
	assert.EqualError(t, calcSubtract("text", "1", nil), err)
	assert.EqualError(t, calcMultiply("1", "text", nil), err)
	assert.EqualError(t, calcMultiply("text", "1", nil), err)
	assert.EqualError(t, calcDiv("1", "text", nil), err)
	assert.EqualError(t, calcDiv("text", "1", nil), err)
}

1504
func TestCalcISBLANK(t *testing.T) {
1505 1506 1507 1508 1509
	argsList := list.New()
	argsList.PushBack(formulaArg{
		Type: ArgUnknown,
	})
	fn := formulaFuncs{}
1510 1511 1512
	result := fn.ISBLANK(argsList)
	assert.Equal(t, result.String, "TRUE")
	assert.Empty(t, result.Error)
1513 1514
}

1515
func TestCalcAND(t *testing.T) {
1516 1517 1518 1519 1520
	argsList := list.New()
	argsList.PushBack(formulaArg{
		Type: ArgUnknown,
	})
	fn := formulaFuncs{}
1521
	result := fn.AND(argsList)
1522
	assert.Equal(t, result.String, "")
1523
	assert.Empty(t, result.Error)
1524 1525
}

1526
func TestCalcOR(t *testing.T) {
1527 1528 1529 1530 1531
	argsList := list.New()
	argsList.PushBack(formulaArg{
		Type: ArgUnknown,
	})
	fn := formulaFuncs{}
1532 1533 1534
	result := fn.OR(argsList)
	assert.Equal(t, result.String, "FALSE")
	assert.Empty(t, result.Error)
1535 1536
}

1537
func TestCalcDet(t *testing.T) {
1538 1539 1540 1541 1542 1543 1544
	assert.Equal(t, det([][]float64{
		{1, 2, 3, 4},
		{2, 3, 4, 5},
		{3, 4, 5, 6},
		{4, 5, 6, 7},
	}), float64(0))
}
xurime's avatar
xurime 已提交
1545

1546 1547 1548 1549 1550
func TestCalcToBool(t *testing.T) {
	b := newBoolFormulaArg(true).ToBool()
	assert.Equal(t, b.Boolean, true)
	assert.Equal(t, b.Number, 1.0)
}
1551 1552 1553 1554 1555 1556 1557

func TestCalcToList(t *testing.T) {
	assert.Equal(t, []formulaArg(nil), newEmptyFormulaArg().ToList())
	formulaList := []formulaArg{newEmptyFormulaArg()}
	assert.Equal(t, formulaList, newListFormulaArg(formulaList).ToList())
}

1558
func TestCalcCompareFormulaArg(t *testing.T) {
xurime's avatar
xurime 已提交
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
	assert.Equal(t, compareFormulaArg(newEmptyFormulaArg(), newEmptyFormulaArg(), false, false), criteriaEq)
	lhs := newListFormulaArg([]formulaArg{newEmptyFormulaArg()})
	rhs := newListFormulaArg([]formulaArg{newEmptyFormulaArg(), newEmptyFormulaArg()})
	assert.Equal(t, compareFormulaArg(lhs, rhs, false, false), criteriaL)
	assert.Equal(t, compareFormulaArg(rhs, lhs, false, false), criteriaG)

	lhs = newListFormulaArg([]formulaArg{newBoolFormulaArg(true)})
	rhs = newListFormulaArg([]formulaArg{newBoolFormulaArg(true)})
	assert.Equal(t, compareFormulaArg(lhs, rhs, false, false), criteriaEq)

	assert.Equal(t, compareFormulaArg(formulaArg{Type: ArgUnknown}, formulaArg{Type: ArgUnknown}, false, false), criteriaErr)
}

1572
func TestCalcMatchPattern(t *testing.T) {
xurime's avatar
xurime 已提交
1573 1574 1575 1576 1577
	assert.True(t, matchPattern("", ""))
	assert.True(t, matchPattern("file/*", "file/abc/bcd/def"))
	assert.True(t, matchPattern("*", ""))
	assert.False(t, matchPattern("file/?", "file/abc/bcd/def"))
}
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613

func TestCalcVLOOKUP(t *testing.T) {
	cellData := [][]interface{}{
		{nil, nil, nil, nil, nil, nil},
		{nil, "Score", "Grade", nil, nil, nil},
		{nil, 0, "F", nil, "Score", 85},
		{nil, 60, "D", nil, "Grade"},
		{nil, 70, "C", nil, nil, nil},
		{nil, 80, "b", nil, nil, nil},
		{nil, 90, "A", nil, nil, nil},
		{nil, 85, "B", nil, nil, nil},
		{nil, nil, nil, nil, nil, nil},
	}
	f := prepareCalcData(cellData)
	calc := map[string]string{
		"=VLOOKUP(F3,B3:C8,2)":       "b",
		"=VLOOKUP(F3,B3:C8,2,TRUE)":  "b",
		"=VLOOKUP(F3,B3:C8,2,FALSE)": "B",
	}
	for formula, expected := range calc {
		assert.NoError(t, f.SetCellFormula("Sheet1", "F4", formula))
		result, err := f.CalcCellValue("Sheet1", "F4")
		assert.NoError(t, err, formula)
		assert.Equal(t, expected, result, formula)
	}
	calcError := map[string]string{
		"=VLOOKUP(INT(1),C3:C3,1,FALSE)": "VLOOKUP no result found",
	}
	for formula, expected := range calcError {
		assert.NoError(t, f.SetCellFormula("Sheet1", "F4", formula))
		result, err := f.CalcCellValue("Sheet1", "F4")
		assert.EqualError(t, err, expected, formula)
		assert.Equal(t, "", result, formula)
	}
}

xurime's avatar
xurime 已提交
1614
func TestCalcBoolean(t *testing.T) {
1615
	cellData := [][]interface{}{
1616
		{0.5, "TRUE", -0.5, "FALSE"},
1617 1618 1619
	}
	f := prepareCalcData(cellData)
	formulaList := map[string]string{
xurime's avatar
xurime 已提交
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631
		"=AVERAGEA(A1:C1)":  "0.333333333333333",
		"=MAX(0.5,B1)":      "0.5",
		"=MAX(A1:B1)":       "0.5",
		"=MAXA(A1:B1)":      "1",
		"=MAXA(0.5,B1)":     "1",
		"=MIN(-0.5,D1)":     "-0.5",
		"=MIN(C1:D1)":       "-0.5",
		"=MINA(C1:D1)":      "-0.5",
		"=MINA(-0.5,D1)":    "-0.5",
		"=STDEV(A1:C1)":     "0.707106781186548",
		"=STDEV(A1,B1,C1)":  "0.707106781186548",
		"=STDEVA(A1:C1,B1)": "0.707106781186548",
1632 1633 1634 1635 1636 1637 1638 1639 1640
	}
	for formula, expected := range formulaList {
		assert.NoError(t, f.SetCellFormula("Sheet1", "B10", formula))
		result, err := f.CalcCellValue("Sheet1", "B10")
		assert.NoError(t, err, formula)
		assert.Equal(t, expected, result, formula)
	}
}

1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
func TestCalcHLOOKUP(t *testing.T) {
	cellData := [][]interface{}{
		{"Example Result Table"},
		{nil, "A", "B", "C", "E", "F"},
		{"Math", .58, .9, .67, .76, .8},
		{"French", .61, .71, .59, .59, .76},
		{"Physics", .75, .45, .39, .52, .69},
		{"Biology", .39, .55, .77, .61, .45},
		{},
		{"Individual Student Score"},
		{"Student:", "Biology Score:"},
		{"E"},
	}
	f := prepareCalcData(cellData)
	formulaList := map[string]string{
		"=HLOOKUP(A10,A2:F6,5,FALSE)":  "0.61",
		"=HLOOKUP(D3,D3:D3,1,TRUE)":    "0.67",
		"=HLOOKUP(F3,D3:F3,1,TRUE)":    "0.8",
		"=HLOOKUP(A5,A2:F2,1,TRUE)":    "F",
		"=HLOOKUP(\"D\",A2:F2,1,TRUE)": "C",
	}
	for formula, expected := range formulaList {
		assert.NoError(t, f.SetCellFormula("Sheet1", "B10", formula))
		result, err := f.CalcCellValue("Sheet1", "B10")
		assert.NoError(t, err, formula)
		assert.Equal(t, expected, result, formula)
	}
	calcError := map[string]string{
		"=HLOOKUP(INT(1),A3:A3,1,FALSE)": "HLOOKUP no result found",
	}
	for formula, expected := range calcError {
		assert.NoError(t, f.SetCellFormula("Sheet1", "B10", formula))
		result, err := f.CalcCellValue("Sheet1", "B10")
		assert.EqualError(t, err, expected, formula)
		assert.Equal(t, "", result, formula)
	}
}