提交 576bfffb 编写于 作者: xurime's avatar xurime

This closes #752, fix incorrectly merged cells on duplicate row, and new...

This closes #752, fix incorrectly merged cells on duplicate row, and new formula function: LOWER, PROPER, UPPER
上级 77978ac6
...@@ -97,7 +97,7 @@ func main() { ...@@ -97,7 +97,7 @@ func main() {
### Add chart to spreadsheet file ### Add chart to spreadsheet file
With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all. With Excelize chart generation and management is as easy as a few lines of code. You can build charts based on data in your worksheet or generate charts without any data in your worksheet at all.
<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p> <p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>
...@@ -111,8 +111,10 @@ import ( ...@@ -111,8 +111,10 @@ import (
) )
func main() { func main() {
categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} categories := map[string]string{
values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8} "A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
values := map[string]int{
"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
f := excelize.NewFile() f := excelize.NewFile()
for k, v := range categories { for k, v := range categories {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
...@@ -120,7 +122,29 @@ func main() { ...@@ -120,7 +122,29 @@ func main() {
for k, v := range values { for k, v := range values {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
} }
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 := 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 {
fmt.Println(err) fmt.Println(err)
return return
} }
...@@ -156,11 +180,18 @@ func main() { ...@@ -156,11 +180,18 @@ func main() {
fmt.Println(err) fmt.Println(err)
} }
// Insert a picture to worksheet with scaling. // Insert a picture to worksheet with scaling.
if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil { if err := f.AddPicture("Sheet1", "D2", "image.jpg",
`{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
fmt.Println(err) fmt.Println(err)
} }
// Insert a picture offset in the cell with printing support. // Insert a picture offset in the cell with printing support.
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 := f.AddPicture("Sheet1", "H2", "image.gif", `{
"x_offset": 15,
"y_offset": 10,
"print_obj": true,
"lock_aspect_ratio": false,
"locked": false
}`); err != nil {
fmt.Println(err) fmt.Println(err)
} }
// Save the spreadsheet with the origin path. // Save the spreadsheet with the origin path.
......
...@@ -99,7 +99,7 @@ func main() { ...@@ -99,7 +99,7 @@ func main() {
使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。 使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。
<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p> <p align="center"><img width="650" src="./test/images/chart.png" alt="使用 Excelize 在 Excel 电子表格文档中创建图表"></p>
```go ```go
package main package main
...@@ -111,8 +111,10 @@ import ( ...@@ -111,8 +111,10 @@ import (
) )
func main() { func main() {
categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} categories := map[string]string{
values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8} "A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
values := map[string]int{
"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
f := excelize.NewFile() f := excelize.NewFile()
for k, v := range categories { for k, v := range categories {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
...@@ -120,7 +122,29 @@ func main() { ...@@ -120,7 +122,29 @@ func main() {
for k, v := range values { for k, v := range values {
f.SetCellValue("Sheet1", k, v) f.SetCellValue("Sheet1", k, v)
} }
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 := 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 {
fmt.Println(err) fmt.Println(err)
return return
} }
...@@ -156,11 +180,18 @@ func main() { ...@@ -156,11 +180,18 @@ func main() {
fmt.Println(err) fmt.Println(err)
} }
// 在工作表中插入图片,并设置图片的缩放比例 // 在工作表中插入图片,并设置图片的缩放比例
if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil { if err := f.AddPicture("Sheet1", "D2", "image.jpg",
`{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
fmt.Println(err) fmt.Println(err)
} }
// 在工作表中插入图片,并设置图片的打印属性 // 在工作表中插入图片,并设置图片的打印属性
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 := f.AddPicture("Sheet1", "H2", "image.gif", `{
"x_offset": 15,
"y_offset": 10,
"print_obj": true,
"lock_aspect_ratio": false,
"locked": false
}`); err != nil {
fmt.Println(err) fmt.Println(err)
} }
// 保存文件 // 保存文件
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode"
"github.com/xuri/efp" "github.com/xuri/efp"
) )
...@@ -123,14 +124,15 @@ var tokenPriority = map[string]int{ ...@@ -123,14 +124,15 @@ var tokenPriority = map[string]int{
// Supported formulas: // Supported formulas:
// //
// ABS, ACOS, ACOSH, ACOT, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN2, ATANH, // ABS, ACOS, ACOSH, ACOT, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN2, ATANH,
// BASE, CEILING, CEILING.MATH, CEILING.PRECISE, COMBIN, COMBINA, COS, // BASE, CEILING, CEILING.MATH, CEILING.PRECISE, CLEAN, COMBIN, COMBINA,
// COSH, COT, COTH, COUNTA, CSC, CSCH, DATE, DECIMAL, DEGREES, EVEN, EXP, // COS, COSH, COT, COTH, COUNTA, CSC, CSCH, DATE, DECIMAL, DEGREES, EVEN,
// FACT, FACTDOUBLE, FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT, ISBLANK, // EXP, FACT, FACTDOUBLE, FLOOR, FLOOR.MATH, FLOOR.PRECISE, GCD, INT,
// ISERR, ISERROR, ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING, ISODD, // ISBLANK, ISERR, ISERROR, ISEVEN, ISNA, ISNONTEXT, ISNUMBER, ISO.CEILING,
// LCM, LN, LOG, LOG10, MDETERM, MEDIAN, MOD, MROUND, MULTINOMIAL, MUNIT, // ISODD, LCM, LN, LOG, LOG10, LOWER, MDETERM, MEDIAN, MOD, MROUND,
// NA, ODD, OR, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN, // MULTINOMIAL, MUNIT, NA, ODD, OR, PI, POWER, PRODUCT, PROPER, QUOTIENT,
// ROUND, ROUNDDOWN, ROUNDUP, SEC, SECH, SIGN, SIN, SINH, SQRT, SQRTPI, // RADIANS, RAND, RANDBETWEEN, ROUND, ROUNDDOWN, ROUNDUP, SEC, SECH, SIGN,
// SUM, SUMIF, SUMSQ, TAN, TANH, TRUNC // SIN, SINH, SQRT, SQRTPI, SUM, SUMIF, SUMSQ, TAN, TANH, TRIM, TRUNC,
// UPPER
// //
func (f *File) CalcCellValue(sheet, cell string) (result string, err error) { func (f *File) CalcCellValue(sheet, cell string) (result string, err error) {
var ( var (
...@@ -2144,7 +2146,7 @@ func (fn *formulaFuncs) MOD(argsList *list.List) (result string, err error) { ...@@ -2144,7 +2146,7 @@ func (fn *formulaFuncs) MOD(argsList *list.List) (result string, err error) {
// MROUND function rounds a supplied number up or down to the nearest multiple // MROUND function rounds a supplied number up or down to the nearest multiple
// of a given number. The syntax of the function is: // of a given number. The syntax of the function is:
// //
// MOD(number,multiple) // MROUND(number,multiple)
// //
func (fn *formulaFuncs) MROUND(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) MROUND(argsList *list.List) (result string, err error) {
if argsList.Len() != 2 { if argsList.Len() != 2 {
...@@ -3243,7 +3245,10 @@ func (fn *formulaFuncs) NA(argsList *list.List) (result string, err error) { ...@@ -3243,7 +3245,10 @@ func (fn *formulaFuncs) NA(argsList *list.List) (result string, err error) {
// Logical Functions // Logical Functions
// AND function tests a number of supplied conditions and returns TRUE or // AND function tests a number of supplied conditions and returns TRUE or
// FALSE. // FALSE. The syntax of the function is:
//
// AND(logical_test1,[logical_test2],...)
//
func (fn *formulaFuncs) AND(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) AND(argsList *list.List) (result string, err error) {
if argsList.Len() == 0 { if argsList.Len() == 0 {
err = errors.New("AND requires at least 1 argument") err = errors.New("AND requires at least 1 argument")
...@@ -3284,7 +3289,10 @@ func (fn *formulaFuncs) AND(argsList *list.List) (result string, err error) { ...@@ -3284,7 +3289,10 @@ func (fn *formulaFuncs) AND(argsList *list.List) (result string, err error) {
} }
// OR function tests a number of supplied conditions and returns either TRUE // OR function tests a number of supplied conditions and returns either TRUE
// or FALSE. // or FALSE. The syntax of the function is:
//
// OR(logical_test1,[logical_test2],...)
//
func (fn *formulaFuncs) OR(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) OR(argsList *list.List) (result string, err error) {
if argsList.Len() == 0 { if argsList.Len() == 0 {
err = errors.New("OR requires at least 1 argument") err = errors.New("OR requires at least 1 argument")
...@@ -3326,7 +3334,11 @@ func (fn *formulaFuncs) OR(argsList *list.List) (result string, err error) { ...@@ -3326,7 +3334,11 @@ func (fn *formulaFuncs) OR(argsList *list.List) (result string, err error) {
// Date and Time Functions // Date and Time Functions
// DATE returns a date, from a user-supplied year, month and day. // DATE returns a date, from a user-supplied year, month and day. The syntax
// of the function is:
//
// DATE(year,month,day)
//
func (fn *formulaFuncs) DATE(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) DATE(argsList *list.List) (result string, err error) {
if argsList.Len() != 3 { if argsList.Len() != 3 {
err = errors.New("DATE requires 3 number arguments") err = errors.New("DATE requires 3 number arguments")
...@@ -3368,7 +3380,11 @@ func daysBetween(startDate, endDate int64) float64 { ...@@ -3368,7 +3380,11 @@ func daysBetween(startDate, endDate int64) float64 {
// Text Functions // Text Functions
// CLEAN removes all non-printable characters from a supplied text string. // CLEAN removes all non-printable characters from a supplied text string. The
// syntax of the function is:
//
// CLEAN(text)
//
func (fn *formulaFuncs) CLEAN(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) CLEAN(argsList *list.List) (result string, err error) {
if argsList.Len() != 1 { if argsList.Len() != 1 {
err = errors.New("CLEAN requires 1 argument") err = errors.New("CLEAN requires 1 argument")
...@@ -3385,7 +3401,11 @@ func (fn *formulaFuncs) CLEAN(argsList *list.List) (result string, err error) { ...@@ -3385,7 +3401,11 @@ func (fn *formulaFuncs) CLEAN(argsList *list.List) (result string, err error) {
} }
// TRIM removes extra spaces (i.e. all spaces except for single spaces between // TRIM removes extra spaces (i.e. all spaces except for single spaces between
// words or characters) from a supplied text string. // words or characters) from a supplied text string. The syntax of the
// function is:
//
// TRIM(text)
//
func (fn *formulaFuncs) TRIM(argsList *list.List) (result string, err error) { func (fn *formulaFuncs) TRIM(argsList *list.List) (result string, err error) {
if argsList.Len() != 1 { if argsList.Len() != 1 {
err = errors.New("TRIM requires 1 argument") err = errors.New("TRIM requires 1 argument")
...@@ -3394,3 +3414,58 @@ func (fn *formulaFuncs) TRIM(argsList *list.List) (result string, err error) { ...@@ -3394,3 +3414,58 @@ func (fn *formulaFuncs) TRIM(argsList *list.List) (result string, err error) {
result = strings.TrimSpace(argsList.Front().Value.(formulaArg).String) result = strings.TrimSpace(argsList.Front().Value.(formulaArg).String)
return return
} }
// LOWER converts all characters in a supplied text string to lower case. The
// syntax of the function is:
//
// LOWER(text)
//
func (fn *formulaFuncs) LOWER(argsList *list.List) (result string, err error) {
if argsList.Len() != 1 {
err = errors.New("LOWER requires 1 argument")
return
}
result = strings.ToLower(argsList.Front().Value.(formulaArg).String)
return
}
// PROPER converts all characters in a supplied text string to proper case
// (i.e. all letters that do not immediately follow another letter are set to
// upper case and all other characters are lower case). The syntax of the
// function is:
//
// PROPER(text)
//
func (fn *formulaFuncs) PROPER(argsList *list.List) (result string, err error) {
if argsList.Len() != 1 {
err = errors.New("PROPER requires 1 argument")
return
}
buf := bytes.Buffer{}
isLetter := false
for _, char := range argsList.Front().Value.(formulaArg).String {
if !isLetter && unicode.IsLetter(char) {
buf.WriteRune(unicode.ToUpper(char))
} else {
buf.WriteRune(unicode.ToLower(char))
}
isLetter = unicode.IsLetter(char)
}
result = buf.String()
return
}
// UPPER converts all characters in a supplied text string to upper case. The
// syntax of the function is:
//
// UPPER(text)
//
func (fn *formulaFuncs) UPPER(argsList *list.List) (result string, err error) {
if argsList.Len() != 1 {
err = errors.New("UPPER requires 1 argument")
return
}
result = strings.ToUpper(argsList.Front().Value.(formulaArg).String)
return
}
...@@ -470,6 +470,21 @@ func TestCalcCellValue(t *testing.T) { ...@@ -470,6 +470,21 @@ func TestCalcCellValue(t *testing.T) {
// TRIM // TRIM
"=TRIM(\" trim text \")": "trim text", "=TRIM(\" trim text \")": "trim text",
"=TRIM(0)": "0", "=TRIM(0)": "0",
// LOWER
"=LOWER(\"test\")": "test",
"=LOWER(\"TEST\")": "test",
"=LOWER(\"Test\")": "test",
"=LOWER(\"TEST 123\")": "test 123",
// PROPER
"=PROPER(\"this is a test sentence\")": "This Is A Test Sentence",
"=PROPER(\"THIS IS A TEST SENTENCE\")": "This Is A Test Sentence",
"=PROPER(\"123tEST teXT\")": "123Test Text",
"=PROPER(\"Mr. SMITH's address\")": "Mr. Smith'S Address",
// UPPER
"=UPPER(\"test\")": "TEST",
"=UPPER(\"TEST\")": "TEST",
"=UPPER(\"Test\")": "TEST",
"=UPPER(\"TEST 123\")": "TEST 123",
} }
for formula, expected := range mathCalc { for formula, expected := range mathCalc {
f := prepareData() f := prepareData()
...@@ -793,6 +808,15 @@ func TestCalcCellValue(t *testing.T) { ...@@ -793,6 +808,15 @@ func TestCalcCellValue(t *testing.T) {
// TRIM // TRIM
"=TRIM()": "TRIM requires 1 argument", "=TRIM()": "TRIM requires 1 argument",
"=TRIM(1,2)": "TRIM requires 1 argument", "=TRIM(1,2)": "TRIM requires 1 argument",
// LOWER
"=LOWER()": "LOWER requires 1 argument",
"=LOWER(1,2)": "LOWER requires 1 argument",
// UPPER
"=UPPER()": "UPPER requires 1 argument",
"=UPPER(1,2)": "UPPER requires 1 argument",
// PROPER
"=PROPER()": "PROPER requires 1 argument",
"=PROPER(1,2)": "PROPER requires 1 argument",
} }
for formula, expected := range mathCalcError { for formula, expected := range mathCalcError {
f := prepareData() f := prepareData()
......
...@@ -602,7 +602,6 @@ func (f *File) duplicateMergeCells(sheet string, ws *xlsxWorksheet, row, row2 in ...@@ -602,7 +602,6 @@ func (f *File) duplicateMergeCells(sheet string, ws *xlsxWorksheet, row, row2 in
if err := f.MergeCell(sheet, from, to); err != nil { if err := f.MergeCell(sheet, from, to); err != nil {
return err return err
} }
i++
} }
} }
return nil return nil
......
...@@ -323,7 +323,7 @@ func TestDuplicateRowFromSingleRow(t *testing.T) { ...@@ -323,7 +323,7 @@ func TestDuplicateRowFromSingleRow(t *testing.T) {
assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"])) assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"]))
assert.NoError(t, f.DuplicateRow(sheet, 1)) assert.NoError(t, f.DuplicateRow(sheet, 1))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FromSingleRow_1"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -339,7 +339,7 @@ func TestDuplicateRowFromSingleRow(t *testing.T) { ...@@ -339,7 +339,7 @@ func TestDuplicateRowFromSingleRow(t *testing.T) {
} }
assert.NoError(t, f.DuplicateRow(sheet, 2)) assert.NoError(t, f.DuplicateRow(sheet, 2))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FromSingleRow_2"))) {
t.FailNow() t.FailNow()
} }
expect = map[string]string{ expect = map[string]string{
...@@ -380,7 +380,7 @@ func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) { ...@@ -380,7 +380,7 @@ func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
assert.NoError(t, f.SetCellStr(sheet, "A2", cells["A2"])) assert.NoError(t, f.SetCellStr(sheet, "A2", cells["A2"]))
assert.NoError(t, f.SetCellStr(sheet, "B2", cells["B2"])) assert.NoError(t, f.SetCellStr(sheet, "B2", cells["B2"]))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "UpdateDuplicatedRows"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -423,7 +423,7 @@ func TestDuplicateRowFirstOfMultipleRows(t *testing.T) { ...@@ -423,7 +423,7 @@ func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
assert.NoError(t, f.DuplicateRow(sheet, 1)) assert.NoError(t, f.DuplicateRow(sheet, 1))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FirstOfMultipleRows"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -451,7 +451,7 @@ func TestDuplicateRowZeroWithNoRows(t *testing.T) { ...@@ -451,7 +451,7 @@ func TestDuplicateRowZeroWithNoRows(t *testing.T) {
assert.EqualError(t, f.DuplicateRow(sheet, 0), "invalid row number 0") assert.EqualError(t, f.DuplicateRow(sheet, 0), "invalid row number 0")
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "ZeroWithNoRows"))) {
t.FailNow() t.FailNow()
} }
...@@ -493,7 +493,7 @@ func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) { ...@@ -493,7 +493,7 @@ func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
assert.NoError(t, f.DuplicateRow(sheet, 99)) assert.NoError(t, f.DuplicateRow(sheet, 99))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "MiddleRowOfEmptyFile"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -537,7 +537,7 @@ func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) { ...@@ -537,7 +537,7 @@ func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 3)) assert.NoError(t, f.DuplicateRowTo(sheet, 1, 3))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "WithLargeOffsetToMiddleOfData"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -582,7 +582,7 @@ func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) { ...@@ -582,7 +582,7 @@ func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 7)) assert.NoError(t, f.DuplicateRowTo(sheet, 1, 7))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "WithLargeOffsetToEmptyRows"))) {
t.FailNow() t.FailNow()
} }
expect := map[string]string{ expect := map[string]string{
...@@ -627,7 +627,7 @@ func TestDuplicateRowInsertBefore(t *testing.T) { ...@@ -627,7 +627,7 @@ func TestDuplicateRowInsertBefore(t *testing.T) {
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1)) assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBefore"))) {
t.FailNow() t.FailNow()
} }
...@@ -673,7 +673,7 @@ func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) { ...@@ -673,7 +673,7 @@ func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
assert.NoError(t, f.DuplicateRowTo(sheet, 3, 1)) assert.NoError(t, f.DuplicateRowTo(sheet, 3, 1))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBeforeWithLargeOffset"))) {
t.FailNow() t.FailNow()
} }
...@@ -722,7 +722,7 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) { ...@@ -722,7 +722,7 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1)) assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 8)) assert.NoError(t, f.DuplicateRowTo(sheet, 1, 8))
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithMergeCells"))) { if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBeforeWithMergeCells"))) {
t.FailNow() t.FailNow()
} }
...@@ -742,9 +742,9 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) { ...@@ -742,9 +742,9 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
}) })
} }
func TestDuplicateRowInvalidRownum(t *testing.T) { func TestDuplicateRowInvalidRowNum(t *testing.T) {
const sheet = "Sheet1" const sheet = "Sheet1"
outFile := filepath.Join("test", "TestDuplicateRowInvalidRownum.%s.xlsx") outFile := filepath.Join("test", "TestDuplicateRow.InvalidRowNum.%s.xlsx")
cells := map[string]string{ cells := map[string]string{
"A1": "A1 Value", "A1": "A1 Value",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册