Prechádzať zdrojové kódy

Fixed #727, rounding numeric with precision for formula calculation

xuri 5 rokov pred
rodič
commit
599a8cb0bc
5 zmenil súbory, kde vykonal 70 pridanie a 54 odobranie
  1. 1 1
      README.md
  2. 1 1
      README_zh.md
  3. 15 0
      calc.go
  4. 42 42
      calc_test.go
  5. 11 10
      rows.go

+ 1 - 1
README.md

@@ -6,7 +6,7 @@
     <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
     <a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
     <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
-    <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
+    <a href="https://www.paypal.com/paypalme/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
 </p>
 
 # Excelize

+ 1 - 1
README_zh.md

@@ -6,7 +6,7 @@
     <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
     <a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
     <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
-    <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
+    <a href="https://www.paypal.com/paypalme/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
 </p>
 
 # Excelize

+ 15 - 0
calc.go

@@ -42,6 +42,14 @@ const (
 	formulaErrorGETTINGDATA = "#GETTING_DATA"
 )
 
+// Numeric precision correct numeric values as legacy Excel application
+// https://en.wikipedia.org/wiki/Numeric_precision_in_Microsoft_Excel In the
+// top figure the fraction 1/9000 in Excel is displayed. Although this number
+// has a decimal representation that is an infinite string of ones, Excel
+// displays only the leading 15 figures. In the second line, the number one
+// is added to the fraction, and again Excel displays only 15 figures.
+const numericPrecision = 1000000000000000
+
 // cellRef defines the structure of a cell reference.
 type cellRef struct {
 	Col   int
@@ -141,6 +149,13 @@ func (f *File) CalcCellValue(sheet, cell string) (result string, err error) {
 		return
 	}
 	result = token.TValue
+	if len(result) > 16 {
+		num, e := roundPrecision(result)
+		if e != nil {
+			return result, err
+		}
+		result = strings.ToUpper(num)
+	}
 	return
 }
 

+ 42 - 42
calc_test.go

@@ -54,42 +54,42 @@ func TestCalcCellValue(t *testing.T) {
 		"=ABS(2-4.5)": "2.5",
 		// ACOS
 		"=ACOS(-1)": "3.141592653589793",
-		"=ACOS(0)":  "1.5707963267948966",
+		"=ACOS(0)":  "1.570796326794897",
 		// ACOSH
 		"=ACOSH(1)":   "0",
 		"=ACOSH(2.5)": "1.566799236972411",
-		"=ACOSH(5)":   "2.2924316695611777",
+		"=ACOSH(5)":   "2.292431669561178",
 		// ACOT
-		"=_xlfn.ACOT(1)":  "0.7853981633974483",
+		"=_xlfn.ACOT(1)":  "0.785398163397448",
 		"=_xlfn.ACOT(-2)": "2.677945044588987",
-		"=_xlfn.ACOT(0)":  "1.5707963267948966",
+		"=_xlfn.ACOT(0)":  "1.570796326794897",
 		// ACOTH
-		"=_xlfn.ACOTH(-5)":  "-0.2027325540540822",
-		"=_xlfn.ACOTH(1.1)": "1.5222612188617113",
-		"=_xlfn.ACOTH(2)":   "0.5493061443340548",
+		"=_xlfn.ACOTH(-5)":  "-0.202732554054082",
+		"=_xlfn.ACOTH(1.1)": "1.522261218861711",
+		"=_xlfn.ACOTH(2)":   "0.549306144334055",
 		// ARABIC
 		`=_xlfn.ARABIC("IV")`:   "4",
 		`=_xlfn.ARABIC("-IV")`:  "-4",
 		`=_xlfn.ARABIC("MCXX")`: "1120",
 		`=_xlfn.ARABIC("")`:     "0",
 		// ASIN
-		"=ASIN(-1)": "-1.5707963267948966",
+		"=ASIN(-1)": "-1.570796326794897",
 		"=ASIN(0)":  "0",
 		// ASINH
 		"=ASINH(0)":    "0",
-		"=ASINH(-0.5)": "-0.48121182505960347",
-		"=ASINH(2)":    "1.4436354751788103",
+		"=ASINH(-0.5)": "-0.481211825059604",
+		"=ASINH(2)":    "1.44363547517881",
 		// ATAN
-		"=ATAN(-1)": "-0.7853981633974483",
+		"=ATAN(-1)": "-0.785398163397448",
 		"=ATAN(0)":  "0",
-		"=ATAN(1)":  "0.7853981633974483",
+		"=ATAN(1)":  "0.785398163397448",
 		// ATANH
-		"=ATANH(-0.8)": "-1.0986122886681098",
+		"=ATANH(-0.8)": "-1.09861228866811",
 		"=ATANH(0)":    "0",
-		"=ATANH(0.5)":  "0.5493061443340548",
+		"=ATANH(0.5)":  "0.549306144334055",
 		// ATAN2
-		"=ATAN2(1,1)":  "0.7853981633974483",
-		"=ATAN2(1,-1)": "-0.7853981633974483",
+		"=ATAN2(1,1)":  "0.785398163397448",
+		"=ATAN2(1,-1)": "-0.785398163397448",
 		"=ATAN2(4,0)":  "0",
 		// BASE
 		"=BASE(12,2)":      "1100",
@@ -145,17 +145,17 @@ func TestCalcCellValue(t *testing.T) {
 		"=COS(0)":           "1",
 		// COSH
 		"=COSH(0)":   "1",
-		"=COSH(0.5)": "1.1276259652063807",
-		"=COSH(-2)":  "3.7621956910836314",
+		"=COSH(0.5)": "1.127625965206381",
+		"=COSH(-2)":  "3.762195691083632",
 		// _xlfn.COT
-		"=_xlfn.COT(0.785398163397448)": "0.9999999999999992",
+		"=_xlfn.COT(0.785398163397448)": "0.999999999999999",
 		// _xlfn.COTH
-		"=_xlfn.COTH(-3.14159265358979)": "-0.9962720762207499",
+		"=_xlfn.COTH(-3.14159265358979)": "-0.99627207622075",
 		// _xlfn.CSC
-		"=_xlfn.CSC(-6)":              "3.5788995472544056",
+		"=_xlfn.CSC(-6)":              "3.578899547254406",
 		"=_xlfn.CSC(1.5707963267949)": "1",
 		// _xlfn.CSCH
-		"=_xlfn.CSCH(-3.14159265358979)": "-0.08658953753004724",
+		"=_xlfn.CSCH(-3.14159265358979)": "-0.086589537530047",
 		// _xlfn.DECIMAL
 		`=_xlfn.DECIMAL("1100",2)`:    "12",
 		`=_xlfn.DECIMAL("186A0",16)`:  "100000",
@@ -174,9 +174,9 @@ func TestCalcCellValue(t *testing.T) {
 		"=EVEN(-4)":   "-4",
 		// EXP
 		"=EXP(100)": "2.6881171418161356E+43",
-		"=EXP(0.1)": "1.1051709180756477",
+		"=EXP(0.1)": "1.105170918075648",
 		"=EXP(0)":   "1",
-		"=EXP(-5)":  "0.006737946999085467",
+		"=EXP(-5)":  "0.006737946999085",
 		// FACT
 		"=FACT(3)":  "6",
 		"=FACT(6)":  "720",
@@ -247,23 +247,23 @@ func TestCalcCellValue(t *testing.T) {
 		// LN
 		"=LN(1)":   "0",
 		"=LN(100)": "4.605170185988092",
-		"=LN(0.5)": "-0.6931471805599453",
+		"=LN(0.5)": "-0.693147180559945",
 		// LOG
 		"=LOG(64,2)":  "6",
 		"=LOG(100)":   "2",
 		"=LOG(4,0.5)": "-2",
-		"=LOG(500)":   "2.6989700043360183",
+		"=LOG(500)":   "2.698970004336019",
 		// LOG10
 		"=LOG10(100)":   "2",
 		"=LOG10(1000)":  "3",
 		"=LOG10(0.001)": "-3",
-		"=LOG10(25)":    "1.3979400086720375",
+		"=LOG10(25)":    "1.397940008672038",
 		// MOD
 		"=MOD(6,4)":      "2",
 		"=MOD(6,3)":      "0",
 		"=MOD(6,2.5)":    "1",
-		"=MOD(6,1.333)":  "0.6680000000000001",
-		"=MOD(-10.23,1)": "0.7699999999999996",
+		"=MOD(6,1.333)":  "0.668",
+		"=MOD(-10.23,1)": "0.77",
 		// MROUND
 		"=MROUND(333.7,0.5)":   "333.5",
 		"=MROUND(333.8,1)":     "334",
@@ -298,7 +298,7 @@ func TestCalcCellValue(t *testing.T) {
 		"=QUOTIENT(4.5,3.1)": "1",
 		"=QUOTIENT(-10,3)":   "-3",
 		// RADIANS
-		"=RADIANS(50)":   "0.8726646259971648",
+		"=RADIANS(50)":   "0.872664625997165",
 		"=RADIANS(-180)": "-3.141592653589793",
 		"=RADIANS(180)":  "3.141592653589793",
 		"=RADIANS(360)":  "6.283185307179586",
@@ -323,13 +323,13 @@ func TestCalcCellValue(t *testing.T) {
 		"=ROUND(991,-1)":    "990",
 		// ROUNDDOWN
 		"=ROUNDDOWN(99.999,1)":   "99.9",
-		"=ROUNDDOWN(99.999,2)":   "99.99000000000002",
+		"=ROUNDDOWN(99.999,2)":   "99.99000000000001",
 		"=ROUNDDOWN(99.999,0)":   "99",
 		"=ROUNDDOWN(99.999,-1)":  "90",
-		"=ROUNDDOWN(-99.999,2)":  "-99.99000000000002",
+		"=ROUNDDOWN(-99.999,2)":  "-99.99000000000001",
 		"=ROUNDDOWN(-99.999,-1)": "-90",
 		// ROUNDUP
-		"=ROUNDUP(11.111,1)":   "11.200000000000001",
+		"=ROUNDUP(11.111,1)":   "11.200000000000003",
 		"=ROUNDUP(11.111,2)":   "11.120000000000003",
 		"=ROUNDUP(11.111,0)":   "12",
 		"=ROUNDUP(11.111,-1)":  "20",
@@ -339,7 +339,7 @@ func TestCalcCellValue(t *testing.T) {
 		"=_xlfn.SEC(-3.14159265358979)": "-1",
 		"=_xlfn.SEC(0)":                 "1",
 		// SECH
-		"=_xlfn.SECH(-3.14159265358979)": "0.0862667383340547",
+		"=_xlfn.SECH(-3.14159265358979)": "0.086266738334055",
 		"=_xlfn.SECH(0)":                 "1",
 		// SIGN
 		"=SIGN(9.5)":        "1",
@@ -348,17 +348,17 @@ func TestCalcCellValue(t *testing.T) {
 		"=SIGN(0.00000001)": "1",
 		"=SIGN(6-7)":        "-1",
 		// SIN
-		"=SIN(0.785398163)": "0.7071067809055092",
+		"=SIN(0.785398163)": "0.707106780905509",
 		// SINH
 		"=SINH(0)":   "0",
-		"=SINH(0.5)": "0.5210953054937474",
+		"=SINH(0.5)": "0.521095305493747",
 		"=SINH(-2)":  "-3.626860407847019",
 		// SQRT
 		"=SQRT(4)":  "2",
 		`=SQRT("")`: "0",
 		// SQRTPI
 		"=SQRTPI(5)":   "3.963327297606011",
-		"=SQRTPI(0.2)": "0.7926654595212022",
+		"=SQRTPI(0.2)": "0.792665459521202",
 		"=SQRTPI(100)": "17.72453850905516",
 		"=SQRTPI(0)":   "0",
 		// SUM
@@ -399,8 +399,8 @@ func TestCalcCellValue(t *testing.T) {
 		"=TAN(0)":           "0",
 		// TANH
 		"=TANH(0)":   "0",
-		"=TANH(0.5)": "0.46211715726000974",
-		"=TANH(-2)":  "-0.9640275800758169",
+		"=TANH(0.5)": "0.46211715726001",
+		"=TANH(-2)":  "-0.964027580075817",
 		// TRUNC
 		"=TRUNC(99.999,1)":   "99.9",
 		"=TRUNC(99.999,2)":   "99.99",
@@ -794,14 +794,14 @@ func TestCalcCellValue(t *testing.T) {
 		// PRODUCT
 		"=PRODUCT(Sheet1!A1:Sheet1!A1:A2,A2)": "4",
 		// SUM
-		"=A1/A3":                          "0.3333333333333333",
+		"=A1/A3":                          "0.333333333333333",
 		"=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",
-		"=1+SUM(SUM(A1+A2/A3)*(2-3),2)":   "1.3333333333333335",
-		"=A1/A2/SUM(A1:A2:B1)":            "0.041666666666666664",
+		"=1+SUM(SUM(A1+A2/A3)*(2-3),2)":   "1.333333333333334",
+		"=A1/A2/SUM(A1:A2:B1)":            "0.041666666666667",
 		"=A1/A2/SUM(A1:A2:B1)*A3":         "0.125",
 	}
 	for formula, expected := range referenceCalc {

+ 11 - 10
rows.go

@@ -345,20 +345,11 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
 		}
 		return f.formattedValue(c.S, c.V), nil
 	default:
-		// correct numeric values as legacy Excel app
-		// https://en.wikipedia.org/wiki/Numeric_precision_in_Microsoft_Excel
-		// In the top figure the fraction 1/9000 in Excel is displayed.
-		// Although this number has a decimal representation that is an infinite string of ones,
-		// Excel displays only the leading 15 figures. In the second line, the number one is added to the fraction, and again Excel displays only 15 figures.
-		const precision = 1000000000000000
 		if len(c.V) > 16 {
-			num, err := strconv.ParseFloat(c.V, 64)
+			val, err := roundPrecision(c.V)
 			if err != nil {
 				return "", err
 			}
-
-			num = math.Round(num*precision) / precision
-			val := fmt.Sprintf("%g", num)
 			if val != c.V {
 				return f.formattedValue(c.S, val), nil
 			}
@@ -367,6 +358,16 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
 	}
 }
 
+// roundPrecision round precision for numeric.
+func roundPrecision(value string) (result string, err error) {
+	var num float64
+	if num, err = strconv.ParseFloat(value, 64); err != nil {
+		return
+	}
+	result = fmt.Sprintf("%g", math.Round(num*numericPrecision)/numericPrecision)
+	return
+}
+
 // SetRowVisible provides a function to set visible of a single row by given
 // worksheet name and Excel row number. For example, hide row 2 in Sheet1:
 //