forked from p30928647/excelize
Resolve #455, init delete picture from spreadsheet support
This commit is contained in:
parent
e2bd08c911
commit
cbc3fd21b7
37
chart.go
37
chart.go
|
@ -10,11 +10,8 @@
|
|||
package excelize
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -766,7 +763,6 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
|||
// DeleteChart provides a function to delete chart in XLSX by given worksheet
|
||||
// and cell name.
|
||||
func (f *File) DeleteChart(sheet, cell string) (err error) {
|
||||
var wsDr *xlsxWsDr
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -781,38 +777,7 @@ func (f *File) DeleteChart(sheet, cell string) (err error) {
|
|||
return
|
||||
}
|
||||
drawingXML := strings.Replace(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl", -1)
|
||||
wsDr, _ = f.drawingParser(drawingXML)
|
||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
||||
if err = nil; wsDr.TwoCellAnchor[idx].From != nil && wsDr.TwoCellAnchor[idx].Pic == nil {
|
||||
if wsDr.TwoCellAnchor[idx].From.Col == col && wsDr.TwoCellAnchor[idx].From.Row == row {
|
||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
||||
idx--
|
||||
}
|
||||
}
|
||||
}
|
||||
return f.deleteChart(col, row, drawingXML, wsDr)
|
||||
}
|
||||
|
||||
// deleteChart provides a function to delete chart graphic frame by given by
|
||||
// given coordinates.
|
||||
func (f *File) deleteChart(col, row int, drawingXML string, wsDr *xlsxWsDr) (err error) {
|
||||
var deTwoCellAnchor *decodeTwoCellAnchor
|
||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
||||
deTwoCellAnchor = new(decodeTwoCellAnchor)
|
||||
if err = f.xmlNewDecoder(bytes.NewReader([]byte("<decodeTwoCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeTwoCellAnchor>"))).
|
||||
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
|
||||
err = fmt.Errorf("xml decode error: %s", err)
|
||||
return
|
||||
}
|
||||
if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic == nil {
|
||||
if deTwoCellAnchor.From.Col == col && deTwoCellAnchor.From.Row == row {
|
||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
||||
idx--
|
||||
}
|
||||
}
|
||||
}
|
||||
f.Drawings[drawingXML] = wsDr
|
||||
return err
|
||||
return f.deleteDrawing(col, row, drawingXML, "Chart")
|
||||
}
|
||||
|
||||
// countCharts provides a function to get chart files count storage in the
|
||||
|
|
|
@ -217,12 +217,6 @@ func TestDeleteChart(t *testing.T) {
|
|||
assert.EqualError(t, f.DeleteChart("SheetN", "A1"), "sheet SheetN is not exist")
|
||||
// Test delete chart with invalid coordinates.
|
||||
assert.EqualError(t, f.DeleteChart("Sheet1", ""), `cannot convert cell "" to coordinates: invalid cell name ""`)
|
||||
// Test delete chart with unsupport charset.
|
||||
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
delete(f.Sheet, "xl/drawings/drawing1.xml")
|
||||
f.XLSX["xl/drawings/drawing1.xml"] = MacintoshCyrillicCharset
|
||||
assert.EqualError(t, f.DeleteChart("Sheet1", "A1"), "xml decode error: XML syntax error on line 1: invalid UTF-8")
|
||||
// Test delete chart on no chart worksheet.
|
||||
assert.NoError(t, NewFile().DeleteChart("Sheet1", "A1"))
|
||||
}
|
||||
|
|
43
drawing.go
43
drawing.go
|
@ -12,6 +12,7 @@ package excelize
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"reflect"
|
||||
|
@ -1207,3 +1208,45 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
|
|||
f.Drawings[drawingXML] = content
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteDrawing provides a function to delete chart graphic frame by given by
|
||||
// given coordinates and graphic type.
|
||||
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (err error) {
|
||||
var (
|
||||
wsDr *xlsxWsDr
|
||||
deTwoCellAnchor *decodeTwoCellAnchor
|
||||
)
|
||||
xdrCellAnchorFuncs := map[string]func(anchor *xdrCellAnchor) bool{
|
||||
"Chart": func(anchor *xdrCellAnchor) bool { return anchor.Pic == nil },
|
||||
"Pic": func(anchor *xdrCellAnchor) bool { return anchor.Pic != nil },
|
||||
}
|
||||
decodeTwoCellAnchorFuncs := map[string]func(anchor *decodeTwoCellAnchor) bool{
|
||||
"Chart": func(anchor *decodeTwoCellAnchor) bool { return anchor.Pic == nil },
|
||||
"Pic": func(anchor *decodeTwoCellAnchor) bool { return anchor.Pic != nil },
|
||||
}
|
||||
wsDr, _ = f.drawingParser(drawingXML)
|
||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
||||
if err = nil; wsDr.TwoCellAnchor[idx].From != nil && xdrCellAnchorFuncs[drawingType](wsDr.TwoCellAnchor[idx]) {
|
||||
if wsDr.TwoCellAnchor[idx].From.Col == col && wsDr.TwoCellAnchor[idx].From.Row == row {
|
||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
||||
idx--
|
||||
}
|
||||
}
|
||||
}
|
||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
||||
deTwoCellAnchor = new(decodeTwoCellAnchor)
|
||||
if err = f.xmlNewDecoder(bytes.NewReader([]byte("<decodeTwoCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeTwoCellAnchor>"))).
|
||||
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
|
||||
err = fmt.Errorf("xml decode error: %s", err)
|
||||
return
|
||||
}
|
||||
if err = nil; deTwoCellAnchor.From != nil && decodeTwoCellAnchorFuncs[drawingType](deTwoCellAnchor) {
|
||||
if deTwoCellAnchor.From.Col == col && deTwoCellAnchor.From.Row == row {
|
||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
||||
idx--
|
||||
}
|
||||
}
|
||||
}
|
||||
f.Drawings[drawingXML] = wsDr
|
||||
return err
|
||||
}
|
||||
|
|
21
picture.go
21
picture.go
|
@ -462,6 +462,27 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
|
|||
return f.getPicture(row, col, drawingXML, drawingRelationships)
|
||||
}
|
||||
|
||||
// DeletePicture provides a function to delete chart in XLSX by given
|
||||
// worksheet and cell name. Note that the image file won't deleted from the
|
||||
// document currently.
|
||||
func (f *File) DeletePicture(sheet, cell string) (err error) {
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
col--
|
||||
row--
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ws.Drawing == nil {
|
||||
return
|
||||
}
|
||||
drawingXML := strings.Replace(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl", -1)
|
||||
return f.deleteDrawing(col, row, drawingXML, "Pic")
|
||||
}
|
||||
|
||||
// getPicture provides a function to get picture base name and raw content
|
||||
// embed in XLSX by given coordinates and drawing relationships.
|
||||
func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string) (ret string, buf []byte, err error) {
|
||||
|
|
|
@ -166,3 +166,18 @@ func TestAddPictureFromBytes(t *testing.T) {
|
|||
assert.Equal(t, 1, imageCount, "Duplicate image should only be stored once.")
|
||||
assert.EqualError(t, f.AddPictureFromBytes("SheetN", fmt.Sprint("A", 1), "", "logo", ".png", imgFile), "sheet SheetN is not exist")
|
||||
}
|
||||
|
||||
func TestDeletePicture(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.DeletePicture("Sheet1", "A1"))
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "P1", filepath.Join("test", "images", "excel.jpg"), ""))
|
||||
assert.NoError(t, f.DeletePicture("Sheet1", "P1"))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeletePicture.xlsx")))
|
||||
// Test delete picture on not exists worksheet.
|
||||
assert.EqualError(t, f.DeletePicture("SheetN", "A1"), "sheet SheetN is not exist")
|
||||
// Test delete picture with invalid coordinates.
|
||||
assert.EqualError(t, f.DeletePicture("Sheet1", ""), `cannot convert cell "" to coordinates: invalid cell name ""`)
|
||||
// Test delete picture on no chart worksheet.
|
||||
assert.NoError(t, NewFile().DeletePicture("Sheet1", "A1"))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue