diff --git a/chart.go b/chart.go
index 2629f0b..227cdee 100644
--- a/chart.go
+++ b/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("" + wsDr.TwoCellAnchor[idx].GraphicFrame + ""))).
- 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
diff --git a/chart_test.go b/chart_test.go
index d8d36d8..98f3555 100644
--- a/chart_test.go
+++ b/chart_test.go
@@ -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"))
}
diff --git a/drawing.go b/drawing.go
index 316897b..e51b6af 100644
--- a/drawing.go
+++ b/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("" + wsDr.TwoCellAnchor[idx].GraphicFrame + ""))).
+ 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
+}
diff --git a/picture.go b/picture.go
index 639cb66..213bae9 100644
--- a/picture.go
+++ b/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) {
diff --git a/picture_test.go b/picture_test.go
index ca38f41..fdc6f0d 100644
--- a/picture_test.go
+++ b/picture_test.go
@@ -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"))
+}