diff options
Diffstat (limited to 'rows.go')
-rw-r--r-- | rows.go | 51 |
1 files changed, 46 insertions, 5 deletions
@@ -21,6 +21,7 @@ import ( "math/big" "os" "strconv" + "sync" "github.com/mohae/deepcopy" ) @@ -244,7 +245,7 @@ func (f *File) Rows(sheet string) (*Rows, error) { decoder *xml.Decoder tempFile *os.File ) - if needClose, decoder, tempFile, err = f.sheetDecoder(name); needClose && err == nil { + if needClose, decoder, tempFile, err = f.xmlDecoder(name); needClose && err == nil { defer tempFile.Close() } for { @@ -271,7 +272,7 @@ func (f *File) Rows(sheet string) (*Rows, error) { if xmlElement.Name.Local == "sheetData" { rows.f = f rows.sheet = name - _, rows.decoder, rows.tempFile, err = f.sheetDecoder(name) + _, rows.decoder, rows.tempFile, err = f.xmlDecoder(name) return &rows, err } } @@ -279,9 +280,46 @@ func (f *File) Rows(sheet string) (*Rows, error) { return &rows, nil } -// sheetDecoder creates XML decoder by given path in the zip from memory data +// getFromStringItemMap build shared string item map from system temporary +// file at one time, and return value by given to string index. +func (f *File) getFromStringItemMap(index int) string { + if f.sharedStringItemMap != nil { + if value, ok := f.sharedStringItemMap.Load(index); ok { + return value.(string) + } + return strconv.Itoa(index) + } + f.sharedStringItemMap = &sync.Map{} + needClose, decoder, tempFile, err := f.xmlDecoder(dafaultXMLPathSharedStrings) + if needClose && err == nil { + defer tempFile.Close() + } + var ( + inElement string + i int + ) + for { + token, _ := decoder.Token() + if token == nil { + break + } + switch xmlElement := token.(type) { + case xml.StartElement: + inElement = xmlElement.Name.Local + if inElement == "si" { + si := xlsxSI{} + _ = decoder.DecodeElement(&si, &xmlElement) + f.sharedStringItemMap.Store(i, si.String()) + i++ + } + } + } + return f.getFromStringItemMap(index) +} + +// xmlDecoder creates XML decoder by given path in the zip from memory data // or system temporary file. -func (f *File) sheetDecoder(name string) (bool, *xml.Decoder, *os.File, error) { +func (f *File) xmlDecoder(name string) (bool, *xml.Decoder, *os.File, error) { var ( content []byte err error @@ -373,7 +411,7 @@ func (f *File) sharedStringsReader() *xlsxSST { relPath := f.getWorkbookRelsPath() if f.SharedStrings == nil { var sharedStrings xlsxSST - ss := f.readXML("xl/sharedStrings.xml") + ss := f.readXML(dafaultXMLPathSharedStrings) if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))). Decode(&sharedStrings); err != nil && err != io.EOF { log.Printf("xml decode error: %s", err) @@ -415,6 +453,9 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) { if c.V != "" { xlsxSI := 0 xlsxSI, _ = strconv.Atoi(c.V) + if _, ok := f.tempFiles.Load(dafaultXMLPathSharedStrings); ok { + return f.formattedValue(c.S, f.getFromStringItemMap(xlsxSI), raw), nil + } if len(d.SI) > xlsxSI { return f.formattedValue(c.S, d.SI[xlsxSI].String(), raw), nil } |