diff options
| author | xuri <xuri.me@gmail.com> | 2020-05-22 16:53:46 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-22 16:53:46 +0800 |
| commit | ec14de32f0c06f7a26b6b79578f666c0cc50b72c (patch) | |
| tree | c6ebd61a7d9a7da5b993ffb82e4fb6c036e75d6a /excelize_test.go | |
| parent | aa7eadbffe6ae2f9f86201bbaaa4c1d1e8829cae (diff) | |
| parent | 2efc7107ff30dc7f1e1a798082616ee488f99489 (diff) | |
Merge branch 'master' into fix/cell_lock
Diffstat (limited to 'excelize_test.go')
| -rw-r--r-- | excelize_test.go | 918 |
1 files changed, 422 insertions, 496 deletions
diff --git a/excelize_test.go b/excelize_test.go index 87fd806..8ee8051 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -1,12 +1,16 @@ package excelize import ( + "bytes" + "compress/gzip" + "encoding/xml" "fmt" "image/color" _ "image/gif" _ "image/jpeg" _ "image/png" "io/ioutil" + "math" "os" "path/filepath" "strconv" @@ -20,12 +24,11 @@ import ( func TestOpenFile(t *testing.T) { // Test update a XLSX file. f, err := OpenFile(filepath.Join("test", "Book1.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() - } + assert.NoError(t, err) // Test get all the rows in a not exists worksheet. - f.GetRows("Sheet4") + _, err = f.GetRows("Sheet4") + assert.EqualError(t, err, "sheet Sheet4 is not exist") // Test get all the rows in a worksheet. rows, err := f.GetRows("Sheet2") assert.NoError(t, err) @@ -35,28 +38,28 @@ func TestOpenFile(t *testing.T) { } t.Log("\r\n") } - f.UpdateLinkedValue() + assert.NoError(t, f.UpdateLinkedValue()) - f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32)) - f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)) + assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))) + assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))) // Test set cell value with illegal row number. assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)), `cannot convert cell "A" to coordinates: invalid cell name "A"`) - f.SetCellInt("Sheet2", "A1", 100) + assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100)) // Test set cell integer value with illegal row number. assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), `cannot convert cell "A" to coordinates: invalid cell name "A"`) - f.SetCellStr("Sheet2", "C11", "Knowns") + assert.NoError(t, f.SetCellStr("Sheet2", "C11", "Knowns")) // Test max characters in a cell. - f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769)) + assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769))) f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.") // Test set worksheet name with illegal name. f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.") - f.SetCellInt("Sheet3", "A23", 10) - f.SetCellStr("Sheet3", "b230", "10") + assert.EqualError(t, f.SetCellInt("Sheet3", "A23", 10), "sheet Sheet3 is not exist") + assert.EqualError(t, f.SetCellStr("Sheet3", "b230", "10"), "sheet Sheet3 is not exist") assert.EqualError(t, f.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 is not exist") // Test set cell string value with illegal row number. @@ -76,8 +79,10 @@ func TestOpenFile(t *testing.T) { _, err = f.GetCellFormula("Sheet1", "B") assert.EqualError(t, err, `cannot convert cell "B" to coordinates: invalid cell name "B"`) // Test get shared cell formula - f.GetCellFormula("Sheet2", "H11") - f.GetCellFormula("Sheet2", "I11") + _, err = f.GetCellFormula("Sheet2", "H11") + assert.NoError(t, err) + _, err = f.GetCellFormula("Sheet2", "I11") + assert.NoError(t, err) getSharedForumula(&xlsxWorksheet{}, "") // Test read cell value with given illegal rows number. @@ -87,10 +92,14 @@ func TestOpenFile(t *testing.T) { assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`) // Test read cell value with given lowercase column number. - f.GetCellValue("Sheet2", "a5") - f.GetCellValue("Sheet2", "C11") - f.GetCellValue("Sheet2", "D11") - f.GetCellValue("Sheet2", "D12") + _, err = f.GetCellValue("Sheet2", "a5") + assert.NoError(t, err) + _, err = f.GetCellValue("Sheet2", "C11") + assert.NoError(t, err) + _, err = f.GetCellValue("Sheet2", "D11") + assert.NoError(t, err) + _, err = f.GetCellValue("Sheet2", "D12") + assert.NoError(t, err) // Test SetCellValue function. assert.NoError(t, f.SetCellValue("Sheet2", "F1", " Hello")) assert.NoError(t, f.SetCellValue("Sheet2", "G1", []byte("World"))) @@ -127,33 +136,34 @@ func TestOpenFile(t *testing.T) { {true, "1"}, } for _, test := range booltest { - f.SetCellValue("Sheet2", "F16", test.value) + assert.NoError(t, f.SetCellValue("Sheet2", "F16", test.value)) val, err := f.GetCellValue("Sheet2", "F16") assert.NoError(t, err) assert.Equal(t, test.expected, val) } - f.SetCellValue("Sheet2", "G2", nil) + assert.NoError(t, f.SetCellValue("Sheet2", "G2", nil)) assert.EqualError(t, f.SetCellValue("Sheet2", "G4", time.Now()), "only UTC time expected") - f.SetCellValue("Sheet2", "G4", time.Now().UTC()) + assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now().UTC())) // 02:46:40 - f.SetCellValue("Sheet2", "G5", time.Duration(1e13)) + assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13))) // Test completion column. - f.SetCellValue("Sheet2", "M2", nil) + assert.NoError(t, f.SetCellValue("Sheet2", "M2", nil)) // Test read cell value with given axis large than exists row. - f.GetCellValue("Sheet2", "E231") + _, err = f.GetCellValue("Sheet2", "E231") + assert.NoError(t, err) // Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index. f.GetSheetName(f.GetActiveSheetIndex()) // Test get worksheet index of XLSX by given worksheet name. f.GetSheetIndex("Sheet1") // Test get worksheet name of XLSX by given invalid worksheet index. f.GetSheetName(4) - // Test get worksheet map of f. + // Test get worksheet map of workbook. f.GetSheetMap() for i := 1; i <= 300; i++ { - f.SetCellStr("Sheet3", "c"+strconv.Itoa(i), strconv.Itoa(i)) + assert.NoError(t, f.SetCellStr("Sheet2", "c"+strconv.Itoa(i), strconv.Itoa(i))) } assert.NoError(t, f.SaveAs(filepath.Join("test", "TestOpenFile.xlsx"))) } @@ -182,6 +192,36 @@ func TestSaveAsWrongPath(t *testing.T) { } } +func TestCharsetTranscoder(t *testing.T) { + f := NewFile() + f.CharsetTranscoder(*new(charsetTranscoderFn)) +} + +func TestOpenReader(t *testing.T) { + _, err := OpenReader(strings.NewReader("")) + assert.EqualError(t, err, "zip: not a valid zip file") + _, err = OpenReader(bytes.NewReader([]byte{ + 0x3c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, + 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x44, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x61, 0x00, 0x53, 0x00, 0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + })) + assert.EqualError(t, err, "not support encrypted file currently") + + // Test unexpected EOF. + var b bytes.Buffer + w := gzip.NewWriter(&b) + defer w.Close() + w.Flush() + + r, _ := gzip.NewReader(&b) + defer r.Close() + + _, err = OpenReader(r) + assert.EqualError(t, err, "unexpected EOF") +} + func TestBrokenFile(t *testing.T) { // Test write file with broken file struct. f := File{} @@ -192,14 +232,14 @@ func TestBrokenFile(t *testing.T) { t.Run("SaveAsEmptyStruct", func(t *testing.T) { // Test write file with broken file struct with given path. - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestBrokenFile.SaveAsEmptyStruct.xlsx"))) + assert.NoError(t, f.SaveAs(filepath.Join("test", "BrokenFile.SaveAsEmptyStruct.xlsx"))) }) t.Run("OpenBadWorkbook", func(t *testing.T) { // Test set active sheet without BookViews and Sheets maps in xl/workbook.xml. f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx")) f3.GetActiveSheetIndex() - f3.SetActiveSheet(2) + f3.SetActiveSheet(1) assert.NoError(t, err) }) @@ -218,8 +258,8 @@ func TestNewFile(t *testing.T) { f.NewSheet("Sheet1") f.NewSheet("XLSXSheet2") f.NewSheet("XLSXSheet3") - f.SetCellInt("XLSXSheet2", "A23", 56) - f.SetCellStr("Sheet1", "B20", "42") + assert.NoError(t, f.SetCellInt("XLSXSheet2", "A23", 56)) + assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42")) f.SetActiveSheet(0) // Test add picture to sheet with scaling and positioning. @@ -244,30 +284,6 @@ func TestNewFile(t *testing.T) { assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx"))) } -func TestColWidth(t *testing.T) { - xlsx := NewFile() - xlsx.SetColWidth("Sheet1", "B", "A", 12) - xlsx.SetColWidth("Sheet1", "A", "B", 12) - xlsx.GetColWidth("Sheet1", "A") - xlsx.GetColWidth("Sheet1", "C") - - // Test set and get column width with illegal cell coordinates. - _, err := xlsx.GetColWidth("Sheet1", "*") - assert.EqualError(t, err, `invalid column name "*"`) - assert.EqualError(t, xlsx.SetColWidth("Sheet1", "*", "B", 1), `invalid column name "*"`) - assert.EqualError(t, xlsx.SetColWidth("Sheet1", "A", "*", 1), `invalid column name "*"`) - - // Test get column width on not exists worksheet. - _, err = xlsx.GetColWidth("SheetN", "A") - assert.EqualError(t, err, "sheet SheetN is not exist") - - err = xlsx.SaveAs(filepath.Join("test", "TestColWidth.xlsx")) - if err != nil { - t.Error(err) - } - convertRowHeightToPixels(0) -} - func TestAddDrawingVML(t *testing.T) { // Test addDrawingVML with illegal cell coordinates. f := NewFile() @@ -292,13 +308,18 @@ func TestSetCellHyperLink(t *testing.T) { assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx"))) - file := NewFile() - for row := 1; row <= 65530; row++ { - cell, err := CoordinatesToCellName(1, row) - assert.NoError(t, err) - assert.NoError(t, file.SetCellHyperLink("Sheet1", cell, "https://github.com/360EntSecGroup-Skylar/excelize", "External")) - } - assert.EqualError(t, file.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet") + f = NewFile() + _, err = f.workSheetReader("Sheet1") + assert.NoError(t, err) + f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{Hyperlink: make([]xlsxHyperlink, 65530)} + assert.EqualError(t, f.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet") + + f = NewFile() + _, err = f.workSheetReader("Sheet1") + assert.NoError(t, err) + f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}} + err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/360EntSecGroup-Skylar/excelize", "External") + assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`) } func TestGetCellHyperLink(t *testing.T) { @@ -319,6 +340,24 @@ func TestGetCellHyperLink(t *testing.T) { link, target, err = f.GetCellHyperLink("Sheet3", "H3") assert.EqualError(t, err, "sheet Sheet3 is not exist") t.Log(link, target) + + f = NewFile() + _, err = f.workSheetReader("Sheet1") + assert.NoError(t, err) + f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{ + Hyperlink: []xlsxHyperlink{{Ref: "A1"}}, + } + link, target, err = f.GetCellHyperLink("Sheet1", "A1") + assert.NoError(t, err) + assert.Equal(t, link, true) + assert.Equal(t, target, "") + + f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}} + link, target, err = f.GetCellHyperLink("Sheet1", "A1") + assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`) + assert.Equal(t, link, false) + assert.Equal(t, target, "") + } func TestSetCellFormula(t *testing.T) { @@ -327,8 +366,8 @@ func TestSetCellFormula(t *testing.T) { t.FailNow() } - f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)") - f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)") + assert.NoError(t, f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")) + assert.NoError(t, f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")) // Test set cell formula with illegal rows number. assert.EqualError(t, f.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)"), `cannot convert cell "C" to coordinates: invalid cell name "C"`) @@ -340,10 +379,10 @@ func TestSetCellFormula(t *testing.T) { t.FailNow() } // Test remove cell formula. - f.SetCellFormula("Sheet1", "A1", "") + assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "")) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx"))) // Test remove all cell formula. - f.SetCellFormula("Sheet1", "B1", "") + assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "")) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx"))) } @@ -381,76 +420,110 @@ func TestSetSheetBackgroundErrors(t *testing.T) { assert.EqualError(t, err, "unsupported image extension") } -func TestMergeCell(t *testing.T) { - f, err := OpenFile(filepath.Join("test", "Book1.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() +// TestWriteArrayFormula tests the extended options of SetCellFormula by writing an array function +// to a workbook. In the resulting file, the lines 2 and 3 as well as 4 and 5 should have matching +// contents. +func TestWriteArrayFormula(t *testing.T) { + cell := func(col, row int) string { + c, err := CoordinatesToCellName(col, row) + if err != nil { + t.Fatal(err) + } + + return c } - f.MergeCell("Sheet1", "D9", "D9") - f.MergeCell("Sheet1", "D9", "E9") - f.MergeCell("Sheet1", "H14", "G13") - f.MergeCell("Sheet1", "C9", "D8") - f.MergeCell("Sheet1", "F11", "G13") - f.MergeCell("Sheet1", "H7", "B15") - f.MergeCell("Sheet1", "D11", "F13") - f.MergeCell("Sheet1", "G10", "K12") - f.SetCellValue("Sheet1", "G11", "set value in merged cell") - f.SetCellInt("Sheet1", "H11", 100) - f.SetCellValue("Sheet1", "I11", float64(0.5)) - f.SetCellHyperLink("Sheet1", "J11", "https://github.com/360EntSecGroup-Skylar/excelize", "External") - f.SetCellFormula("Sheet1", "G12", "SUM(Sheet1!B19,Sheet1!C19)") - f.GetCellValue("Sheet1", "H11") - f.GetCellValue("Sheet2", "A6") // Merged cell ref is single coordinate. - f.GetCellFormula("Sheet1", "G12") - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestMergeCell.xlsx"))) -} + f := NewFile() -func TestGetMergeCells(t *testing.T) { - wants := []struct { - value string - start string - end string - }{{ - value: "A1", - start: "A1", - end: "B1", - }, { - value: "A2", - start: "A2", - end: "A3", - }, { - value: "A4", - start: "A4", - end: "B5", - }, { - value: "A7", - start: "A7", - end: "C10", - }} - - f, err := OpenFile(filepath.Join("test", "MergeCell.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() + sample := []string{"Sample 1", "Sample 2", "Sample 3"} + values := []int{1855, 1709, 1462, 1115, 1524, 625, 773, 126, 1027, 1696, 1078, 1917, 1109, 1753, 1884, 659, 994, 1911, 1925, 899, 196, 244, 1488, 1056, 1986, 66, 784, 725, 767, 1722, 1541, 1026, 1455, 264, 1538, 877, 1581, 1098, 383, 762, 237, 493, 29, 1923, 474, 430, 585, 688, 308, 200, 1259, 622, 798, 1048, 996, 601, 582, 332, 377, 805, 250, 1860, 1360, 840, 911, 1346, 1651, 1651, 665, 584, 1057, 1145, 925, 1752, 202, 149, 1917, 1398, 1894, 818, 714, 624, 1085, 1566, 635, 78, 313, 1686, 1820, 494, 614, 1913, 271, 1016, 338, 1301, 489, 1733, 1483, 1141} + assoc := []int{2, 0, 0, 0, 0, 1, 1, 0, 0, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 2, 0, 2, 1, 2, 2, 2, 1, 0, 1, 0, 1, 1, 2, 0, 2, 1, 0, 2, 1, 0, 1, 0, 0, 2, 0, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 0, 1, 0, 2, 0, 0, 1, 2, 1, 0, 1, 0, 0, 2, 1, 1, 2, 0, 2, 1, 0, 2, 2, 2, 1, 0, 0, 1, 1, 1, 2, 0, 2, 0, 1, 1} + if len(values) != len(assoc) { + t.Fatal("values and assoc must be of same length") + } + + // Average calculates the average of the n-th sample (0 <= n < len(sample)). + average := func(n int) int { + sum := 0 + count := 0 + for i := 0; i != len(values); i++ { + if assoc[i] == n { + sum += values[i] + count++ + } + } + + return int(math.Round(float64(sum) / float64(count))) } - sheet1 := f.GetSheetName(1) - mergeCells, err := f.GetMergeCells(sheet1) - if !assert.Len(t, mergeCells, len(wants)) { - t.FailNow() + // Stdev calculates the standard deviation of the n-th sample (0 <= n < len(sample)). + stdev := func(n int) int { + avg := average(n) + + sum := 0 + count := 0 + for i := 0; i != len(values); i++ { + if assoc[i] == n { + sum += (values[i] - avg) * (values[i] - avg) + count++ + } + } + + return int(math.Round(math.Sqrt(float64(sum) / float64(count)))) } - assert.NoError(t, err) - for i, m := range mergeCells { - assert.Equal(t, wants[i].value, m.GetCellValue()) - assert.Equal(t, wants[i].start, m.GetStartAxis()) - assert.Equal(t, wants[i].end, m.GetEndAxis()) + // Line 2 contains the results of AVERAGEIF + assert.NoError(t, f.SetCellStr("Sheet1", "A2", "Average")) + + // Line 3 contains the average that was calculated in Go + assert.NoError(t, f.SetCellStr("Sheet1", "A3", "Average (calculated)")) + + // Line 4 contains the results of the array function that calculates the standard deviation + assert.NoError(t, f.SetCellStr("Sheet1", "A4", "Std. deviation")) + + // Line 5 contains the standard deviations calculated in Go + assert.NoError(t, f.SetCellStr("Sheet1", "A5", "Std. deviation (calculated)")) + + assert.NoError(t, f.SetCellStr("Sheet1", "B1", sample[0])) + assert.NoError(t, f.SetCellStr("Sheet1", "C1", sample[1])) + assert.NoError(t, f.SetCellStr("Sheet1", "D1", sample[2])) + + firstResLine := 8 + assert.NoError(t, f.SetCellStr("Sheet1", cell(1, firstResLine-1), "Result Values")) + assert.NoError(t, f.SetCellStr("Sheet1", cell(2, firstResLine-1), "Sample")) + + for i := 0; i != len(values); i++ { + valCell := cell(1, i+firstResLine) + assocCell := cell(2, i+firstResLine) + + assert.NoError(t, f.SetCellInt("Sheet1", valCell, values[i])) + assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]])) } - // Test get merged cells on not exists worksheet. - _, err = f.GetMergeCells("SheetN") - assert.EqualError(t, err, "sheet SheetN is not exist") + valRange := fmt.Sprintf("$A$%d:$A$%d", firstResLine, len(values)+firstResLine-1) + assocRange := fmt.Sprintf("$B$%d:$B$%d", firstResLine, len(values)+firstResLine-1) + + for i := 0; i != len(sample); i++ { + nameCell := cell(i+2, 1) + avgCell := cell(i+2, 2) + calcAvgCell := cell(i+2, 3) + stdevCell := cell(i+2, 4) + calcStdevCell := cell(i+2, 5) + + assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, average(i))) + assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, stdev(i))) + + // Average can be done with AVERAGEIF + assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange))) + + ref := stdevCell + ":" + stdevCell + t := STCellFormulaTypeArray + // Use an array formula for standard deviation + f.SetCellFormula("Sheet1", stdevCell, fmt.Sprintf("ROUND(STDEVP(IF(%s=%s,%s)),0)", assocRange, nameCell, valRange), + FormulaOpts{}, FormulaOpts{Type: &t}, FormulaOpts{Ref: &ref}) + } + + assert.NoError(t, f.SaveAs(filepath.Join("test", "TestWriteArrayFormula.xlsx"))) } func TestSetCellStyleAlignment(t *testing.T) { @@ -507,7 +580,45 @@ func TestSetCellStyleBorder(t *testing.T) { assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style)) // Test set border and solid style pattern fill for a single cell. - style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`) + style, err = f.NewStyle(&Style{ + Border: []Border{ + { + Type: "left", + Color: "0000FF", + Style: 8, + }, + { + Type: "top", + Color: "00FF00", + Style: 9, + }, + { + Type: "bottom", + Color: "FFFF00", + Style: 10, + }, + { + Type: "right", + Color: "FF0000", + Style: 11, + }, + { + Type: "diagonalDown", + Color: "A020F0", + Style: 12, + }, + { + Type: "diagonalUp", + Color: "A020F0", + Style: 13, + }, + }, + Fill: Fill{ + Type: "pattern", + Color: []string{"#E0EBF5"}, + Pattern: 1, + }, + }) if !assert.NoError(t, err) { t.FailNow() } @@ -552,9 +663,9 @@ func TestSetCellStyleNumberFormat(t *testing.T) { var val float64 val, err = strconv.ParseFloat(v, 64) if err != nil { - f.SetCellValue("Sheet2", c, v) + assert.NoError(t, f.SetCellValue("Sheet2", c, v)) } else { - f.SetCellValue("Sheet2", c, val) + assert.NoError(t, f.SetCellValue("Sheet2", c, val)) } style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`) if !assert.NoError(t, err) { @@ -581,8 +692,8 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) { t.FailNow() } - f.SetCellValue("Sheet1", "A1", 56) - f.SetCellValue("Sheet1", "A2", -32.3) + assert.NoError(t, f.SetCellValue("Sheet1", "A1", 56)) + assert.NoError(t, f.SetCellValue("Sheet1", "A2", -32.3)) var style int style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`) if !assert.NoError(t, err) { @@ -605,8 +716,8 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) { if !assert.NoError(t, err) { t.FailNow() } - f.SetCellValue("Sheet1", "A1", 42920.5) - f.SetCellValue("Sheet1", "A2", 42920.5) + assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5)) + assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5)) _, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`) if !assert.NoError(t, err) { @@ -638,8 +749,8 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) { func TestSetCellStyleCustomNumberFormat(t *testing.T) { f := NewFile() - f.SetCellValue("Sheet1", "A1", 42920.5) - f.SetCellValue("Sheet1", "A2", 42920.5) + assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5)) + assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5)) style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`) if err != nil { t.Log(err) @@ -696,7 +807,7 @@ func TestSetCellStyleFont(t *testing.T) { } var style int - style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}}`) + style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}`) if !assert.NoError(t, err) { t.FailNow() } @@ -724,7 +835,7 @@ func TestSetCellStyleFont(t *testing.T) { assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style)) - style, err = f.NewStyle(`{"font":{"color":"#777777"}}`) + style, err = f.NewStyle(`{"font":{"color":"#777777","strike":true}}`) if !assert.NoError(t, err) { t.FailNow() } @@ -770,8 +881,8 @@ func TestSetDeleteSheet(t *testing.T) { t.FailNow() } f.DeleteSheet("Sheet1") - f.AddComment("Sheet1", "A1", "") - f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`) + assert.EqualError(t, f.AddComment("Sheet1", "A1", ""), "unexpected end of JSON input") + assert.NoError(t, f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`)) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook4.xlsx"))) }) } @@ -782,52 +893,14 @@ func TestSheetVisibility(t *testing.T) { t.FailNow() } - f.SetSheetVisible("Sheet2", false) - f.SetSheetVisible("Sheet1", false) - f.SetSheetVisible("Sheet1", true) - f.GetSheetVisible("Sheet1") + assert.NoError(t, f.SetSheetVisible("Sheet2", false)) + assert.NoError(t, f.SetSheetVisible("Sheet1", false)) + assert.NoError(t, f.SetSheetVisible("Sheet1", true)) + assert.Equal(t, true, f.GetSheetVisible("Sheet1")) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx"))) } -func TestColumnVisibility(t *testing.T) { - t.Run("TestBook1", func(t *testing.T) { - f, err := prepareTestBook1() - if !assert.NoError(t, err) { - t.FailNow() - } - - assert.NoError(t, f.SetColVisible("Sheet1", "F", false)) - assert.NoError(t, f.SetColVisible("Sheet1", "F", true)) - visible, err := f.GetColVisible("Sheet1", "F") - assert.Equal(t, true, visible) - assert.NoError(t, err) - - // Test get column visiable on not exists worksheet. - _, err = f.GetColVisible("SheetN", "F") - assert.EqualError(t, err, "sheet SheetN is not exist") - - // Test get column visiable with illegal cell coordinates. - _, err = f.GetColVisible("Sheet1", "*") - assert.EqualError(t, err, `invalid column name "*"`) - assert.EqualError(t, f.SetColVisible("Sheet1", "*", false), `invalid column name "*"`) - - f.NewSheet("Sheet3") - assert.NoError(t, f.SetColVisible("Sheet3", "E", false)) - - assert.EqualError(t, f.SetColVisible("SheetN", "E", false), "sheet SheetN is not exist") - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestColumnVisibility.xlsx"))) - }) - - t.Run("TestBook3", func(t *testing.T) { - f, err := prepareTestBook3() - if !assert.NoError(t, err) { - t.FailNow() - } - f.GetColVisible("Sheet1", "B") - }) -} - func TestCopySheet(t *testing.T) { f, err := prepareTestBook1() if !assert.NoError(t, err) { @@ -835,9 +908,9 @@ func TestCopySheet(t *testing.T) { } idx := f.NewSheet("CopySheet") - assert.EqualError(t, f.CopySheet(1, idx), "sheet sheet1 is not exist") + assert.NoError(t, f.CopySheet(0, idx)) - f.SetCellValue("Sheet4", "F1", "Hello") + assert.NoError(t, f.SetCellValue("CopySheet", "F1", "Hello")) val, err := f.GetCellValue("Sheet1", "F1") assert.NoError(t, err) assert.NotEqual(t, "Hello", val) @@ -851,258 +924,61 @@ func TestCopySheetError(t *testing.T) { t.FailNow() } - err = f.CopySheet(0, -1) - if !assert.EqualError(t, err, "invalid worksheet index") { + assert.EqualError(t, f.copySheet(-1, -2), "sheet is not exist") + if !assert.EqualError(t, f.CopySheet(-1, -2), "invalid worksheet index") { t.FailNow() } 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() - } - - f.AddShape("Sheet1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`) - f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`) - f.AddShape("Sheet1", "C30", `{"type":"rect","paragraph":[]}`) - f.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}}], "height": 90}`) - f.AddShape("Sheet3", "H1", "") - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape.xlsx"))) -} - -func TestAddComments(t *testing.T) { - f, err := prepareTestBook1() - if !assert.NoError(t, err) { - t.FailNow() - } - - s := strings.Repeat("c", 32768) - f.AddComment("Sheet1", "A30", `{"author":"`+s+`","text":"`+s+`"}`) - f.AddComment("Sheet2", "B7", `{"author":"Excelize: ","text":"This is a comment."}`) - - if assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx"))) { - assert.Len(t, f.GetComments(), 2) - } -} - func TestGetSheetComments(t *testing.T) { f := NewFile() - assert.Equal(t, "", f.getSheetComments(0)) + assert.Equal(t, "", f.getSheetComments("sheet0")) } -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) { + f := NewFile() + f.WorkBook.BookViews = nil + f.SetActiveSheet(1) + f.WorkBook.BookViews = &xlsxBookViews{WorkBookView: []xlsxWorkBookView{}} + f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}} + f.SetActiveSheet(1) + f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = nil + f.SetActiveSheet(1) } -func TestAddChart(t *testing.T) { - f, err := OpenFile(filepath.Join("test", "Book1.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() - } - - categories := map[string]string{"A30": "Small", "A31": "Normal", "A32": "Large", "B29": "Apple", "C29": "Orange", "D29": "Pear"} - values := map[string]int{"B30": 2, "C30": 3, "D30": 3, "B31": 5, "C31": 2, "D31": 4, "B32": 6, "C32": 7, "D32": 8} - for k, v := range categories { - assert.NoError(t, f.SetCellValue("Sheet1", k, v)) - } - for k, v := range values { - assert.NoError(t, f.SetCellValue("Sheet1", k, v)) - } - assert.EqualError(t, f.AddChart("Sheet1", "P1", ""), "unexpected end of JSON input") - - // Test add chart on not exists worksheet. - assert.EqualError(t, f.AddChart("SheetN", "P1", "{}"), "sheet SheetN is not exist") - - assert.NoError(t, f.AddChart("Sheet1", "P1", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "X1", `{"type":"colStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Stacked Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "P16", `{"type":"colPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 100% Stacked Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "X16", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Clustered Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "P30", `{"type":"col3DStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D 100% Stacked Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "X30", `{"type":"col3DPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D 100% Stacked Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet1", "P45", `{"type":"col3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P1", `{"type":"radar","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"top_right","show_legend_key":false},"title":{"name":"Fruit Radar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"span"}`)) - assert.NoError(t, f.AddChart("Sheet2", "X1", `{"type":"scatter","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit Scatter Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P16", `{"type":"doughnut","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"right","show_legend_key":false},"title":{"name":"Fruit Doughnut Chart"},"plotarea":{"show_bubble_size":false,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "X16", `{"type":"line","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"top","show_legend_key":false},"title":{"name":"Fruit Line Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P32", `{"type":"pie3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "X32", `{"type":"pie","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"gap"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P48", `{"type":"bar","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Clustered Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "X48", `{"type":"barStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Stacked Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P64", `{"type":"barPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Stacked 100% Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "X64", `{"type":"bar3DClustered","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D Clustered Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "P80", `{"type":"bar3DStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D Stacked Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","y_axis":{"maximum":7.5,"minimum":0.5}}`)) - assert.NoError(t, f.AddChart("Sheet2", "X80", `{"type":"bar3DPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D 100% Stacked Bar Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"reverse_order":true,"maximum":0,"minimum":0},"y_axis":{"reverse_order":true,"maximum":0,"minimum":0}}`)) - // area series charts - assert.NoError(t, f.AddChart("Sheet2", "AF1", `{"type":"area","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "AN1", `{"type":"areaStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D Stacked Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "AF16", `{"type":"areaPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 2D 100% Stacked Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "AN16", `{"type":"area3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "AF32", `{"type":"area3DStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D Stacked Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - assert.NoError(t, f.AddChart("Sheet2", "AN32", `{"type":"area3DPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Fruit 3D 100% Stacked Area Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`)) - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChart.xlsx"))) +func TestSetSheetVisible(t *testing.T) { + f := NewFile() + f.WorkBook.Sheets.Sheet[0].Name = "SheetN" + assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "sheet SheetN is not exist") } -func TestInsertCol(t *testing.T) { +func TestGetActiveSheetIndex(t *testing.T) { f := NewFile() - sheet1 := f.GetSheetName(1) - - fillCells(f, sheet1, 10, 10) - - f.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External") - f.MergeCell(sheet1, "A1", "C3") - - err := f.AutoFilter(sheet1, "A2", "B2", `{"column":"B","expression":"x != blanks"}`) - if !assert.NoError(t, err) { - t.FailNow() - } - - assert.NoError(t, f.InsertCol(sheet1, "A")) - - // Test insert column with illegal cell coordinates. - assert.EqualError(t, f.InsertCol("Sheet1", "*"), `invalid column name "*"`) - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertCol.xlsx"))) + f.WorkBook.BookViews = nil + assert.Equal(t, 0, f.GetActiveSheetIndex()) } -func TestRemoveCol(t *testing.T) { +func TestRelsWriter(t *testing.T) { f := NewFile() - sheet1 := f.GetSheetName(1) - - fillCells(f, sheet1, 10, 15) - - f.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External") - f.SetCellHyperLink(sheet1, "C5", "https://github.com", "External") - - f.MergeCell(sheet1, "A1", "B1") - f.MergeCell(sheet1, "A2", "B2") - - assert.NoError(t, f.RemoveCol(sheet1, "A")) - assert.NoError(t, f.RemoveCol(sheet1, "A")) - - // Test remove column with illegal cell coordinates. - assert.EqualError(t, f.RemoveCol("Sheet1", "*"), `invalid column name "*"`) - - // Test remove column on not exists worksheet. - assert.EqualError(t, f.RemoveCol("SheetN", "B"), "sheet SheetN is not exist") - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemoveCol.xlsx"))) + f.Relationships["xl/worksheets/sheet/rels/sheet1.xml.rel"] = &xlsxRelationships{} + f.relsWriter() } -func TestSetPane(t *testing.T) { +func TestGetSheetView(t *testing.T) { f := NewFile() - f.SetPanes("Sheet1", `{"freeze":false,"split":false}`) - f.NewSheet("Panes 2") - f.SetPanes("Panes 2", `{"freeze":true,"split":false,"x_split":1,"y_split":0,"top_left_cell":"B1","active_pane":"topRight","panes":[{"sqref":"K16","active_cell":"K16","pane":"topRight"}]}`) - f.NewSheet("Panes 3") - f.SetPanes("Panes 3", `{"freeze":false,"split":true,"x_split":3270,"y_split":1800,"top_left_cell":"N57","active_pane":"bottomLeft","panes":[{"sqref":"I36","active_cell":"I36"},{"sqref":"G33","active_cell":"G33","pane":"topRight"},{"sqref":"J60","active_cell":"J60","pane":"bottomLeft"},{"sqref":"O60","active_cell":"O60","pane":"bottomRight"}]}`) - f.NewSheet("Panes 4") - f.SetPanes("Panes 4", `{"freeze":true,"split":false,"x_split":0,"y_split":9,"top_left_cell":"A34","active_pane":"bottomLeft","panes":[{"sqref":"A11:XFD11","active_cell":"A11","pane":"bottomLeft"}]}`) - f.SetPanes("Panes 4", "") - - assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetPane.xlsx"))) + _, err := f.getSheetView("SheetN", 0) + assert.EqualError(t, err, "sheet SheetN is not exist") } func TestConditionalFormat(t *testing.T) { f := NewFile() - sheet1 := f.GetSheetName(1) + sheet1 := f.GetSheetName(0) fillCells(f, sheet1, 10, 15) - var format1, format2, format3 int + var format1, format2, format3, format4 int var err error // Rose format for bad conditional. format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`) @@ -1122,32 +998,43 @@ func TestConditionalFormat(t *testing.T) { t.FailNow() } + // conditional style with align and left border. + format4, err = f.NewConditionalStyle(`{"alignment":{"wrap_text":true},"border":[{"type":"left","color":"#000000","style":1}]}`) + if !assert.NoError(t, err) { + t.FailNow() + } + // Color scales: 2 color. - f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`) + assert.NoError(t, f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`)) // Color scales: 3 color. - f.SetConditionalFormat(sheet1, "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`) + assert.NoError(t, f.SetConditionalFormat(sheet1, "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`)) // Hightlight cells rules: between... - f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1))) // Hightlight cells rules: Greater Than... - f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3))) // Hightlight cells rules: Equal To... - f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3))) // Hightlight cells rules: Not Equal To... - f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2))) // Hightlight cells rules: Duplicate Values... - f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2))) // Top/Bottom rules: Top 10%. - f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1))) // Top/Bottom rules: Above Average... - f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3))) // Top/Bottom rules: Below Average... - f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1)) + assert.NoError(t, f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1))) // Data Bars: Gradient Fill. - f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`) + assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)) // Use a formula to determine which cells to format. - f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1)) - // Test set invalid format set in conditional format - f.SetConditionalFormat(sheet1, "L1:L10", "") + assert.NoError(t, f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1))) + // Alignment/Border cells rules. + assert.NoError(t, f.SetConditionalFormat(sheet1, "M1:M10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"0"}]`, format4))) + + // Test set invalid format set in conditional format. + assert.EqualError(t, f.SetConditionalFormat(sheet1, "L1:L10", ""), "unexpected end of JSON input") + // Set conditional format on not exists worksheet. + assert.EqualError(t, f.SetConditionalFormat("SheetN", "L1:L10", "[]"), "sheet SheetN is not exist") err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx")) if !assert.NoError(t, err) { @@ -1155,9 +1042,9 @@ func TestConditionalFormat(t *testing.T) { } // Set conditional format with illegal valid type. - f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`) + assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)) // Set conditional format with illegal criteria type. - f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`) + assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)) // Set conditional format with file without dxfs element shold not return error. f, err = OpenFile(filepath.Join("test", "Book1.xlsx")) @@ -1173,11 +1060,11 @@ func TestConditionalFormat(t *testing.T) { func TestConditionalFormatError(t *testing.T) { f := NewFile() - sheet1 := f.GetSheetName(1) + sheet1 := f.GetSheetName(0) fillCells(f, sheet1, 10, 15) - // Set conditional format with illegal JSON string should return error + // Set conditional format with illegal JSON string should return error. _, err := f.NewConditionalStyle("") if !assert.EqualError(t, err, "unexpected end of JSON input") { t.FailNow() @@ -1189,7 +1076,16 @@ func TestSharedStrings(t *testing.T) { if !assert.NoError(t, err) { t.FailNow() } - f.GetRows("Sheet1") + rows, err := f.GetRows("Sheet1") + if !assert.NoError(t, err) { + t.FailNow() + } + assert.Equal(t, "A", rows[0][0]) + rows, err = f.GetRows("Sheet2") + if !assert.NoError(t, err) { + t.FailNow() + } + assert.Equal(t, "Test Weight (Kgs)", rows[0][0]) } func TestSetSheetRow(t *testing.T) { @@ -1198,7 +1094,7 @@ func TestSetSheetRow(t *testing.T) { t.FailNow() } - f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()}) + assert.NoError(t, f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()})) assert.EqualError(t, f.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}), `cannot convert cell "" to coordinates: invalid cell name ""`) @@ -1208,48 +1104,6 @@ func TestSetSheetRow(t *testing.T) { assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx"))) } -func TestOutlineLevel(t *testing.T) { - f := NewFile() - f.NewSheet("Sheet2") - f.SetColOutlineLevel("Sheet1", "D", 4) - f.GetColOutlineLevel("Sheet1", "D") - f.GetColOutlineLevel("Shee2", "A") - f.SetColWidth("Sheet2", "A", "D", 13) - f.SetColOutlineLevel("Sheet2", "B", 2) - f.SetRowOutlineLevel("Sheet1", 2, 250) - - // Test set and get column outline level with illegal cell coordinates. - assert.EqualError(t, f.SetColOutlineLevel("Sheet1", "*", 1), `invalid column name "*"`) - _, err := f.GetColOutlineLevel("Sheet1", "*") - assert.EqualError(t, err, `invalid column name "*"`) - - // Test set column outline level on not exists worksheet. - assert.EqualError(t, f.SetColOutlineLevel("SheetN", "E", 2), "sheet SheetN is not exist") - - assert.EqualError(t, f.SetRowOutlineLevel("Sheet1", 0, 1), "invalid row number 0") - level, err := f.GetRowOutlineLevel("Sheet1", 2) - assert.NoError(t, err) - assert.Equal(t, uint8(250), level) - - _, err = f.GetRowOutlineLevel("Sheet1", 0) - assert.EqualError(t, err, `invalid row number 0`) - - level, err = f.GetRowOutlineLevel("Sheet1", 10) - assert.NoError(t, err) - assert.Equal(t, uint8(0), level) - - err = f.SaveAs(filepath.Join("test", "TestOutlineLevel.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() - } - - f, err = OpenFile(filepath.Join("test", "Book1.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() - } - f.SetColOutlineLevel("Sheet2", "B", 2) -} - func TestThemeColor(t *testing.T) { t.Log(ThemeColor("000000", -0.1)) t.Log(ThemeColor("000000", 0)) @@ -1275,29 +1129,13 @@ func TestHSL(t *testing.T) { t.Log(RGBToHSL(250, 50, 100)) } -func TestSearchSheet(t *testing.T) { - f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx")) - if !assert.NoError(t, err) { - t.FailNow() - } - - // Test search in a not exists worksheet. - t.Log(f.SearchSheet("Sheet4", "")) - // Test search a not exists value. - t.Log(f.SearchSheet("Sheet1", "X")) - t.Log(f.SearchSheet("Sheet1", "A")) - // Test search the coordinates where the numerical value in the range of - // "0-9" of Sheet1 is described by regular expression: - t.Log(f.SearchSheet("Sheet1", "[0-9]", true)) -} - func TestProtectSheet(t *testing.T) { f := NewFile() - f.ProtectSheet("Sheet1", nil) - f.ProtectSheet("Sheet1", &FormatSheetProtection{ + assert.NoError(t, f.ProtectSheet("Sheet1", nil)) + assert.NoError(t, f.ProtectSheet("Sheet1", &FormatSheetProtection{ Password: "password", EditScenarios: false, - }) + })) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx"))) // Test protect not exists worksheet. @@ -1312,7 +1150,7 @@ func TestUnprotectSheet(t *testing.T) { // Test unprotect not exists worksheet. assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist") - f.UnprotectSheet("Sheet1") + assert.NoError(t, f.UnprotectSheet("Sheet1")) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx"))) } @@ -1322,6 +1160,72 @@ func TestSetDefaultTimeStyle(t *testing.T) { assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist") } +func TestAddVBAProject(t *testing.T) { + f := NewFile() + assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1"))) + assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory") + assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), "unsupported VBA project extension") + assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin"))) + // Test add VBA project twice. + assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin"))) + assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddVBAProject.xlsm"))) +} + +func TestContentTypesReader(t *testing.T) { + // Test unsupport charset. + f := NewFile() + f.ContentTypes = nil + f.XLSX["[Content_Types].xml"] = MacintoshCyrillicCharset + f.contentTypesReader() +} + +func TestWorkbookReader(t *testing.T) { + // Test unsupport charset. + f := NewFile() + f.WorkBook = nil + f.XLSX["xl/workbook.xml"] = MacintoshCyrillicCharset + f.workbookReader() +} + +func TestWorkSheetReader(t *testing.T) { + // Test unsupport charset. + f := NewFile() + delete(f.Sheet, "xl/worksheets/sheet1.xml") + f.XLSX["xl/worksheets/sheet1.xml"] = MacintoshCyrillicCharset + _, err := f.workSheetReader("Sheet1") + assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8") + + // Test on no checked worksheet. + f = NewFile() + delete(f.Sheet, "xl/worksheets/sheet1.xml") + f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData/></worksheet>`) + f.checked = nil + _, err = f.workSheetReader("Sheet1") + assert.NoError(t, err) +} + +func TestRelsReader(t *testing.T) { + // Test unsupport charset. + f := NewFile() + rels := "xl/_rels/workbook.xml.rels" + f.Relationships[rels] = nil + f.XLSX[rels] = MacintoshCyrillicCharset + f.relsReader(rels) +} + +func TestDeleteSheetFromWorkbookRels(t *testing.T) { + f := NewFile() + rels := "xl/_rels/workbook.xml.rels" + f.Relationships[rels] = nil + assert.Equal(t, f.deleteSheetFromWorkbookRels("rID"), "") +} + +func TestAttrValToInt(t *testing.T) { + _, err := attrValToInt("r", []xml.Attr{ + {Name: xml.Name{Local: "r"}, Value: "s"}}) + assert.EqualError(t, err, `strconv.Atoi: parsing "s": invalid syntax`) +} + func prepareTestBook1() (*File, error) { f, err := OpenFile(filepath.Join("test", "Book1.xlsx")) if err != nil { @@ -1359,8 +1263,12 @@ func prepareTestBook3() (*File, error) { f.NewSheet("Sheet1") f.NewSheet("XLSXSheet2") f.NewSheet("XLSXSheet3") - f.SetCellInt("XLSXSheet2", "A23", 56) - f.SetCellStr("Sheet1", "B20", "42") + if err := f.SetCellInt("XLSXSheet2", "A23", 56); err != nil { + return nil, err + } + if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil { + return nil, err + } f.SetActiveSheet(0) err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"), @@ -1379,10 +1287,18 @@ func prepareTestBook3() (*File, error) { func prepareTestBook4() (*File, error) { f := NewFile() - f.SetColWidth("Sheet1", "B", "A", 12) - f.SetColWidth("Sheet1", "A", "B", 12) - f.GetColWidth("Sheet1", "A") - f.GetColWidth("Sheet1", "C") + if err := f.SetColWidth("Sheet1", "B", "A", 12); err != nil { + return f, err + } + if err := f.SetColWidth("Sheet1", "A", "B", 12); err != nil { + return f, err + } + if _, err := f.GetColWidth("Sheet1", "A"); err != nil { + return f, err + } + if _, err := f.GetColWidth("Sheet1", "C"); err != nil { + return f, err + } return f, nil } @@ -1391,7 +1307,17 @@ func fillCells(f *File, sheet string, colCount, rowCount int) { for col := 1; col <= colCount; col++ { for row := 1; row <= rowCount; row++ { cell, _ := CoordinatesToCellName(col, row) - f.SetCellStr(sheet, cell, cell) + if err := f.SetCellStr(sheet, cell, cell); err != nil { + fmt.Println(err) + } + } + } +} + +func BenchmarkOpenFile(b *testing.B) { + for i := 0; i < b.N; i++ { + if _, err := OpenFile(filepath.Join("test", "Book1.xlsx")); err != nil { + b.Error(err) } } } |
