Rename SetLegacyDrawingHF to AddHeaderFooterImage (#2023)
- Add new exported HeaderFooterImagePositionType enumeration - An error will be return if the image format is unsupported - Rename exported data type HeaderFooterGraphics to HeaderFooterImageOptions - Support add and update exist header and footer images - Changes the VML data ID to sheet ID - Update unit tests - Update dependencies modules
This commit is contained in:
parent
d2be5cdf8e
commit
30d3561d0e
6
go.mod
6
go.mod
|
@ -8,10 +8,10 @@ require (
|
|||
github.com/stretchr/testify v1.8.4
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/crypto v0.29.0
|
||||
golang.org/x/image v0.18.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/text v0.19.0
|
||||
golang.org/x/net v0.31.0
|
||||
golang.org/x/text v0.20.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
12
go.sum
12
go.sum
|
@ -15,14 +15,14 @@ github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7
|
|||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
2
sheet.go
2
sheet.go
|
@ -1239,7 +1239,7 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
|
|||
// |
|
||||
// &F | Current workbook's file name
|
||||
// |
|
||||
// &G | Drawing object as background (Use SetLegacyDrawingHF)
|
||||
// &G | Drawing object as background (Use AddHeaderFooterImage)
|
||||
// |
|
||||
// &H | Shadow text format
|
||||
// |
|
||||
|
|
206
vml.go
206
vml.go
|
@ -36,6 +36,16 @@ const (
|
|||
FormControlScrollBar
|
||||
)
|
||||
|
||||
// HeaderFooterImagePositionType is the type of header and footer image position.
|
||||
type HeaderFooterImagePositionType byte
|
||||
|
||||
// Worksheet header and footer image position types enumeration.
|
||||
const (
|
||||
HeaderFooterImagePositionLeft HeaderFooterImagePositionType = iota
|
||||
HeaderFooterImagePositionCenter
|
||||
HeaderFooterImagePositionRight
|
||||
)
|
||||
|
||||
// GetComments retrieves all comments in a worksheet by given worksheet name.
|
||||
func (f *File) GetComments(sheet string) ([]Comment, error) {
|
||||
var comments []Comment
|
||||
|
@ -519,6 +529,7 @@ func (f *File) addVMLObject(opts vmlOptions) error {
|
|||
}
|
||||
vmlID = f.countVMLDrawing() + 1
|
||||
}
|
||||
sheetID := f.getSheetID(opts.sheet)
|
||||
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||
sheetXMLPath, _ := f.getSheetXMLPath(opts.sheet)
|
||||
|
@ -534,7 +545,7 @@ func (f *File) addVMLObject(opts vmlOptions) error {
|
|||
f.addSheetNameSpace(opts.sheet, SourceRelationship)
|
||||
f.addSheetLegacyDrawing(opts.sheet, rID)
|
||||
}
|
||||
if err = f.addDrawingVML(vmlID, drawingVML, prepareFormCtrlOptions(&opts)); err != nil {
|
||||
if err = f.addDrawingVML(sheetID, drawingVML, prepareFormCtrlOptions(&opts)); err != nil {
|
||||
return err
|
||||
}
|
||||
if !opts.formCtrl {
|
||||
|
@ -823,7 +834,7 @@ func (f *File) addFormCtrlShape(preset formCtrlPreset, col, row int, anchor stri
|
|||
// anchor value is a comma-separated list of data written out as: LeftColumn,
|
||||
// LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow,
|
||||
// BottomOffset.
|
||||
func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) error {
|
||||
func (f *File) addDrawingVML(sheetID int, drawingVML string, opts *vmlOptions) error {
|
||||
col, row, err := CellNameToCoordinates(opts.FormControl.Cell)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -843,7 +854,7 @@ func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) er
|
|||
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
||||
XMLNSmv: "http://macVmlSchemaUri",
|
||||
ShapeLayout: &xlsxShapeLayout{
|
||||
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: dataID},
|
||||
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: sheetID},
|
||||
},
|
||||
ShapeType: &xlsxShapeType{
|
||||
ID: fmt.Sprintf("_x0000_t%d", vmlID),
|
||||
|
@ -1071,79 +1082,138 @@ func extractVMLFont(font []decodeVMLFont) []RichTextRun {
|
|||
return runs
|
||||
}
|
||||
|
||||
// SetLegacyDrawingHF provides a mechanism to set the graphics that
|
||||
// can be referenced in the Header/Footer defitions via &G.
|
||||
// AddHeaderFooterImage provides a mechanism to set the graphics that can be
|
||||
// referenced in the header and footer definitions via &G, file base name,
|
||||
// extension name and file bytes, supported image types: EMF, EMZ, GIF, JPEG,
|
||||
// JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ.
|
||||
//
|
||||
// The extension should be provided with a "." in front, e.g. ".png".
|
||||
// The width/height should have units in them, e.g. "100pt".
|
||||
func (f *File) SetLegacyDrawingHF(sheet string, g *HeaderFooterGraphics) error {
|
||||
// The width and height should have units in them, e.g. "100pt".
|
||||
func (f *File) AddHeaderFooterImage(sheet string, opts *HeaderFooterImageOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ext, ok := supportedImageTypes[strings.ToLower(opts.Extension)]
|
||||
if !ok {
|
||||
return ErrImgExt
|
||||
}
|
||||
sheetID := f.getSheetID(sheet)
|
||||
vmlID := f.countVMLDrawing() + 1
|
||||
|
||||
vml := &vmlDrawing{
|
||||
XMLNSv: "urn:schemas-microsoft-com:vml",
|
||||
XMLNSo: "urn:schemas-microsoft-com:office:office",
|
||||
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
||||
ShapeLayout: &xlsxShapeLayout{
|
||||
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: vmlID},
|
||||
},
|
||||
ShapeType: &xlsxShapeType{
|
||||
ID: "_x0000_t75",
|
||||
CoordSize: "21600,21600",
|
||||
Spt: 75,
|
||||
PreferRelative: "t",
|
||||
Path: "m@4@5l@4@11@9@11@9@5xe",
|
||||
Filled: "f",
|
||||
Stroked: "f",
|
||||
Stroke: &xlsxStroke{JoinStyle: "miter"},
|
||||
VFormulas: &vFormulas{
|
||||
Formulas: []vFormula{
|
||||
{Equation: "if lineDrawn pixelLineWidth 0"},
|
||||
{Equation: "sum @0 1 0"},
|
||||
{Equation: "sum 0 0 @1"},
|
||||
{Equation: "prod @2 1 2"},
|
||||
{Equation: "prod @3 21600 pixelWidth"},
|
||||
{Equation: "prod @3 21600 pixelHeight"},
|
||||
{Equation: "sum @0 0 1"},
|
||||
{Equation: "prod @6 1 2"},
|
||||
{Equation: "prod @7 21600 pixelWidth"},
|
||||
{Equation: "sum @8 21600 0"},
|
||||
{Equation: "prod @7 21600 pixelHeight"},
|
||||
{Equation: "sum @10 21600 0"},
|
||||
},
|
||||
},
|
||||
VPath: &vPath{ExtrusionOK: "f", GradientShapeOK: "t", ConnectType: "rect"},
|
||||
Lock: &oLock{Ext: "edit", AspectRatio: "t"},
|
||||
},
|
||||
}
|
||||
|
||||
style := fmt.Sprintf("position:absolute;margin-left:0;margin-top:0;width:%s;height:%s;z-index:1", g.Width, g.Height)
|
||||
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||
drawingVMLRels := "xl/drawings/_rels/vmlDrawing" + strconv.Itoa(vmlID) + ".vml.rels"
|
||||
|
||||
mediaStr := ".." + strings.TrimPrefix(f.addMedia(g.File, g.Extension), "xl")
|
||||
imageID := f.addRels(drawingVMLRels, SourceRelationshipImage, mediaStr, "")
|
||||
|
||||
shape := xlsxShape{
|
||||
ID: "RH",
|
||||
Spid: "_x0000_s1025",
|
||||
Type: "#_x0000_t75",
|
||||
Style: style,
|
||||
}
|
||||
s, _ := xml.Marshal(encodeShape{
|
||||
ImageData: &vImageData{RelID: "rId" + strconv.Itoa(imageID)},
|
||||
Lock: &oLock{Ext: "edit", Rotation: "t"},
|
||||
})
|
||||
shape.Val = string(s[13 : len(s)-14])
|
||||
vml.Shape = append(vml.Shape, shape)
|
||||
f.VMLDrawing[drawingVML] = vml
|
||||
|
||||
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||
sheetXMLPath, _ := f.getSheetXMLPath(sheet)
|
||||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetXMLPath, "xl/worksheets/") + ".rels"
|
||||
if ws.LegacyDrawingHF != nil {
|
||||
// The worksheet already has a VML relationships, use the relationships drawing ../drawings/vmlDrawing%d.vml.
|
||||
sheetRelationshipsDrawingVML = f.getSheetRelationshipsTargetByID(sheet, ws.LegacyDrawingHF.RID)
|
||||
vmlID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingVML, "../drawings/vmlDrawing"), ".vml"))
|
||||
drawingVML = strings.ReplaceAll(sheetRelationshipsDrawingVML, "..", "xl")
|
||||
} else {
|
||||
// Add first VML drawing for given sheet.
|
||||
rID := f.addRels(sheetRels, SourceRelationshipDrawingVML, sheetRelationshipsDrawingVML, "")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
f.addSheetLegacyDrawingHF(sheet, rID)
|
||||
}
|
||||
|
||||
shapeID := map[HeaderFooterImagePositionType]string{
|
||||
HeaderFooterImagePositionLeft: "L",
|
||||
HeaderFooterImagePositionCenter: "C",
|
||||
HeaderFooterImagePositionRight: "R",
|
||||
}[opts.Position] +
|
||||
map[bool]string{false: "H", true: "F"}[opts.IsFooter] +
|
||||
map[bool]string{false: "", true: "FIRST"}[opts.FirstPage]
|
||||
vml := f.VMLDrawing[drawingVML]
|
||||
if vml == nil {
|
||||
vml = &vmlDrawing{
|
||||
XMLNSv: "urn:schemas-microsoft-com:vml",
|
||||
XMLNSo: "urn:schemas-microsoft-com:office:office",
|
||||
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
||||
ShapeLayout: &xlsxShapeLayout{
|
||||
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: sheetID},
|
||||
},
|
||||
ShapeType: &xlsxShapeType{
|
||||
ID: "_x0000_t75",
|
||||
CoordSize: "21600,21600",
|
||||
Spt: 75,
|
||||
PreferRelative: "t",
|
||||
Path: "m@4@5l@4@11@9@11@9@5xe",
|
||||
Filled: "f",
|
||||
Stroked: "f",
|
||||
Stroke: &xlsxStroke{JoinStyle: "miter"},
|
||||
VFormulas: &vFormulas{
|
||||
Formulas: []vFormula{
|
||||
{Equation: "if lineDrawn pixelLineWidth 0"},
|
||||
{Equation: "sum @0 1 0"},
|
||||
{Equation: "sum 0 0 @1"},
|
||||
{Equation: "prod @2 1 2"},
|
||||
{Equation: "prod @3 21600 pixelWidth"},
|
||||
{Equation: "prod @3 21600 pixelHeight"},
|
||||
{Equation: "sum @0 0 1"},
|
||||
{Equation: "prod @6 1 2"},
|
||||
{Equation: "prod @7 21600 pixelWidth"},
|
||||
{Equation: "sum @8 21600 0"},
|
||||
{Equation: "prod @7 21600 pixelHeight"},
|
||||
{Equation: "sum @10 21600 0"},
|
||||
},
|
||||
},
|
||||
VPath: &vPath{ExtrusionOK: "f", GradientShapeOK: "t", ConnectType: "rect"},
|
||||
Lock: &oLock{Ext: "edit", AspectRatio: "t"},
|
||||
},
|
||||
}
|
||||
// Load exist VML shapes from xl/drawings/vmlDrawing%d.vml
|
||||
d, err := f.decodeVMLDrawingReader(drawingVML)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d != nil {
|
||||
vml.ShapeType.ID = d.ShapeType.ID
|
||||
vml.ShapeType.CoordSize = d.ShapeType.CoordSize
|
||||
vml.ShapeType.Spt = d.ShapeType.Spt
|
||||
vml.ShapeType.PreferRelative = d.ShapeType.PreferRelative
|
||||
vml.ShapeType.Path = d.ShapeType.Path
|
||||
vml.ShapeType.Filled = d.ShapeType.Filled
|
||||
vml.ShapeType.Stroked = d.ShapeType.Stroked
|
||||
for _, v := range d.Shape {
|
||||
s := xlsxShape{
|
||||
ID: v.ID,
|
||||
SpID: v.SpID,
|
||||
Type: v.Type,
|
||||
Style: v.Style,
|
||||
Val: v.Val,
|
||||
}
|
||||
vml.Shape = append(vml.Shape, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for idx, shape := range vml.Shape {
|
||||
if shape.ID == shapeID {
|
||||
vml.Shape = append(vml.Shape[:idx], vml.Shape[idx+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
style := fmt.Sprintf("position:absolute;margin-left:0;margin-top:0;width:%s;height:%s;z-index:1", opts.Width, opts.Height)
|
||||
drawingVMLRels := "xl/drawings/_rels/vmlDrawing" + strconv.Itoa(vmlID) + ".vml.rels"
|
||||
|
||||
mediaStr := ".." + strings.TrimPrefix(f.addMedia(opts.File, ext), "xl")
|
||||
imageID := f.addRels(drawingVMLRels, SourceRelationshipImage, mediaStr, "")
|
||||
|
||||
shape := xlsxShape{
|
||||
ID: shapeID,
|
||||
SpID: "_x0000_s1025",
|
||||
Type: "#_x0000_t75",
|
||||
Style: style,
|
||||
}
|
||||
sp, _ := xml.Marshal(encodeShape{
|
||||
ImageData: &vImageData{RelID: "rId" + strconv.Itoa(imageID)},
|
||||
Lock: &oLock{Ext: "edit", Rotation: "t"},
|
||||
})
|
||||
|
||||
shape.Val = string(sp[13 : len(sp)-14])
|
||||
vml.Shape = append(vml.Shape, shape)
|
||||
f.VMLDrawing[drawingVML] = vml
|
||||
|
||||
drawingID := f.addRels(sheetRels, SourceRelationshipDrawingVML, sheetRelationshipsDrawingVML, "")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
f.addSheetLegacyDrawingHF(sheet, drawingID)
|
||||
if err := f.setContentTypePartImageExtensions(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ type xlsxIDmap struct {
|
|||
type xlsxShape struct {
|
||||
XMLName xml.Name `xml:"v:shape"`
|
||||
ID string `xml:"id,attr"`
|
||||
Spid string `xml:"o:spid,attr,omitempty"`
|
||||
SpID string `xml:"o:spid,attr,omitempty"`
|
||||
Type string `xml:"type,attr"`
|
||||
Style string `xml:"style,attr"`
|
||||
Button string `xml:"o:button,attr,omitempty"`
|
||||
|
@ -193,15 +193,19 @@ type decodeVmlDrawing struct {
|
|||
// decodeShapeType defines the structure used to parse the shapetype element in
|
||||
// the file xl/drawings/vmlDrawing%d.vml.
|
||||
type decodeShapeType struct {
|
||||
ID string `xml:"id,attr"`
|
||||
CoordSize string `xml:"coordsize,attr"`
|
||||
Spt int `xml:"spt,attr"`
|
||||
Path string `xml:"path,attr"`
|
||||
ID string `xml:"id,attr"`
|
||||
CoordSize string `xml:"coordsize,attr"`
|
||||
Spt int `xml:"spt,attr"`
|
||||
PreferRelative string `xml:"preferrelative,attr,omitempty"`
|
||||
Path string `xml:"path,attr"`
|
||||
Filled string `xml:"filled,attr,omitempty"`
|
||||
Stroked string `xml:"stroked,attr,omitempty"`
|
||||
}
|
||||
|
||||
// decodeShape defines the structure used to parse the particular shape element.
|
||||
type decodeShape struct {
|
||||
ID string `xml:"id,attr"`
|
||||
SpID string `xml:"spid,attr,omitempty"`
|
||||
Type string `xml:"type,attr"`
|
||||
Style string `xml:"style,attr"`
|
||||
Button string `xml:"button,attr,omitempty"`
|
||||
|
@ -335,10 +339,13 @@ type FormControl struct {
|
|||
Format GraphicOptions
|
||||
}
|
||||
|
||||
// HeaderFooterGraphics defines the settings for an image to be
|
||||
// accessible from the header/footer options.
|
||||
type HeaderFooterGraphics struct {
|
||||
// HeaderFooterImageOptions defines the settings for an image to be accessible
|
||||
// from the worksheet header and footer options.
|
||||
type HeaderFooterImageOptions struct {
|
||||
Position HeaderFooterImagePositionType
|
||||
File []byte
|
||||
IsFooter bool
|
||||
FirstPage bool
|
||||
Extension string
|
||||
Width string
|
||||
Height string
|
||||
|
|
89
vml_test.go
89
vml_test.go
|
@ -413,32 +413,97 @@ func TestExtractFormControl(t *testing.T) {
|
|||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
}
|
||||
|
||||
func TestSetLegacyDrawingHF(t *testing.T) {
|
||||
f := NewFile()
|
||||
sheet := "Sheet1"
|
||||
func TestAddHeaderFooterImage(t *testing.T) {
|
||||
f, sheet, wb := NewFile(), "Sheet1", filepath.Join("test", "TestAddHeaderFooterImage.xlsx")
|
||||
headerFooterOptions := HeaderFooterOptions{
|
||||
OddHeader: "&LExcelize&R&G",
|
||||
DifferentFirst: true,
|
||||
OddHeader: "&L&GExcelize&C&G&R&G",
|
||||
OddFooter: "&L&GExcelize&C&G&R&G",
|
||||
FirstHeader: "&L&GExcelize&C&G&R&G",
|
||||
FirstFooter: "&L&GExcelize&C&G&R&G",
|
||||
}
|
||||
assert.NoError(t, f.SetHeaderFooter(sheet, &headerFooterOptions))
|
||||
file, err := os.ReadFile(filepath.Join("test", "images", "excel.png"))
|
||||
assert.NoError(t, f.SetSheetView(sheet, -1, &ViewOptions{View: stringPtr("pageLayout")}))
|
||||
images := map[string][]byte{
|
||||
".wmf": nil, ".tif": nil, ".png": nil,
|
||||
".jpg": nil, ".gif": nil, ".emz": nil, ".emf": nil,
|
||||
}
|
||||
for ext := range images {
|
||||
img, err := os.ReadFile(filepath.Join("test", "images", "excel"+ext))
|
||||
assert.NoError(t, err)
|
||||
images[ext] = img
|
||||
}
|
||||
for _, opt := range []struct {
|
||||
position HeaderFooterImagePositionType
|
||||
file []byte
|
||||
isFooter bool
|
||||
firstPage bool
|
||||
ext string
|
||||
}{
|
||||
{position: HeaderFooterImagePositionLeft, file: images[".tif"], firstPage: true, ext: ".tif"},
|
||||
{position: HeaderFooterImagePositionCenter, file: images[".gif"], firstPage: true, ext: ".gif"},
|
||||
{position: HeaderFooterImagePositionRight, file: images[".png"], firstPage: true, ext: ".png"},
|
||||
{position: HeaderFooterImagePositionLeft, file: images[".emf"], isFooter: true, firstPage: true, ext: ".emf"},
|
||||
{position: HeaderFooterImagePositionCenter, file: images[".wmf"], isFooter: true, firstPage: true, ext: ".wmf"},
|
||||
{position: HeaderFooterImagePositionRight, file: images[".emz"], isFooter: true, firstPage: true, ext: ".emz"},
|
||||
{position: HeaderFooterImagePositionLeft, file: images[".png"], ext: ".png"},
|
||||
{position: HeaderFooterImagePositionCenter, file: images[".png"], ext: ".png"},
|
||||
{position: HeaderFooterImagePositionRight, file: images[".png"], ext: ".png"},
|
||||
{position: HeaderFooterImagePositionLeft, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||
{position: HeaderFooterImagePositionCenter, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||
{position: HeaderFooterImagePositionRight, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||
} {
|
||||
assert.NoError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||
Position: opt.position,
|
||||
File: opt.file,
|
||||
IsFooter: opt.isFooter,
|
||||
FirstPage: opt.firstPage,
|
||||
Extension: opt.ext,
|
||||
Width: "50pt",
|
||||
Height: "32pt",
|
||||
}))
|
||||
}
|
||||
assert.NoError(t, f.SetCellValue(sheet, "A1", "Example"))
|
||||
|
||||
// Test add header footer image with not exist sheet
|
||||
assert.EqualError(t, f.AddHeaderFooterImage("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test add header footer image with unsupported file type
|
||||
assert.Equal(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||
Extension: "jpg",
|
||||
}), ErrImgExt)
|
||||
assert.NoError(t, f.SaveAs(wb))
|
||||
assert.NoError(t, f.Close())
|
||||
// Test change already exist header image with the different image
|
||||
f, err := OpenFile(wb)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetLegacyDrawingHF(sheet, &HeaderFooterGraphics{
|
||||
Extension: ".png",
|
||||
File: file,
|
||||
assert.NoError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||
File: images[".jpg"],
|
||||
FirstPage: true,
|
||||
Extension: ".jpg",
|
||||
Width: "50pt",
|
||||
Height: "32pt",
|
||||
}))
|
||||
assert.NoError(t, f.SetCellValue(sheet, "A1", "Example"))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetLegacyDrawingHF.xlsx")))
|
||||
assert.NoError(t, f.Save())
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test add header image with unsupported charset VML drawing
|
||||
f, err = OpenFile(wb)
|
||||
assert.NoError(t, err)
|
||||
f.Pkg.Store("xl/drawings/vmlDrawing1.vml", MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||
File: images[".jpg"],
|
||||
Extension: ".jpg",
|
||||
Width: "50pt",
|
||||
Height: "32pt",
|
||||
}), "XML syntax error on line 1: invalid UTF-8")
|
||||
assert.NoError(t, f.Close())
|
||||
// Test set legacy drawing header/footer with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetLegacyDrawingHF(sheet, &HeaderFooterGraphics{
|
||||
assert.EqualError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||
Extension: ".png",
|
||||
File: file,
|
||||
File: images[".png"],
|
||||
Width: "50pt",
|
||||
Height: "32pt",
|
||||
}), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
|
Loading…
Reference in New Issue