Skip to content

Commit 4717ea1

Browse files
committed
Speedup UTF16 string length count, back port countUTF16String function from PR 2206
- Update dependencies modules - Update docs for the AddChart function
1 parent 42840b3 commit 4717ea1

File tree

9 files changed

+38
-23
lines changed

9 files changed

+38
-23
lines changed

calc.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"sync"
3030
"time"
3131
"unicode"
32-
"unicode/utf16"
3332
"unicode/utf8"
3433
"unsafe"
3534

@@ -14509,7 +14508,7 @@ func (fn *formulaFuncs) TEXTJOIN(argsList *list.List) formulaArg {
1450914508
return ok
1451014509
}
1451114510
result := strings.Join(args, delimiter.Value())
14512-
if len(utf16.Encode([]rune(result))) > TotalCellChars {
14511+
if countUTF16String(result) > TotalCellChars {
1451314512
return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("TEXTJOIN function exceeds %d characters", TotalCellChars))
1451414513
}
1451514514
return newStringFormulaArg(result)

cell.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"strconv"
2222
"strings"
2323
"time"
24-
"unicode/utf16"
2524

2625
"github.com/xuri/efp"
2726
)
@@ -447,7 +446,7 @@ func (f *File) SetCellStr(sheet, cell, value string) error {
447446

448447
// setCellString provides a function to set string type to shared string table.
449448
func (f *File) setCellString(value string) (t, v string, err error) {
450-
if len(utf16.Encode([]rune(value))) > TotalCellChars {
449+
if countUTF16String(value) > TotalCellChars {
451450
value = truncateUTF16Units(value, TotalCellChars)
452451
}
453452
t = "s"
@@ -510,7 +509,7 @@ func (f *File) setSharedString(val string) (int, error) {
510509

511510
// trimCellValue provides a function to set string type to cell.
512511
func trimCellValue(value string, escape bool) (v string, ns xml.Attr) {
513-
if len(utf16.Encode([]rune(value))) > TotalCellChars {
512+
if countUTF16String(value) > TotalCellChars {
514513
value = truncateUTF16Units(value, TotalCellChars)
515514
}
516515
if value != "" {
@@ -1211,7 +1210,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
12111210
totalCellChars int
12121211
)
12131212
for _, textRun := range runs {
1214-
totalCellChars += len(utf16.Encode([]rune(textRun.Text)))
1213+
totalCellChars += countUTF16String(textRun.Text)
12151214
if totalCellChars > TotalCellChars {
12161215
return textRuns, ErrCellCharsLength
12171216
}

chart.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,9 @@ func (opts *Chart) parseTitle() {
904904
// ShowPercent
905905
// ShowSerName
906906
// ShowVal
907+
// Fill
908+
// UpBars
909+
// DownBars
907910
// NumFmt
908911
//
909912
// SecondPlotValues: Specifies the values in second plot for the 'PieOfPie' and
@@ -935,6 +938,14 @@ func (opts *Chart) parseTitle() {
935938
// ShowVal: Specifies that the value shall be shown in a data label.
936939
// The 'ShowVal' property is optional. The default value is false.
937940
//
941+
// Fill: Set fill color of the chart.
942+
//
943+
// UpBars: Specifies the format for stock chart up bars. The 'UpBars' property
944+
// is optional.
945+
//
946+
// DownBars: Specifies the format for stock chart down bars. The 'DownBars'
947+
// property is optional.
948+
//
938949
// NumFmt: Specifies that if linked to source and set custom number format code
939950
// for data labels. The 'NumFmt' property is optional. The default format code
940951
// is 'General'.

datavalidation.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"math"
1919
"slices"
2020
"strings"
21-
"unicode/utf16"
2221
)
2322

2423
// DataValidationType defined the type of data validation.
@@ -150,7 +149,7 @@ func (dv *DataValidation) SetInput(title, msg string) {
150149
// for their cells.
151150
func (dv *DataValidation) SetDropList(keys []string) error {
152151
formula := strings.Join(keys, ",")
153-
if MaxFieldLength < len(utf16.Encode([]rune(formula))) {
152+
if MaxFieldLength < countUTF16String(formula) {
154153
return ErrDataValidationFormulaLength
155154
}
156155
dv.Type = dataValidationTypeMap[DataValidationTypeList]

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
module github.com/xuri/excelize/v2
22

3-
go 1.23.0
3+
go 1.24.0
44

55
require (
66
github.com/richardlehane/mscfb v1.0.4
77
github.com/stretchr/testify v1.10.0
88
github.com/tiendc/go-deepcopy v1.6.1
99
github.com/xuri/efp v0.0.1
1010
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9
11-
golang.org/x/crypto v0.40.0
11+
golang.org/x/crypto v0.42.0
1212
golang.org/x/image v0.25.0
13-
golang.org/x/net v0.42.0
14-
golang.org/x/text v0.27.0
13+
golang.org/x/net v0.44.0
14+
golang.org/x/text v0.29.0
1515
)
1616

1717
require (

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
1515
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
1616
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
1717
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
18-
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
19-
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
18+
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
19+
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
2020
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
2121
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
22-
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
23-
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
24-
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
25-
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
22+
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
23+
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
24+
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
25+
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
2626
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2727
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2828
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

lib.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,15 @@ func setPtrFieldsVal(fields []string, immutable, mutable reflect.Value) {
941941
}
942942
}
943943

944+
// countUTF16String returns the number of UTF-16 code units in a string.
945+
func countUTF16String(s string) int {
946+
var cnt int
947+
for _, r := range s {
948+
cnt += utf16.RuneLen(r)
949+
}
950+
return cnt
951+
}
952+
944953
// truncateUTF16Units truncates a string to a maximum number of UTF-16 code
945954
// units.
946955
func truncateUTF16Units(s string, length int) string {

lib_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"strings"
1212
"sync"
1313
"testing"
14-
"unicode/utf16"
1514

1615
"github.com/stretchr/testify/assert"
1716
"github.com/stretchr/testify/require"
@@ -357,7 +356,7 @@ func TestBstrMarshal(t *testing.T) {
357356
func TestTruncateUTF16Units(t *testing.T) {
358357
assertTrunc := func(s string, max int, expected string) {
359358
assert.Equal(t, expected, truncateUTF16Units(s, max), "src=%q max=%d", s, max)
360-
assert.LessOrEqual(t, len(utf16.Encode([]rune(truncateUTF16Units(s, max)))), max)
359+
assert.LessOrEqual(t, countUTF16String(truncateUTF16Units(s, max)), max)
361360
}
362361
// No truncation
363362
assertTrunc("ABC", 3, "ABC")

sheet.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"sort"
2525
"strconv"
2626
"strings"
27-
"unicode/utf16"
2827

2928
"github.com/tiendc/go-deepcopy"
3029
)
@@ -1341,7 +1340,7 @@ func (f *File) SetHeaderFooter(sheet string, opts *HeaderFooterOptions) error {
13411340
// Check 6 string type fields: OddHeader, OddFooter, EvenHeader, EvenFooter,
13421341
// FirstFooter, FirstHeader
13431342
for i := 4; i < v.NumField()-1; i++ {
1344-
if len(utf16.Encode([]rune(v.Field(i).String()))) > MaxFieldLength {
1343+
if countUTF16String(v.Field(i).String()) > MaxFieldLength {
13451344
return newFieldLengthError(v.Type().Field(i).Name)
13461345
}
13471346
}
@@ -1484,7 +1483,7 @@ func checkSheetName(name string) error {
14841483
if name == "" {
14851484
return ErrSheetNameBlank
14861485
}
1487-
if len(utf16.Encode([]rune(name))) > MaxSheetNameLength {
1486+
if countUTF16String(name) > MaxSheetNameLength {
14881487
return ErrSheetNameLength
14891488
}
14901489
if strings.HasPrefix(name, "'") || strings.HasSuffix(name, "'") {

0 commit comments

Comments
 (0)