• R/O
  • HTTP
  • SSH
  • HTTPS

excelize: 提交

Go language library for reading and writing Microsoft Excel™ (XLAM / XLSM / XLSX / XLTM / XLTX) spreadsheets


Commit MetaInfo

修订版76f336809f5419343702de5b3284d46feb9ed266 (tree)
时间2022-08-20 00:24:13
作者NaturalGao <43291304+NaturalGao@user...>
CommiterGitHub

Log Message

This closes #849, add new function DeleteComment for delete comment (#1317)

- Update unit tests for the delete comment
- Add 3 errors function for error messages

更改概述

差异

--- a/comment.go
+++ b/comment.go
@@ -140,6 +140,39 @@ func (f *File) AddComment(sheet, cell, format string) error {
140140 return err
141141 }
142142
143+// DeleteComment provides the method to delete comment in a sheet by given
144+// worksheet. For example, delete the comment in Sheet1!$A$30:
145+//
146+// err := f.DeleteComment("Sheet1", "A30")
147+func (f *File) DeleteComment(sheet, cell string) (err error) {
148+ sheetXMLPath, ok := f.getSheetXMLPath(sheet)
149+ if !ok {
150+ err = newNoExistSheetError(sheet)
151+ return
152+ }
153+ commentsXML := f.getSheetComments(filepath.Base(sheetXMLPath))
154+ if !strings.HasPrefix(commentsXML, "/") {
155+ commentsXML = "xl" + strings.TrimPrefix(commentsXML, "..")
156+ }
157+ commentsXML = strings.TrimPrefix(commentsXML, "/")
158+ if comments := f.commentsReader(commentsXML); comments != nil {
159+ for i, cmt := range comments.CommentList.Comment {
160+ if cmt.Ref == cell {
161+ if len(comments.CommentList.Comment) > 1 {
162+ comments.CommentList.Comment = append(
163+ comments.CommentList.Comment[:i],
164+ comments.CommentList.Comment[i+1:]...,
165+ )
166+ continue
167+ }
168+ comments.CommentList.Comment = nil
169+ }
170+ }
171+ f.Comments[commentsXML] = comments
172+ }
173+ return
174+}
175+
143176 // addDrawingVML provides a function to create comment as
144177 // xl/drawings/vmlDrawing%d.vml by given commit ID and cell.
145178 func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount, colCount int) error {
--- a/comment_test.go
+++ b/comment_test.go
@@ -46,6 +46,32 @@ func TestAddComments(t *testing.T) {
4646 assert.EqualValues(t, len(NewFile().GetComments()), 0)
4747 }
4848
49+func TestDeleteComment(t *testing.T) {
50+ f, err := prepareTestBook1()
51+ if !assert.NoError(t, err) {
52+ t.FailNow()
53+ }
54+
55+ assert.NoError(t, f.AddComment("Sheet2", "A40", `{"author":"Excelize: ","text":"This is a comment1."}`))
56+ assert.NoError(t, f.AddComment("Sheet2", "A41", `{"author":"Excelize: ","text":"This is a comment2."}`))
57+ assert.NoError(t, f.AddComment("Sheet2", "C41", `{"author":"Excelize: ","text":"This is a comment3."}`))
58+
59+ assert.NoError(t, f.DeleteComment("Sheet2", "A40"))
60+
61+ assert.EqualValues(t, 2, len(f.GetComments()["Sheet2"]))
62+ assert.EqualValues(t, len(NewFile().GetComments()), 0)
63+
64+ // Test delete all comments in a worksheet
65+ assert.NoError(t, f.DeleteComment("Sheet2", "A41"))
66+ assert.NoError(t, f.DeleteComment("Sheet2", "C41"))
67+ assert.EqualValues(t, 0, len(f.GetComments()["Sheet2"]))
68+ // Test delete comment on not exists worksheet
69+ assert.EqualError(t, f.DeleteComment("SheetN", "A1"), "sheet SheetN is not exist")
70+ // Test delete comment with worksheet part
71+ f.Pkg.Delete("xl/worksheets/sheet1.xml")
72+ assert.NoError(t, f.DeleteComment("Sheet1", "A22"))
73+}
74+
4975 func TestDecodeVMLDrawingReader(t *testing.T) {
5076 f := NewFile()
5177 path := "xl/drawings/vmlDrawing1.xml"
--- a/docProps.go
+++ b/docProps.go
@@ -14,7 +14,6 @@ package excelize
1414 import (
1515 "bytes"
1616 "encoding/xml"
17- "fmt"
1817 "io"
1918 "reflect"
2019 )
@@ -76,7 +75,7 @@ func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
7675 app = new(xlsxProperties)
7776 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
7877 Decode(app); err != nil && err != io.EOF {
79- err = fmt.Errorf("xml decode error: %s", err)
78+ err = newDecodeXMLError(err)
8079 return
8180 }
8281 fields = []string{"Application", "ScaleCrop", "DocSecurity", "Company", "LinksUpToDate", "HyperlinksChanged", "AppVersion"}
@@ -103,7 +102,7 @@ func (f *File) GetAppProps() (ret *AppProperties, err error) {
103102 app := new(xlsxProperties)
104103 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
105104 Decode(app); err != nil && err != io.EOF {
106- err = fmt.Errorf("xml decode error: %s", err)
105+ err = newDecodeXMLError(err)
107106 return
108107 }
109108 ret, err = &AppProperties{
@@ -181,7 +180,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
181180 core = new(decodeCoreProperties)
182181 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
183182 Decode(core); err != nil && err != io.EOF {
184- err = fmt.Errorf("xml decode error: %s", err)
183+ err = newDecodeXMLError(err)
185184 return
186185 }
187186 newProps, err = &xlsxCoreProperties{
@@ -236,7 +235,7 @@ func (f *File) GetDocProps() (ret *DocProperties, err error) {
236235
237236 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
238237 Decode(core); err != nil && err != io.EOF {
239- err = fmt.Errorf("xml decode error: %s", err)
238+ err = newDecodeXMLError(err)
240239 return
241240 }
242241 ret, err = &DocProperties{
--- a/drawing.go
+++ b/drawing.go
@@ -14,7 +14,6 @@ package excelize
1414 import (
1515 "bytes"
1616 "encoding/xml"
17- "fmt"
1817 "io"
1918 "log"
2019 "reflect"
@@ -1322,7 +1321,7 @@ func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (err
13221321 deTwoCellAnchor = new(decodeTwoCellAnchor)
13231322 if err = f.xmlNewDecoder(strings.NewReader("<decodeTwoCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeTwoCellAnchor>")).
13241323 Decode(deTwoCellAnchor); err != nil && err != io.EOF {
1325- err = fmt.Errorf("xml decode error: %s", err)
1324+ err = newDecodeXMLError(err)
13261325 return
13271326 }
13281327 if err = nil; deTwoCellAnchor.From != nil && decodeTwoCellAnchorFuncs[drawingType](deTwoCellAnchor) {
--- a/errors.go
+++ b/errors.go
@@ -70,6 +70,23 @@ func newCellNameToCoordinatesError(cell string, err error) error {
7070 return fmt.Errorf("cannot convert cell %q to coordinates: %v", cell, err)
7171 }
7272
73+// newNoExistSheetError defined the error message on receiving the not exist
74+// sheet name.
75+func newNoExistSheetError(name string) error {
76+ return fmt.Errorf("sheet %s is not exist", name)
77+}
78+
79+// newNotWorksheetError defined the error message on receiving a sheet which
80+// not a worksheet.
81+func newNotWorksheetError(name string) error {
82+ return fmt.Errorf("sheet %s is not a worksheet", name)
83+}
84+
85+// newDecodeXMLError defined the error message on decode XML error.
86+func newDecodeXMLError(err error) error {
87+ return fmt.Errorf("xml decode error: %s", err)
88+}
89+
7390 var (
7491 // ErrStreamSetColWidth defined the error message on set column width in
7592 // stream writing mode.
--- a/excelize.go
+++ b/excelize.go
@@ -231,7 +231,7 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
231231 ok bool
232232 )
233233 if name, ok = f.getSheetXMLPath(sheet); !ok {
234- err = fmt.Errorf("sheet %s is not exist", sheet)
234+ err = newNoExistSheetError(sheet)
235235 return
236236 }
237237 if worksheet, ok := f.Sheet.Load(name); ok && worksheet != nil {
@@ -240,7 +240,7 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
240240 }
241241 for _, sheetType := range []string{"xl/chartsheets", "xl/dialogsheet", "xl/macrosheet"} {
242242 if strings.HasPrefix(name, sheetType) {
243- err = fmt.Errorf("sheet %s is not a worksheet", sheet)
243+ err = newNotWorksheetError(sheet)
244244 return
245245 }
246246 }
@@ -251,7 +251,7 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
251251 }
252252 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readBytes(name)))).
253253 Decode(ws); err != nil && err != io.EOF {
254- err = fmt.Errorf("xml decode error: %s", err)
254+ err = newDecodeXMLError(err)
255255 return
256256 }
257257 err = nil
@@ -424,7 +424,7 @@ func (f *File) UpdateLinkedValue() error {
424424 for _, name := range f.GetSheetList() {
425425 ws, err := f.workSheetReader(name)
426426 if err != nil {
427- if err.Error() == fmt.Sprintf("sheet %s is not a worksheet", trimSheetName(name)) {
427+ if err.Error() == newNotWorksheetError(name).Error() {
428428 continue
429429 }
430430 return err
--- a/picture.go
+++ b/picture.go
@@ -15,7 +15,6 @@ import (
1515 "bytes"
1616 "encoding/json"
1717 "encoding/xml"
18- "fmt"
1918 "image"
2019 "io"
2120 "io/ioutil"
@@ -554,7 +553,7 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
554553 deWsDr = new(decodeWsDr)
555554 if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(drawingXML)))).
556555 Decode(deWsDr); err != nil && err != io.EOF {
557- err = fmt.Errorf("xml decode error: %s", err)
556+ err = newDecodeXMLError(err)
558557 return
559558 }
560559 err = nil
@@ -562,7 +561,7 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
562561 deTwoCellAnchor = new(decodeTwoCellAnchor)
563562 if err = f.xmlNewDecoder(strings.NewReader("<decodeTwoCellAnchor>" + anchor.Content + "</decodeTwoCellAnchor>")).
564563 Decode(deTwoCellAnchor); err != nil && err != io.EOF {
565- err = fmt.Errorf("xml decode error: %s", err)
564+ err = newDecodeXMLError(err)
566565 return
567566 }
568567 if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic != nil {
--- a/stream.go
+++ b/stream.go
@@ -92,7 +92,7 @@ type StreamWriter struct {
9292 func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
9393 sheetID := f.getSheetID(sheet)
9494 if sheetID == -1 {
95- return nil, fmt.Errorf("sheet %s is not exist", sheet)
95+ return nil, newNoExistSheetError(sheet)
9696 }
9797 sw := &StreamWriter{
9898 File: f,
Show on old repository browser