From 5c99300ee44de15e92bd8c5a92f2183c804d1379 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 26 May 2020 02:09:39 +0800 Subject: [PATCH] Fix #622, storage string to SST (shared string table) --- cell.go | 46 ++++++++++++++++++++++++++++++++++----------- rows.go | 10 ++++++++++ xmlSharedStrings.go | 2 +- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/cell.go b/cell.go index 97feb0a6..e64ef261 100644 --- a/cell.go +++ b/cell.go @@ -274,10 +274,43 @@ func (f *File) SetCellStr(sheet, axis, value string) error { return err } cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T, cellData.V, cellData.XMLSpace = setCellStr(value) + cellData.T, cellData.V, cellData.XMLSpace = f.setCellString(value) return err } +// setCellString provides a function to set string type to shared string +// table. +func (f *File) setCellString(value string) (t string, v string, ns xml.Attr) { + if len(value) > 32767 { + value = value[0:32767] + } + // Leading and ending space(s) character detection. + if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) { + ns = xml.Attr{ + Name: xml.Name{Space: NameSpaceXML, Local: "space"}, + Value: "preserve", + } + } + t = "s" + v = strconv.Itoa(f.setSharedString(value)) + return +} + +// setSharedString provides a function to add string to the share string table. +func (f *File) setSharedString(val string) int { + sst := f.sharedStringsReader() + for i, si := range sst.SI { + if si.T == val { + return i + } + } + sst.Count++ + sst.UniqueCount++ + sst.SI = append(sst.SI, xlsxSI{T: val}) + return sst.UniqueCount - 1 +} + +// setCellStr provides a function to set string type to cell. func setCellStr(value string) (t string, v string, ns xml.Attr) { if len(value) > 32767 { value = value[0:32767] @@ -590,7 +623,7 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error { for _, textRun := range runs { run := xlsxR{T: &xlsxT{Val: textRun.Text}} if strings.ContainsAny(textRun.Text, "\r\n ") { - run.T.Space = "preserve" + run.T.Space = xml.Attr{Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve"} } fnt := textRun.Font if fnt != nil { @@ -625,15 +658,6 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error { sst.Count++ sst.UniqueCount++ cellData.T, cellData.V = "s", strconv.Itoa(len(sst.SI)-1) - f.addContentTypePart(0, "sharedStrings") - rels := f.relsReader("xl/_rels/workbook.xml.rels") - for _, rel := range rels.Relationships { - if rel.Target == "sharedStrings.xml" { - return err - } - } - // Update xl/_rels/workbook.xml.rels - f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipSharedStrings, "sharedStrings.xml", "") return err } diff --git a/rows.go b/rows.go index 17216df2..5be3182b 100644 --- a/rows.go +++ b/rows.go @@ -285,12 +285,22 @@ func (f *File) sharedStringsReader() *xlsxSST { ss := f.readXML("xl/sharedStrings.xml") if len(ss) == 0 { ss = f.readXML("xl/SharedStrings.xml") + delete(f.XLSX, "xl/SharedStrings.xml") } if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))). Decode(&sharedStrings); err != nil && err != io.EOF { log.Printf("xml decode error: %s", err) } f.SharedStrings = &sharedStrings + f.addContentTypePart(0, "sharedStrings") + rels := f.relsReader("xl/_rels/workbook.xml.rels") + for _, rel := range rels.Relationships { + if rel.Target == "sharedStrings.xml" { + return f.SharedStrings + } + } + // Update xl/_rels/workbook.xml.rels + f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipSharedStrings, "sharedStrings.xml", "") } return f.SharedStrings diff --git a/xmlSharedStrings.go b/xmlSharedStrings.go index a6525df1..6e34abc2 100644 --- a/xmlSharedStrings.go +++ b/xmlSharedStrings.go @@ -66,7 +66,7 @@ type xlsxR struct { // xlsxT directly maps the t element in the run properties. type xlsxT struct { XMLName xml.Name `xml:"t"` - Space string `xml:"xml:space,attr,omitempty"` + Space xml.Attr `xml:"space,attr,omitempty"` Val string `xml:",innerxml"` }