Introduce new exported PictureInsertType enumeration (#1864)

This commit is contained in:
yangyile-yyle88 2024-03-27 14:50:51 +07:00 committed by GitHub
parent 838232fd27
commit 5e500f5e5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 12 deletions

View File

@ -23,6 +23,17 @@ import (
"strings" "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 // parseGraphicOptions provides a function to parse the format settings of
// the picture with default value. // the picture with default value.
func parseGraphicOptions(opts *GraphicOptions) *GraphicOptions { 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 // 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) // 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, // 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 // 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 // AddPictureFromBytes provides the method to add picture in a sheet by given
// picture format set (such as offset, scale, aspect ratio setting and print // picture format set (such as offset, scale, aspect ratio setting and print
// settings), file base name, extension name and file bytes, supported image // 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 // types: EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ. Note that
// example: // 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 // package main
// //
@ -211,6 +227,9 @@ func (f *File) AddPictureFromBytes(sheet, cell string, pic *Picture) error {
if !ok { if !ok {
return ErrImgExt return ErrImgExt
} }
if pic.InsertType != PictureInsertTypePlaceOverCells {
return ErrParameterInvalid
}
options := parseGraphicOptions(pic.Format) options := parseGraphicOptions(pic.Format)
img, _, err := image.DecodeConfig(bytes.NewReader(pic.File)) img, _, err := image.DecodeConfig(bytes.NewReader(pic.File))
if err != nil { 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 } cond := func(from *xlsxFrom) bool { return from.Col == col && from.Row == row }
cond2 := func(from *decodeFrom) 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) { 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 { if buffer, _ := f.Pkg.Load(strings.ReplaceAll(r.Target, "..", "xl")); buffer != nil {
pic.File = buffer.([]byte) pic.File = buffer.([]byte)
pic.Format.AltText = a.Pic.NvPicPr.CNvPr.Descr 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) { 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 { if buffer, _ := f.Pkg.Load(strings.ReplaceAll(r.Target, "..", "xl")); buffer != nil {
pic.File = buffer.([]byte) pic.File = buffer.([]byte)
pic.Format.AltText = a.Pic.NvPicPr.CNvPr.Descr 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 { if err != nil || r == nil {
return "", true, err 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 { if buffer, _ := f.Pkg.Load(strings.TrimPrefix(strings.ReplaceAll(r.Target, "..", "xl"), "/")); buffer != nil {
pic.File = buffer.([]byte) pic.File = buffer.([]byte)
pics = append(pics, pic) pics = append(pics, pic)
@ -882,7 +901,7 @@ func (f *File) getDispImages(sheet, cell string) ([]Picture, error) {
if cellImg.Pic.NvPicPr.CNvPr.Name == imgID { if cellImg.Pic.NvPicPr.CNvPr.Name == imgID {
for _, r := range rels.Relationships { for _, r := range rels.Relationships {
if r.ID == cellImg.Pic.BlipFill.Blip.Embed { 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 { if buffer, _ := f.Pkg.Load("xl/" + r.Target); buffer != nil {
pic.File = buffer.([]byte) pic.File = buffer.([]byte)
pic.Format.AltText = cellImg.Pic.NvPicPr.CNvPr.Descr pic.Format.AltText = cellImg.Pic.NvPicPr.CNvPr.Descr

View File

@ -12,10 +12,9 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
_ "golang.org/x/image/bmp" _ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff" _ "golang.org/x/image/tiff"
"github.com/stretchr/testify/assert"
) )
func BenchmarkAddPictureFromBytes(b *testing.B) { func BenchmarkAddPictureFromBytes(b *testing.B) {
@ -59,6 +58,8 @@ func TestAddPicture(t *testing.T) {
// Test add picture to worksheet from bytes // Test add picture to worksheet from bytes
assert.NoError(t, f.AddPictureFromBytes("Sheet1", "Q1", &Picture{Extension: ".png", File: file, Format: &GraphicOptions{AltText: "Excel Logo"}})) 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 // 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"}})) 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.NoError(t, err)
assert.Len(t, pics[0].File, 13233) assert.Len(t, pics[0].File, 13233)
assert.Empty(t, pics[0].Format.AltText) assert.Empty(t, pics[0].Format.AltText)
assert.Equal(t, PictureInsertTypePlaceOverCells, pics[0].InsertType)
f, err = prepareTestBook1() f, err = prepareTestBook1()
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
@ -249,6 +251,7 @@ func TestGetPicture(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, pics, 2) assert.Len(t, pics, 2)
assert.Equal(t, "CellImage1", pics[0].Format.AltText) assert.Equal(t, "CellImage1", pics[0].Format.AltText)
assert.Equal(t, PictureInsertTypeDISPIMG, pics[0].InsertType)
// Test get embedded cell pictures with invalid formula // Test get embedded cell pictures with invalid formula
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=_xlfn.DISPIMG()")) assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=_xlfn.DISPIMG()"))
@ -463,6 +466,7 @@ func TestGetCellImages(t *testing.T) {
pics, err := f.GetPictures("Sheet1", "A1") pics, err := f.GetPictures("Sheet1", "A1")
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 1, len(pics)) assert.Equal(t, 1, len(pics))
assert.Equal(t, PictureInsertTypePlaceInCell, pics[0].InsertType)
cells, err := f.GetPictureCells("Sheet1") cells, err := f.GetPictureCells("Sheet1")
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, []string{"A1"}, cells) assert.Equal(t, []string{"A1"}, cells)

View File

@ -409,9 +409,10 @@ type xdrTxBody struct {
// Picture maps the format settings of the picture. // Picture maps the format settings of the picture.
type Picture struct { type Picture struct {
Extension string Extension string
File []byte File []byte
Format *GraphicOptions Format *GraphicOptions
InsertType PictureInsertType
} }
// GraphicOptions directly maps the format settings of the picture. // GraphicOptions directly maps the format settings of the picture.