Browse Source

add unit tests to functions

xuri 6 years ago
parent
commit
a88459d5f1
12 changed files with 356 additions and 175 deletions
  1. 5 3
      adjust_test.go
  2. 54 29
      cell.go
  3. 5 0
      chart_test.go
  4. 1 1
      date_test.go
  5. 1 1
      excelize.go
  6. 100 58
      excelize_test.go
  7. 2 2
      picture_test.go
  8. 151 16
      rows_test.go
  9. 7 7
      sheet.go
  10. 21 29
      sheet_test.go
  11. 9 27
      sheetpr_test.go
  12. 0 2
      styles_test.go

+ 5 - 3
adjust_test.go

@@ -12,7 +12,7 @@ func TestAdjustMergeCells(t *testing.T) {
 	assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
 		MergeCells: &xlsxMergeCells{
 			Cells: []*xlsxMergeCell{
-				&xlsxMergeCell{
+				{
 					Ref: "A:B1",
 				},
 			},
@@ -21,7 +21,7 @@ func TestAdjustMergeCells(t *testing.T) {
 	assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
 		MergeCells: &xlsxMergeCells{
 			Cells: []*xlsxMergeCell{
-				&xlsxMergeCell{
+				{
 					Ref: "A1:B",
 				},
 			},
@@ -50,7 +50,7 @@ func TestAdjustHelper(t *testing.T) {
 	f.Sheet["xl/worksheets/sheet1.xml"] = &xlsxWorksheet{
 		MergeCells: &xlsxMergeCells{
 			Cells: []*xlsxMergeCell{
-				&xlsxMergeCell{
+				{
 					Ref: "A:B1",
 				},
 			},
@@ -64,4 +64,6 @@ func TestAdjustHelper(t *testing.T) {
 	// testing adjustHelper with illegal cell coordinates.
 	assert.EqualError(t, f.adjustHelper("Sheet1", rows, 0, 0), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
 	assert.EqualError(t, f.adjustHelper("Sheet2", rows, 0, 0), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
+	// testing adjustHelper on not exists worksheet.
+	assert.EqualError(t, f.adjustHelper("SheetN", rows, 0, 0), "sheet SheetN is not exist")
 }

+ 54 - 29
cell.go

@@ -69,6 +69,38 @@ func (f *File) GetCellValue(sheet, axis string) (string, error) {
 // Note that default date format is m/d/yy h:mm of time.Time type value. You can
 // set numbers format by SetCellStyle() method.
 func (f *File) SetCellValue(sheet, axis string, value interface{}) error {
+	var err error
+	switch v := value.(type) {
+	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+		err = f.setCellIntFunc(sheet, axis, v)
+	case float32:
+		err = f.SetCellFloat(sheet, axis, float64(v), -1, 32)
+	case float64:
+		err = f.SetCellFloat(sheet, axis, v, -1, 64)
+	case string:
+		err = f.SetCellStr(sheet, axis, v)
+	case []byte:
+		err = f.SetCellStr(sheet, axis, string(v))
+	case time.Duration:
+		err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32))
+		if err != nil {
+			return err
+		}
+		err = f.setDefaultTimeStyle(sheet, axis, 21)
+	case time.Time:
+		err = f.setCellTimeFunc(sheet, axis, v)
+	case bool:
+		err = f.SetCellBool(sheet, axis, v)
+	case nil:
+		err = f.SetCellStr(sheet, axis, "")
+	default:
+		err = f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
+	}
+	return err
+}
+
+// setCellIntFunc is a wrapper of SetCellInt.
+func (f *File) setCellIntFunc(sheet, axis string, value interface{}) error {
 	var err error
 	switch v := value.(type) {
 	case int:
@@ -91,34 +123,31 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) error {
 		err = f.SetCellInt(sheet, axis, int(v))
 	case uint64:
 		err = f.SetCellInt(sheet, axis, int(v))
-	case float32:
-		err = f.SetCellFloat(sheet, axis, float64(v), -1, 32)
-	case float64:
-		err = f.SetCellFloat(sheet, axis, v, -1, 64)
-	case string:
-		err = f.SetCellStr(sheet, axis, v)
-	case []byte:
-		err = f.SetCellStr(sheet, axis, string(v))
-	case time.Duration:
-		err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32))
-		err = f.setDefaultTimeStyle(sheet, axis, 21)
-	case time.Time:
-		excelTime, err := timeToExcelTime(v)
+	}
+	return err
+}
+
+// setCellTimeFunc provides a method to process time type of value for
+// SetCellValue.
+func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
+	excelTime, err := timeToExcelTime(value)
+	if err != nil {
+		return err
+	}
+	if excelTime > 0 {
+		err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(excelTime, 'f', -1, 64))
 		if err != nil {
 			return err
 		}
-		if excelTime > 0 {
-			err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(excelTime, 'f', -1, 64))
-			err = f.setDefaultTimeStyle(sheet, axis, 22)
-		} else {
-			err = f.SetCellStr(sheet, axis, v.Format(time.RFC3339Nano))
+		err = f.setDefaultTimeStyle(sheet, axis, 22)
+		if err != nil {
+			return err
+		}
+	} else {
+		err = f.SetCellStr(sheet, axis, value.Format(time.RFC3339Nano))
+		if err != nil {
+			return err
 		}
-	case bool:
-		err = f.SetCellBool(sheet, axis, v)
-	case nil:
-		err = f.SetCellStr(sheet, axis, "")
-	default:
-		err = f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
 	}
 	return err
 }
@@ -398,8 +427,6 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
 	}
 	if xlsx.MergeCells != nil {
 		ref := hcell + ":" + vcell
-		cells := make([]*xlsxMergeCell, 0, len(xlsx.MergeCells.Cells))
-
 		// Delete the merged cells of the overlapping area.
 		for _, cellData := range xlsx.MergeCells.Cells {
 			cc := strings.Split(cellData.Ref, ":")
@@ -413,10 +440,8 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
 			if !(!c1 && !c2 && !c3 && !c4) {
 				return nil
 			}
-			cells = append(cells, cellData)
 		}
-		cells = append(xlsx.MergeCells.Cells, &xlsxMergeCell{Ref: ref})
-		xlsx.MergeCells.Cells = cells
+		xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells, &xlsxMergeCell{Ref: ref})
 	} else {
 		xlsx.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: hcell + ":" + vcell}}}
 	}

+ 5 - 0
chart_test.go

@@ -96,3 +96,8 @@ func TestChartSize(t *testing.T) {
 		t.FailNow()
 	}
 }
+
+func TestAddDrawingChart(t *testing.T) {
+	f := NewFile()
+	assert.EqualError(t, f.addDrawingChart("SheetN", "", "", 0, 0, 0, nil), `cannot convert cell "" to coordinates: invalid cell name ""`)
+}

+ 1 - 1
date_test.go

@@ -69,7 +69,7 @@ func TestTimeFromExcelTime(t *testing.T) {
 }
 
 func TestTimeFromExcelTime_1904(t *testing.T) {
-	shiftJulianToNoon(1, -0.6)
+	_, _ = shiftJulianToNoon(1, -0.6)
 	timeFromExcelTime(61, true)
 	timeFromExcelTime(62, true)
 }

+ 1 - 1
excelize.go

@@ -116,7 +116,7 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error {
 func (f *File) workSheetReader(sheet string) (*xlsxWorksheet, error) {
 	name, ok := f.sheetMap[trimSheetName(sheet)]
 	if !ok {
-		return nil, fmt.Errorf("Sheet %s is not exist", sheet)
+		return nil, fmt.Errorf("sheet %s is not exist", sheet)
 	}
 	if f.Sheet[name] == nil {
 		var xlsx xlsxWorksheet

+ 100 - 58
excelize_test.go

@@ -57,7 +57,7 @@ func TestOpenFile(t *testing.T) {
 	xlsx.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
 	xlsx.SetCellInt("Sheet3", "A23", 10)
 	xlsx.SetCellStr("Sheet3", "b230", "10")
-	assert.EqualError(t, xlsx.SetCellStr("Sheet10", "b230", "10"), "Sheet Sheet10 is not exist")
+	assert.EqualError(t, xlsx.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 is not exist")
 
 	// Test set cell string value with illegal row number.
 	assert.EqualError(t, xlsx.SetCellStr("Sheet1", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
@@ -92,24 +92,31 @@ func TestOpenFile(t *testing.T) {
 	xlsx.GetCellValue("Sheet2", "D11")
 	xlsx.GetCellValue("Sheet2", "D12")
 	// Test SetCellValue function.
-	xlsx.SetCellValue("Sheet2", "F1", " Hello")
-	xlsx.SetCellValue("Sheet2", "G1", []byte("World"))
-	xlsx.SetCellValue("Sheet2", "F2", 42)
-	xlsx.SetCellValue("Sheet2", "F3", int8(1<<8/2-1))
-	xlsx.SetCellValue("Sheet2", "F4", int16(1<<16/2-1))
-	xlsx.SetCellValue("Sheet2", "F5", int32(1<<32/2-1))
-	xlsx.SetCellValue("Sheet2", "F6", int64(1<<32/2-1))
-	xlsx.SetCellValue("Sheet2", "F7", float32(42.65418))
-	xlsx.SetCellValue("Sheet2", "F8", float64(-42.65418))
-	xlsx.SetCellValue("Sheet2", "F9", float32(42))
-	xlsx.SetCellValue("Sheet2", "F10", float64(42))
-	xlsx.SetCellValue("Sheet2", "F11", uint(1<<32-1))
-	xlsx.SetCellValue("Sheet2", "F12", uint8(1<<8-1))
-	xlsx.SetCellValue("Sheet2", "F13", uint16(1<<16-1))
-	xlsx.SetCellValue("Sheet2", "F14", uint32(1<<32-1))
-	xlsx.SetCellValue("Sheet2", "F15", uint64(1<<32-1))
-	xlsx.SetCellValue("Sheet2", "F16", true)
-	xlsx.SetCellValue("Sheet2", "F17", complex64(5+10i))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F1", " Hello"))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "G1", []byte("World")))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F2", 42))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F3", int8(1<<8/2-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F4", int16(1<<16/2-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F7", float32(42.65418)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F8", float64(-42.65418)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F9", float32(42)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F10", float64(42)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F12", uint8(1<<8-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F13", uint16(1<<16-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F14", uint32(1<<32-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F15", uint64(1<<32-1)))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F16", true))
+	assert.NoError(t, xlsx.SetCellValue("Sheet2", "F17", complex64(5+10i)))
+
+	// Test on not exists worksheet.
+	assert.EqualError(t, xlsx.SetCellDefault("SheetN", "A1", ""), "sheet SheetN is not exist")
+	assert.EqualError(t, xlsx.SetCellFloat("SheetN", "A1", 42.65418, 2, 32), "sheet SheetN is not exist")
+	assert.EqualError(t, xlsx.SetCellBool("SheetN", "A1", true), "sheet SheetN is not exist")
+	assert.EqualError(t, xlsx.SetCellFormula("SheetN", "A1", ""), "sheet SheetN is not exist")
+	assert.EqualError(t, xlsx.SetCellHyperLink("SheetN", "A1", "Sheet1!A40", "Location"), "sheet SheetN is not exist")
 
 	// Test boolean write
 	booltest := []struct {
@@ -250,6 +257,10 @@ func TestColWidth(t *testing.T) {
 	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)
@@ -288,17 +299,17 @@ func TestGetCellHyperLink(t *testing.T) {
 		t.FailNow()
 	}
 
-	link, target, err := xlsx.GetCellHyperLink("Sheet1", "")
+	_, _, err = xlsx.GetCellHyperLink("Sheet1", "")
 	assert.EqualError(t, err, `invalid cell name ""`)
 
-	link, target, err = xlsx.GetCellHyperLink("Sheet1", "A22")
+	link, target, err := xlsx.GetCellHyperLink("Sheet1", "A22")
 	assert.NoError(t, err)
 	t.Log(link, target)
 	link, target, err = xlsx.GetCellHyperLink("Sheet2", "D6")
 	assert.NoError(t, err)
 	t.Log(link, target)
 	link, target, err = xlsx.GetCellHyperLink("Sheet3", "H3")
-	assert.EqualError(t, err, "Sheet Sheet3 is not exist")
+	assert.EqualError(t, err, "sheet Sheet3 is not exist")
 	t.Log(link, target)
 }
 
@@ -421,12 +432,17 @@ func TestGetMergeCells(t *testing.T) {
 	if !assert.Len(t, mergeCells, len(wants)) {
 		t.FailNow()
 	}
+	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())
 	}
+
+	// Test get merged cells on not exists worksheet.
+	_, err = xlsx.GetMergeCells("SheetN")
+	assert.EqualError(t, err, "sheet SheetN is not exist")
 }
 
 func TestSetCellStyleAlignment(t *testing.T) {
@@ -779,13 +795,19 @@ func TestColumnVisibility(t *testing.T) {
 		assert.Equal(t, true, visible)
 		assert.NoError(t, err)
 
+		// Test get column visiable on not exists worksheet.
+		_, err = xlsx.GetColVisible("SheetN", "F")
+		assert.EqualError(t, err, "sheet SheetN is not exist")
+
 		// Test get column visiable with illegal cell coordinates.
 		_, err = xlsx.GetColVisible("Sheet1", "*")
 		assert.EqualError(t, err, `invalid column name "*"`)
 		assert.EqualError(t, xlsx.SetColVisible("Sheet1", "*", false), `invalid column name "*"`)
 
-		err = xlsx.SetColVisible("Sheet3", "E", false)
-		assert.EqualError(t, err, "Sheet Sheet3 is not exist")
+		xlsx.NewSheet("Sheet3")
+		assert.NoError(t, xlsx.SetColVisible("Sheet3", "E", false))
+
+		assert.EqualError(t, xlsx.SetColVisible("SheetN", "E", false), "sheet SheetN is not exist")
 		assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestColumnVisibility.xlsx")))
 	})
 
@@ -805,7 +827,7 @@ func TestCopySheet(t *testing.T) {
 	}
 
 	idx := xlsx.NewSheet("CopySheet")
-	assert.EqualError(t, xlsx.CopySheet(1, idx), "Sheet sheet1 is not exist")
+	assert.EqualError(t, xlsx.CopySheet(1, idx), "sheet sheet1 is not exist")
 
 	xlsx.SetCellValue("Sheet4", "F1", "Hello")
 	val, err := xlsx.GetCellValue("Sheet1", "F1")
@@ -920,8 +942,8 @@ func TestAutoFilter(t *testing.T) {
 
 	for i, format := range formats {
 		t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
-			err = xlsx.AutoFilter("Sheet3", "D4", "B1", format)
-			assert.EqualError(t, err, "Sheet Sheet3 is not exist")
+			err = xlsx.AutoFilter("Sheet1", "D4", "B1", format)
+			assert.NoError(t, err)
 			assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, i+1)))
 		})
 	}
@@ -966,38 +988,42 @@ func TestAddChart(t *testing.T) {
 	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 {
-		xlsx.SetCellValue("Sheet1", k, v)
+		assert.NoError(t, xlsx.SetCellValue("Sheet1", k, v))
 	}
 	for k, v := range values {
-		xlsx.SetCellValue("Sheet1", k, v)
-	}
-	xlsx.AddChart("Sheet1", "P1", "")
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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}}`)
-	xlsx.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}}`)
+		assert.NoError(t, xlsx.SetCellValue("Sheet1", k, v))
+	}
+	assert.EqualError(t, xlsx.AddChart("Sheet1", "P1", ""), "unexpected end of JSON input")
+
+	// Test add chart on not exists worksheet.
+	assert.EqualError(t, xlsx.AddChart("SheetN", "P1", "{}"), "sheet SheetN is not exist")
+
+	assert.NoError(t, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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"}`)
-	xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.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, xlsx.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
 }
@@ -1042,6 +1068,9 @@ func TestRemoveCol(t *testing.T) {
 	// Test remove column with illegal cell coordinates.
 	assert.EqualError(t, xlsx.RemoveCol("Sheet1", "*"), `invalid column name "*"`)
 
+	// Test remove column on not exists worksheet.
+	assert.EqualError(t, xlsx.RemoveCol("SheetN", "B"), "sheet SheetN is not exist")
+
 	assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRemoveCol.xlsx")))
 }
 
@@ -1183,11 +1212,14 @@ func TestOutlineLevel(t *testing.T) {
 
 	// Test set and get column outline level with illegal cell coordinates.
 	assert.EqualError(t, xlsx.SetColOutlineLevel("Sheet1", "*", 1), `invalid column name "*"`)
-	level, err := xlsx.GetColOutlineLevel("Sheet1", "*")
+	_, err := xlsx.GetColOutlineLevel("Sheet1", "*")
 	assert.EqualError(t, err, `invalid column name "*"`)
 
+	// Test set column outline level on not exists worksheet.
+	assert.EqualError(t, xlsx.SetColOutlineLevel("SheetN", "E", 2), "sheet SheetN is not exist")
+
 	assert.EqualError(t, xlsx.SetRowOutlineLevel("Sheet1", 0, 1), "invalid row number 0")
-	level, err = xlsx.GetRowOutlineLevel("Sheet1", 2)
+	level, err := xlsx.GetRowOutlineLevel("Sheet1", 2)
 	assert.NoError(t, err)
 	assert.Equal(t, uint8(250), level)
 
@@ -1260,6 +1292,8 @@ func TestProtectSheet(t *testing.T) {
 	})
 
 	assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
+	// Test protect not exists worksheet.
+	assert.EqualError(t, xlsx.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
 }
 
 func TestUnprotectSheet(t *testing.T) {
@@ -1267,11 +1301,19 @@ func TestUnprotectSheet(t *testing.T) {
 	if !assert.NoError(t, err) {
 		t.FailNow()
 	}
+	// Test unprotect not exists worksheet.
+	assert.EqualError(t, xlsx.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
 
 	xlsx.UnprotectSheet("Sheet1")
 	assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
 }
 
+func TestSetDefaultTimeStyle(t *testing.T) {
+	f := NewFile()
+	// Test set default time style on not exists worksheet.
+	assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist")
+}
+
 func prepareTestBook1() (*File, error) {
 	xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
 	if err != nil {

+ 2 - 2
picture_test.go

@@ -97,12 +97,12 @@ func TestGetPicture(t *testing.T) {
 	}
 
 	// Try to get picture from a worksheet with illegal cell coordinates.
-	file, raw, err = xlsx.GetPicture("Sheet1", "A")
+	_, _, err = xlsx.GetPicture("Sheet1", "A")
 	assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
 
 	// Try to get picture from a worksheet that doesn't contain any images.
 	file, raw, err = xlsx.GetPicture("Sheet3", "I9")
-	assert.EqualError(t, err, "Sheet Sheet3 is not exist")
+	assert.EqualError(t, err, "sheet Sheet3 is not exist")
 	assert.Empty(t, file)
 	assert.Empty(t, raw)
 

+ 151 - 16
rows_test.go

@@ -50,7 +50,7 @@ func TestRowsError(t *testing.T) {
 		t.FailNow()
 	}
 	_, err = xlsx.Rows("SheetN")
-	assert.EqualError(t, err, "Sheet SheetN is not exist")
+	assert.EqualError(t, err, "sheet SheetN is not exist")
 }
 
 func TestRowHeight(t *testing.T) {
@@ -59,11 +59,11 @@ func TestRowHeight(t *testing.T) {
 
 	assert.EqualError(t, xlsx.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0), "invalid row number 0")
 
-	height, err := xlsx.GetRowHeight("Sheet1", 0)
+	_, err := xlsx.GetRowHeight("Sheet1", 0)
 	assert.EqualError(t, err, "invalid row number 0")
 
 	assert.NoError(t, xlsx.SetRowHeight(sheet1, 1, 111.0))
-	height, err = xlsx.GetRowHeight(sheet1, 1)
+	height, err := xlsx.GetRowHeight(sheet1, 1)
 	assert.NoError(t, err)
 	assert.Equal(t, 111.0, height)
 
@@ -82,6 +82,11 @@ func TestRowHeight(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, defaultRowHeightPixels, height)
 
+	// Test set and get row height on not exists worksheet.
+	assert.EqualError(t, xlsx.SetRowHeight("SheetN", 1, 111.0), "sheet SheetN is not exist")
+	_, err = xlsx.GetRowHeight("SheetN", 3)
+	assert.EqualError(t, err, "sheet SheetN is not exist")
+
 	err = xlsx.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
 	if !assert.NoError(t, err) {
 		t.FailNow()
@@ -95,9 +100,9 @@ func TestRowVisibility(t *testing.T) {
 	if !assert.NoError(t, err) {
 		t.FailNow()
 	}
-
-	assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, false), "Sheet Sheet3 is not exist")
-	assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, true), "Sheet Sheet3 is not exist")
+	xlsx.NewSheet("Sheet3")
+	assert.NoError(t, xlsx.SetRowVisible("Sheet3", 2, false))
+	assert.NoError(t, xlsx.SetRowVisible("Sheet3", 2, true))
 	xlsx.GetRowVisible("Sheet3", 2)
 	xlsx.GetRowVisible("Sheet3", 25)
 	assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
@@ -213,7 +218,7 @@ func TestInsertRowInEmptyFile(t *testing.T) {
 	assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
 }
 
-func TestDuplicateRow(t *testing.T) {
+func TestDuplicateRowFromSingleRow(t *testing.T) {
 	const sheet = "Sheet1"
 	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
 
@@ -226,15 +231,6 @@ func TestDuplicateRow(t *testing.T) {
 		"B3": "B3 Value",
 	}
 
-	newFileWithDefaults := func() *File {
-		f := NewFile()
-		for cell, val := range cells {
-			f.SetCellStr(sheet, cell, val)
-
-		}
-		return f
-	}
-
 	t.Run("FromSingleRow", func(t *testing.T) {
 		xlsx := NewFile()
 		xlsx.SetCellStr(sheet, "A1", cells["A1"])
@@ -273,6 +269,20 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
 
 	t.Run("UpdateDuplicatedRows", func(t *testing.T) {
 		xlsx := NewFile()
@@ -299,6 +309,29 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
+
+	newFileWithDefaults := func() *File {
+		f := NewFile()
+		for cell, val := range cells {
+			f.SetCellStr(sheet, cell, val)
+
+		}
+		return f
+	}
 
 	t.Run("FirstOfMultipleRows", func(t *testing.T) {
 		xlsx := newFileWithDefaults()
@@ -322,6 +355,11 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowZeroWithNoRows(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
 
 	t.Run("ZeroWithNoRows", func(t *testing.T) {
 		xlsx := NewFile()
@@ -359,6 +397,11 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
 
 	t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
 		xlsx := NewFile()
@@ -381,6 +424,29 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
+
+	newFileWithDefaults := func() *File {
+		f := NewFile()
+		for cell, val := range cells {
+			f.SetCellStr(sheet, cell, val)
+
+		}
+		return f
+	}
 
 	t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
 		xlsx := newFileWithDefaults()
@@ -404,6 +470,29 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
+
+	newFileWithDefaults := func() *File {
+		f := NewFile()
+		for cell, val := range cells {
+			f.SetCellStr(sheet, cell, val)
+
+		}
+		return f
+	}
 
 	t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
 		xlsx := newFileWithDefaults()
@@ -427,6 +516,29 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowInsertBefore(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
+
+	newFileWithDefaults := func() *File {
+		f := NewFile()
+		for cell, val := range cells {
+			f.SetCellStr(sheet, cell, val)
+
+		}
+		return f
+	}
 
 	t.Run("InsertBefore", func(t *testing.T) {
 		xlsx := newFileWithDefaults()
@@ -451,6 +563,29 @@ func TestDuplicateRow(t *testing.T) {
 			}
 		}
 	})
+}
+
+func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
+	const sheet = "Sheet1"
+	outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
+
+	cells := map[string]string{
+		"A1": "A1 Value",
+		"A2": "A2 Value",
+		"A3": "A3 Value",
+		"B1": "B1 Value",
+		"B2": "B2 Value",
+		"B3": "B3 Value",
+	}
+
+	newFileWithDefaults := func() *File {
+		f := NewFile()
+		for cell, val := range cells {
+			f.SetCellStr(sheet, cell, val)
+
+		}
+		return f
+	}
 
 	t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
 		xlsx := newFileWithDefaults()

+ 7 - 7
sheet.go

@@ -684,15 +684,16 @@ func (f *File) GetSheetVisible(name string) bool {
 //    result, err := xlsx.SearchSheet("Sheet1", "[0-9]", true)
 //
 func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
-	var regSearch bool
+	var (
+		regSearch bool
+		result    []string
+		inElement string
+		r         xlsxRow
+	)
 	for _, r := range reg {
 		regSearch = r
 	}
 
-	var (
-		result []string
-	)
-
 	xlsx, err := f.workSheetReader(sheet)
 	if err != nil {
 		return result, err
@@ -708,8 +709,7 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
 	}
 	xml.NewDecoder(bytes.NewReader(f.readXML(name)))
 	d := f.sharedStringsReader()
-	var inElement string
-	var r xlsxRow
+
 	decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
 	for {
 		token, _ := decoder.Token()

+ 21 - 29
sheet_test.go

@@ -11,7 +11,6 @@ import (
 
 func ExampleFile_SetPageLayout() {
 	xl := excelize.NewFile()
-	const sheet = "Sheet1"
 
 	if err := xl.SetPageLayout(
 		"Sheet1",
@@ -30,7 +29,6 @@ func ExampleFile_SetPageLayout() {
 
 func ExampleFile_GetPageLayout() {
 	xl := excelize.NewFile()
-	const sheet = "Sheet1"
 	var (
 		orientation excelize.PageLayoutOrientation
 		paperSize   excelize.PageLayoutPaperSize
@@ -73,38 +71,24 @@ func TestPageLayoutOption(t *testing.T) {
 
 			xl := excelize.NewFile()
 			// Get the default value
-			if !assert.NoError(t, xl.GetPageLayout(sheet, def), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetPageLayout(sheet, def), opt)
 			// Get again and check
-			if !assert.NoError(t, xl.GetPageLayout(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetPageLayout(sheet, val1), opt)
 			if !assert.Equal(t, val1, def, opt) {
 				t.FailNow()
 			}
 			// Set the same value
-			if !assert.NoError(t, xl.SetPageLayout(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetPageLayout(sheet, val1), opt)
 			// Get again and check
-			if !assert.NoError(t, xl.GetPageLayout(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetPageLayout(sheet, val1), opt)
 			if !assert.Equal(t, val1, def, "%T: value should not have changed", opt) {
 				t.FailNow()
 			}
 			// Set a different value
-			if !assert.NoError(t, xl.SetPageLayout(sheet, test.nonDefault), opt) {
-				t.FailNow()
-			}
-			if !assert.NoError(t, xl.GetPageLayout(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetPageLayout(sheet, test.nonDefault), opt)
+			assert.NoError(t, xl.GetPageLayout(sheet, val1), opt)
 			// Get again and compare
-			if !assert.NoError(t, xl.GetPageLayout(sheet, val2), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetPageLayout(sheet, val2), opt)
 			if !assert.Equal(t, val1, val2, "%T: value should not have changed", opt) {
 				t.FailNow()
 			}
@@ -113,15 +97,23 @@ func TestPageLayoutOption(t *testing.T) {
 				t.FailNow()
 			}
 			// Restore the default value
-			if !assert.NoError(t, xl.SetPageLayout(sheet, def), opt) {
-				t.FailNow()
-			}
-			if !assert.NoError(t, xl.GetPageLayout(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetPageLayout(sheet, def), opt)
+			assert.NoError(t, xl.GetPageLayout(sheet, val1), opt)
 			if !assert.Equal(t, def, val1) {
 				t.FailNow()
 			}
 		})
 	}
 }
+
+func TestSetPageLayout(t *testing.T) {
+	f := excelize.NewFile()
+	// Test set page layout on not exists worksheet.
+	assert.EqualError(t, f.SetPageLayout("SheetN"), "sheet SheetN is not exist")
+}
+
+func TestGetPageLayout(t *testing.T) {
+	f := excelize.NewFile()
+	// Test get page layout on not exists worksheet.
+	assert.EqualError(t, f.GetPageLayout("SheetN"), "sheet SheetN is not exist")
+}

+ 9 - 27
sheetpr_test.go

@@ -112,38 +112,24 @@ func TestSheetPrOptions(t *testing.T) {
 
 			xl := excelize.NewFile()
 			// Get the default value
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, def), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, def), opt)
 			// Get again and check
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt)
 			if !assert.Equal(t, val1, def, opt) {
 				t.FailNow()
 			}
 			// Set the same value
-			if !assert.NoError(t, xl.SetSheetPrOptions(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetSheetPrOptions(sheet, val1), opt)
 			// Get again and check
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt)
 			if !assert.Equal(t, val1, def, "%T: value should not have changed", opt) {
 				t.FailNow()
 			}
 			// Set a different value
-			if !assert.NoError(t, xl.SetSheetPrOptions(sheet, test.nonDefault), opt) {
-				t.FailNow()
-			}
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetSheetPrOptions(sheet, test.nonDefault), opt)
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt)
 			// Get again and compare
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, val2), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, val2), opt)
 			if !assert.Equal(t, val1, val2, "%T: value should not have changed", opt) {
 				t.FailNow()
 			}
@@ -152,12 +138,8 @@ func TestSheetPrOptions(t *testing.T) {
 				t.FailNow()
 			}
 			// Restore the default value
-			if !assert.NoError(t, xl.SetSheetPrOptions(sheet, def), opt) {
-				t.FailNow()
-			}
-			if !assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt) {
-				t.FailNow()
-			}
+			assert.NoError(t, xl.SetSheetPrOptions(sheet, def), opt)
+			assert.NoError(t, xl.GetSheetPrOptions(sheet, val1), opt)
 			if !assert.Equal(t, def, val1) {
 				t.FailNow()
 			}

+ 0 - 2
styles_test.go

@@ -23,8 +23,6 @@ func TestStyleFill(t *testing.T) {
 
 	for _, testCase := range cases {
 		xl := NewFile()
-		const sheet = "Sheet1"
-
 		styleID, err := xl.NewStyle(testCase.format)
 		if err != nil {
 			t.Fatalf("%v", err)