Improve code coverage unit tests

This commit is contained in:
xuri 2019-12-29 16:02:31 +08:00
parent 5c87effc7e
commit 09485b3f9f
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
54 changed files with 383 additions and 320 deletions

View File

@ -1,7 +1,7 @@
BSD 3-Clause License BSD 3-Clause License
Copyright (c) 2016-2019, 360 Enterprise Security Group, Endpoint Security, Inc. Copyright (c) 2016-2020, 360 Enterprise Security Group, Endpoint Security, Inc.
Copyright (c) 2011-2017, Geoffrey J. Teale (complying with the tealeg/xlsx license) Copyright (c) 2011-2017, Geoffrey J. Teale
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -31,11 +31,7 @@ Here is a minimal example usage that will create XLSX file.
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
f := excelize.NewFile() f := excelize.NewFile()
@ -47,9 +43,8 @@ func main() {
// Set active sheet of the workbook. // Set active sheet of the workbook.
f.SetActiveSheet(index) f.SetActiveSheet(index)
// Save xlsx file by the given path. // Save xlsx file by the given path.
err := f.SaveAs("./Book1.xlsx") if err := f.SaveAs("Book1.xlsx"); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```
@ -61,32 +56,28 @@ The following constitutes the bare to read a XLSX document.
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
f, err := excelize.OpenFile("./Book1.xlsx") f, err := excelize.OpenFile("Book1.xlsx")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
// Get value from cell by given worksheet name and axis. // Get value from cell by given worksheet name and axis.
cell, err := f.GetCellValue("Sheet1", "B2") cell, err := f.GetCellValue("Sheet1", "B2")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
fmt.Println(cell) println(cell)
// Get all the rows in the Sheet1. // Get all the rows in the Sheet1.
rows, err := f.GetRows("Sheet1") rows, err := f.GetRows("Sheet1")
for _, row := range rows { for _, row := range rows {
for _, colCell := range row { for _, colCell := range row {
fmt.Print(colCell, "\t") print(colCell, "\t")
} }
fmt.Println() println()
} }
} }
``` ```
@ -100,11 +91,7 @@ With Excelize chart generation and management is as easy as a few lines of code.
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
@ -116,15 +103,13 @@ func main() {
for k, v := range values { for k, v := range values {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
} }
err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`) if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
return return
} }
// Save xlsx file by the given path. // Save xlsx file by the given path.
err = f.SaveAs("./Book1.xlsx") if err := f.SaveAs("Book1.xlsx"); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```
@ -135,7 +120,6 @@ func main() {
package main package main
import ( import (
"fmt"
_ "image/gif" _ "image/gif"
_ "image/jpeg" _ "image/jpeg"
_ "image/png" _ "image/png"
@ -144,30 +128,26 @@ import (
) )
func main() { func main() {
f, err := excelize.OpenFile("./Book1.xlsx") f, err := excelize.OpenFile("Book1.xlsx")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
// Insert a picture. // Insert a picture.
err = f.AddPicture("Sheet1", "A2", "./image1.png", "") if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// Insert a picture to worksheet with scaling. // Insert a picture to worksheet with scaling.
err = f.AddPicture("Sheet1", "D2", "./image2.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`) if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// Insert a picture offset in the cell with printing support. // Insert a picture offset in the cell with printing support.
err = f.AddPicture("Sheet1", "H2", "./image3.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`) if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// Save the xlsx file with the origin path. // Save the xlsx file with the origin path.
err = f.Save() if err = f.Save(); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```

View File

@ -30,11 +30,7 @@ go get github.com/360EntSecGroup-Skylar/excelize
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
f := excelize.NewFile() f := excelize.NewFile()
@ -46,9 +42,8 @@ func main() {
// 设置工作簿的默认工作表 // 设置工作簿的默认工作表
f.SetActiveSheet(index) f.SetActiveSheet(index)
// 根据指定路径保存文件 // 根据指定路径保存文件
err := f.SaveAs("./Book1.xlsx") if err := f.SaveAs("Book1.xlsx"); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```
@ -60,32 +55,28 @@ func main() {
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
f, err := excelize.OpenFile("./Book1.xlsx") f, err := excelize.OpenFile("Book1.xlsx")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
// 获取工作表中指定单元格的值 // 获取工作表中指定单元格的值
cell, err := f.GetCellValue("Sheet1", "B2") cell, err := f.GetCellValue("Sheet1", "B2")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
fmt.Println(cell) println(cell)
// 获取 Sheet1 上所有单元格 // 获取 Sheet1 上所有单元格
rows, err := f.GetRows("Sheet1") rows, err := f.GetRows("Sheet1")
for _, row := range rows { for _, row := range rows {
for _, colCell := range row { for _, colCell := range row {
fmt.Print(colCell, "\t") print(colCell, "\t")
} }
fmt.Println() println()
} }
} }
``` ```
@ -99,11 +90,7 @@ func main() {
```go ```go
package main package main
import ( import "github.com/360EntSecGroup-Skylar/excelize"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() { func main() {
categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
@ -115,18 +102,15 @@ func main() {
for k, v := range values { for k, v := range values {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
} }
err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`) if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
return return
} }
// 根据指定路径保存文件 // 根据指定路径保存文件
err = f.SaveAs("./Book1.xlsx") if err := f.SaveAs("Book1.xlsx"); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```
### 向 Excel 文档中插入图片 ### 向 Excel 文档中插入图片
@ -135,7 +119,6 @@ func main() {
package main package main
import ( import (
"fmt"
_ "image/gif" _ "image/gif"
_ "image/jpeg" _ "image/jpeg"
_ "image/png" _ "image/png"
@ -144,30 +127,26 @@ import (
) )
func main() { func main() {
f, err := excelize.OpenFile("./Book1.xlsx") f, err := excelize.OpenFile("Book1.xlsx")
if err != nil { if err != nil {
fmt.Println(err) println(err.Error())
return return
} }
// 插入图片 // 插入图片
err = f.AddPicture("Sheet1", "A2", "./image1.png", "") if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// 在工作表中插入图片,并设置图片的缩放比例 // 在工作表中插入图片,并设置图片的缩放比例
err = f.AddPicture("Sheet1", "D2", "./image2.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`) if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// 在工作表中插入图片,并设置图片的打印属性 // 在工作表中插入图片,并设置图片的打印属性
err = f.AddPicture("Sheet1", "H2", "./image3.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`) if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
// 保存文件 // 保存文件
err = f.Save() if err = f.Save(); err != nil {
if err != nil { println(err.Error())
fmt.Println(err)
} }
} }
``` ```

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //
@ -213,6 +213,8 @@ func areaRangeToCoordinates(firstCell, lastCell string) ([]int, error) {
return coordinates, err return coordinates, err
} }
// sortCoordinates provides a function to correct the coordinate area, such
// correct C1:B3 to B1:C3.
func sortCoordinates(coordinates []int) error { func sortCoordinates(coordinates []int) error {
if len(coordinates) != 4 { if len(coordinates) != 4 {
return errors.New("coordinates length must be 4") return errors.New("coordinates length must be 4")

View File

@ -114,3 +114,7 @@ func TestCoordinatesToAreaRef(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, ref, "A1:A1") assert.EqualValues(t, ref, "A1:A1")
} }
func TestSortCoordinates(t *testing.T) {
assert.EqualError(t, sortCoordinates(make([]int, 3)), "coordinates length must be 4")
}

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //
@ -43,13 +43,7 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
return err return err
} }
// Correct the coordinate area, such correct C1:B3 to B1:C3. // Correct the coordinate area, such correct C1:B3 to B1:C3.
if rect1[2] < rect1[0] { _ = sortCoordinates(rect1)
rect1[0], rect1[2] = rect1[2], rect1[0]
}
if rect1[3] < rect1[1] {
rect1[1], rect1[3] = rect1[3], rect1[1]
}
hcell, _ = CoordinatesToCellName(rect1[0], rect1[1]) hcell, _ = CoordinatesToCellName(rect1[0], rect1[1])
vcell, _ = CoordinatesToCellName(rect1[2], rect1[3]) vcell, _ = CoordinatesToCellName(rect1[2], rect1[3])
@ -123,12 +117,8 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
return err return err
} }
if rect1[2] < rect1[0] { // Correct the coordinate area, such correct C1:B3 to B1:C3.
rect1[0], rect1[2] = rect1[2], rect1[0] _ = sortCoordinates(rect1)
}
if rect1[3] < rect1[1] {
rect1[1], rect1[3] = rect1[3], rect1[1]
}
// return nil since no MergeCells in the sheet // return nil since no MergeCells in the sheet
if xlsx.MergeCells == nil { if xlsx.MergeCells == nil {

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //
@ -657,6 +657,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
// //
// major_grid_lines // major_grid_lines
// minor_grid_lines // minor_grid_lines
// tick_label_skip
// reverse_order // reverse_order
// maximum // maximum
// minimum // minimum
@ -666,7 +667,6 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
// major_grid_lines // major_grid_lines
// minor_grid_lines // minor_grid_lines
// major_unit // major_unit
// tick_label_skip
// reverse_order // reverse_order
// maximum // maximum
// minimum // minimum

2
col.go
View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.

View File

@ -894,124 +894,11 @@ func TestCopySheetError(t *testing.T) {
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx"))) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
} }
func TestAddTable(t *testing.T) {
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet1", "B26", "A21", `{}`)
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet2", "A2", "B5", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`)
if !assert.NoError(t, err) {
t.FailNow()
}
// Test add table with illegal formatset.
assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
// Test add table with illegal cell coordinates.
assert.EqualError(t, f.AddTable("Sheet1", "A", "B1", `{}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.AddTable("Sheet1", "A1", "B", `{}`), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddTable.xlsx")))
// Test addTable with illegal cell coordinates.
f = NewFile()
assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
}
func TestAddShape(t *testing.T) {
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
assert.NoError(t, f.AddShape("Sheet1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`))
assert.NoError(t, f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`))
assert.NoError(t, f.AddShape("Sheet1", "C30", `{"type":"rect","paragraph":[]}`))
assert.EqualError(t, f.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`), "sheet Sheet3 is not exist")
assert.EqualError(t, f.AddShape("Sheet3", "H1", ""), "unexpected end of JSON input")
assert.EqualError(t, f.AddShape("Sheet1", "A", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape1.xlsx")))
// Test add first shape for given sheet.
f = NewFile()
assert.NoError(t, f.AddShape("Sheet1", "A1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape2.xlsx")))
}
func TestGetSheetComments(t *testing.T) { func TestGetSheetComments(t *testing.T) {
f := NewFile() f := NewFile()
assert.Equal(t, "", f.getSheetComments(0)) assert.Equal(t, "", f.getSheetComments(0))
} }
func TestAutoFilter(t *testing.T) {
outFile := filepath.Join("test", "TestAutoFilter%d.xlsx")
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
formats := []string{
``,
`{"column":"B","expression":"x != blanks"}`,
`{"column":"B","expression":"x == blanks"}`,
`{"column":"B","expression":"x != nonblanks"}`,
`{"column":"B","expression":"x == nonblanks"}`,
`{"column":"B","expression":"x <= 1 and x >= 2"}`,
`{"column":"B","expression":"x == 1 or x == 2"}`,
`{"column":"B","expression":"x == 1 or x == 2*"}`,
}
for i, format := range formats {
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
err = f.AutoFilter("Sheet1", "D4", "B1", format)
assert.NoError(t, err)
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
})
}
// testing AutoFilter with illegal cell coordinates.
assert.EqualError(t, f.AutoFilter("Sheet1", "A", "B1", ""), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.AutoFilter("Sheet1", "A1", "B", ""), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
}
func TestAutoFilterError(t *testing.T) {
outFile := filepath.Join("test", "TestAutoFilterError%d.xlsx")
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
formats := []string{
`{"column":"B","expression":"x <= 1 and x >= blanks"}`,
`{"column":"B","expression":"x -- y or x == *2*"}`,
`{"column":"B","expression":"x != y or x ? *2"}`,
`{"column":"B","expression":"x -- y o r x == *2"}`,
`{"column":"B","expression":"x -- y"}`,
`{"column":"A","expression":"x -- y"}`,
}
for i, format := range formats {
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
err = f.AutoFilter("Sheet3", "D4", "B1", format)
if assert.Error(t, err) {
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
}
})
}
}
func TestSetActiveSheet(t *testing.T) { func TestSetActiveSheet(t *testing.T) {
f := NewFile() f := NewFile()
f.WorkBook.BookViews = nil f.WorkBook.BookViews = nil

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

2
lib.go
View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

28
shape_test.go Normal file
View File

@ -0,0 +1,28 @@
package excelize
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestAddShape(t *testing.T) {
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
assert.NoError(t, f.AddShape("Sheet1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`))
assert.NoError(t, f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`))
assert.NoError(t, f.AddShape("Sheet1", "C30", `{"type":"rect","paragraph":[]}`))
assert.EqualError(t, f.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`), "sheet Sheet3 is not exist")
assert.EqualError(t, f.AddShape("Sheet3", "H1", ""), "unexpected end of JSON input")
assert.EqualError(t, f.AddShape("Sheet1", "A", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape1.xlsx")))
// Test add first shape for given sheet.
f = NewFile()
assert.NoError(t, f.AddShape("Sheet1", "A1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape2.xlsx")))
}

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

127
stream.go
View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //
@ -36,20 +36,27 @@ type StreamWriter struct {
// rows, you must call the 'Flush' method to end the streaming writing // rows, you must call the 'Flush' method to end the streaming writing
// process and ensure that the order of line numbers is ascending. For // process and ensure that the order of line numbers is ascending. For
// example, set data for worksheet of size 102400 rows x 50 columns with // example, set data for worksheet of size 102400 rows x 50 columns with
// numbers: // numbers and style:
// //
// file := excelize.NewFile() // file := excelize.NewFile()
// streamWriter, err := file.NewStreamWriter("Sheet1") // streamWriter, err := file.NewStreamWriter("Sheet1")
// if err != nil { // if err != nil {
// panic(err) // panic(err)
// } // }
// for rowID := 1; rowID <= 102400; rowID++ { // styleID, err := file.NewStyle(`{"font":{"color":"#777777"}}`)
// if err != nil {
// panic(err)
// }
// if err := streamWriter.SetRow("A1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Data"}}); err != nil {
// panic(err)
// }
// for rowID := 2; rowID <= 102400; rowID++ {
// row := make([]interface{}, 50) // row := make([]interface{}, 50)
// for colID := 0; colID < 50; colID++ { // for colID := 0; colID < 50; colID++ {
// row[colID] = rand.Intn(640000) // row[colID] = rand.Intn(640000)
// } // }
// cell, _ := excelize.CoordinatesToCellName(1, rowID) // cell, _ := excelize.CoordinatesToCellName(1, rowID)
// if err := streamWriter.SetRow(cell, row, nil); err != nil { // if err := streamWriter.SetRow(cell, row); err != nil {
// panic(err) // panic(err)
// } // }
// } // }
@ -107,7 +114,7 @@ func (sw *StreamWriter) AddTable(hcell, vcell, format string) error {
if err != nil { if err != nil {
return err return err
} }
sortCoordinates(coordinates) _ = sortCoordinates(coordinates)
// Correct the minimum number of rows, the table at least two lines. // Correct the minimum number of rows, the table at least two lines.
if coordinates[1] == coordinates[3] { if coordinates[1] == coordinates[3] {
@ -188,7 +195,7 @@ func (sw *StreamWriter) getRowValues(hrow, hcol, vcol int) (res []string, err er
return nil, err return nil, err
} }
dec := xml.NewDecoder(r) dec := sw.File.xmlNewDecoder(r)
for { for {
token, err := dec.Token() token, err := dec.Token()
if err == io.EOF { if err == io.EOF {
@ -248,7 +255,7 @@ func getRowElement(token xml.Token, hrow int) (startElement xml.StartElement, ok
// a value. // a value.
type Cell struct { type Cell struct {
StyleID int StyleID int
Value interface{} Value interface{}
} }
// SetRow writes an array to stream rows by giving a worksheet name, starting // SetRow writes an array to stream rows by giving a worksheet name, starting
@ -277,47 +284,8 @@ func (sw *StreamWriter) SetRow(axis string, values []interface{}) error {
c.S = v.StyleID c.S = v.StyleID
val = v.Value val = v.Value
} }
switch val := val.(type) { if err = setCellValFunc(&c, val); err != nil {
case int: sw.rawData.WriteString(`</row>`)
c.T, c.V = setCellInt(val)
case int8:
c.T, c.V = setCellInt(int(val))
case int16:
c.T, c.V = setCellInt(int(val))
case int32:
c.T, c.V = setCellInt(int(val))
case int64:
c.T, c.V = setCellInt(int(val))
case uint:
c.T, c.V = setCellInt(int(val))
case uint8:
c.T, c.V = setCellInt(int(val))
case uint16:
c.T, c.V = setCellInt(int(val))
case uint32:
c.T, c.V = setCellInt(int(val))
case uint64:
c.T, c.V = setCellInt(int(val))
case float32:
c.T, c.V = setCellFloat(float64(val), -1, 32)
case float64:
c.T, c.V = setCellFloat(val, -1, 64)
case string:
c.T, c.V, c.XMLSpace = setCellStr(val)
case []byte:
c.T, c.V, c.XMLSpace = setCellStr(string(val))
case time.Duration:
c.T, c.V = setCellDuration(val)
case time.Time:
c.T, c.V, _, err = setCellTime(val)
case bool:
c.T, c.V = setCellBool(val)
case nil:
c.T, c.V, c.XMLSpace = setCellStr("")
default:
c.T, c.V, c.XMLSpace = setCellStr(fmt.Sprint(val))
}
if err != nil {
return err return err
} }
writeCell(&sw.rawData, c) writeCell(&sw.rawData, c)
@ -326,6 +294,61 @@ func (sw *StreamWriter) SetRow(axis string, values []interface{}) error {
return sw.rawData.Sync() return sw.rawData.Sync()
} }
// setCellValFunc provides a function to set value of a cell.
func setCellValFunc(c *xlsxC, val interface{}) (err error) {
switch val := val.(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
err = setCellIntFunc(c, val)
case float32:
c.T, c.V = setCellFloat(float64(val), -1, 32)
case float64:
c.T, c.V = setCellFloat(val, -1, 64)
case string:
c.T, c.V, c.XMLSpace = setCellStr(val)
case []byte:
c.T, c.V, c.XMLSpace = setCellStr(string(val))
case time.Duration:
c.T, c.V = setCellDuration(val)
case time.Time:
c.T, c.V, _, err = setCellTime(val)
case bool:
c.T, c.V = setCellBool(val)
case nil:
c.T, c.V, c.XMLSpace = setCellStr("")
default:
c.T, c.V, c.XMLSpace = setCellStr(fmt.Sprint(val))
}
return err
}
// setCellIntFunc is a wrapper of SetCellInt.
func setCellIntFunc(c *xlsxC, val interface{}) (err error) {
switch val := val.(type) {
case int:
c.T, c.V = setCellInt(val)
case int8:
c.T, c.V = setCellInt(int(val))
case int16:
c.T, c.V = setCellInt(int(val))
case int32:
c.T, c.V = setCellInt(int(val))
case int64:
c.T, c.V = setCellInt(int(val))
case uint:
c.T, c.V = setCellInt(int(val))
case uint8:
c.T, c.V = setCellInt(int(val))
case uint16:
c.T, c.V = setCellInt(int(val))
case uint32:
c.T, c.V = setCellInt(int(val))
case uint64:
c.T, c.V = setCellInt(int(val))
default:
}
return
}
func writeCell(buf *bufferedWriter, c xlsxC) { func writeCell(buf *bufferedWriter, c xlsxC) {
buf.WriteString(`<c`) buf.WriteString(`<c`)
if c.XMLSpace.Value != "" { if c.XMLSpace.Value != "" {
@ -391,8 +414,8 @@ func bulkAppendOtherFields(w io.Writer, ws *xlsxWorksheet, skip ...string) {
// bufferedWriter uses a temp file to store an extended buffer. Writes are // bufferedWriter uses a temp file to store an extended buffer. Writes are
// always made to an in-memory buffer, which will always succeed. The buffer // always made to an in-memory buffer, which will always succeed. The buffer
// is written to the temp file with Sync, which may return an error. Therefore, // is written to the temp file with Sync, which may return an error.
// Sync should be periodically called and the error checked. // Therefore, Sync should be periodically called and the error checked.
type bufferedWriter struct { type bufferedWriter struct {
tmp *os.File tmp *os.File
buf bytes.Buffer buf bytes.Buffer
@ -454,8 +477,8 @@ func (bw *bufferedWriter) Bytes() ([]byte, error) {
return buf.Bytes(), err return buf.Bytes(), err
} }
// Sync will write the in-memory buffer to a temp file, if the in-memory buffer // Sync will write the in-memory buffer to a temp file, if the in-memory
// has grown large enough. Any error will be returned. // buffer has grown large enough. Any error will be returned.
func (bw *bufferedWriter) Sync() (err error) { func (bw *bufferedWriter) Sync() (err error) {
// Try to use local storage // Try to use local storage
const chunk = 1 << 24 const chunk = 1 << 24

View File

@ -3,10 +3,13 @@ package excelize
import ( import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io/ioutil"
"math/rand" "math/rand"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -49,6 +52,13 @@ func TestStreamWriter(t *testing.T) {
row[0] = []byte("Word") row[0] = []byte("Word")
assert.NoError(t, streamWriter.SetRow("A3", row)) assert.NoError(t, streamWriter.SetRow("A3", row))
// Test set cell with style.
styleID, err := file.NewStyle(`{"font":{"color":"#777777"}}`)
assert.NoError(t, err)
assert.NoError(t, streamWriter.SetRow("A4", []interface{}{Cell{StyleID: styleID}}))
assert.NoError(t, streamWriter.SetRow("A5", []interface{}{&Cell{StyleID: styleID, Value: "cell"}}))
assert.EqualError(t, streamWriter.SetRow("A6", []interface{}{time.Now()}), "only UTC time expected")
for rowID := 10; rowID <= 51200; rowID++ { for rowID := 10; rowID <= 51200; rowID++ {
row := make([]interface{}, 50) row := make([]interface{}, 50)
for colID := 0; colID < 50; colID++ { for colID := 0; colID < 50; colID++ {
@ -62,7 +72,7 @@ func TestStreamWriter(t *testing.T) {
// Save xlsx file by the given path. // Save xlsx file by the given path.
assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamWriter.xlsx"))) assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamWriter.xlsx")))
// Test close temporary file error // Test close temporary file error.
file = NewFile() file = NewFile()
streamWriter, err = file.NewStreamWriter("Sheet1") streamWriter, err = file.NewStreamWriter("Sheet1")
assert.NoError(t, err) assert.NoError(t, err)
@ -76,6 +86,12 @@ func TestStreamWriter(t *testing.T) {
} }
assert.NoError(t, streamWriter.rawData.Close()) assert.NoError(t, streamWriter.rawData.Close())
assert.Error(t, streamWriter.Flush()) assert.Error(t, streamWriter.Flush())
streamWriter.rawData.tmp, err = ioutil.TempFile(os.TempDir(), "excelize-")
assert.NoError(t, err)
_, err = streamWriter.rawData.Reader()
assert.NoError(t, err)
assert.NoError(t, os.Remove(streamWriter.rawData.tmp.Name()))
} }
func TestStreamTable(t *testing.T) { func TestStreamTable(t *testing.T) {
@ -100,6 +116,14 @@ func TestStreamTable(t *testing.T) {
assert.Equal(t, "A", table.TableColumns.TableColumn[0].Name) assert.Equal(t, "A", table.TableColumns.TableColumn[0].Name)
assert.Equal(t, "B", table.TableColumns.TableColumn[1].Name) assert.Equal(t, "B", table.TableColumns.TableColumn[1].Name)
assert.Equal(t, "C", table.TableColumns.TableColumn[2].Name) assert.Equal(t, "C", table.TableColumns.TableColumn[2].Name)
assert.NoError(t, streamWriter.AddTable("A1", "C1", ``))
// Test add table with illegal formatset.
assert.EqualError(t, streamWriter.AddTable("B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
// Test add table with illegal cell coordinates.
assert.EqualError(t, streamWriter.AddTable("A", "B1", `{}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, streamWriter.AddTable("A1", "B", `{}`), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
} }
func TestNewStreamWriter(t *testing.T) { func TestNewStreamWriter(t *testing.T) {
@ -118,3 +142,26 @@ func TestSetRow(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualError(t, streamWriter.SetRow("A", []interface{}{}), `cannot convert cell "A" to coordinates: invalid cell name "A"`) assert.EqualError(t, streamWriter.SetRow("A", []interface{}{}), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
} }
func TestSetCellValFunc(t *testing.T) {
c := &xlsxC{}
assert.NoError(t, setCellValFunc(c, 128))
assert.NoError(t, setCellValFunc(c, int8(-128)))
assert.NoError(t, setCellValFunc(c, int16(-32768)))
assert.NoError(t, setCellValFunc(c, int32(-2147483648)))
assert.NoError(t, setCellValFunc(c, int64(-9223372036854775808)))
assert.NoError(t, setCellValFunc(c, uint(128)))
assert.NoError(t, setCellValFunc(c, uint8(255)))
assert.NoError(t, setCellValFunc(c, uint16(65535)))
assert.NoError(t, setCellValFunc(c, uint32(4294967295)))
assert.NoError(t, setCellValFunc(c, uint64(18446744073709551615)))
assert.NoError(t, setCellValFunc(c, float32(100.1588)))
assert.NoError(t, setCellValFunc(c, float64(100.1588)))
assert.NoError(t, setCellValFunc(c, " Hello"))
assert.NoError(t, setCellValFunc(c, []byte(" Hello")))
assert.NoError(t, setCellValFunc(c, time.Now().UTC()))
assert.NoError(t, setCellValFunc(c, time.Duration(1e13)))
assert.NoError(t, setCellValFunc(c, true))
assert.NoError(t, setCellValFunc(c, nil))
assert.NoError(t, setCellValFunc(c, complex64(5+10i)))
}

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -169,9 +169,7 @@ func TestSetConditionalFormat(t *testing.T) {
func TestNewStyle(t *testing.T) { func TestNewStyle(t *testing.T) {
f := NewFile() f := NewFile()
styleID, err := f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777"}}`) styleID, err := f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777"}}`)
if err != nil { assert.NoError(t, err)
t.Fatal(err)
}
styles := f.stylesReader() styles := f.stylesReader()
fontID := styles.CellXfs.Xf[styleID].FontID fontID := styles.CellXfs.Xf[styleID].FontID
font := styles.Fonts.Font[fontID] font := styles.Fonts.Font[fontID]

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

125
table_test.go Normal file
View File

@ -0,0 +1,125 @@
package excelize
import (
"fmt"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestAddTable(t *testing.T) {
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet1", "B26", "A21", `{}`)
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet2", "A2", "B5", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
if !assert.NoError(t, err) {
t.FailNow()
}
err = f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`)
if !assert.NoError(t, err) {
t.FailNow()
}
// Test add table with illegal formatset.
assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
// Test add table with illegal cell coordinates.
assert.EqualError(t, f.AddTable("Sheet1", "A", "B1", `{}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.AddTable("Sheet1", "A1", "B", `{}`), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddTable.xlsx")))
// Test addTable with illegal cell coordinates.
f = NewFile()
assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
}
func TestAutoFilter(t *testing.T) {
outFile := filepath.Join("test", "TestAutoFilter%d.xlsx")
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
formats := []string{
``,
`{"column":"B","expression":"x != blanks"}`,
`{"column":"B","expression":"x == blanks"}`,
`{"column":"B","expression":"x != nonblanks"}`,
`{"column":"B","expression":"x == nonblanks"}`,
`{"column":"B","expression":"x <= 1 and x >= 2"}`,
`{"column":"B","expression":"x == 1 or x == 2"}`,
`{"column":"B","expression":"x == 1 or x == 2*"}`,
}
for i, format := range formats {
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
err = f.AutoFilter("Sheet1", "D4", "B1", format)
assert.NoError(t, err)
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
})
}
// testing AutoFilter with illegal cell coordinates.
assert.EqualError(t, f.AutoFilter("Sheet1", "A", "B1", ""), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.AutoFilter("Sheet1", "A1", "B", ""), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
}
func TestAutoFilterError(t *testing.T) {
outFile := filepath.Join("test", "TestAutoFilterError%d.xlsx")
f, err := prepareTestBook1()
if !assert.NoError(t, err) {
t.FailNow()
}
formats := []string{
`{"column":"B","expression":"x <= 1 and x >= blanks"}`,
`{"column":"B","expression":"x -- y or x == *2*"}`,
`{"column":"B","expression":"x != y or x ? *2"}`,
`{"column":"B","expression":"x -- y o r x == *2"}`,
`{"column":"B","expression":"x -- y"}`,
`{"column":"A","expression":"x -- y"}`,
}
for i, format := range formats {
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
err = f.AutoFilter("Sheet3", "D4", "B1", format)
if assert.Error(t, err) {
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
}
})
}
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &formatAutoFilter{
Column: "-",
Expression: "-",
}), `invalid column name "-"`)
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 100, &formatAutoFilter{
Column: "A",
Expression: "-",
}), `incorrect index of column 'A'`)
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &formatAutoFilter{
Column: "A",
Expression: "-",
}), `incorrect number of tokens in criteria '-'`)
}
func TestParseFilterTokens(t *testing.T) {
f := NewFile()
// Test with unknown operator.
_, _, err := f.parseFilterTokens("", []string{"", "!"})
assert.EqualError(t, err, "unknown operator: !")
// Test invalid operator in context.
_, _, err = f.parseFilterTokens("", []string{"", "<", "x != blanks"})
assert.EqualError(t, err, "the operator '<' in expression '' is not valid in relation to Blanks/NonBlanks'")
}

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //

View File

@ -1,4 +1,4 @@
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of // Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in // this source code is governed by a BSD-style license that can be found in
// the LICENSE file. // the LICENSE file.
// //