diff --git a/README.md b/README.md index 84ddde0d..7774a508 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ ## Introduction -Excelize is a library written in pure Go and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Microsoft Excel™ 2007 and later. Support save file without losing original charts of XLSX. This library needs Go version 1.8 or later. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize) 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 XLSX files. Supports reading and writing XLSX file generated by Microsoft Excel™ 2007 and later. +Supports saving a file without losing original charts of XLSX. This library needs Go version 1.8 or later. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize) and [docs reference](https://xuri.me/excelize/). ## Basic Usage diff --git a/picture.go b/picture.go index 9a9ff09e..16572d41 100644 --- a/picture.go +++ b/picture.go @@ -151,10 +151,10 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, xlsx := f.workSheetReader(sheet) // Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder. drawingID := f.countDrawings() + 1 - pictureID := f.countMedia() + 1 drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml" drawingID, drawingXML = f.prepareDrawing(xlsx, drawingID, sheet, drawingXML) - drawingRID := f.addDrawingRelationships(drawingID, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, hyperlinkType) + mediaStr := ".." + strings.TrimPrefix(f.addMedia(file, ext), "xl") + drawingRID := f.addDrawingRelationships(drawingID, SourceRelationshipImage, mediaStr, hyperlinkType) // Add picture with hyperlink. if formatSet.Hyperlink != "" && formatSet.HyperlinkType != "" { if formatSet.HyperlinkType == "External" { @@ -166,7 +166,6 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, if err != nil { return err } - f.addMedia(file, ext) f.addContentTypePart(drawingID, "drawings") return err } @@ -363,12 +362,22 @@ func (f *File) countMedia() int { return count } -// addMedia provides a function to add picture into folder xl/media/image by -// given file and extension name. -func (f *File) addMedia(file []byte, ext string) { +// addMedia provides a function to add a picture into folder xl/media/image by +// given file and extension name. Duplicate images are only actually stored once +// and drawings that use it will reference the same image. +func (f *File) addMedia(file []byte, ext string) string { count := f.countMedia() + for name, existing := range f.XLSX { + if !strings.HasPrefix(name, "xl/media/image") { + continue + } + if bytes.Equal(file, existing) { + return name + } + } media := "xl/media/image" + strconv.Itoa(count+1) + ext f.XLSX[media] = file + return media } // setContentTypePartImageExtensions provides a function to set the content diff --git a/picture_test.go b/picture_test.go index 518713ff..2b39ed80 100644 --- a/picture_test.go +++ b/picture_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -146,3 +147,20 @@ func TestAddDrawingPicture(t *testing.T) { f := NewFile() assert.EqualError(t, f.addDrawingPicture("sheet1", "", "A", "", 0, 0, 0, 0, nil), `cannot convert cell "A" to coordinates: invalid cell name "A"`) } + +func TestAddPictureFromBytes(t *testing.T) { + f := NewFile() + imgFile, err := ioutil.ReadFile("logo.png") + if err != nil { + t.Error("Unable to load logo for test") + } + f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", 1), "", "logo", ".png", imgFile) + f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", 50), "", "logo", ".png", imgFile) + imageCount := 0 + for fileName := range f.XLSX { + if strings.Contains(fileName, "media/image") { + imageCount++ + } + } + assert.Equal(t, 1, imageCount, "Duplicate image should only be stored once.") +}