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
This commit is contained in:
xuri 2023-04-26 00:04:47 +08:00
parent 612f6f104c
commit 65fc25e7a6
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 25 additions and 12 deletions

View File

@ -460,6 +460,8 @@ func (f *File) setSharedString(val string) (int, error) {
if i, ok := f.sharedStringsMap[val]; ok { if i, ok := f.sharedStringsMap[val]; ok {
return i, nil return i, nil
} }
sst.mu.Lock()
defer sst.mu.Unlock()
sst.Count++ sst.Count++
sst.UniqueCount++ sst.UniqueCount++
t := xlsxT{Val: val} 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 { if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
return f.formattedValue(&xlsxC{S: c.S, V: f.getFromStringItem(xlsxSI)}, raw, CellTypeSharedString) 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 { if len(d.SI) > xlsxSI {
return f.formattedValue(&xlsxC{S: c.S, V: d.SI[xlsxSI].String()}, raw, CellTypeSharedString) return f.formattedValue(&xlsxC{S: c.S, V: d.SI[xlsxSI].String()}, raw, CellTypeSharedString)
} }

View File

@ -948,13 +948,10 @@ func (nf *numberFormat) zeroHandler() string {
// textHandler will be handling text selection for a number format expression. // textHandler will be handling text selection for a number format expression.
func (nf *numberFormat) textHandler() (result string) { func (nf *numberFormat) textHandler() (result string) {
for _, token := range nf.section[nf.sectionIdx].Items { 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 { if token.TType == nfp.TokenTypeLiteral {
result += token.TValue 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 result += nf.value
} }
} }
@ -964,6 +961,9 @@ func (nf *numberFormat) textHandler() (result string) {
// getValueSectionType returns its applicable number format expression section // getValueSectionType returns its applicable number format expression section
// based on the given value. // based on the given value.
func (nf *numberFormat) getValueSectionType(value string) (float64, string) { func (nf *numberFormat) getValueSectionType(value string) (float64, string) {
if nf.cellType != CellTypeNumber && nf.cellType != CellTypeDate {
return 0, nfp.TokenSectionText
}
isNum, _, _ := isNumeric(value) isNum, _, _ := isNumeric(value)
if !isNum { if !isNum {
return 0, nfp.TokenSectionText return 0, nfp.TokenSectionText

View File

@ -1008,12 +1008,17 @@ func TestNumFmt(t *testing.T) {
result := format(item[0], item[1], false, CellTypeNumber) result := format(item[0], item[1], false, CellTypeNumber)
assert.Equal(t, item[2], result, item) assert.Equal(t, item[2], result, item)
} }
for _, item := range [][]string{ for _, cellType := range []CellType{CellTypeSharedString, CellTypeInlineString} {
{"1234.5678", "General", "1234.5678"}, for _, item := range [][]string{
{"1234.5678", "yyyy\"年\"m\"月\"d\"日\";@", "1234.5678"}, {"1234.5678", "General", "1234.5678"},
{"1234.5678", "0_);[Red]\\(0\\)", "1234.5678"}, {"1234.5678", "yyyy\"年\"m\"月\"d\"日\";@", "1234.5678"},
} { {"1234.5678", "h\"时\"mm\"分\"ss\"秒\";@", "1234.5678"},
result := format(item[0], item[1], false, CellTypeSharedString) {"1234.5678", "\"¥\"#,##0.00_);\\(\"¥\"#,##0.00\\)", "1234.5678"},
assert.Equal(t, item[2], result, item) {"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)
}
} }
} }

View File

@ -11,7 +11,10 @@
package excelize package excelize
import "encoding/xml" import (
"encoding/xml"
"sync"
)
// xlsxSST directly maps the sst element from the namespace // xlsxSST directly maps the sst element from the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main. String values may // 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 // is an indexed list of string values, shared across the workbook, which allows
// implementations to store values only once. // implementations to store values only once.
type xlsxSST struct { type xlsxSST struct {
mu sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main sst"` XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main sst"`
Count int `xml:"count,attr"` Count int `xml:"count,attr"`
UniqueCount int `xml:"uniqueCount,attr"` UniqueCount int `xml:"uniqueCount,attr"`