Fix #622, storage string to SST (shared string table)

This commit is contained in:
xuri 2020-05-26 02:09:39 +08:00
parent 1aeb818235
commit 5c99300ee4
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
3 changed files with 46 additions and 12 deletions

46
cell.go
View File

@ -274,10 +274,43 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
return err return err
} }
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) 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 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) { func setCellStr(value string) (t string, v string, ns xml.Attr) {
if len(value) > 32767 { if len(value) > 32767 {
value = value[0:32767] value = value[0:32767]
@ -590,7 +623,7 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
for _, textRun := range runs { for _, textRun := range runs {
run := xlsxR{T: &xlsxT{Val: textRun.Text}} run := xlsxR{T: &xlsxT{Val: textRun.Text}}
if strings.ContainsAny(textRun.Text, "\r\n ") { 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 fnt := textRun.Font
if fnt != nil { if fnt != nil {
@ -625,15 +658,6 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
sst.Count++ sst.Count++
sst.UniqueCount++ sst.UniqueCount++
cellData.T, cellData.V = "s", strconv.Itoa(len(sst.SI)-1) 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 return err
} }

10
rows.go
View File

@ -285,12 +285,22 @@ func (f *File) sharedStringsReader() *xlsxSST {
ss := f.readXML("xl/sharedStrings.xml") ss := f.readXML("xl/sharedStrings.xml")
if len(ss) == 0 { if len(ss) == 0 {
ss = f.readXML("xl/SharedStrings.xml") ss = f.readXML("xl/SharedStrings.xml")
delete(f.XLSX, "xl/SharedStrings.xml")
} }
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))). if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))).
Decode(&sharedStrings); err != nil && err != io.EOF { Decode(&sharedStrings); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err) log.Printf("xml decode error: %s", err)
} }
f.SharedStrings = &sharedStrings 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 return f.SharedStrings

View File

@ -66,7 +66,7 @@ type xlsxR struct {
// xlsxT directly maps the t element in the run properties. // xlsxT directly maps the t element in the run properties.
type xlsxT struct { type xlsxT struct {
XMLName xml.Name `xml:"t"` XMLName xml.Name `xml:"t"`
Space string `xml:"xml:space,attr,omitempty"` Space xml.Attr `xml:"space,attr,omitempty"`
Val string `xml:",innerxml"` Val string `xml:",innerxml"`
} }