Go 1.16 and later required, migration of deprecation package `ioutil`

- Improving performance for stream writer `SetRow` function,  reduces memory usage over and speedup about 19%
- Update dependencies module
- Update GitHub workflow
This commit is contained in:
xuri 2022-10-13 00:02:53 +08:00
parent 0e657c887b
commit 7363c1e333
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
15 changed files with 109 additions and 67 deletions

View File

@ -5,7 +5,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x]
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x]
os: [ubuntu-latest, macos-latest, windows-latest]
targetplatform: [x86, x64]

View File

@ -13,7 +13,7 @@
## Introduction
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.15 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.16 or later. The full docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
## Basic Usage

View File

@ -13,7 +13,7 @@
## 简介
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写函数,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.16 或更高版本,完整的使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
## 快速上手

View File

@ -12,7 +12,7 @@
package excelize
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
@ -32,7 +32,7 @@ func TestEncrypt(t *testing.T) {
assert.Equal(t, "SECRET", cell)
assert.NoError(t, f.Close())
// Test decrypt spreadsheet with unsupported encrypt mechanism
raw, err := ioutil.ReadFile(filepath.Join("test", "encryptAES.xlsx"))
raw, err := os.ReadFile(filepath.Join("test", "encryptAES.xlsx"))
assert.NoError(t, err)
raw[2050] = 3
_, err = Decrypt(raw, &Options{Password: "password"})

View File

@ -18,7 +18,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
@ -137,7 +136,7 @@ func newFile() *File {
// OpenReader read data stream from io.Reader and return a populated
// spreadsheet file.
func OpenReader(r io.Reader, opts ...Options) (*File, error) {
b, err := ioutil.ReadAll(r)
b, err := io.ReadAll(r)
if err != nil {
return nil, err
}
@ -488,7 +487,7 @@ func (f *File) AddVBAProject(bin string) error {
Type: SourceRelationshipVBAProject,
})
}
file, _ := ioutil.ReadFile(filepath.Clean(bin))
file, _ := os.ReadFile(filepath.Clean(bin))
f.Pkg.Store("xl/vbaProject.bin", file)
return err
}

View File

@ -10,7 +10,6 @@ import (
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"io/ioutil"
"math"
"os"
"path/filepath"
@ -1388,7 +1387,7 @@ func prepareTestBook1() (*File, error) {
return nil, err
}
file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
file, err := os.ReadFile(filepath.Join("test", "images", "excel.jpg"))
if err != nil {
return nil, err
}

17
go.mod
View File

@ -1,18 +1,17 @@
module github.com/xuri/excelize/v2
go 1.15
go 1.16
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/richardlehane/mscfb v1.0.4
github.com/richardlehane/msoleps v1.0.3 // indirect
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.0
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
golang.org/x/net v0.0.0-20221004154528-8021a29435af
golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.0 // indirect
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458
golang.org/x/text v0.3.8
)
require github.com/richardlehane/msoleps v1.0.3 // indirect

40
go.sum
View File

@ -11,31 +11,51 @@ github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTK
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0=
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20221004154528-8021a29435af h1:wv66FM3rLZGPdxpYL+ApnDe2HzHcTFta3z5nsc13wI4=
golang.org/x/net v0.0.0-20221004154528-8021a29435af/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458 h1:MgJ6t2zo8v0tbmLCueaCbF1RM+TtB0rs3Lv8DGtOIpY=
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

5
lib.go
View File

@ -18,7 +18,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
"regexp"
@ -73,7 +72,7 @@ func (f *File) ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
// unzipToTemp unzip the zip entity to the system temporary directory and
// returned the unzipped file path.
func (f *File) unzipToTemp(zipFile *zip.File) (string, error) {
tmp, err := ioutil.TempFile(os.TempDir(), "excelize-")
tmp, err := os.CreateTemp(os.TempDir(), "excelize-")
if err != nil {
return "", err
}
@ -111,7 +110,7 @@ func (f *File) readBytes(name string) []byte {
if err != nil {
return content
}
content, _ = ioutil.ReadAll(file)
content, _ = io.ReadAll(file)
f.Pkg.Store(name, content)
_ = file.Close()
return content

View File

@ -17,7 +17,6 @@ import (
"encoding/xml"
"image"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
@ -115,7 +114,7 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
if !ok {
return ErrImgExt
}
file, _ := ioutil.ReadFile(filepath.Clean(picture))
file, _ := os.ReadFile(filepath.Clean(picture))
_, name := filepath.Split(picture)
return f.AddPictureFromBytes(sheet, cell, format, name, ext, file)
}
@ -129,7 +128,7 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
// import (
// "fmt"
// _ "image/jpeg"
// "io/ioutil"
// "os"
//
// "github.com/xuri/excelize/v2"
// )
@ -137,7 +136,7 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
// func main() {
// f := excelize.NewFile()
//
// file, err := ioutil.ReadFile("image.jpg")
// file, err := os.ReadFile("image.jpg")
// if err != nil {
// fmt.Println(err)
// }
@ -486,7 +485,7 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
// fmt.Println(err)
// return
// }
// if err := ioutil.WriteFile(file, raw, 0644); err != nil {
// if err := os.WriteFile(file, raw, 0644); err != nil {
// fmt.Println(err)
// }
func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {

View File

@ -7,7 +7,7 @@ import (
_ "image/jpeg"
_ "image/png"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
@ -19,7 +19,7 @@ import (
func BenchmarkAddPictureFromBytes(b *testing.B) {
f := NewFile()
imgFile, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.png"))
imgFile, err := os.ReadFile(filepath.Join("test", "images", "excel.png"))
if err != nil {
b.Error("unable to load image for benchmark")
}
@ -42,7 +42,7 @@ func TestAddPicture(t *testing.T) {
assert.NoError(t, f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.jpg"),
`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/xuri/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`))
file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.png"))
file, err := os.ReadFile(filepath.Join("test", "images", "excel.png"))
assert.NoError(t, err)
// Test add picture to worksheet with autofit.
@ -114,7 +114,7 @@ func TestGetPicture(t *testing.T) {
file, raw, err := f.GetPicture("Sheet1", "F21")
assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0o644)) {
!assert.NoError(t, os.WriteFile(filepath.Join("test", file), raw, 0o644)) {
t.FailNow()
}
@ -148,7 +148,7 @@ func TestGetPicture(t *testing.T) {
file, raw, err = f.GetPicture("Sheet1", "F21")
assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0o644)) {
!assert.NoError(t, os.WriteFile(filepath.Join("test", file), raw, 0o644)) {
t.FailNow()
}
@ -180,7 +180,7 @@ func TestAddDrawingPicture(t *testing.T) {
func TestAddPictureFromBytes(t *testing.T) {
f := NewFile()
imgFile, err := ioutil.ReadFile("logo.png")
imgFile, err := os.ReadFile("logo.png")
assert.NoError(t, err, "Unable to load logo for test")
assert.NoError(t, f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", 1), "", "logo", ".png", imgFile))
assert.NoError(t, f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", 50), "", "logo", ".png", imgFile))

View File

@ -16,7 +16,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"math"
"os"
@ -296,7 +295,7 @@ func (f *File) getFromStringItem(index int) string {
defer tempFile.Close()
}
f.sharedStringItem = [][]uint{}
f.sharedStringTemp, _ = ioutil.TempFile(os.TempDir(), "excelize-")
f.sharedStringTemp, _ = os.CreateTemp(os.TempDir(), "excelize-")
f.tempFiles.Store(defaultTempFileSST, f.sharedStringTemp.Name())
var (
inElement string

View File

@ -17,7 +17,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path"
@ -479,7 +478,7 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
if !ok {
return ErrImgExt
}
file, _ := ioutil.ReadFile(filepath.Clean(picture))
file, _ := os.ReadFile(filepath.Clean(picture))
name := f.addMedia(file, ext)
sheetXMLPath, _ := f.getSheetXMLPath(sheet)
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetXMLPath, "xl/worksheets/") + ".rels"

View File

@ -16,7 +16,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"os"
"reflect"
"strconv"
@ -30,7 +29,7 @@ type StreamWriter struct {
Sheet string
SheetID int
sheetWritten bool
cols string
cols strings.Builder
worksheet *xlsxWorksheet
rawData bufferedWriter
mergeCellsCount int
@ -310,24 +309,32 @@ type RowOpts struct {
}
// marshalAttrs prepare attributes of the row.
func (r *RowOpts) marshalAttrs() (attrs string, err error) {
func (r *RowOpts) marshalAttrs() (strings.Builder, error) {
var (
err error
attrs strings.Builder
)
if r == nil {
return
return attrs, err
}
if r.Height > MaxRowHeight {
err = ErrMaxRowHeight
return
return attrs, err
}
if r.StyleID > 0 {
attrs += fmt.Sprintf(` s="%d" customFormat="true"`, r.StyleID)
attrs.WriteString(` s="`)
attrs.WriteString(strconv.Itoa(r.StyleID))
attrs.WriteString(`" customFormat="1"`)
}
if r.Height > 0 {
attrs += fmt.Sprintf(` ht="%v" customHeight="true"`, r.Height)
attrs.WriteString(` ht="`)
attrs.WriteString(strconv.FormatFloat(r.Height, 'f', -1, 64))
attrs.WriteString(`" customHeight="1"`)
}
if r.Hidden {
attrs += ` hidden="true"`
attrs.WriteString(` hidden="1"`)
}
return
return attrs, err
}
// parseRowOpts provides a function to parse the optional settings for
@ -357,7 +364,11 @@ func (sw *StreamWriter) SetRow(cell string, values []interface{}, opts ...RowOpt
if err != nil {
return err
}
_, _ = fmt.Fprintf(&sw.rawData, `<row r="%d"%s>`, row, attrs)
sw.rawData.WriteString(`<row r="`)
sw.rawData.WriteString(strconv.Itoa(row))
sw.rawData.WriteString(`"`)
sw.rawData.WriteString(attrs.String())
sw.rawData.WriteString(`>`)
for i, val := range values {
if val == nil {
continue
@ -405,7 +416,14 @@ func (sw *StreamWriter) SetColWidth(min, max int, width float64) error {
if min > max {
min, max = max, min
}
sw.cols += fmt.Sprintf(`<col min="%d" max="%d" width="%f" customWidth="1"/>`, min, max, width)
sw.cols.WriteString(`<col min="`)
sw.cols.WriteString(strconv.Itoa(min))
sw.cols.WriteString(`" max="`)
sw.cols.WriteString(strconv.Itoa(max))
sw.cols.WriteString(`" width="`)
sw.cols.WriteString(strconv.FormatFloat(width, 'f', -1, 64))
sw.cols.WriteString(`" customWidth="1"/>`)
return nil
}
@ -515,14 +533,24 @@ func setCellIntFunc(c *xlsxC, val interface{}) (err error) {
func writeCell(buf *bufferedWriter, c xlsxC) {
_, _ = buf.WriteString(`<c`)
if c.XMLSpace.Value != "" {
fmt.Fprintf(buf, ` xml:%s="%s"`, c.XMLSpace.Name.Local, c.XMLSpace.Value)
_, _ = buf.WriteString(` xml:`)
_, _ = buf.WriteString(c.XMLSpace.Name.Local)
_, _ = buf.WriteString(`="`)
_, _ = buf.WriteString(c.XMLSpace.Value)
_, _ = buf.WriteString(`"`)
}
fmt.Fprintf(buf, ` r="%s"`, c.R)
_, _ = buf.WriteString(` r="`)
_, _ = buf.WriteString(c.R)
_, _ = buf.WriteString(`"`)
if c.S != 0 {
fmt.Fprintf(buf, ` s="%d"`, c.S)
_, _ = buf.WriteString(` s="`)
_, _ = buf.WriteString(strconv.Itoa(c.S))
_, _ = buf.WriteString(`"`)
}
if c.T != "" {
fmt.Fprintf(buf, ` t="%s"`, c.T)
_, _ = buf.WriteString(` t="`)
_, _ = buf.WriteString(c.T)
_, _ = buf.WriteString(`"`)
}
_, _ = buf.WriteString(`>`)
if c.F != nil {
@ -549,8 +577,10 @@ func writeCell(buf *bufferedWriter, c xlsxC) {
func (sw *StreamWriter) writeSheetData() {
if !sw.sheetWritten {
bulkAppendFields(&sw.rawData, sw.worksheet, 4, 5)
if len(sw.cols) > 0 {
_, _ = sw.rawData.WriteString("<cols>" + sw.cols + "</cols>")
if sw.cols.Len() > 0 {
_, _ = sw.rawData.WriteString("<cols>")
_, _ = sw.rawData.WriteString(sw.cols.String())
_, _ = sw.rawData.WriteString("</cols>")
}
_, _ = sw.rawData.WriteString(`<sheetData>`)
sw.sheetWritten = true
@ -642,7 +672,7 @@ func (bw *bufferedWriter) Sync() (err error) {
return nil
}
if bw.tmp == nil {
bw.tmp, err = ioutil.TempFile(os.TempDir(), "excelize-")
bw.tmp, err = os.CreateTemp(os.TempDir(), "excelize-")
if err != nil {
// can not use local storage
return nil

View File

@ -3,7 +3,6 @@ package excelize
import (
"encoding/xml"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
@ -95,7 +94,7 @@ func TestStreamWriter(t *testing.T) {
assert.NoError(t, streamWriter.rawData.Close())
assert.Error(t, streamWriter.Flush())
streamWriter.rawData.tmp, err = ioutil.TempFile(os.TempDir(), "excelize-")
streamWriter.rawData.tmp, err = os.CreateTemp(os.TempDir(), "excelize-")
assert.NoError(t, err)
_, err = streamWriter.rawData.Reader()
assert.NoError(t, err)