forked from p30928647/excelize
Fixed parsing decimal precision issue
This commit is contained in:
parent
f87c39c41d
commit
07be993631
20
cell.go
20
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
|
||||
|
|
|
@ -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) {
|
|||
<c r="S1"><v>275.39999999999998</v></c>
|
||||
<c r="T1"><v>68.900000000000006</v></c>
|
||||
<c r="U1"><v>8.8880000000000001E-2</v></c>
|
||||
<c r="V1"><v>4.0000000000000003E-5</v></c>
|
||||
<c r="V1"><v>4.0000000000000003e-5</v></c>
|
||||
<c r="W1"><v>2422.3000000000002</v></c>
|
||||
<c r="X1"><v>1101.5999999999999</v></c>
|
||||
<c r="Y1"><v>275.39999999999998</v></c>
|
||||
<c r="Z1"><v>68.900000000000006</v></c>
|
||||
<c r="AA1"><v>1.1000000000000001</v></c>
|
||||
<c r="AA2"><v>1234567890123_4</v></c>
|
||||
<c r="AA3"><v>123456789_0123_4</v></c>
|
||||
</row>`)))
|
||||
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)
|
||||
}
|
||||
|
|
9
lib.go
9
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
|
||||
}
|
||||
|
|
28
numfmt.go
28
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.
|
||||
|
|
Loading…
Reference in New Issue