From 65fc25e7a60c096cea25e16d354d67b327596889 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 26 Apr 2023 00:04:47 +0800 Subject: [PATCH] Ref #1533, this made number format text handler just handle text tokens - Fix race conditions for concurrency read and write shared string table - Unit tests has been updated --- cell.go | 4 ++++ numfmt.go | 8 ++++---- numfmt_test.go | 19 ++++++++++++------- xmlSharedStrings.go | 6 +++++- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cell.go b/cell.go index f455edff..61dbed62 100644 --- a/cell.go +++ b/cell.go @@ -460,6 +460,8 @@ func (f *File) setSharedString(val string) (int, error) { if i, ok := f.sharedStringsMap[val]; ok { return i, nil } + sst.mu.Lock() + defer sst.mu.Unlock() sst.Count++ sst.UniqueCount++ t := xlsxT{Val: val} @@ -581,6 +583,8 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) { if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok { return f.formattedValue(&xlsxC{S: c.S, V: f.getFromStringItem(xlsxSI)}, raw, CellTypeSharedString) } + d.mu.Lock() + defer d.mu.Unlock() if len(d.SI) > xlsxSI { return f.formattedValue(&xlsxC{S: c.S, V: d.SI[xlsxSI].String()}, raw, CellTypeSharedString) } diff --git a/numfmt.go b/numfmt.go index cad67a2d..29702302 100644 --- a/numfmt.go +++ b/numfmt.go @@ -948,13 +948,10 @@ func (nf *numberFormat) zeroHandler() string { // textHandler will be handling text selection for a number format expression. func (nf *numberFormat) textHandler() (result string) { for _, token := range nf.section[nf.sectionIdx].Items { - if inStrSlice([]string{nfp.TokenTypeDateTimes, nfp.TokenTypeElapsedDateTimes}, token.TType, false) != -1 { - return nf.value - } if token.TType == nfp.TokenTypeLiteral { result += token.TValue } - if token.TType == nfp.TokenTypeGeneral || token.TType == nfp.TokenTypeTextPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder { + if token.TType == nfp.TokenTypeTextPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder { result += nf.value } } @@ -964,6 +961,9 @@ func (nf *numberFormat) textHandler() (result string) { // getValueSectionType returns its applicable number format expression section // based on the given value. func (nf *numberFormat) getValueSectionType(value string) (float64, string) { + if nf.cellType != CellTypeNumber && nf.cellType != CellTypeDate { + return 0, nfp.TokenSectionText + } isNum, _, _ := isNumeric(value) if !isNum { return 0, nfp.TokenSectionText diff --git a/numfmt_test.go b/numfmt_test.go index 773fac32..1e6f6bb8 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -1008,12 +1008,17 @@ func TestNumFmt(t *testing.T) { result := format(item[0], item[1], false, CellTypeNumber) assert.Equal(t, item[2], result, item) } - for _, item := range [][]string{ - {"1234.5678", "General", "1234.5678"}, - {"1234.5678", "yyyy\"年\"m\"月\"d\"日\";@", "1234.5678"}, - {"1234.5678", "0_);[Red]\\(0\\)", "1234.5678"}, - } { - result := format(item[0], item[1], false, CellTypeSharedString) - assert.Equal(t, item[2], result, item) + for _, cellType := range []CellType{CellTypeSharedString, CellTypeInlineString} { + for _, item := range [][]string{ + {"1234.5678", "General", "1234.5678"}, + {"1234.5678", "yyyy\"年\"m\"月\"d\"日\";@", "1234.5678"}, + {"1234.5678", "h\"时\"mm\"分\"ss\"秒\";@", "1234.5678"}, + {"1234.5678", "\"¥\"#,##0.00_);\\(\"¥\"#,##0.00\\)", "1234.5678"}, + {"1234.5678", "0_);[Red]\\(0\\)", "1234.5678"}, + {"1234.5678", "\"text\"@", "text1234.5678"}, + } { + result := format(item[0], item[1], false, cellType) + assert.Equal(t, item[2], result, item) + } } } diff --git a/xmlSharedStrings.go b/xmlSharedStrings.go index 704002c7..b2b65d1e 100644 --- a/xmlSharedStrings.go +++ b/xmlSharedStrings.go @@ -11,7 +11,10 @@ package excelize -import "encoding/xml" +import ( + "encoding/xml" + "sync" +) // xlsxSST directly maps the sst element from the namespace // http://schemas.openxmlformats.org/spreadsheetml/2006/main. String values may @@ -21,6 +24,7 @@ import "encoding/xml" // is an indexed list of string values, shared across the workbook, which allows // implementations to store values only once. type xlsxSST struct { + mu sync.Mutex XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main sst"` Count int `xml:"count,attr"` UniqueCount int `xml:"uniqueCount,attr"`