Improve compatibility for SetRichText (#976)

- support escaped string literal
- maximum character limit added
- fix missing preserve character in some case

Co-authored-by: xuri <xuri.me@gmail.com>
This commit is contained in:
Arnie97 2021-07-31 14:20:29 +08:00 committed by GitHub
parent 7ac37edfeb
commit eaf9781e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 18 deletions

34
cell.go
View File

@ -307,16 +307,8 @@ func (f *File) setSharedString(val string) int {
} }
sst.Count++ sst.Count++
sst.UniqueCount++ sst.UniqueCount++
val = bstrMarshal(val)
t := xlsxT{Val: val} t := xlsxT{Val: val}
// Leading and ending space(s) character detection. _, val, t.Space = setCellStr(val)
if len(val) > 0 && (val[0] == 32 || val[len(val)-1] == 32) {
ns := xml.Attr{
Name: xml.Name{Space: NameSpaceXML, Local: "space"},
Value: "preserve",
}
t.Space = ns
}
sst.SI = append(sst.SI, xlsxSI{T: &t}) sst.SI = append(sst.SI, xlsxSI{T: &t})
f.sharedStringsMap[val] = sst.UniqueCount - 1 f.sharedStringsMap[val] = sst.UniqueCount - 1
return sst.UniqueCount - 1 return sst.UniqueCount - 1
@ -327,11 +319,16 @@ func setCellStr(value string) (t string, v string, ns xml.Attr) {
if len(value) > TotalCellChars { if len(value) > TotalCellChars {
value = value[0:TotalCellChars] value = value[0:TotalCellChars]
} }
// Leading and ending space(s) character detection. if len(value) > 0 {
if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) { prefix, suffix := value[0], value[len(value)-1]
ns = xml.Attr{ for _, ascii := range []byte{10, 13, 32} {
Name: xml.Name{Space: NameSpaceXML, Local: "space"}, if prefix == ascii || suffix == ascii {
Value: "preserve", ns = xml.Attr{
Name: xml.Name{Space: NameSpaceXML, Local: "space"},
Value: "preserve",
}
break
}
} }
} }
t = "str" t = "str"
@ -702,11 +699,14 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
si := xlsxSI{} si := xlsxSI{}
sst := f.sharedStringsReader() sst := f.sharedStringsReader()
textRuns := []xlsxR{} textRuns := []xlsxR{}
totalCellChars := 0
for _, textRun := range runs { for _, textRun := range runs {
run := xlsxR{T: &xlsxT{Val: textRun.Text}} totalCellChars += len(textRun.Text)
if strings.ContainsAny(textRun.Text, "\r\n ") { if totalCellChars > TotalCellChars {
run.T.Space = xml.Attr{Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve"} return ErrCellCharsLength
} }
run := xlsxR{T: &xlsxT{}}
_, run.T.Val, run.T.Space = setCellStr(textRun.Text)
fnt := textRun.Font fnt := textRun.Font
if fnt != nil { if fnt != nil {
rpr := xlsxRPr{} rpr := xlsxRPr{}

View File

@ -401,6 +401,9 @@ func TestSetCellRichText(t *testing.T) {
assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN is not exist") assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN is not exist")
// Test set cell rich text with illegal cell coordinates // Test set cell rich text with illegal cell coordinates
assert.EqualError(t, f.SetCellRichText("Sheet1", "A", richTextRun), `cannot convert cell "A" to coordinates: invalid cell name "A"`) assert.EqualError(t, f.SetCellRichText("Sheet1", "A", richTextRun), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
richTextRun = []RichTextRun{{Text: strings.Repeat("s", TotalCellChars+1)}}
// Test set cell rich text with characters over the maximum limit
assert.EqualError(t, f.SetCellRichText("Sheet1", "A1", richTextRun), ErrCellCharsLength.Error())
} }
func TestFormattedValue2(t *testing.T) { func TestFormattedValue2(t *testing.T) {

View File

@ -45,7 +45,7 @@ var (
ErrColumnNumber = errors.New("column number exceeds maximum limit") ErrColumnNumber = errors.New("column number exceeds maximum limit")
// ErrColumnWidth defined the error message on receive an invalid column // ErrColumnWidth defined the error message on receive an invalid column
// width. // width.
ErrColumnWidth = errors.New("the width of the column must be smaller than or equal to 255 characters") ErrColumnWidth = fmt.Errorf("the width of the column must be smaller than or equal to %d characters", MaxColumnWidth)
// ErrOutlineLevel defined the error message on receive an invalid outline // ErrOutlineLevel defined the error message on receive an invalid outline
// level number. // level number.
ErrOutlineLevel = errors.New("invalid outline level") ErrOutlineLevel = errors.New("invalid outline level")
@ -111,4 +111,7 @@ var (
// ErrDataValidationRange defined the error message on set decimal range // ErrDataValidationRange defined the error message on set decimal range
// exceeds limit. // exceeds limit.
ErrDataValidationRange = errors.New("data validation range exceeds limit") ErrDataValidationRange = errors.New("data validation range exceeds limit")
// ErrCellCharsLength defined the error message for receiving a cell
// characters length that exceeds the limit.
ErrCellCharsLength = fmt.Errorf("cell value must be 0-%d characters", TotalCellChars)
) )