This improved formula calculate precision and added zero placeholder number format support

This commit is contained in:
xuri 2022-03-19 00:05:47 +08:00
parent 14b461420f
commit 94f197c4fe
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
10 changed files with 178 additions and 130 deletions

View File

@ -5,7 +5,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.16.x, 1.17.x]
go-version: [1.15.x, 1.16.x, 1.17.x, 1.18.x]
os: [ubuntu-latest, macos-latest, windows-latest]
targetplatform: [x86, x64]

View File

@ -65,19 +65,19 @@ func TestCalcCellValue(t *testing.T) {
`="A"<>"A"`: "FALSE",
// Engineering Functions
// BESSELI
"=BESSELI(4.5,1)": "15.389222753735925",
"=BESSELI(4.5,1)": "15.3892227537359",
"=BESSELI(32,1)": "5502845511211.25",
// BESSELJ
"=BESSELJ(1.9,2)": "0.329925727692387",
// BESSELK
"=BESSELK(0.05,0)": "3.11423403428966",
"=BESSELK(0.05,1)": "19.90967432724863",
"=BESSELK(0.05,1)": "19.9096743272486",
"=BESSELK(0.05,2)": "799.501207124235",
"=BESSELK(3,2)": "0.0615104585619118",
// BESSELY
"=BESSELY(0.05,0)": "-1.97931100684153",
"=BESSELY(0.05,1)": "-12.789855163794034",
"=BESSELY(0.05,2)": "-509.61489554491976",
"=BESSELY(0.05,1)": "-12.789855163794",
"=BESSELY(0.05,2)": "-509.61489554492",
"=BESSELY(9,2)": "-0.229082087487741",
// BIN2DEC
"=BIN2DEC(\"10\")": "2",
@ -213,7 +213,7 @@ func TestCalcCellValue(t *testing.T) {
"=IMCOSH(\"2-i\")": "2.0327230070196656-3.0518977991518i",
"=IMCOSH(COMPLEX(1,-1))": "0.8337300251311491-0.9888977057628651i",
// IMCOT
"=IMCOT(0.5)": "1.830487721712452",
"=IMCOT(0.5)": "1.83048772171245",
"=IMCOT(\"3+0.5i\")": "-0.4793455787473728-2.016092521506228i",
"=IMCOT(\"2-i\")": "-0.171383612909185+0.8213297974938518i",
"=IMCOT(COMPLEX(1,-1))": "0.21762156185440268+0.868014142895925i",
@ -247,7 +247,7 @@ func TestCalcCellValue(t *testing.T) {
"=IMREAL(\"3i\")": "0",
"=IMREAL(COMPLEX(4,1))": "4",
// IMSEC
"=IMSEC(0.5)": "1.139493927324549",
"=IMSEC(0.5)": "1.13949392732455",
"=IMSEC(\"3+0.5i\")": "-0.8919131797403304+0.05875317818173977i",
"=IMSEC(\"2-i\")": "-0.4131493442669401-0.687527438655479i",
"=IMSEC(COMPLEX(1,-1))": "0.49833703055518686-0.5910838417210451i",
@ -271,7 +271,7 @@ func TestCalcCellValue(t *testing.T) {
"=IMSQRT(\"i\")": "0.7071067811865476+0.7071067811865476i",
"=IMSQRT(\"2-i\")": "1.455346690225355-0.34356074972251244i",
"=IMSQRT(\"5+2i\")": "2.27872385417085+0.4388421169022545i",
"=IMSQRT(6)": "2.449489742783178",
"=IMSQRT(6)": "2.44948974278318",
"=IMSQRT(\"-2-4i\")": "1.1117859405028423-1.7989074399478673i",
// IMSUB
"=IMSUB(\"5+i\",\"1+4i\")": "4-3i",
@ -313,17 +313,17 @@ func TestCalcCellValue(t *testing.T) {
"=ABS(2-4.5)": "2.5",
"=ABS(ABS(-1))": "1",
// ACOS
"=ACOS(-1)": "3.141592653589793",
"=ACOS(-1)": "3.14159265358979",
"=ACOS(0)": "1.5707963267949",
"=ACOS(ABS(0))": "1.5707963267949",
// ACOSH
"=ACOSH(1)": "0",
"=ACOSH(2.5)": "1.566799236972411",
"=ACOSH(2.5)": "1.56679923697241",
"=ACOSH(5)": "2.29243166956118",
"=ACOSH(ACOSH(5))": "1.47138332153668",
// ACOT
"=_xlfn.ACOT(1)": "0.785398163397448",
"=_xlfn.ACOT(-2)": "2.677945044588987",
"=_xlfn.ACOT(-2)": "2.67794504458899",
"=_xlfn.ACOT(0)": "1.5707963267949",
"=_xlfn.ACOT(_xlfn.ACOT(0))": "0.566911504941009",
// ACOTH
@ -445,9 +445,9 @@ func TestCalcCellValue(t *testing.T) {
`=_xlfn.DECIMAL("70122",8)`: "28754",
`=_xlfn.DECIMAL("0x70122",8)`: "28754",
// DEGREES
"=DEGREES(1)": "57.29577951308232",
"=DEGREES(2.5)": "143.2394487827058",
"=DEGREES(DEGREES(1))": "3282.806350011744",
"=DEGREES(1)": "57.2957795130823",
"=DEGREES(2.5)": "143.239448782706",
"=DEGREES(DEGREES(1))": "3282.80635001174",
// EVEN
"=EVEN(23)": "24",
"=EVEN(2.22)": "4",
@ -461,7 +461,7 @@ func TestCalcCellValue(t *testing.T) {
"=EXP(0.1)": "1.10517091807565",
"=EXP(0)": "1",
"=EXP(-5)": "0.00673794699908547",
"=EXP(EXP(0))": "2.718281828459045",
"=EXP(EXP(0))": "2.71828182845905",
// FACT
"=FACT(3)": "6",
"=FACT(6)": "720",
@ -473,12 +473,12 @@ func TestCalcCellValue(t *testing.T) {
"=FACTDOUBLE(13)": "135135",
"=FACTDOUBLE(FACTDOUBLE(1))": "1",
// FLOOR
"=FLOOR(26.75,0.1)": "26.700000000000003",
"=FLOOR(26.75,0.1)": "26.7",
"=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,-0.1)": "-26.7",
"=FLOOR(-26.75,-1)": "-26",
"=FLOOR(-26.75,-5)": "-25",
"=FLOOR(FLOOR(26.75,1),1)": "26",
@ -493,7 +493,7 @@ func TestCalcCellValue(t *testing.T) {
"=_xlfn.FLOOR.MATH(-58.55,10)": "-60",
"=_xlfn.FLOOR.MATH(_xlfn.FLOOR.MATH(1),10)": "0",
// _xlfn.FLOOR.PRECISE
"=_xlfn.FLOOR.PRECISE(26.75,0.1)": "26.700000000000003",
"=_xlfn.FLOOR.PRECISE(26.75,0.1)": "26.7",
"=_xlfn.FLOOR.PRECISE(26.75,0.5)": "26.5",
"=_xlfn.FLOOR.PRECISE(26.75,1)": "26",
"=_xlfn.FLOOR.PRECISE(26.75)": "26",
@ -524,7 +524,7 @@ func TestCalcCellValue(t *testing.T) {
"=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,0.1)": "-22.2",
"=ISO.CEILING(-22.25,5)": "-20",
"=ISO.CEILING(-22.25,0)": "0",
"=ISO.CEILING(1,ISO.CEILING(1,0))": "0",
@ -539,7 +539,7 @@ func TestCalcCellValue(t *testing.T) {
`=LCM(0,LCM(0,0))`: "0",
// LN
"=LN(1)": "0",
"=LN(100)": "4.605170185988092",
"=LN(100)": "4.60517018598809",
"=LN(0.5)": "-0.693147180559945",
"=LN(LN(100))": "1.5271796258079",
// LOG
@ -557,7 +557,7 @@ func TestCalcCellValue(t *testing.T) {
// IMLOG2
"=IMLOG2(\"5+2i\")": "2.4289904975637864+0.5489546632866347i",
"=IMLOG2(\"2-i\")": "1.1609640474436813-0.6689021062254881i",
"=IMLOG2(6)": "2.584962500721156",
"=IMLOG2(6)": "2.58496250072116",
"=IMLOG2(\"3i\")": "1.584962500721156+2.266180070913597i",
"=IMLOG2(\"4+i\")": "2.04373142062517+0.3534295024167349i",
// IMPOWER
@ -604,7 +604,7 @@ func TestCalcCellValue(t *testing.T) {
"=ODD(-3)": "-3",
"=ODD(ODD(1))": "1",
// PI
"=PI()": "3.141592653589793",
"=PI()": "3.14159265358979",
// POWER
"=POWER(4,2)": "16",
"=POWER(4,POWER(1,1))": "4",
@ -619,9 +619,9 @@ func TestCalcCellValue(t *testing.T) {
"=QUOTIENT(QUOTIENT(1,2),3)": "0",
// RADIANS
"=RADIANS(50)": "0.872664625997165",
"=RADIANS(-180)": "-3.141592653589793",
"=RADIANS(180)": "3.141592653589793",
"=RADIANS(360)": "6.283185307179586",
"=RADIANS(-180)": "-3.14159265358979",
"=RADIANS(180)": "3.14159265358979",
"=RADIANS(360)": "6.28318530717959",
"=RADIANS(RADIANS(360))": "0.109662271123215",
// ROMAN
"=ROMAN(499,0)": "CDXCIX",
@ -634,9 +634,9 @@ func TestCalcCellValue(t *testing.T) {
"=ROMAN(1999,5)": "MIM",
"=ROMAN(1999,ODD(1))": "MLMVLIV",
// ROUND
"=ROUND(100.319,1)": "100.30000000000001",
"=ROUND(5.28,1)": "5.300000000000001",
"=ROUND(5.9999,3)": "6.000000000000002",
"=ROUND(100.319,1)": "100.3",
"=ROUND(5.28,1)": "5.3",
"=ROUND(5.9999,3)": "6",
"=ROUND(99.5,0)": "100",
"=ROUND(-6.3,0)": "-6",
"=ROUND(-100.5,0)": "-101",
@ -646,18 +646,18 @@ func TestCalcCellValue(t *testing.T) {
"=ROUND(ROUND(100,1),-1)": "100",
// ROUNDDOWN
"=ROUNDDOWN(99.999,1)": "99.9",
"=ROUNDDOWN(99.999,2)": "99.99000000000002",
"=ROUNDDOWN(99.999,2)": "99.99",
"=ROUNDDOWN(99.999,0)": "99",
"=ROUNDDOWN(99.999,-1)": "90",
"=ROUNDDOWN(-99.999,2)": "-99.99000000000002",
"=ROUNDDOWN(-99.999,2)": "-99.99",
"=ROUNDDOWN(-99.999,-1)": "-90",
"=ROUNDDOWN(ROUNDDOWN(100,1),-1)": "100",
// ROUNDUP`
"=ROUNDUP(11.111,1)": "11.200000000000001",
"=ROUNDUP(11.111,2)": "11.120000000000003",
"=ROUNDUP(11.111,1)": "11.2",
"=ROUNDUP(11.111,2)": "11.12",
"=ROUNDUP(11.111,0)": "12",
"=ROUNDUP(11.111,-1)": "20",
"=ROUNDUP(-11.111,2)": "-11.120000000000003",
"=ROUNDUP(-11.111,2)": "-11.12",
"=ROUNDUP(-11.111,-1)": "-20",
"=ROUNDUP(ROUNDUP(100,1),-1)": "100",
// SEC
@ -681,26 +681,26 @@ func TestCalcCellValue(t *testing.T) {
// SINH
"=SINH(0)": "0",
"=SINH(0.5)": "0.521095305493747",
"=SINH(-2)": "-3.626860407847019",
"=SINH(-2)": "-3.62686040784702",
"=SINH(SINH(0))": "0",
// SQRT
"=SQRT(4)": "2",
"=SQRT(SQRT(16))": "2",
// SQRTPI
"=SQRTPI(5)": "3.963327297606011",
"=SQRTPI(5)": "3.96332729760601",
"=SQRTPI(0.2)": "0.792665459521202",
"=SQRTPI(100)": "17.72453850905516",
"=SQRTPI(100)": "17.7245385090552",
"=SQRTPI(0)": "0",
"=SQRTPI(SQRTPI(0))": "0",
// STDEV
"=STDEV(F2:F9)": "10724.978287523809",
"=STDEV(F2:F9)": "10724.9782875238",
"=STDEV(MUNIT(2))": "0.577350269189626",
"=STDEV(0,INT(0))": "0",
"=STDEV(INT(1),INT(1))": "0",
// STDEV.S
"=STDEV.S(F2:F9)": "10724.978287523809",
"=STDEV.S(F2:F9)": "10724.9782875238",
// STDEVA
"=STDEVA(F2:F9)": "10724.978287523809",
"=STDEVA(F2:F9)": "10724.9782875238",
"=STDEVA(MUNIT(2))": "0.577350269189626",
"=STDEVA(0,INT(0))": "0",
// POISSON.DIST
@ -723,7 +723,7 @@ func TestCalcCellValue(t *testing.T) {
"=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",
"=1+SUM(SUM(1,2*3),4)*4/3+5+(4+2)*3": "38.6666666666667",
"=SUM(1+ROW())": "2",
"=SUM((SUM(2))+1)": "3",
// SUMIF
@ -754,7 +754,7 @@ func TestCalcCellValue(t *testing.T) {
// SUMXMY2
"=SUMXMY2(A1:A4,B1:B4)": "18",
// TAN
"=TAN(1.047197551)": "1.732050806782486",
"=TAN(1.047197551)": "1.73205080678249",
"=TAN(0)": "0",
"=TAN(TAN(0))": "0",
// TANH
@ -796,7 +796,7 @@ func TestCalcCellValue(t *testing.T) {
"=BETADIST(0.4,2,100)": "1",
"=BETADIST(0.75,3,4)": "0.96240234375",
"=BETADIST(0.2,0.7,4)": "0.71794309318323",
"=BETADIST(0.01,3,4)": "1.955359E-05",
"=BETADIST(0.01,3,4)": "1.9553589999999998e-05",
"=BETADIST(0.75,130,140)": "1",
// BETAINV
"=BETAINV(0.2,4,5,0,1)": "0.303225844664082",
@ -808,7 +808,7 @@ func TestCalcCellValue(t *testing.T) {
// CHIINV
"=CHIINV(0.5,1)": "0.454936423119572",
"=CHIINV(0.75,1)": "0.101531044267622",
"=CHIINV(0.1,2)": "4.605170185988088",
"=CHIINV(0.1,2)": "4.60517018598809",
"=CHIINV(0.8,2)": "0.446287102628419",
// CONFIDENCE
"=CONFIDENCE(0.05,0.07,100)": "0.0137197479028414",
@ -850,10 +850,10 @@ func TestCalcCellValue(t *testing.T) {
"=FISHERINV(INT(0))": "0",
"=FISHERINV(2.8)": "0.992631520201128",
// GAMMA
"=GAMMA(0.1)": "9.513507698668732",
"=GAMMA(0.1)": "9.51350769866873",
"=GAMMA(INT(1))": "1",
"=GAMMA(1.5)": "0.886226925452758",
"=GAMMA(5.5)": "52.34277778455352",
"=GAMMA(5.5)": "52.3427777845535",
// GAMMA.DIST
"=GAMMA.DIST(6,3,2,FALSE)": "0.112020903827694",
"=GAMMA.DIST(6,3,2,TRUE)": "0.576809918873156",
@ -861,10 +861,10 @@ func TestCalcCellValue(t *testing.T) {
"=GAMMADIST(6,3,2,FALSE)": "0.112020903827694",
"=GAMMADIST(6,3,2,TRUE)": "0.576809918873156",
// GAMMA.INV
"=GAMMA.INV(0.5,3,2)": "5.348120627447122",
"=GAMMA.INV(0.5,3,2)": "5.34812062744712",
"=GAMMA.INV(0.5,0.5,1)": "0.227468211559786",
// GAMMAINV
"=GAMMAINV(0.5,3,2)": "5.348120627447122",
"=GAMMAINV(0.5,3,2)": "5.34812062744712",
"=GAMMAINV(0.5,0.5,1)": "0.227468211559786",
// GAMMALN
"=GAMMALN(4.5)": "2.45373657084244",
@ -925,11 +925,11 @@ func TestCalcCellValue(t *testing.T) {
"=NORMDIST(0.8,1,0.3,TRUE)": "0.252492537546923",
"=NORMDIST(50,40,20,FALSE)": "0.017603266338215",
// NORM.INV
"=NORM.INV(0.6,5,2)": "5.506694205719997",
"=NORM.INV(0.6,5,2)": "5.50669420572",
// NORMINV
"=NORMINV(0.6,5,2)": "5.506694205719997",
"=NORMINV(0.99,40,1.5)": "43.489521811582044",
"=NORMINV(0.02,40,1.5)": "36.91937663649545",
"=NORMINV(0.6,5,2)": "5.50669420572",
"=NORMINV(0.99,40,1.5)": "43.489521811582",
"=NORMINV(0.02,40,1.5)": "36.9193766364954",
// NORM.S.DIST
"=NORM.S.DIST(0.8,TRUE)": "0.788144601416603",
// NORMSDIST
@ -1052,7 +1052,7 @@ func TestCalcCellValue(t *testing.T) {
"=TRIMMEAN(A1:B4,10%)": "2.5",
"=TRIMMEAN(A1:B4,70%)": "2.5",
// VAR
"=VAR(1,3,5,0,C1)": "4.916666666666667",
"=VAR(1,3,5,0,C1)": "4.91666666666667",
"=VAR(1,3,5,0,C1,TRUE)": "4",
// VARA
"=VARA(1,3,5,0,C1)": "4.7",
@ -1063,16 +1063,16 @@ func TestCalcCellValue(t *testing.T) {
// VAR.P
"=VAR.P(A1:A5)": "1.25",
// VAR.S
"=VAR.S(1,3,5,0,C1)": "4.916666666666667",
"=VAR.S(1,3,5,0,C1)": "4.91666666666667",
"=VAR.S(1,3,5,0,C1,TRUE)": "4",
// VARPA
"=VARPA(1,3,5,0,C1)": "3.76",
"=VARPA(1,3,5,0,C1,TRUE)": "3.22222222222222",
// WEIBULL
"=WEIBULL(1,3,1,FALSE)": "1.103638323514327",
"=WEIBULL(1,3,1,FALSE)": "1.10363832351433",
"=WEIBULL(2,5,1.5,TRUE)": "0.985212776817482",
// WEIBULL.DIST
"=WEIBULL.DIST(1,3,1,FALSE)": "1.103638323514327",
"=WEIBULL.DIST(1,3,1,FALSE)": "1.10363832351433",
"=WEIBULL.DIST(2,5,1.5,TRUE)": "0.985212776817482",
// Information Functions
// ERROR.TYPE
@ -1286,7 +1286,7 @@ func TestCalcCellValue(t *testing.T) {
"=YEARFRAC(\"01/31/2015\",\"03/31/2015\")": "0.166666666666667",
"=YEARFRAC(\"01/30/2015\",\"03/31/2015\")": "0.166666666666667",
"=YEARFRAC(\"02/29/2000\", \"02/29/2008\")": "8",
"=YEARFRAC(\"02/29/2000\", \"02/29/2008\",1)": "7.998175182481752",
"=YEARFRAC(\"02/29/2000\", \"02/29/2008\",1)": "7.99817518248175",
"=YEARFRAC(\"02/29/2000\", \"01/29/2001\",1)": "0.915300546448087",
"=YEARFRAC(\"02/29/2000\", \"03/29/2000\",1)": "0.0792349726775956",
"=YEARFRAC(\"01/31/2000\", \"03/29/2000\",4)": "0.163888888888889",
@ -1472,7 +1472,7 @@ func TestCalcCellValue(t *testing.T) {
"=VALUE(\"5,000\")": "5000",
"=VALUE(\"20%\")": "0.2",
"=VALUE(\"12:00:00\")": "0.5",
"=VALUE(\"01/02/2006 15:04:05\")": "38719.62783564815",
"=VALUE(\"01/02/2006 15:04:05\")": "38719.6278356481",
// Conditional Functions
// IF
"=IF(1=1)": "TRUE",
@ -1627,16 +1627,16 @@ func TestCalcCellValue(t *testing.T) {
"=COUPPCD(\"10/25/2011\",\"01/01/2012\",4)": "40817",
// CUMIPMT
"=CUMIPMT(0.05/12,60,50000,1,12,0)": "-2294.97753732664",
"=CUMIPMT(0.05/12,60,50000,13,24,0)": "-1833.1000665738893",
"=CUMIPMT(0.05/12,60,50000,13,24,0)": "-1833.10006657389",
// CUMPRINC
"=CUMPRINC(0.05/12,60,50000,1,12,0)": "-9027.762649079885",
"=CUMPRINC(0.05/12,60,50000,13,24,0)": "-9489.640119832635",
"=CUMPRINC(0.05/12,60,50000,1,12,0)": "-9027.76264907988",
"=CUMPRINC(0.05/12,60,50000,13,24,0)": "-9489.64011983263",
// DB
"=DB(0,1000,5,1)": "0",
"=DB(10000,1000,5,1)": "3690",
"=DB(10000,1000,5,2)": "2328.39",
"=DB(10000,1000,5,1,6)": "1845",
"=DB(10000,1000,5,6,6)": "238.52712458788187",
"=DB(10000,1000,5,6,6)": "238.527124587882",
// DDB
"=DDB(0,1000,5,1)": "0",
"=DDB(10000,1000,5,1)": "4000",
@ -1651,13 +1651,13 @@ func TestCalcCellValue(t *testing.T) {
// DOLLARFR
"=DOLLARFR(1.0625,16)": "1.01",
// DURATION
"=DURATION(\"04/01/2015\",\"03/31/2025\",10%,8%,4)": "6.674422798483131",
"=DURATION(\"04/01/2015\",\"03/31/2025\",10%,8%,4)": "6.67442279848313",
// EFFECT
"=EFFECT(0.1,4)": "0.103812890625",
"=EFFECT(0.025,2)": "0.02515625",
// FV
"=FV(0.05/12,60,-1000)": "68006.08284084337",
"=FV(0.1/4,16,-2000,0,1)": "39729.46089416617",
"=FV(0.05/12,60,-1000)": "68006.0828408434",
"=FV(0.1/4,16,-2000,0,1)": "39729.4608941662",
"=FV(0,16,-2000)": "32000",
// FVSCHEDULE
"=FVSCHEDULE(10000,A1:A5)": "240000",
@ -1665,60 +1665,60 @@ func TestCalcCellValue(t *testing.T) {
// INTRATE
"=INTRATE(\"04/01/2005\",\"03/31/2010\",1000,2125)": "0.225",
// IPMT
"=IPMT(0.05/12,2,60,50000)": "-205.26988187971995",
"=IPMT(0.035/4,2,8,0,5000,1)": "5.257455237829077",
"=IPMT(0.05/12,2,60,50000)": "-205.26988187972",
"=IPMT(0.035/4,2,8,0,5000,1)": "5.25745523782908",
// ISPMT
"=ISPMT(0.05/12,1,60,50000)": "-204.8611111111111",
"=ISPMT(0.05/12,2,60,50000)": "-201.38888888888886",
"=ISPMT(0.05/12,2,1,50000)": "208.33333333333334",
"=ISPMT(0.05/12,1,60,50000)": "-204.861111111111",
"=ISPMT(0.05/12,2,60,50000)": "-201.388888888889",
"=ISPMT(0.05/12,2,1,50000)": "208.333333333333",
// MDURATION
"=MDURATION(\"04/01/2015\",\"03/31/2025\",10%,8%,4)": "6.543551763218756",
"=MDURATION(\"04/01/2015\",\"03/31/2025\",10%,8%,4)": "6.54355176321876",
// NOMINAL
"=NOMINAL(0.025,12)": "0.0247180352381129",
// NPER
"=NPER(0.04,-6000,50000)": "10.338035071507665",
"=NPER(0,-6000,50000)": "8.333333333333334",
"=NPER(0.06/4,-2000,60000,30000,1)": "52.794773709274764",
"=NPER(0.04,-6000,50000)": "10.3380350715077",
"=NPER(0,-6000,50000)": "8.33333333333333",
"=NPER(0.06/4,-2000,60000,30000,1)": "52.7947737092748",
// NPV
"=NPV(0.02,-5000,\"\",800)": "-4133.025759323337",
"=NPV(0.02,-5000,\"\",800)": "-4133.02575932334",
// ODDFPRICE
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,2)": "107.69183025662932",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,1)": "106.76691501092883",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,3)": "106.7819138146997",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,4)": "106.77191377246672",
"=ODDFPRICE(\"11/11/2008\",\"03/01/2021\",\"10/15/2008\",\"03/01/2009\",7.85%,6.25%,100,2,1)": "113.59771747407883",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"09/30/2017\",5.5%,3.5%,100,4,0)": "106.72930611878041",
"=ODDFPRICE(\"11/11/2008\",\"03/29/2021\", \"08/15/2008\", \"03/29/2009\", 0.0785, 0.0625, 100, 2, 1)": "113.61826640813996",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,2)": "107.691830256629",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,1)": "106.766915010929",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,3)": "106.7819138147",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"03/31/2017\",5.5%,3.5%,100,4,4)": "106.771913772467",
"=ODDFPRICE(\"11/11/2008\",\"03/01/2021\",\"10/15/2008\",\"03/01/2009\",7.85%,6.25%,100,2,1)": "113.597717474079",
"=ODDFPRICE(\"02/01/2017\",\"03/31/2021\",\"12/01/2016\",\"09/30/2017\",5.5%,3.5%,100,4,0)": "106.72930611878",
"=ODDFPRICE(\"11/11/2008\",\"03/29/2021\", \"08/15/2008\", \"03/29/2009\", 0.0785, 0.0625, 100, 2, 1)": "113.61826640814",
// PDURATION
"=PDURATION(0.04,10000,15000)": "10.33803507150765",
"=PDURATION(0.04,10000,15000)": "10.3380350715076",
// PMT
"=PMT(0,8,0,5000,1)": "-625",
"=PMT(0.035/4,8,0,5000,1)": "-600.8520271804658",
"=PMT(0.035/4,8,0,5000,1)": "-600.852027180466",
// PRICE
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2)": "110.65510517844305",
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2,4)": "110.65510517844305",
"=PRICE(\"04/01/2012\",\"03/31/2020\",12%,10%,100,2)": "110.83448359321572",
"=PRICE(\"01/01/2010\",\"06/30/2010\",0.5,1,1,1,4)": "8.924190888476605",
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2)": "110.655105178443",
"=PRICE(\"04/01/2012\",\"02/01/2020\",12%,10%,100,2,4)": "110.655105178443",
"=PRICE(\"04/01/2012\",\"03/31/2020\",12%,10%,100,2)": "110.834483593216",
"=PRICE(\"01/01/2010\",\"06/30/2010\",0.5,1,1,1,4)": "8.92419088847661",
// PPMT
"=PPMT(0.05/12,2,60,50000)": "-738.2918003208238",
"=PPMT(0.035/4,2,8,0,5000,1)": "-606.1094824182949",
"=PPMT(0.05/12,2,60,50000)": "-738.291800320824",
"=PPMT(0.035/4,2,8,0,5000,1)": "-606.109482418295",
// PRICEDISC
"=PRICEDISC(\"04/01/2017\",\"03/31/2021\",2.5%,100)": "90",
"=PRICEDISC(\"04/01/2017\",\"03/31/2021\",2.5%,100,3)": "90",
// PRICEMAT
"=PRICEMAT(\"04/01/2017\",\"03/31/2021\",\"01/01/2017\",4.5%,2.5%)": "107.17045454545453",
"=PRICEMAT(\"04/01/2017\",\"03/31/2021\",\"01/01/2017\",4.5%,2.5%,0)": "107.17045454545453",
"=PRICEMAT(\"04/01/2017\",\"03/31/2021\",\"01/01/2017\",4.5%,2.5%)": "107.170454545455",
"=PRICEMAT(\"04/01/2017\",\"03/31/2021\",\"01/01/2017\",4.5%,2.5%,0)": "107.170454545455",
// PV
"=PV(0,60,1000)": "-60000",
"=PV(5%/12,60,1000)": "-52990.70632392748",
"=PV(10%/4,16,2000,0,1)": "-26762.75545288113",
"=PV(5%/12,60,1000)": "-52990.7063239275",
"=PV(10%/4,16,2000,0,1)": "-26762.7554528811",
// RATE
"=RATE(60,-1000,50000)": "0.0061834131621292",
"=RATE(24,-800,0,20000,1)": "0.00325084350160374",
"=RATE(48,-200,8000,3,1,0.5)": "0.0080412665831637",
// RECEIVED
"=RECEIVED(\"04/01/2011\",\"03/31/2016\",1000,4.5%)": "1290.3225806451612",
"=RECEIVED(\"04/01/2011\",\"03/31/2016\",1000,4.5%,0)": "1290.3225806451612",
"=RECEIVED(\"04/01/2011\",\"03/31/2016\",1000,4.5%)": "1290.32258064516",
"=RECEIVED(\"04/01/2011\",\"03/31/2016\",1000,4.5%,0)": "1290.32258064516",
// RRI
"=RRI(10,10000,15000)": "0.0413797439924106",
// SLN
@ -1729,7 +1729,7 @@ func TestCalcCellValue(t *testing.T) {
// TBILLEQ
"=TBILLEQ(\"01/01/2017\",\"06/30/2017\",2.5%)": "0.0256680731364276",
// TBILLPRICE
"=TBILLPRICE(\"02/01/2017\",\"06/30/2017\",2.75%)": "98.86180555555556",
"=TBILLPRICE(\"02/01/2017\",\"06/30/2017\",2.75%)": "98.8618055555556",
// TBILLYIELD
"=TBILLYIELD(\"02/01/2017\",\"06/30/2017\",99)": "0.024405125076266",
// VDB
@ -1739,10 +1739,10 @@ func TestCalcCellValue(t *testing.T) {
"=VDB(10000,1000,5,3,5,0.2,FALSE)": "3600",
"=VDB(10000,1000,5,3,5,0.2,TRUE)": "693.633024",
"=VDB(24000,3000,10,0,0.875,2)": "4200",
"=VDB(24000,3000,10,0.1,1)": "4233.599999999999",
"=VDB(24000,3000,10,0.1,1,1)": "2138.3999999999996",
"=VDB(24000,3000,100,50,100,1)": "10377.294418465235",
"=VDB(24000,3000,100,50,100,2)": "5740.072322090805",
"=VDB(24000,3000,10,0.1,1)": "4233.6",
"=VDB(24000,3000,10,0.1,1,1)": "2138.4",
"=VDB(24000,3000,100,50,100,1)": "10377.2944184652",
"=VDB(24000,3000,100,50,100,2)": "5740.0723220908",
// YIELD
"=YIELD(\"01/01/2010\",\"06/30/2015\",10%,101,100,4)": "0.0975631546829798",
"=YIELD(\"01/01/2010\",\"06/30/2015\",10%,101,100,4,4)": "0.0976269355643988",
@ -4284,7 +4284,7 @@ func TestCalcXNPV(t *testing.T) {
}
f := prepareCalcData(cellData)
formulaList := map[string]string{
"=XNPV(B1,B2:B7,A2:A7)": "4447.938009440515",
"=XNPV(B1,B2:B7,A2:A7)": "4447.93800944052",
}
for formula, expected := range formulaList {
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))

22
cell.go
View File

@ -1088,22 +1088,12 @@ func (f *File) formattedValue(s int, v string, raw bool) string {
if raw {
return v
}
precise := v
isNum, precision := isNumeric(v)
if isNum {
if precision > 15 {
precise = roundPrecision(v, 15)
}
if precision <= 15 {
precise = roundPrecision(v, -1)
}
}
if s == 0 {
return precise
return v
}
styleSheet := f.stylesReader()
if s >= len(styleSheet.CellXfs.Xf) {
return precise
return v
}
var numFmtID int
if styleSheet.CellXfs.Xf[s].NumFmtID != nil {
@ -1112,17 +1102,17 @@ func (f *File) formattedValue(s int, v string, raw bool) string {
ok := builtInNumFmtFunc[numFmtID]
if ok != nil {
return ok(precise, builtInNumFmt[numFmtID])
return ok(v, builtInNumFmt[numFmtID])
}
if styleSheet == nil || styleSheet.NumFmts == nil {
return precise
return v
}
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
if xlsxFmt.NumFmtID == numFmtID {
return format(precise, xlsxFmt.FormatCode)
return format(v, xlsxFmt.FormatCode)
}
}
return precise
return v
}
// prepareCellStyle provides a function to prepare style index of cell in

View File

@ -81,7 +81,7 @@ func (f *File) SaveAs(name string, opt ...Options) error {
return ErrWorkbookExt
}
f.setContentTypePartProjectExtensions(contentType)
file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o600)
if err != nil {
return err
}

7
lib.go
View File

@ -688,12 +688,15 @@ func isNumeric(s string) (bool, int) {
if i == 0 && v == '-' {
continue
}
if e && (v == '+' || v == '-') {
if e && v == '-' {
return true, 0
}
if e && v == '+' {
p = 15
continue
}
return false, 0
} else if dot {
} else {
p++
}
n = true

View File

@ -342,7 +342,7 @@ func TestReadBytes(t *testing.T) {
func TestUnzipToTemp(t *testing.T) {
os.Setenv("TMPDIR", "test")
defer os.Unsetenv("TMPDIR")
assert.NoError(t, os.Chmod(os.TempDir(), 0444))
assert.NoError(t, os.Chmod(os.TempDir(), 0o444))
f := NewFile()
data := []byte("PK\x03\x040000000PK\x01\x0200000" +
"0000000000000000000\x00" +
@ -364,7 +364,7 @@ func TestUnzipToTemp(t *testing.T) {
_, err = f.unzipToTemp(z.File[0])
require.Error(t, err)
assert.NoError(t, os.Chmod(os.TempDir(), 0755))
assert.NoError(t, os.Chmod(os.TempDir(), 0o755))
_, err = f.unzipToTemp(z.File[0])
assert.EqualError(t, err, "EOF")

View File

@ -13,6 +13,7 @@ package excelize
import (
"fmt"
"math"
"strconv"
"strings"
"time"
@ -41,13 +42,15 @@ type numberFormat struct {
var (
// supportedTokenTypes list the supported number format token types currently.
supportedTokenTypes = []string{
nfp.TokenSubTypeLanguageInfo,
nfp.TokenTypeColor,
nfp.TokenTypeCurrencyLanguage,
nfp.TokenTypeDateTimes,
nfp.TokenTypeElapsedDateTimes,
nfp.TokenTypeGeneral,
nfp.TokenTypeLiteral,
nfp.TokenTypeTextPlaceHolder,
nfp.TokenSubTypeLanguageInfo,
nfp.TokenTypeZeroPlaceHolder,
}
// supportedLanguageInfo directly maps the supported language ID and tags.
supportedLanguageInfo = map[string]languageInfo{
@ -276,11 +279,9 @@ var (
// prepareNumberic split the number into two before and after parts by a
// decimal point.
func (nf *numberFormat) prepareNumberic(value string) {
prec := 0
if nf.isNumberic, prec = isNumeric(value); !nf.isNumberic {
if nf.isNumberic, _ = isNumeric(value); !nf.isNumberic {
return
}
nf.beforePoint, nf.afterPoint = value[:len(value)-prec-1], value[len(value)-prec:]
}
// format provides a function to return a string parse by number format
@ -336,6 +337,20 @@ func (nf *numberFormat) positiveHandler() (result string) {
nf.result += token.TValue
continue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == "0" {
if isNum, precision := isNumeric(nf.value); isNum {
if nf.number < 1 {
nf.result += "0"
continue
}
if precision > 15 {
nf.result += roundPrecision(nf.value, 15)
} else {
nf.result += fmt.Sprintf("%.f", nf.number)
}
continue
}
}
}
result = nf.result
return
@ -874,8 +889,33 @@ func (nf *numberFormat) secondsNext(i int) bool {
// negativeHandler will be handling negative selection for a number format
// expression.
func (nf *numberFormat) negativeHandler() string {
return nf.value
func (nf *numberFormat) negativeHandler() (result string) {
for _, token := range nf.section[nf.sectionIdx].Items {
if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral {
result = nf.value
return
}
if token.TType == nfp.TokenTypeLiteral {
nf.result += token.TValue
continue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == "0" {
if isNum, precision := isNumeric(nf.value); isNum {
if math.Abs(nf.number) < 1 {
nf.result += "0"
continue
}
if precision > 15 {
nf.result += strings.TrimLeft(roundPrecision(nf.value, 15), "-")
} else {
nf.result += fmt.Sprintf("%.f", math.Abs(nf.number))
}
continue
}
}
}
result = nf.result
return
}
// zeroHandler will be handling zero selection for a number format expression.

View File

@ -996,6 +996,14 @@ func TestNumFmt(t *testing.T) {
{"44896.18957170139", "[$-435]mmmmm dd yyyy h:mm AM/PM", "D 01 2022 4:32 AM"},
{"text_", "General", "text_"},
{"text_", "\"=====\"@@@\"--\"@\"----\"", "=====text_text_text_--text_----"},
{"0.0450685976001E+21", "0_);[Red]\\(0\\)", "45068597600100000000"},
{"8.0450685976001E+21", "0_);[Red]\\(0\\)", "8045068597600100000000"},
{"8.0450685976001E-21", "0_);[Red]\\(0\\)", "0"},
{"8.04506", "0_);[Red]\\(0\\)", "8"},
{"-0.0450685976001E+21", "0_);[Red]\\(0\\)", "(45068597600100000000)"},
{"-8.0450685976001E+21", "0_);[Red]\\(0\\)", "(8045068597600100000000)"},
{"-8.0450685976001E-21", "0_);[Red]\\(0\\)", "(0)"},
{"-8.04506", "0_);[Red]\\(0\\)", "(8)"},
} {
result := format(item[0], item[1])
assert.Equal(t, item[2], result, item)

View File

@ -102,7 +102,7 @@ func TestGetPicture(t *testing.T) {
file, raw, err := f.GetPicture("Sheet1", "F21")
assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0644)) {
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0o644)) {
t.FailNow()
}
@ -137,7 +137,7 @@ func TestGetPicture(t *testing.T) {
file, raw, err = f.GetPicture("Sheet1", "F21")
assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0644)) {
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0o644)) {
t.FailNow()
}

View File

@ -459,6 +459,13 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
}
return f.formattedValue(c.S, c.V, raw), nil
default:
if isNum, precision := isNumeric(c.V); isNum && !raw {
if precision == 0 {
c.V = roundPrecision(c.V, 15)
} else {
c.V = roundPrecision(c.V, -1)
}
}
return f.formattedValue(c.S, c.V, raw), nil
}
}