Skip to content

Commit d1ca080

Browse files
committed
Introduce new function SetZipWriter
- Add new ZipWriter data type - Add new field ZipWriter in the File data type - Made the CharsetTranscoder function parameter not use the internal data type charsetTranscoderFn - Update unit tests
1 parent 7bf0bbb commit d1ca080

File tree

4 files changed

+32
-26
lines changed

4 files changed

+32
-26
lines changed

excelize.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"bytes"
1818
"encoding/xml"
1919
"io"
20+
"io/fs"
2021
"os"
2122
"path/filepath"
2223
"strconv"
@@ -41,7 +42,7 @@ type File struct {
4142
tempFiles sync.Map
4243
xmlAttr sync.Map
4344
CalcChain *xlsxCalcChain
44-
CharsetReader charsetTranscoderFn
45+
CharsetReader func(charset string, input io.Reader) (rdr io.Reader, err error)
4546
Comments map[string]*xlsxComments
4647
ContentTypes *xlsxTypes
4748
DecodeVMLDrawing map[string]*decodeVmlDrawing
@@ -58,11 +59,17 @@ type File struct {
5859
VMLDrawing map[string]*vmlDrawing
5960
VolatileDeps *xlsxVolTypes
6061
WorkBook *xlsxWorkbook
62+
ZipWriter func(io.Writer) ZipWriter
6163
}
6264

63-
// charsetTranscoderFn set user-defined codepage transcoder function for open
64-
// the spreadsheet from non-UTF-8 encoding.
65-
type charsetTranscoderFn func(charset string, input io.Reader) (rdr io.Reader, err error)
65+
// ZipWriter defines an interface for writing files to a ZIP archive. It
66+
// provides methods to create new files within the archive, add files from a
67+
// filesystem, and close the archive when writing is complete.
68+
type ZipWriter interface {
69+
Create(name string) (io.Writer, error)
70+
AddFS(fsys fs.FS) error
71+
Close() error
72+
}
6673

6774
// Options define the options for opening and reading the spreadsheet.
6875
//
@@ -153,6 +160,7 @@ func newFile() *File {
153160
VMLDrawing: make(map[string]*vmlDrawing),
154161
Relationships: sync.Map{},
155162
CharsetReader: charset.NewReaderLabel,
163+
ZipWriter: func(w io.Writer) ZipWriter { return zip.NewWriter(w) },
156164
}
157165
}
158166

@@ -232,9 +240,15 @@ func (f *File) getOptions(opts ...Options) *Options {
232240
return options
233241
}
234242

235-
// CharsetTranscoder Set user defined codepage transcoder function for open
243+
// CharsetTranscoder set user defined codepage transcoder function for open
236244
// workbook from non UTF-8 encoding.
237-
func (f *File) CharsetTranscoder(fn charsetTranscoderFn) *File { f.CharsetReader = fn; return f }
245+
func (f *File) CharsetTranscoder(fn func(charset string, input io.Reader) (rdr io.Reader, err error)) *File {
246+
f.CharsetReader = fn
247+
return f
248+
}
249+
250+
// SetZipWriter set user defined zip writer function for saving the workbook.
251+
func (f *File) SetZipWriter(fn func(io.Writer) ZipWriter) *File { f.ZipWriter = fn; return f }
238252

239253
// Creates new XML decoder with charset reader.
240254
func (f *File) xmlNewDecoder(rdr io.Reader) (ret *xml.Decoder) {

excelize_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"time"
2222

2323
"github.com/stretchr/testify/assert"
24+
"golang.org/x/net/html/charset"
2425
)
2526

2627
func TestOpenFile(t *testing.T) {
@@ -244,7 +245,7 @@ func TestSaveAsWrongPath(t *testing.T) {
244245

245246
func TestCharsetTranscoder(t *testing.T) {
246247
f := NewFile()
247-
f.CharsetTranscoder(*new(charsetTranscoderFn))
248+
f.CharsetTranscoder(charset.NewReaderLabel)
248249
}
249250

250251
func TestOpenReader(t *testing.T) {
@@ -355,7 +356,7 @@ func TestOpenReader(t *testing.T) {
355356

356357
func TestBrokenFile(t *testing.T) {
357358
// Test write file with broken file struct
358-
f := File{}
359+
f := File{ZipWriter: func(w io.Writer) ZipWriter { return zip.NewWriter(w) }}
359360

360361
t.Run("SaveWithoutName", func(t *testing.T) {
361362
assert.EqualError(t, f.Save(), "no path defined for file, consider File.WriteTo or File.Write")

file.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
package excelize
1313

1414
import (
15-
"archive/zip"
1615
"bytes"
1716
"encoding/binary"
1817
"encoding/xml"
1918
"io"
20-
"io/fs"
2119
"math"
2220
"os"
2321
"path/filepath"
@@ -137,22 +135,8 @@ func (f *File) WriteTo(w io.Writer, opts ...Options) (int64, error) {
137135
// WriteToBuffer provides a function to get bytes.Buffer from the saved file,
138136
// and it allocates space in memory. Be careful when the file size is large.
139137
func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
140-
return f.WriteToBufferCustomZIP(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
141-
}
142-
143-
type ZipWriter interface {
144-
Create(name string) (io.Writer, error)
145-
AddFS(fsys fs.FS) error
146-
Close() error
147-
}
148-
149-
// WriteToBufferCustomZIP provides a function to write to a buffer using a custom ZIP writer
150-
// factory. This allows for custom ZIP compression implementations to be used when saving
151-
// the spreadsheet to memory. The factory function should return a zipWriter interface
152-
// that will be used to create the final ZIP archive.
153-
func (f *File) WriteToBufferCustomZIP(factory func(io.Writer) ZipWriter) (*bytes.Buffer, error) {
154138
buf := new(bytes.Buffer)
155-
zw := factory(buf)
139+
zw := f.ZipWriter(buf)
156140

157141
if err := f.writeToZip(zw); err != nil {
158142
_ = zw.Close()
@@ -173,7 +157,7 @@ func (f *File) WriteToBufferCustomZIP(factory func(io.Writer) ZipWriter) (*bytes
173157
return buf, nil
174158
}
175159

176-
// writeToZip provides a function to write to zipWriter
160+
// writeToZip provides a function to write to ZipWriter.
177161
func (f *File) writeToZip(zw ZipWriter) error {
178162
f.calcChainWriter()
179163
f.commentsWriter()

file_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package excelize
22

33
import (
4+
"archive/zip"
45
"bufio"
56
"bytes"
67
"encoding/binary"
8+
"io"
79
"math"
810
"os"
911
"path/filepath"
@@ -43,6 +45,7 @@ func TestWriteTo(t *testing.T) {
4345
// Test WriteToBuffer err
4446
{
4547
f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
48+
f.SetZipWriter(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
4649
f.Pkg.Store("/d/", []byte("s"))
4750
_, err := f.WriteTo(bufio.NewWriter(&buf))
4851
assert.EqualError(t, err, "zip: write to directory")
@@ -51,6 +54,7 @@ func TestWriteTo(t *testing.T) {
5154
// Test file path overflow
5255
{
5356
f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
57+
f.SetZipWriter(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
5458
const maxUint16 = 1<<16 - 1
5559
f.Pkg.Store(strings.Repeat("s", maxUint16+1), nil)
5660
_, err := f.WriteTo(bufio.NewWriter(&buf))
@@ -59,6 +63,7 @@ func TestWriteTo(t *testing.T) {
5963
// Test StreamsWriter err
6064
{
6165
f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
66+
f.SetZipWriter(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
6267
f.Pkg.Store("s", nil)
6368
f.streams = make(map[string]*StreamWriter)
6469
file, _ := os.Open("123")
@@ -69,6 +74,7 @@ func TestWriteTo(t *testing.T) {
6974
// Test write with temporary file
7075
{
7176
f, buf := File{tempFiles: sync.Map{}}, bytes.Buffer{}
77+
f.SetZipWriter(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
7278
const maxUint16 = 1<<16 - 1
7379
f.tempFiles.Store("s", "")
7480
f.tempFiles.Store(strings.Repeat("s", maxUint16+1), "")
@@ -78,6 +84,7 @@ func TestWriteTo(t *testing.T) {
7884
// Test write with unsupported workbook file format
7985
{
8086
f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
87+
f.SetZipWriter(func(w io.Writer) ZipWriter { return zip.NewWriter(w) })
8188
f.Pkg.Store("/d", []byte("s"))
8289
f.Path = "Book1.xls"
8390
_, err := f.WriteTo(bufio.NewWriter(&buf))

0 commit comments

Comments
 (0)