From 07be99363156b2d1011954be7b5a4cc8f33b256b Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 18 Feb 2022 00:02:39 +0800 Subject: [PATCH] Fixed parsing decimal precision issue --- cell.go | 20 ++++++++++---------- cell_test.go | 8 ++++++-- lib.go | 9 +++++++-- numfmt.go | 28 +++++++++++++++------------- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/cell.go b/cell.go index b6ddd35..b44ed82 100644 --- a/cell.go +++ b/cell.go @@ -1082,23 +1082,23 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c // it is possible to apply a format to the cell value, it will do so, if not // then an error will be returned, along with the raw value of the cell. func (f *File) formattedValue(s int, v string, raw bool) string { - precise := v - isNum, precision := isNumeric(v) - if isNum && precision > 10 { - precise = roundPrecision(v, -1) - } if raw { return v } - if !isNum { - v = roundPrecision(v, 15) - precise = 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 } styleSheet := f.stylesReader() - if s >= len(styleSheet.CellXfs.Xf) { return precise } @@ -1116,7 +1116,7 @@ func (f *File) formattedValue(s int, v string, raw bool) string { } for _, xlsxFmt := range styleSheet.NumFmts.NumFmt { if xlsxFmt.NumFmtID == numFmtID { - return format(v, xlsxFmt.FormatCode) + return format(precise, xlsxFmt.FormatCode) } } return precise diff --git a/cell_test.go b/cell_test.go index f6f1098..92d3d2f 100644 --- a/cell_test.go +++ b/cell_test.go @@ -130,7 +130,7 @@ func TestSetCellFloat(t *testing.T) { assert.Equal(t, "123", val, "A1 should be 123") val, err = f.GetCellValue(sheet, "A2") assert.NoError(t, err) - assert.Equal(t, "123.0", val, "A2 should be 123.0") + assert.Equal(t, "123", val, "A2 should be 123") }) t.Run("with a decimal and precision limit", func(t *testing.T) { @@ -288,12 +288,14 @@ func TestGetCellValue(t *testing.T) { 275.39999999999998 68.900000000000006 8.8880000000000001E-2 - 4.0000000000000003E-5 + 4.0000000000000003e-5 2422.3000000000002 1101.5999999999999 275.39999999999998 68.900000000000006 1.1000000000000001 + 1234567890123_4 + 123456789_0123_4 `))) f.checked = nil rows, err = f.GetRows("Sheet1") @@ -325,6 +327,8 @@ func TestGetCellValue(t *testing.T) { "275.4", "68.9", "1.1", + "1234567890123_4", + "123456789_0123_4", }}, rows) assert.NoError(t, err) } diff --git a/lib.go b/lib.go index 47ce2fe..d0ae62c 100644 --- a/lib.go +++ b/lib.go @@ -675,22 +675,27 @@ func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) { // isNumeric determines whether an expression is a valid numeric type and get // the precision for the numeric. func isNumeric(s string) (bool, int) { - dot, n, p := false, false, 0 + dot, e, n, p := false, false, false, 0 for i, v := range s { if v == '.' { if dot { return false, 0 } dot = true + } else if v == 'E' || v == 'e' { + e = true } else if v < '0' || v > '9' { if i == 0 && v == '-' { continue } + if e && v == '-' { + continue + } return false, 0 } else if dot { - n = true p++ } + n = true } return n, p } diff --git a/numfmt.go b/numfmt.go index 4549110..1a02d46 100644 --- a/numfmt.go +++ b/numfmt.go @@ -20,6 +20,7 @@ import ( "github.com/xuri/nfp" ) +// languageInfo defined the required fields of localization support for number format. type languageInfo struct { apFmt string tags []string @@ -191,16 +192,17 @@ func format(value, numFmt string) string { if section.Type != nf.valueSectionType { continue } - switch section.Type { - case nfp.TokenSectionPositive: - return nf.positiveHandler() - case nfp.TokenSectionNegative: - return nf.negativeHandler() - case nfp.TokenSectionZero: - return nf.zeroHandler() - default: - return nf.textHandler() + if nf.isNumberic { + switch section.Type { + case nfp.TokenSectionPositive: + return nf.positiveHandler() + case nfp.TokenSectionNegative: + return nf.negativeHandler() + default: + return nf.zeroHandler() + } } + return nf.textHandler() } return value } @@ -211,12 +213,12 @@ func (nf *numberFormat) positiveHandler() (result string) { nf.t, nf.hours, nf.seconds = timeFromExcelTime(nf.number, false), false, false for i, token := range nf.section[nf.sectionIdx].Items { if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral { - result = fmt.Sprint(nf.number) + result = nf.value return } if token.TType == nfp.TokenTypeCurrencyLanguage { if err := nf.currencyLanguageHandler(i, token); err != nil { - result = fmt.Sprint(nf.number) + result = nf.value return } } @@ -587,12 +589,12 @@ func (nf *numberFormat) secondsNext(i int) bool { // negativeHandler will be handling negative selection for a number format // expression. func (nf *numberFormat) negativeHandler() string { - return fmt.Sprint(nf.number) + return nf.value } // zeroHandler will be handling zero selection for a number format expression. func (nf *numberFormat) zeroHandler() string { - return fmt.Sprint(nf.number) + return nf.value } // textHandler will be handling text selection for a number format expression.