summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2022-09-08 22:20:21 +0800
committerxuri <xuri.me@gmail.com>2022-09-08 22:20:21 +0800
commitfb1aab7add52808c96c9cc10570fe73ce797b7f4 (patch)
tree778202a8944ecad3c7f74edf4f9ac4b0a150f79d
parent0c5cdfec1868f31f6e355cdcb0a91220bad80522 (diff)
This closes #744, the `Save`, `Write` and `WriteTo` function accept saving options
-rw-r--r--crypt_test.go2
-rw-r--r--excelize.go4
-rw-r--r--excelize_test.go9
-rw-r--r--file.go42
-rw-r--r--file_test.go8
-rw-r--r--xmlDrawing.go9
6 files changed, 44 insertions, 30 deletions
diff --git a/crypt_test.go b/crypt_test.go
index f7c465e..95b6f52 100644
--- a/crypt_test.go
+++ b/crypt_test.go
@@ -48,6 +48,8 @@ func TestEncrypt(t *testing.T) {
cell, err = f.GetCellValue("Sheet1", "A1")
assert.NoError(t, err)
assert.Equal(t, "SECRET", cell)
+ // Test remove password by save workbook with options
+ assert.NoError(t, f.Save(Options{Password: ""}))
assert.NoError(t, f.Close())
}
diff --git a/excelize.go b/excelize.go
index f1269fe..bb4bde0 100644
--- a/excelize.go
+++ b/excelize.go
@@ -136,13 +136,13 @@ func newFile() *File {
// OpenReader read data stream from io.Reader and return a populated
// spreadsheet file.
-func OpenReader(r io.Reader, opt ...Options) (*File, error) {
+func OpenReader(r io.Reader, opts ...Options) (*File, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
f := newFile()
- f.options = parseOptions(opt...)
+ f.options = parseOptions(opts...)
if f.options.UnzipSizeLimit == 0 {
f.options.UnzipSizeLimit = UnzipSizeLimit
if f.options.UnzipXMLSizeLimit > f.options.UnzipSizeLimit {
diff --git a/excelize_test.go b/excelize_test.go
index 19aba7e..93cd2bf 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -186,18 +186,15 @@ func TestOpenFile(t *testing.T) {
func TestSaveFile(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
- if !assert.NoError(t, err) {
- t.FailNow()
- }
+ assert.NoError(t, err)
assert.EqualError(t, f.SaveAs(filepath.Join("test", "TestSaveFile.xlsb")), ErrWorkbookFileFormat.Error())
for _, ext := range []string{".xlam", ".xlsm", ".xlsx", ".xltm", ".xltx"} {
assert.NoError(t, f.SaveAs(filepath.Join("test", fmt.Sprintf("TestSaveFile%s", ext))))
}
assert.NoError(t, f.Close())
+
f, err = OpenFile(filepath.Join("test", "TestSaveFile.xlsx"))
- if !assert.NoError(t, err) {
- t.FailNow()
- }
+ assert.NoError(t, err)
assert.NoError(t, f.Save())
assert.NoError(t, f.Close())
}
diff --git a/file.go b/file.go
index 065e7c5..c83d17e 100644
--- a/file.go
+++ b/file.go
@@ -55,44 +55,32 @@ func NewFile() *File {
}
// Save provides a function to override the spreadsheet with origin path.
-func (f *File) Save() error {
+func (f *File) Save(opts ...Options) error {
if f.Path == "" {
return ErrSave
}
- if f.options != nil {
- return f.SaveAs(f.Path, *f.options)
+ for i := range opts {
+ f.options = &opts[i]
}
- return f.SaveAs(f.Path)
+ return f.SaveAs(f.Path, *f.options)
}
// SaveAs provides a function to create or update to a spreadsheet at the
// provided path.
-func (f *File) SaveAs(name string, opt ...Options) error {
+func (f *File) SaveAs(name string, opts ...Options) error {
if len(name) > MaxFilePathLength {
return ErrMaxFilePathLength
}
f.Path = name
- contentType, ok := map[string]string{
- ".xlam": ContentTypeAddinMacro,
- ".xlsm": ContentTypeMacro,
- ".xlsx": ContentTypeSheetML,
- ".xltm": ContentTypeTemplateMacro,
- ".xltx": ContentTypeTemplate,
- }[filepath.Ext(f.Path)]
- if !ok {
+ if _, ok := supportedContentType[filepath.Ext(f.Path)]; !ok {
return ErrWorkbookFileFormat
}
- f.setContentTypePartProjectExtensions(contentType)
file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
if err != nil {
return err
}
defer file.Close()
- f.options = nil
- for i := range opt {
- f.options = &opt[i]
- }
- return f.Write(file)
+ return f.Write(file, opts...)
}
// Close closes and cleanup the open temporary file for the spreadsheet.
@@ -113,13 +101,23 @@ func (f *File) Close() error {
}
// Write provides a function to write to an io.Writer.
-func (f *File) Write(w io.Writer) error {
- _, err := f.WriteTo(w)
+func (f *File) Write(w io.Writer, opts ...Options) error {
+ _, err := f.WriteTo(w, opts...)
return err
}
// WriteTo implements io.WriterTo to write the file.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
+func (f *File) WriteTo(w io.Writer, opts ...Options) (int64, error) {
+ for i := range opts {
+ f.options = &opts[i]
+ }
+ if len(f.Path) != 0 {
+ contentType, ok := supportedContentType[filepath.Ext(f.Path)]
+ if !ok {
+ return 0, ErrWorkbookFileFormat
+ }
+ f.setContentTypePartProjectExtensions(contentType)
+ }
if f.options != nil && f.options.Password != "" {
buf, err := f.WriteToBuffer()
if err != nil {
diff --git a/file_test.go b/file_test.go
index 8e65c5d..83a9b78 100644
--- a/file_test.go
+++ b/file_test.go
@@ -71,6 +71,14 @@ func TestWriteTo(t *testing.T) {
_, err := f.WriteTo(bufio.NewWriter(&buf))
assert.EqualError(t, err, "zip: FileHeader.Name too long")
}
+ // Test write with unsupported workbook file format
+ {
+ f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
+ f.Pkg.Store("/d", []byte("s"))
+ f.Path = "Book1.xls"
+ _, err := f.WriteTo(bufio.NewWriter(&buf))
+ assert.EqualError(t, err, ErrWorkbookFileFormat.Error())
+ }
}
func TestClose(t *testing.T) {
diff --git a/xmlDrawing.go b/xmlDrawing.go
index 34c9858..fc8dee5 100644
--- a/xmlDrawing.go
+++ b/xmlDrawing.go
@@ -144,6 +144,15 @@ const (
// supportedImageTypes defined supported image types.
var supportedImageTypes = map[string]string{".gif": ".gif", ".jpg": ".jpeg", ".jpeg": ".jpeg", ".png": ".png", ".tif": ".tiff", ".tiff": ".tiff", ".emf": ".emf", ".wmf": ".wmf", ".emz": ".emz", ".wmz": ".wmz"}
+// supportedContentType defined supported file format types.
+var supportedContentType = map[string]string{
+ ".xlam": ContentTypeAddinMacro,
+ ".xlsm": ContentTypeMacro,
+ ".xlsx": ContentTypeSheetML,
+ ".xltm": ContentTypeTemplateMacro,
+ ".xltx": ContentTypeTemplate,
+}
+
// xlsxCNvPr directly maps the cNvPr (Non-Visual Drawing Properties). This
// element specifies non-visual canvas properties. This allows for additional
// information that does not affect the appearance of the picture to be stored.