diff --git a/excelize.go b/excelize.go index bc37c0a..3c81db2 100644 --- a/excelize.go +++ b/excelize.go @@ -4,6 +4,9 @@ import ( "archive/zip" "bytes" "encoding/xml" + "io" + "io/ioutil" + "os" "strconv" "strings" ) @@ -19,20 +22,31 @@ type File struct { // OpenFile take the name of an XLSX file and returns a populated XLSX file // struct for it. func OpenFile(filename string) (*File, error) { - var f *zip.ReadCloser - var err error - file := make(map[string]string) - c := make(map[string]bool) - sheetCount := 0 - f, err = zip.OpenReader(filename) + file, err := os.Open(filename) if err != nil { - return &File{}, err + return nil, err + } + b, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + return OpenReader(bytes.NewReader(b), int64(len(b))) +} + +// OpenReader take an io.Reader and return a populated XLSX file. +func OpenReader(r io.ReaderAt, size int64) (*File, error) { + zr, err := zip.NewReader(r, size) + if err != nil { + return nil, err + } + file, sheetCount, err := ReadZipReader(zr) + if err != nil { + return nil, err } - file, sheetCount, _ = ReadZip(f) return &File{ - checked: c, + checked: make(map[string]bool), XLSX: file, - Path: filename, + Path: "", SheetCount: sheetCount, }, nil } diff --git a/file.go b/file.go index 2a044f0..17a8bba 100644 --- a/file.go +++ b/file.go @@ -3,6 +3,8 @@ package excelize import ( "archive/zip" "bytes" + "fmt" + "io" "os" ) @@ -29,53 +31,45 @@ func CreateFile() *File { // Save provides function to override the xlsx file with origin path. func (f *File) Save() error { - buf := new(bytes.Buffer) - w := zip.NewWriter(buf) - for path, content := range f.XLSX { - f, err := w.Create(path) - if err != nil { - return err - } - _, err = f.Write([]byte(content)) - if err != nil { - return err - } + if f.Path == "" { + return fmt.Errorf("No path defined for file, consider File.WriteTo or File.Write") } - err := w.Close() - if err != nil { - return err - } - file, err := os.OpenFile(f.Path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) - if err != nil { - return err - } - buf.WriteTo(file) - return err + return f.WriteTo(f.Path) } // WriteTo provides function to create or update to an xlsx file at the provided // path. func (f *File) WriteTo(name string) error { - buf := new(bytes.Buffer) - w := zip.NewWriter(buf) - for path, content := range f.XLSX { - f, err := w.Create(path) - if err != nil { - return err - } - _, err = f.Write([]byte(content)) - if err != nil { - return err - } - } - err := w.Close() - if err != nil { - return err - } file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) if err != nil { return err } - buf.WriteTo(file) - return err + defer file.Close() + return f.Write(file) +} + +// Write provides function to write to an io.Writer. +func (f *File) Write(w io.Writer) error { + buf := new(bytes.Buffer) + zw := zip.NewWriter(buf) + for path, content := range f.XLSX { + fi, err := zw.Create(path) + if err != nil { + return err + } + _, err = fi.Write([]byte(content)) + if err != nil { + return err + } + } + err := zw.Close() + if err != nil { + return err + } + + if _, err := buf.WriteTo(w); err != nil { + return err + } + + return nil } diff --git a/lib.go b/lib.go index c3767e3..8c56f1b 100644 --- a/lib.go +++ b/lib.go @@ -8,14 +8,6 @@ import ( "math" ) -// ReadZip takes a pointer to a zip.ReadCloser and returns a xlsx.File struct -// populated with its contents. In most cases ReadZip is not used directly, but -// is called internally by OpenFile. -func ReadZip(f *zip.ReadCloser) (map[string]string, int, error) { - defer f.Close() - return ReadZipReader(&f.Reader) -} - // ReadZipReader can be used to read an XLSX in memory without touching the // filesystem. func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {