diff --git a/picture.go b/picture.go index e6410dc9821ba87ecd0933f383dd0e8e58c64d6c..d784079d75ac95aea9f87f431ee79354004621f4 100644 --- a/picture.go +++ b/picture.go @@ -23,6 +23,17 @@ import ( "strings" ) +// PictureInsertType defines the type of the picture has been inserted into the +// worksheet. +type PictureInsertType int + +// Insert picture types. +const ( + PictureInsertTypePlaceOverCells PictureInsertType = iota + PictureInsertTypePlaceInCell + PictureInsertTypeDISPIMG +) + // parseGraphicOptions provides a function to parse the format settings of // the picture with default value. func parseGraphicOptions(opts *GraphicOptions) *GraphicOptions { @@ -52,7 +63,10 @@ func parseGraphicOptions(opts *GraphicOptions) *GraphicOptions { // AddPicture provides the method to add picture in a sheet by given picture // format set (such as offset, scale, aspect ratio setting and print settings) // and file path, supported image types: BMP, EMF, EMZ, GIF, JPEG, JPG, PNG, -// SVG, TIF, TIFF, WMF, and WMZ. This function is concurrency safe. For example: +// SVG, TIF, TIFF, WMF, and WMZ. This function is concurrency-safe. Note that +// this function only supports adding pictures placed over the cells currently, +// and doesn't support adding pictures placed in cells or creating the Kingsoft +// WPS Office embedded image cells. For example: // // package main // @@ -167,8 +181,10 @@ func (f *File) AddPicture(sheet, cell, name string, opts *GraphicOptions) error // AddPictureFromBytes provides the method to add picture in a sheet by given // picture format set (such as offset, scale, aspect ratio setting and print // settings), file base name, extension name and file bytes, supported image -// types: EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ. For -// example: +// types: EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ. Note that +// this function only supports adding pictures placed over the cells currently, +// and doesn't support adding pictures placed in cells or creating the Kingsoft +// WPS Office embedded image cells.For example: // // package main // @@ -211,6 +227,9 @@ func (f *File) AddPictureFromBytes(sheet, cell string, pic *Picture) error { if !ok { return ErrImgExt } + if pic.InsertType != PictureInsertTypePlaceOverCells { + return ErrParameterInvalid + } options := parseGraphicOptions(pic.Format) img, _, err := image.DecodeConfig(bytes.NewReader(pic.File)) if err != nil { @@ -577,7 +596,7 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string) cond := func(from *xlsxFrom) bool { return from.Col == col && from.Row == row } cond2 := func(from *decodeFrom) bool { return from.Col == col && from.Row == row } cb := func(a *xdrCellAnchor, r *xlsxRelationship) { - pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}} + pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}, InsertType: PictureInsertTypePlaceOverCells} if buffer, _ := f.Pkg.Load(strings.ReplaceAll(r.Target, "..", "xl")); buffer != nil { pic.File = buffer.([]byte) pic.Format.AltText = a.Pic.NvPicPr.CNvPr.Descr @@ -585,7 +604,7 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string) } } cb2 := func(a *decodeCellAnchor, r *xlsxRelationship) { - pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}} + pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}, InsertType: PictureInsertTypePlaceOverCells} if buffer, _ := f.Pkg.Load(strings.ReplaceAll(r.Target, "..", "xl")); buffer != nil { pic.File = buffer.([]byte) pic.Format.AltText = a.Pic.NvPicPr.CNvPr.Descr @@ -845,7 +864,7 @@ func (f *File) getCellImages(sheet, cell string) ([]Picture, error) { if err != nil || r == nil { return "", true, err } - pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}} + pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}, InsertType: PictureInsertTypePlaceInCell} if buffer, _ := f.Pkg.Load(strings.TrimPrefix(strings.ReplaceAll(r.Target, "..", "xl"), "/")); buffer != nil { pic.File = buffer.([]byte) pics = append(pics, pic) @@ -882,7 +901,7 @@ func (f *File) getDispImages(sheet, cell string) ([]Picture, error) { if cellImg.Pic.NvPicPr.CNvPr.Name == imgID { for _, r := range rels.Relationships { if r.ID == cellImg.Pic.BlipFill.Blip.Embed { - pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}} + pic := Picture{Extension: filepath.Ext(r.Target), Format: &GraphicOptions{}, InsertType: PictureInsertTypeDISPIMG} if buffer, _ := f.Pkg.Load("xl/" + r.Target); buffer != nil { pic.File = buffer.([]byte) pic.Format.AltText = cellImg.Pic.NvPicPr.CNvPr.Descr diff --git a/picture_test.go b/picture_test.go index dfd5f623daa0b16d1cae16be30f1be125fd1be87..7d08b8d48a2a10c5ce4e3b1d4190fc8831196460 100644 --- a/picture_test.go +++ b/picture_test.go @@ -12,10 +12,9 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" _ "golang.org/x/image/bmp" _ "golang.org/x/image/tiff" - - "github.com/stretchr/testify/assert" ) func BenchmarkAddPictureFromBytes(b *testing.B) { @@ -59,6 +58,8 @@ func TestAddPicture(t *testing.T) { // Test add picture to worksheet from bytes assert.NoError(t, f.AddPictureFromBytes("Sheet1", "Q1", &Picture{Extension: ".png", File: file, Format: &GraphicOptions{AltText: "Excel Logo"}})) + // Test add picture to worksheet from bytes with unsupported insert type + assert.Equal(t, ErrParameterInvalid, f.AddPictureFromBytes("Sheet1", "Q1", &Picture{Extension: ".png", File: file, Format: &GraphicOptions{AltText: "Excel Logo"}, InsertType: PictureInsertTypePlaceInCell})) // Test add picture to worksheet from bytes with illegal cell reference assert.Equal(t, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")), f.AddPictureFromBytes("Sheet1", "A", &Picture{Extension: ".png", File: file, Format: &GraphicOptions{AltText: "Excel Logo"}})) @@ -150,6 +151,7 @@ func TestGetPicture(t *testing.T) { assert.NoError(t, err) assert.Len(t, pics[0].File, 13233) assert.Empty(t, pics[0].Format.AltText) + assert.Equal(t, PictureInsertTypePlaceOverCells, pics[0].InsertType) f, err = prepareTestBook1() if !assert.NoError(t, err) { @@ -249,6 +251,7 @@ func TestGetPicture(t *testing.T) { assert.NoError(t, err) assert.Len(t, pics, 2) assert.Equal(t, "CellImage1", pics[0].Format.AltText) + assert.Equal(t, PictureInsertTypeDISPIMG, pics[0].InsertType) // Test get embedded cell pictures with invalid formula assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=_xlfn.DISPIMG()")) @@ -463,6 +466,7 @@ func TestGetCellImages(t *testing.T) { pics, err := f.GetPictures("Sheet1", "A1") assert.NoError(t, err) assert.Equal(t, 1, len(pics)) + assert.Equal(t, PictureInsertTypePlaceInCell, pics[0].InsertType) cells, err := f.GetPictureCells("Sheet1") assert.NoError(t, err) assert.Equal(t, []string{"A1"}, cells) diff --git a/xmlDrawing.go b/xmlDrawing.go index 5cca3cf2515976d112529076d3bd2bf0723ab40e..7981166a804e91ffb4b1addf9c0ec83743bf7bd3 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -409,9 +409,10 @@ type xdrTxBody struct { // Picture maps the format settings of the picture. type Picture struct { - Extension string - File []byte - Format *GraphicOptions + Extension string + File []byte + Format *GraphicOptions + InsertType PictureInsertType } // GraphicOptions directly maps the format settings of the picture.