Skip to content

Commit 60b9d02

Browse files
committed
Breaking changes: changed the function signature for 4 exported functions
- Change `func (f *File) AddVBAProject(bin string) error` to `func (f *File) AddVBAProject(file []byte) error` - Change `func (f *File) GetComments() (map[string][]Comment, error)` to `func (f *File) GetComments(sheet string) ([]Comment, error)` - Change `func (f *File) AddTable(sheet, rangeRef string, opts *TableOptions) error` to `func (f *File) AddTable(sheet string, table *Table) error` - Change `func (sw *StreamWriter) AddTable(rangeRef string, opts *TableOptions) error` to `func (sw *StreamWriter) AddTable(table *Table) error` - Rename exported data type `TableOptions` to `Table` - Simplify the assert statements in the unit tests - Update documents for the functions - Update unit tests
1 parent 5878fbd commit 60b9d02

20 files changed

+162
-145
lines changed

adjust_test.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,24 @@ import (
1111
func TestAdjustMergeCells(t *testing.T) {
1212
f := NewFile()
1313
// Test adjustAutoFilter with illegal cell reference
14-
assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
14+
assert.Equal(t, f.adjustMergeCells(&xlsxWorksheet{
1515
MergeCells: &xlsxMergeCells{
1616
Cells: []*xlsxMergeCell{
1717
{
1818
Ref: "A:B1",
1919
},
2020
},
2121
},
22-
}, rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
23-
assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
22+
}, rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
23+
assert.Equal(t, f.adjustMergeCells(&xlsxWorksheet{
2424
MergeCells: &xlsxMergeCells{
2525
Cells: []*xlsxMergeCell{
2626
{
2727
Ref: "A1:B",
2828
},
2929
},
3030
},
31-
}, rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
31+
}, rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
3232
assert.NoError(t, f.adjustMergeCells(&xlsxWorksheet{
3333
MergeCells: &xlsxMergeCells{
3434
Cells: []*xlsxMergeCell{
@@ -272,7 +272,7 @@ func TestAdjustMergeCells(t *testing.T) {
272272
}
273273
for _, c := range cases {
274274
assert.NoError(t, f.adjustMergeCells(c.ws, c.dir, c.num, -1))
275-
assert.Equal(t, 0, len(c.ws.MergeCells.Cells), c.label)
275+
assert.Len(t, c.ws.MergeCells.Cells, 0, c.label)
276276
}
277277

278278
f = NewFile()
@@ -293,22 +293,23 @@ func TestAdjustAutoFilter(t *testing.T) {
293293
},
294294
}, rows, 1, -1))
295295
// Test adjustAutoFilter with illegal cell reference
296-
assert.EqualError(t, f.adjustAutoFilter(&xlsxWorksheet{
296+
assert.Equal(t, f.adjustAutoFilter(&xlsxWorksheet{
297297
AutoFilter: &xlsxAutoFilter{
298298
Ref: "A:B1",
299299
},
300-
}, rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
301-
assert.EqualError(t, f.adjustAutoFilter(&xlsxWorksheet{
300+
}, rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
301+
assert.Equal(t, f.adjustAutoFilter(&xlsxWorksheet{
302302
AutoFilter: &xlsxAutoFilter{
303303
Ref: "A1:B",
304304
},
305-
}, rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
305+
}, rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
306306
}
307307

308308
func TestAdjustTable(t *testing.T) {
309309
f, sheetName := NewFile(), "Sheet1"
310310
for idx, reference := range []string{"B2:C3", "E3:F5", "H5:H8", "J5:K9"} {
311-
assert.NoError(t, f.AddTable(sheetName, reference, &TableOptions{
311+
assert.NoError(t, f.AddTable(sheetName, &Table{
312+
Range: reference,
312313
Name: fmt.Sprintf("table%d", idx),
313314
StyleName: "TableStyleMedium2",
314315
ShowFirstColumn: true,
@@ -323,7 +324,7 @@ func TestAdjustTable(t *testing.T) {
323324
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustTable.xlsx")))
324325

325326
f = NewFile()
326-
assert.NoError(t, f.AddTable(sheetName, "A1:D5", nil))
327+
assert.NoError(t, f.AddTable(sheetName, &Table{Range: "A1:D5"}))
327328
// Test adjust table with non-table part
328329
f.Pkg.Delete("xl/tables/table1.xml")
329330
assert.NoError(t, f.RemoveRow(sheetName, 1))
@@ -346,8 +347,8 @@ func TestAdjustHelper(t *testing.T) {
346347
AutoFilter: &xlsxAutoFilter{Ref: "A1:B"},
347348
})
348349
// Test adjustHelper with illegal cell reference
349-
assert.EqualError(t, f.adjustHelper("Sheet1", rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
350-
assert.EqualError(t, f.adjustHelper("Sheet2", rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
350+
assert.Equal(t, f.adjustHelper("Sheet1", rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
351+
assert.Equal(t, f.adjustHelper("Sheet2", rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
351352
// Test adjustHelper on not exists worksheet
352353
assert.EqualError(t, f.adjustHelper("SheetN", rows, 0, 0), "sheet SheetN does not exist")
353354
}
@@ -363,7 +364,7 @@ func TestAdjustCalcChain(t *testing.T) {
363364
assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
364365

365366
f.CalcChain.C[1].R = "invalid coordinates"
366-
assert.EqualError(t, f.InsertCols("Sheet1", "A", 1), newCellNameToCoordinatesError("invalid coordinates", newInvalidCellNameError("invalid coordinates")).Error())
367+
assert.Equal(t, f.InsertCols("Sheet1", "A", 1), newCellNameToCoordinatesError("invalid coordinates", newInvalidCellNameError("invalid coordinates")))
367368
f.CalcChain = nil
368369
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
369370
}

cell.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,8 @@ type FormulaOpts struct {
694694
// return
695695
// }
696696
// }
697-
// if err := f.AddTable("Sheet1", "A1:C2", &excelize.TableOptions{
698-
// Name: "Table1", StyleName: "TableStyleMedium2",
697+
// if err := f.AddTable("Sheet1", &excelize.Table{
698+
// Range: "A1:C2", Name: "Table1", StyleName: "TableStyleMedium2",
699699
// }); err != nil {
700700
// fmt.Println(err)
701701
// return

cell_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ func TestSetCellFormula(t *testing.T) {
571571
for idx, row := range [][]interface{}{{"A", "B", "C"}, {1, 2}} {
572572
assert.NoError(t, f.SetSheetRow("Sheet1", fmt.Sprintf("A%d", idx+1), &row))
573573
}
574-
assert.NoError(t, f.AddTable("Sheet1", "A1:C2", &TableOptions{Name: "Table1", StyleName: "TableStyleMedium2"}))
574+
assert.NoError(t, f.AddTable("Sheet1", &Table{Range: "A1:C2", Name: "Table1", StyleName: "TableStyleMedium2"}))
575575
formulaType = STCellFormulaTypeDataTable
576576
assert.NoError(t, f.SetCellFormula("Sheet1", "C2", "=SUM(Table1[[A]:[B]])", FormulaOpts{Type: &formulaType}))
577577
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula6.xlsx")))

comment.go

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,46 +21,43 @@ import (
2121
"strings"
2222
)
2323

24-
// GetComments retrieves all comments and returns a map of worksheet name to
25-
// the worksheet comments.
26-
func (f *File) GetComments() (map[string][]Comment, error) {
27-
comments := map[string][]Comment{}
28-
for n, path := range f.sheetMap {
29-
target := f.getSheetComments(filepath.Base(path))
30-
if target == "" {
31-
continue
32-
}
33-
if !strings.HasPrefix(target, "/") {
34-
target = "xl" + strings.TrimPrefix(target, "..")
35-
}
36-
cmts, err := f.commentsReader(strings.TrimPrefix(target, "/"))
37-
if err != nil {
38-
return comments, err
39-
}
40-
if cmts != nil {
41-
var sheetComments []Comment
42-
for _, comment := range cmts.CommentList.Comment {
43-
sheetComment := Comment{}
44-
if comment.AuthorID < len(cmts.Authors.Author) {
45-
sheetComment.Author = cmts.Authors.Author[comment.AuthorID]
46-
}
47-
sheetComment.Cell = comment.Ref
48-
sheetComment.AuthorID = comment.AuthorID
49-
if comment.Text.T != nil {
50-
sheetComment.Text += *comment.Text.T
51-
}
52-
for _, text := range comment.Text.R {
53-
if text.T != nil {
54-
run := RichTextRun{Text: text.T.Val}
55-
if text.RPr != nil {
56-
run.Font = newFont(text.RPr)
57-
}
58-
sheetComment.Runs = append(sheetComment.Runs, run)
24+
// GetComments retrieves all comments in a worksheet by given worksheet name.
25+
func (f *File) GetComments(sheet string) ([]Comment, error) {
26+
var comments []Comment
27+
sheetXMLPath, ok := f.getSheetXMLPath(sheet)
28+
if !ok {
29+
return comments, newNoExistSheetError(sheet)
30+
}
31+
commentsXML := f.getSheetComments(filepath.Base(sheetXMLPath))
32+
if !strings.HasPrefix(commentsXML, "/") {
33+
commentsXML = "xl" + strings.TrimPrefix(commentsXML, "..")
34+
}
35+
commentsXML = strings.TrimPrefix(commentsXML, "/")
36+
cmts, err := f.commentsReader(commentsXML)
37+
if err != nil {
38+
return comments, err
39+
}
40+
if cmts != nil {
41+
for _, cmt := range cmts.CommentList.Comment {
42+
comment := Comment{}
43+
if cmt.AuthorID < len(cmts.Authors.Author) {
44+
comment.Author = cmts.Authors.Author[cmt.AuthorID]
45+
}
46+
comment.Cell = cmt.Ref
47+
comment.AuthorID = cmt.AuthorID
48+
if cmt.Text.T != nil {
49+
comment.Text += *cmt.Text.T
50+
}
51+
for _, text := range cmt.Text.R {
52+
if text.T != nil {
53+
run := RichTextRun{Text: text.T.Val}
54+
if text.RPr != nil {
55+
run.Font = newFont(text.RPr)
5956
}
57+
comment.Runs = append(comment.Runs, run)
6058
}
61-
sheetComments = append(sheetComments, sheetComment)
6259
}
63-
comments[n] = sheetComments
60+
comments = append(comments, comment)
6461
}
6562
}
6663
return comments, nil

comment_test.go

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,29 +34,33 @@ func TestAddComment(t *testing.T) {
3434
assert.EqualError(t, f.AddComment("SheetN", Comment{Cell: "B7", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), "sheet SheetN does not exist")
3535
// Test add comment on with illegal cell reference
3636
assert.EqualError(t, f.AddComment("Sheet1", Comment{Cell: "A", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
37-
comments, err := f.GetComments()
37+
comments, err := f.GetComments("Sheet1")
3838
assert.NoError(t, err)
39-
if assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx"))) {
40-
assert.Len(t, comments, 2)
41-
}
39+
assert.Len(t, comments, 2)
40+
comments, err = f.GetComments("Sheet2")
41+
assert.NoError(t, err)
42+
assert.Len(t, comments, 1)
43+
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx")))
4244

4345
f.Comments["xl/comments2.xml"] = nil
4446
f.Pkg.Store("xl/comments2.xml", []byte(xml.Header+`<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><authors><author>Excelize: </author></authors><commentList><comment ref="B7" authorId="0"><text><t>Excelize: </t></text></comment></commentList></comments>`))
45-
comments, err = f.GetComments()
47+
comments, err = f.GetComments("Sheet1")
4648
assert.NoError(t, err)
47-
assert.EqualValues(t, 2, len(comments["Sheet1"]))
48-
assert.EqualValues(t, 1, len(comments["Sheet2"]))
49-
comments, err = NewFile().GetComments()
49+
assert.Len(t, comments, 2)
50+
comments, err = f.GetComments("Sheet2")
5051
assert.NoError(t, err)
51-
assert.EqualValues(t, len(comments), 0)
52+
assert.Len(t, comments, 1)
53+
comments, err = NewFile().GetComments("Sheet1")
54+
assert.NoError(t, err)
55+
assert.Len(t, comments, 0)
5256

5357
// Test add comments with invalid sheet name
5458
assert.EqualError(t, f.AddComment("Sheet:1", Comment{Cell: "A1", Author: "Excelize", Text: "This is a comment."}), ErrSheetNameInvalid.Error())
5559

5660
// Test add comments with unsupported charset
5761
f.Comments["xl/comments2.xml"] = nil
5862
f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
59-
_, err = f.GetComments()
63+
_, err = f.GetComments("Sheet2")
6064
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
6165

6266
// Test add comments with unsupported charset
@@ -68,6 +72,11 @@ func TestAddComment(t *testing.T) {
6872
f.Styles = nil
6973
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
7074
assert.EqualError(t, f.AddComment("Sheet2", Comment{Cell: "A30", Text: "Comment"}), "XML syntax error on line 1: invalid UTF-8")
75+
76+
// Test get comments on not exists worksheet
77+
comments, err = f.GetComments("SheetN")
78+
assert.Len(t, comments, 0)
79+
assert.EqualError(t, err, "sheet SheetN does not exist")
7180
}
7281

7382
func TestDeleteComment(t *testing.T) {
@@ -85,23 +94,23 @@ func TestDeleteComment(t *testing.T) {
8594

8695
assert.NoError(t, f.DeleteComment("Sheet2", "A40"))
8796

88-
comments, err := f.GetComments()
97+
comments, err := f.GetComments("Sheet2")
8998
assert.NoError(t, err)
90-
assert.EqualValues(t, 5, len(comments["Sheet2"]))
99+
assert.Len(t, comments, 5)
91100

92-
comments, err = NewFile().GetComments()
101+
comments, err = NewFile().GetComments("Sheet1")
93102
assert.NoError(t, err)
94-
assert.EqualValues(t, len(comments), 0)
103+
assert.Len(t, comments, 0)
95104

96105
// Test delete comment with invalid sheet name
97106
assert.EqualError(t, f.DeleteComment("Sheet:1", "A1"), ErrSheetNameInvalid.Error())
98107
// Test delete all comments in a worksheet
99108
assert.NoError(t, f.DeleteComment("Sheet2", "A41"))
100109
assert.NoError(t, f.DeleteComment("Sheet2", "C41"))
101110
assert.NoError(t, f.DeleteComment("Sheet2", "C42"))
102-
comments, err = f.GetComments()
111+
comments, err = f.GetComments("Sheet2")
103112
assert.NoError(t, err)
104-
assert.EqualValues(t, 0, len(comments["Sheet2"]))
113+
assert.EqualValues(t, 0, len(comments))
105114
// Test delete comment on not exists worksheet
106115
assert.EqualError(t, f.DeleteComment("SheetN", "A1"), "sheet SheetN does not exist")
107116
// Test delete comment with worksheet part

datavalidation_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestDataValidation(t *testing.T) {
3535

3636
dataValidations, err := f.GetDataValidations("Sheet1")
3737
assert.NoError(t, err)
38-
assert.Equal(t, len(dataValidations), 1)
38+
assert.Len(t, dataValidations, 1)
3939

4040
assert.NoError(t, f.SaveAs(resultFile))
4141

@@ -47,7 +47,7 @@ func TestDataValidation(t *testing.T) {
4747

4848
dataValidations, err = f.GetDataValidations("Sheet1")
4949
assert.NoError(t, err)
50-
assert.Equal(t, len(dataValidations), 2)
50+
assert.Len(t, dataValidations, 2)
5151

5252
assert.NoError(t, f.SaveAs(resultFile))
5353

@@ -62,10 +62,10 @@ func TestDataValidation(t *testing.T) {
6262
assert.NoError(t, f.AddDataValidation("Sheet2", dv))
6363
dataValidations, err = f.GetDataValidations("Sheet1")
6464
assert.NoError(t, err)
65-
assert.Equal(t, len(dataValidations), 2)
65+
assert.Len(t, dataValidations, 2)
6666
dataValidations, err = f.GetDataValidations("Sheet2")
6767
assert.NoError(t, err)
68-
assert.Equal(t, len(dataValidations), 1)
68+
assert.Len(t, dataValidations, 1)
6969

7070
dv = NewDataValidation(true)
7171
dv.Sqref = "A5:B6"
@@ -87,7 +87,7 @@ func TestDataValidation(t *testing.T) {
8787

8888
dataValidations, err = f.GetDataValidations("Sheet1")
8989
assert.NoError(t, err)
90-
assert.Equal(t, len(dataValidations), 3)
90+
assert.Len(t,dataValidations, 3)
9191

9292
// Test get data validation on no exists worksheet
9393
_, err = f.GetDataValidations("SheetN")

errors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ var (
129129
ErrInvalidFormula = errors.New("formula not valid")
130130
// ErrAddVBAProject defined the error message on add the VBA project in
131131
// the workbook.
132-
ErrAddVBAProject = errors.New("unsupported VBA project extension")
132+
ErrAddVBAProject = errors.New("unsupported VBA project")
133133
// ErrMaxRows defined the error message on receive a row number exceeds maximum limit.
134134
ErrMaxRows = errors.New("row number exceeds maximum limit")
135135
// ErrMaxRowHeight defined the error message on receive an invalid row

excelize.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ import (
1616
"archive/zip"
1717
"bytes"
1818
"encoding/xml"
19-
"fmt"
2019
"io"
2120
"os"
22-
"path"
2321
"path/filepath"
2422
"strconv"
2523
"strings"
@@ -460,27 +458,33 @@ func (f *File) UpdateLinkedValue() error {
460458
}
461459

462460
// AddVBAProject provides the method to add vbaProject.bin file which contains
463-
// functions and/or macros. The file extension should be .xlsm. For example:
461+
// functions and/or macros. The file extension should be XLSM or XLTM. For
462+
// example:
464463
//
465464
// codeName := "Sheet1"
466465
// if err := f.SetSheetProps("Sheet1", &excelize.SheetPropsOptions{
467466
// CodeName: &codeName,
468467
// }); err != nil {
469468
// fmt.Println(err)
469+
// return
470470
// }
471-
// if err := f.AddVBAProject("vbaProject.bin"); err != nil {
471+
// file, err := os.ReadFile("vbaProject.bin")
472+
// if err != nil {
472473
// fmt.Println(err)
474+
// return
475+
// }
476+
// if err := f.AddVBAProject(file); err != nil {
477+
// fmt.Println(err)
478+
// return
473479
// }
474480
// if err := f.SaveAs("macros.xlsm"); err != nil {
475481
// fmt.Println(err)
482+
// return
476483
// }
477-
func (f *File) AddVBAProject(bin string) error {
484+
func (f *File) AddVBAProject(file []byte) error {
478485
var err error
479486
// Check vbaProject.bin exists first.
480-
if _, err = os.Stat(bin); os.IsNotExist(err) {
481-
return fmt.Errorf("stat %s: no such file or directory", bin)
482-
}
483-
if path.Ext(bin) != ".bin" {
487+
if !bytes.Contains(file, oleIdentifier) {
484488
return ErrAddVBAProject
485489
}
486490
rels, err := f.relsReader(f.getWorkbookRelsPath())
@@ -509,7 +513,6 @@ func (f *File) AddVBAProject(bin string) error {
509513
Type: SourceRelationshipVBAProject,
510514
})
511515
}
512-
file, _ := os.ReadFile(filepath.Clean(bin))
513516
f.Pkg.Store("xl/vbaProject.bin", file)
514517
return err
515518
}

0 commit comments

Comments
 (0)