Просмотр исходного кода

- API changed, use worksheet name instead of "sheet" + index, related issue #25, #43, #47, #51, #89, #101, #116 and #120.
- go test updated

Ri Xu 8 лет назад
Родитель
Сommit
f05f799f8d
11 измененных файлов с 159 добавлено и 145 удалено
  1. 8 10
      README.md
  2. 1 1
      cell.go
  3. 2 2
      col.go
  4. 10 4
      excelize.go
  5. 58 56
      excelize_test.go
  6. 12 3
      file.go
  7. 7 7
      picture.go
  8. 7 12
      rows.go
  9. 47 42
      sheet.go
  10. 2 3
      styles.go
  11. 5 5
      table.go

+ 8 - 10
README.md

@@ -38,12 +38,12 @@ import (
 func main() {
     xlsx := excelize.NewFile()
     // Create a new sheet.
-    xlsx.NewSheet(2, "Sheet2")
+    index := xlsx.NewSheet("Sheet2")
     // Set value of a cell.
     xlsx.SetCellValue("Sheet2", "A2", "Hello world.")
     xlsx.SetCellValue("Sheet1", "B2", 100)
     // Set active sheet of the workbook.
-    xlsx.SetActiveSheet(2)
+    xlsx.SetActiveSheet(index)
     // Save xlsx file by the given path.
     err := xlsx.SaveAs("./Workbook.xlsx")
     if err != nil {
@@ -63,7 +63,6 @@ package main
 import (
     "fmt"
     "os"
-    "strconv"
 
     "github.com/xuri/excelize"
 )
@@ -74,13 +73,11 @@ func main() {
         fmt.Println(err)
         os.Exit(1)
     }
-    // Get value from cell by given sheet index and axis.
+    // Get value from cell by given worksheet name and axis.
     cell := xlsx.GetCellValue("Sheet1", "B2")
     fmt.Println(cell)
-    // Get sheet index.
-    index := xlsx.GetSheetIndex("Sheet2")
-    // Get all the rows in a sheet.
-    rows := xlsx.GetRows("sheet" + strconv.Itoa(index))
+    // Get all the rows in the Sheet1.
+    rows := xlsx.GetRows("Sheet1")
     for _, row := range rows {
         for _, colCell := range row {
             fmt.Print(colCell, "\t")
@@ -88,11 +85,12 @@ func main() {
         fmt.Println()
     }
 }
+
 ```
 
 ### Add chart to XLSX file
 
-With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your sheet at all.
+With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all.
 
 ![Excelize](./test/images/chart.png "Excelize")
 
@@ -152,7 +150,7 @@ func main() {
     if err != nil {
         fmt.Println(err)
     }
-    // Insert a picture to sheet with scaling.
+    // Insert a picture to worksheet with scaling.
     err = xlsx.AddPicture("Sheet1", "D2", "./image2.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`)
     if err != nil {
         fmt.Println(err)

+ 1 - 1
cell.go

@@ -263,7 +263,7 @@ func (f *File) GetCellHyperLink(sheet, axis string) (bool, string) {
 // MergeCell provides function to merge cells by given coordinate area and sheet
 // name. For example create a merged cell of D3:E9 on Sheet1:
 //
-//    xlsx.MergeCell("sheet1", "D3", "E9")
+//    xlsx.MergeCell("Sheet1", "D3", "E9")
 //
 // If you create a merged cell that overlaps with another existing merged cell,
 // those merged cells that already exist will be removed.

+ 2 - 2
col.go

@@ -225,7 +225,7 @@ func (f *File) getColWidth(sheet string, col int) int {
 	return int(defaultColWidthPixels)
 }
 
-// GetColWidth provides function to get column width by given sheet name and
+// GetColWidth provides function to get column width by given worksheet name and
 // column index.
 func (f *File) GetColWidth(sheet, column string) float64 {
 	col := TitleToNumber(strings.ToUpper(column)) + 1
@@ -255,7 +255,7 @@ func (f *File) InsertCol(sheet, column string) {
 	f.adjustHelper(sheet, col, -1, 1)
 }
 
-// RemoveCol provides function to remove single column by given worksheet index
+// RemoveCol provides function to remove single column by given worksheet name
 // and column index. For example, remove column C in Sheet1:
 //
 //    xlsx.RemoveCol("Sheet1", "C")

+ 10 - 4
excelize.go

@@ -14,6 +14,7 @@ import (
 // File define a populated XLSX file struct.
 type File struct {
 	checked       map[string]bool
+	sheetMap      map[string]string
 	ContentTypes  *xlsxTypes
 	Path          string
 	SharedStrings *xlsxSST
@@ -38,6 +39,8 @@ func OpenFile(filename string) (*File, error) {
 		return nil, err
 	}
 	f.Path = filename
+	f.sheetMap = f.getSheetMap()
+	f.Styles = f.stylesReader()
 	return f, nil
 }
 
@@ -77,7 +80,10 @@ func (f *File) setDefaultTimeStyle(sheet, axis string) {
 // workSheetReader provides function to get the pointer to the structure after
 // deserialization by given worksheet index.
 func (f *File) workSheetReader(sheet string) *xlsxWorksheet {
-	name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
+	name, ok := f.sheetMap[sheet]
+	if !ok {
+		name = "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
+	}
 	if f.Sheet[name] == nil {
 		var xlsx xlsxWorksheet
 		xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
@@ -159,8 +165,8 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string {
 //    </row>
 //
 func (f *File) UpdateLinkedValue() {
-	for i := 1; i <= f.SheetCount; i++ {
-		xlsx := f.workSheetReader("sheet" + strconv.Itoa(i))
+	for _, name := range f.GetSheetMap() {
+		xlsx := f.workSheetReader(name)
 		for indexR, row := range xlsx.SheetData.Row {
 			for indexC, col := range row.C {
 				if col.F != nil && col.V != "" {
@@ -176,7 +182,7 @@ func (f *File) UpdateLinkedValue() {
 // hyperlinks, merged cells and auto filter when inserting or deleting rows or
 // columns.
 //
-// sheet: Worksheet index that we're editing
+// sheet: Worksheet name that we're editing
 // column: Index number of the column we're inserting/deleting before
 // row: Index number of the row we're inserting/deleting before
 // offset: Number of rows/column to insert/delete negative values indicate deletion

+ 58 - 56
excelize_test.go

@@ -18,9 +18,9 @@ func TestOpenFile(t *testing.T) {
 	if err != nil {
 		t.Log(err)
 	}
-	// Test get all the rows in a not exists sheet.
+	// Test get all the rows in a not exists worksheet.
 	rows := xlsx.GetRows("Sheet4")
-	// Test get all the rows in a sheet.
+	// Test get all the rows in a worksheet.
 	rows = xlsx.GetRows("Sheet2")
 	for _, row := range rows {
 		for _, cell := range row {
@@ -29,21 +29,22 @@ func TestOpenFile(t *testing.T) {
 		t.Log("\r\n")
 	}
 	xlsx.UpdateLinkedValue()
-	xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
-	xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
-	xlsx.SetCellInt("SHEET2", "A1", 100)
-	xlsx.SetCellStr("SHEET2", "C11", "Knowns")
+	xlsx.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
+	xlsx.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
+	xlsx.SetCellInt("Sheet2", "A1", 100)
+	xlsx.SetCellStr("Sheet2", "C11", "Knowns")
+
 	// Test max characters in a cell.
-	xlsx.SetCellStr("SHEET2", "D11", strings.Repeat("c", 32769))
-	xlsx.NewSheet(3, ":\\/?*[]Maximum 31 characters allowed in sheet title.")
-	// Test set sheet name with illegal name.
+	xlsx.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769))
+	xlsx.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
+	// Test set worksheet name with illegal name.
 	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")
-	xlsx.SetCellStr("SHEET10", "b230", "10")
+	xlsx.SetCellStr("Sheet3", "b230", "10")
+	xlsx.SetCellStr("Sheet10", "b230", "10")
 	xlsx.SetActiveSheet(2)
 	xlsx.GetCellFormula("Sheet1", "B19") // Test get cell formula with given rows number.
-	xlsx.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal sheet index.
+	xlsx.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal worksheet index.
 	xlsx.GetCellFormula("Sheet1", "B20") // Test get cell formula with illegal rows number.
 	// Test read cell value with given illegal rows number.
 	xlsx.GetCellValue("Sheet2", "a-1")
@@ -71,16 +72,16 @@ func TestOpenFile(t *testing.T) {
 	xlsx.SetCellValue("Sheet2", "M2", nil)
 	// Test read cell value with given axis large than exists row.
 	xlsx.GetCellValue("Sheet2", "E231")
-	// Test get active sheet of XLSX and get sheet name of XLSX by given sheet index.
+	// Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index.
 	xlsx.GetSheetName(xlsx.GetActiveSheetIndex())
-	// Test get sheet index of XLSX by given worksheet name.
+	// Test get worksheet index of XLSX by given worksheet name.
 	xlsx.GetSheetIndex("Sheet1")
-	// Test get sheet name of XLSX by given invalid sheet index.
+	// Test get worksheet name of XLSX by given invalid worksheet index.
 	xlsx.GetSheetName(4)
-	// Test get sheet map of XLSX.
+	// Test get worksheet map of XLSX.
 	xlsx.GetSheetMap()
 	for i := 1; i <= 300; i++ {
-		xlsx.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
+		xlsx.SetCellStr("Sheet3", "c"+strconv.Itoa(i), strconv.Itoa(i))
 	}
 	err = xlsx.Save()
 	if err != nil {
@@ -91,6 +92,7 @@ func TestOpenFile(t *testing.T) {
 	if err != nil {
 		t.Log(err)
 	}
+
 }
 
 func TestAddPicture(t *testing.T) {
@@ -156,10 +158,10 @@ func TestBrokenFile(t *testing.T) {
 func TestNewFile(t *testing.T) {
 	// Test create a XLSX file.
 	xlsx := NewFile()
-	xlsx.NewSheet(2, "XLSXSheet2")
-	xlsx.NewSheet(3, "XLSXSheet3")
-	xlsx.SetCellInt("Sheet2", "A23", 56)
-	xlsx.SetCellStr("SHEET1", "B20", "42")
+	xlsx.NewSheet("XLSXSheet2")
+	xlsx.NewSheet("XLSXSheet3")
+	xlsx.SetCellInt("XLSXSheet2", "A23", 56)
+	xlsx.SetCellStr("Sheet1", "B20", "42")
 	xlsx.SetActiveSheet(0)
 	// Test add picture to sheet with scaling.
 	err := xlsx.AddPicture("Sheet1", "H2", "./test/images/excel.gif", `{"x_scale": 0.5, "y_scale": 0.5}`)
@@ -178,10 +180,10 @@ func TestNewFile(t *testing.T) {
 
 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")
+	xlsx.SetColWidth("Sheet1", "B", "A", 12)
+	xlsx.SetColWidth("Sheet1", "A", "B", 12)
+	xlsx.GetColWidth("Sheet1", "A")
+	xlsx.GetColWidth("Sheet1", "C")
 	err := xlsx.SaveAs("./test/Workbook_4.xlsx")
 	if err != nil {
 		t.Log(err)
@@ -208,13 +210,13 @@ func TestSetCellHyperLink(t *testing.T) {
 		t.Log(err)
 	}
 	// Test set cell hyperlink in a work sheet already have hyperlinks.
-	xlsx.SetCellHyperLink("sheet1", "B19", "https://github.com/xuri/excelize", "External")
+	xlsx.SetCellHyperLink("Sheet1", "B19", "https://github.com/xuri/excelize", "External")
 	// Test add first hyperlink in a work sheet.
-	xlsx.SetCellHyperLink("sheet2", "C1", "https://github.com/xuri/excelize", "External")
+	xlsx.SetCellHyperLink("Sheet2", "C1", "https://github.com/xuri/excelize", "External")
 	// Test add Location hyperlink in a work sheet.
-	xlsx.SetCellHyperLink("sheet2", "D6", "Sheet1!D8", "Location")
-	xlsx.SetCellHyperLink("sheet2", "C3", "Sheet1!D8", "")
-	xlsx.SetCellHyperLink("sheet2", "", "Sheet1!D60", "Location")
+	xlsx.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location")
+	xlsx.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", "")
+	xlsx.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location")
 	err = xlsx.Save()
 	if err != nil {
 		t.Log(err)
@@ -241,8 +243,8 @@ func TestSetCellFormula(t *testing.T) {
 	if err != nil {
 		t.Log(err)
 	}
-	xlsx.SetCellFormula("sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
-	xlsx.SetCellFormula("sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
+	xlsx.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
+	xlsx.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
 	err = xlsx.Save()
 	if err != nil {
 		t.Log(err)
@@ -254,19 +256,19 @@ func TestSetSheetBackground(t *testing.T) {
 	if err != nil {
 		t.Log(err)
 	}
-	err = xlsx.SetSheetBackground("sheet2", "./test/images/background.png")
+	err = xlsx.SetSheetBackground("Sheet2", "./test/images/background.png")
 	if err != nil {
 		t.Log(err)
 	}
-	err = xlsx.SetSheetBackground("sheet2", "./test/Workbook1.xlsx")
+	err = xlsx.SetSheetBackground("Sheet2", "./test/Workbook1.xlsx")
 	if err != nil {
 		t.Log(err)
 	}
-	err = xlsx.SetSheetBackground("sheet2", "./test/images/background.jpg")
+	err = xlsx.SetSheetBackground("Sheet2", "./test/images/background.jpg")
 	if err != nil {
 		t.Log(err)
 	}
-	err = xlsx.SetSheetBackground("sheet2", "./test/images/background.jpg")
+	err = xlsx.SetSheetBackground("Sheet2", "./test/images/background.jpg")
 	if err != nil {
 		t.Log(err)
 	}
@@ -674,8 +676,8 @@ func TestCopySheet(t *testing.T) {
 	if err != nil {
 		t.Log(err)
 	}
-	xlsx.NewSheet(4, "CopySheet")
-	err = xlsx.CopySheet(1, 4)
+	idx := xlsx.NewSheet("CopySheet")
+	err = xlsx.CopySheet(1, idx)
 	if err != nil {
 		t.Log(err)
 	}
@@ -784,14 +786,14 @@ func TestAddChart(t *testing.T) {
 	for k, v := range values {
 		xlsx.SetCellValue("Sheet1", k, v)
 	}
-	xlsx.AddChart("SHEET1", "P1", `{"type":"bar3D","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 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", "X1", `{"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 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", "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("SHEET1", "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("SHEET1", "P30", `{"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("SHEET1", "X30", `{"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", "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("Sheet1", "P1", `{"type":"bar3D","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 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", "X1", `{"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 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", "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("Sheet1", "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("Sheet1", "P30", `{"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("Sheet1", "X30", `{"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", "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"}`)
 	// Save xlsx file by the given path.
 	err = xlsx.SaveAs("./test/Workbook_addchart.xlsx")
 	if err != nil {
@@ -808,7 +810,7 @@ func TestInsertCol(t *testing.T) {
 		}
 	}
 	xlsx.SetCellHyperLink("Sheet1", "A5", "https://github.com/xuri/excelize", "External")
-	xlsx.MergeCell("sheet1", "A1", "C3")
+	xlsx.MergeCell("Sheet1", "A1", "C3")
 	err := xlsx.AutoFilter("Sheet1", "A2", "B2", `{"column":"B","expression":"x != blanks"}`)
 	t.Log(err)
 	xlsx.InsertCol("Sheet1", "A")
@@ -828,8 +830,8 @@ func TestRemoveCol(t *testing.T) {
 	}
 	xlsx.SetCellHyperLink("Sheet1", "A5", "https://github.com/xuri/excelize", "External")
 	xlsx.SetCellHyperLink("Sheet1", "C5", "https://github.com", "External")
-	xlsx.MergeCell("sheet1", "A1", "B1")
-	xlsx.MergeCell("sheet1", "A2", "B2")
+	xlsx.MergeCell("Sheet1", "A1", "B1")
+	xlsx.MergeCell("Sheet1", "A2", "B2")
 	xlsx.RemoveCol("Sheet1", "A")
 	xlsx.RemoveCol("Sheet1", "A")
 	err := xlsx.SaveAs("./test/Workbook_removecol.xlsx")
@@ -858,12 +860,12 @@ func TestInsertRow(t *testing.T) {
 func TestSetPane(t *testing.T) {
 	xlsx := NewFile()
 	xlsx.SetPanes("Sheet1", `{"freeze":false,"split":false}`)
-	xlsx.NewSheet(2, "Panes 2")
-	xlsx.SetPanes("Sheet2", `{"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"}]}`)
-	xlsx.NewSheet(3, "Panes 3")
-	xlsx.SetPanes("Sheet3", `{"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"}]}`)
-	xlsx.NewSheet(4, "Panes 4")
-	xlsx.SetPanes("Sheet4", `{"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"}]}`)
+	xlsx.NewSheet("Panes 2")
+	xlsx.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"}]}`)
+	xlsx.NewSheet("Panes 3")
+	xlsx.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"}]}`)
+	xlsx.NewSheet("Panes 4")
+	xlsx.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"}]}`)
 	err := xlsx.SaveAs("./test/Workbook_set_panes.xlsx")
 	if err != nil {
 		t.Log(err)
@@ -881,7 +883,7 @@ func TestRemoveRow(t *testing.T) {
 	xlsx.SetCellHyperLink("Sheet1", "A5", "https://github.com/xuri/excelize", "External")
 	xlsx.RemoveRow("Sheet1", -1)
 	xlsx.RemoveRow("Sheet1", 4)
-	xlsx.MergeCell("sheet1", "B3", "B5")
+	xlsx.MergeCell("Sheet1", "B3", "B5")
 	xlsx.RemoveRow("Sheet1", 2)
 	xlsx.RemoveRow("Sheet1", 4)
 	err := xlsx.AutoFilter("Sheet1", "A2", "A2", `{"column":"A","expression":"x != blanks"}`)

+ 12 - 3
file.go

@@ -24,10 +24,19 @@ func NewFile() *File {
 	file["xl/styles.xml"] = XMLHeader + templateStyles
 	file["xl/workbook.xml"] = XMLHeader + templateWorkbook
 	file["[Content_Types].xml"] = XMLHeader + templateContentTypes
-	return &File{
-		Sheet: make(map[string]*xlsxWorksheet),
-		XLSX:  file,
+	f := &File{
+		sheetMap:   make(map[string]string),
+		Sheet:      make(map[string]*xlsxWorksheet),
+		SheetCount: 1,
+		XLSX:       file,
 	}
+	f.ContentTypes = f.contentTypesReader()
+	f.Styles = f.stylesReader()
+	f.WorkBook = f.workbookReader()
+	f.WorkBookRels = f.workbookRelsReader()
+	f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1")
+	f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml"
+	return f
 }
 
 // Save provides function to override the xlsx file with origin path.

+ 7 - 7
picture.go

@@ -99,8 +99,8 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
 }
 
 // addSheetRelationships provides function to add
-// xl/worksheets/_rels/sheet%d.xml.rels by given sheet name, relationship type
-// and target.
+// xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name, relationship
+// type and target.
 func (f *File) addSheetRelationships(sheet, relType, target, targetMode string) int {
 	var rels = "xl/worksheets/_rels/" + strings.ToLower(sheet) + ".xml.rels"
 	var sheetRels xlsxWorkbookRels
@@ -128,7 +128,7 @@ func (f *File) addSheetRelationships(sheet, relType, target, targetMode string)
 }
 
 // deleteSheetRelationships provides function to delete relationships in
-// xl/worksheets/_rels/sheet%d.xml.rels by given sheet name and relationship
+// xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name and relationship
 // index.
 func (f *File) deleteSheetRelationships(sheet, rID string) {
 	var rels = "xl/worksheets/_rels/" + strings.ToLower(sheet) + ".xml.rels"
@@ -145,7 +145,7 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
 }
 
 // addSheetLegacyDrawing provides function to add legacy drawing element to
-// xl/worksheets/sheet%d.xml by given sheet name and relationship index.
+// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
 func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
 	xlsx := f.workSheetReader(sheet)
 	xlsx.LegacyDrawing = &xlsxLegacyDrawing{
@@ -154,7 +154,7 @@ func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
 }
 
 // addSheetDrawing provides function to add drawing element to
-// xl/worksheets/sheet%d.xml by given sheet name and relationship index.
+// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
 func (f *File) addSheetDrawing(sheet string, rID int) {
 	xlsx := f.workSheetReader(sheet)
 	xlsx.Drawing = &xlsxDrawing{
@@ -163,7 +163,7 @@ func (f *File) addSheetDrawing(sheet string, rID int) {
 }
 
 // addSheetPicture provides function to add picture element to
-// xl/worksheets/sheet%d.xml by given sheet name and relationship index.
+// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
 func (f *File) addSheetPicture(sheet string, rID int) {
 	xlsx := f.workSheetReader(sheet)
 	xlsx.Picture = &xlsxPicture{
@@ -356,7 +356,7 @@ func (f *File) addContentTypePart(index int, contentType string) {
 }
 
 // getSheetRelationshipsTargetByID provides function to get Target attribute
-// value in xl/worksheets/_rels/sheet%d.xml.rels by given sheet name and
+// value in xl/worksheets/_rels/sheet%d.xml.rels by given worksheet name and
 // relationship index.
 func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
 	var rels = "xl/worksheets/_rels/" + strings.ToLower(sheet) + ".xml.rels"

+ 7 - 12
rows.go

@@ -8,15 +8,10 @@ import (
 	"strings"
 )
 
-// GetRows return all the rows in a sheet by given "sheet" + index. For now you
-// should use sheet_name like "sheet3" where "sheet" is a constant part and "3"
-// is a sheet number. For example, if sheet named as "SomeUniqueData" and it is
-// second if spreadsheet program interface - you should use "sheet2" here. For
-// example:
+// GetRows return all the rows in a sheet by given worksheet name (case
+// sensitive). For example:
 //
-//    index := xlsx.GetSheetIndex("Sheet2")
-//    rows := xlsx.GetRows("sheet" + strconv.Itoa(index))
-//    for _, row := range rows {
+//    for _, row := range xlsx.GetRows("Sheet1") {
 //        for _, colCell := range row {
 //            fmt.Print(colCell, "\t")
 //        }
@@ -70,7 +65,7 @@ func (f *File) GetRows(sheet string) [][]string {
 }
 
 // getTotalRowsCols provides a function to get total columns and rows in a
-// sheet.
+// worksheet.
 func (f *File) getTotalRowsCols(sheet string) (int, int) {
 	name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
 	decoder := xml.NewDecoder(strings.NewReader(f.readXML(name)))
@@ -182,7 +177,7 @@ func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
 }
 
 // SetRowVisible provides a function to set visible of a single row by given
-// worksheet index and row index. For example, hide row 3 in Sheet1:
+// worksheet name and row index. For example, hide row 3 in Sheet1:
 //
 //    xlsx.SetRowVisible("Sheet1", 2, false)
 //
@@ -199,7 +194,7 @@ func (f *File) SetRowVisible(sheet string, rowIndex int, visible bool) {
 }
 
 // GetRowVisible provides a function to get visible of a single row by given
-// worksheet index and row index. For example, get visible state of row 3 in
+// worksheet name and row index. For example, get visible state of row 3 in
 // Sheet1:
 //
 //    xlsx.GetRowVisible("Sheet1", 2)
@@ -212,7 +207,7 @@ func (f *File) GetRowVisible(sheet string, rowIndex int) bool {
 	return !xlsx.SheetData.Row[rowIndex].Hidden
 }
 
-// RemoveRow provides function to remove single row by given worksheet index and
+// RemoveRow provides function to remove single row by given worksheet name and
 // row index. For example, remove row 3 in Sheet1:
 //
 //    xlsx.RemoveRow("Sheet1", 2)

+ 47 - 42
sheet.go

@@ -14,19 +14,20 @@ import (
 
 // NewSheet provides function to create a new sheet by given index, when
 // creating a new XLSX file, the default sheet will be create, when you create a
-// new file, you need to ensure that the index is continuous.
-func (f *File) NewSheet(index int, name string) {
+// new file.
+func (f *File) NewSheet(name string) int {
+	f.SheetCount++
 	// Update docProps/app.xml
 	f.setAppXML()
 	// Update [Content_Types].xml
-	f.setContentTypes(index)
+	f.setContentTypes(f.SheetCount)
 	// Create new sheet /xl/worksheets/sheet%d.xml
-	f.setSheet(index)
+	f.setSheet(f.SheetCount, name)
 	// Update xl/_rels/workbook.xml.rels
-	rID := f.addXlsxWorkbookRels(index)
+	rID := f.addXlsxWorkbookRels(f.SheetCount)
 	// Update xl/workbook.xml
 	f.setWorkbook(name, rID)
-	f.SheetCount++
+	return f.SheetCount
 }
 
 // contentTypesReader provides function to get the pointer to the
@@ -109,23 +110,23 @@ func (f *File) setContentTypes(index int) {
 }
 
 // Update sheet property by given index.
-func (f *File) setSheet(index int) {
+func (f *File) setSheet(index int, name string) {
 	var xlsx xlsxWorksheet
 	xlsx.Dimension.Ref = "A1"
 	xlsx.SheetViews.SheetView = append(xlsx.SheetViews.SheetView, xlsxSheetView{
 		WorkbookViewID: 0,
 	})
 	path := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
+	f.sheetMap[trimSheetName(name)] = path
 	f.Sheet[path] = &xlsx
 }
 
 // setWorkbook update workbook property of XLSX. Maximum 31 characters are
 // allowed in sheet title.
 func (f *File) setWorkbook(name string, rid int) {
-	name = trimSheetName(name)
 	content := f.workbookReader()
 	content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
-		Name:    name,
+		Name:    trimSheetName(name),
 		SheetID: strconv.Itoa(rid),
 		ID:      "rId" + strconv.Itoa(rid),
 	})
@@ -210,12 +211,10 @@ func (f *File) SetActiveSheet(index int) {
 			ActiveTab: index,
 		})
 	}
-	sheets := len(content.Sheets.Sheet)
 	index++
-	for i := 0; i < sheets; i++ {
-		sheetIndex := i + 1
-		xlsx := f.workSheetReader("sheet" + strconv.Itoa(sheetIndex))
-		if index == sheetIndex {
+	for idx, name := range f.GetSheetMap() {
+		xlsx := f.workSheetReader(name)
+		if index == idx {
 			if len(xlsx.SheetViews.SheetView) > 0 {
 				xlsx.SheetViews.SheetView[0].TabSelected = true
 			} else {
@@ -254,8 +253,8 @@ func (f *File) GetActiveSheetIndex() int {
 	return 0
 }
 
-// SetSheetName provides function to set the sheet name be given old and new
-// sheet name. Maximum 31 characters are allowed in sheet title and this
+// SetSheetName provides function to set the worksheet name be given old and new
+// worksheet name. Maximum 31 characters are allowed in sheet title and this
 // function only changes the name of the sheet and will not update the sheet
 // name in the formula or reference associated with the cell. So there may be
 // problem formula error or reference missing.
@@ -266,12 +265,15 @@ func (f *File) SetSheetName(oldName, newName string) {
 	for k, v := range content.Sheets.Sheet {
 		if v.Name == oldName {
 			content.Sheets.Sheet[k].Name = newName
+			f.sheetMap[newName] = f.sheetMap[oldName]
+			delete(f.sheetMap, oldName)
 		}
 	}
 }
 
-// GetSheetName provides function to get sheet name of XLSX by given worksheet
-// index. If given sheet index is invalid, will return an empty string.
+// GetSheetName provides function to get worksheet name of XLSX by given
+// worksheet index. If given sheet index is invalid, will return an empty
+// string.
 func (f *File) GetSheetName(index int) string {
 	content := f.workbookReader()
 	rels := f.workbookRelsReader()
@@ -289,7 +291,8 @@ func (f *File) GetSheetName(index int) string {
 }
 
 // GetSheetIndex provides function to get worksheet index of XLSX by given sheet
-// name. If given sheet name is invalid, will return an integer type value 0.
+// name. If given worksheet name is invalid, will return an integer type value
+// 0.
 func (f *File) GetSheetIndex(name string) int {
 	content := f.workbookReader()
 	rels := f.workbookRelsReader()
@@ -306,15 +309,16 @@ func (f *File) GetSheetIndex(name string) int {
 	return 0
 }
 
-// GetSheetMap provides function to get sheet map of XLSX. For example:
+// GetSheetMap provides function to get worksheet name and index map of XLSX.
+// For example:
 //
 //    xlsx, err := excelize.OpenFile("./Workbook.xlsx")
 //    if err != nil {
 //        fmt.Println(err)
 //        os.Exit(1)
 //    }
-//    for k, v := range xlsx.GetSheetMap() {
-//        fmt.Println(k, v)
+//    for index, name := range xlsx.GetSheetMap() {
+//        fmt.Println(index, name)
 //    }
 //
 func (f *File) GetSheetMap() map[int]string {
@@ -332,6 +336,16 @@ func (f *File) GetSheetMap() map[int]string {
 	return sheetMap
 }
 
+// getSheetMap provides function to get worksheet name and XML file path map of
+// XLSX.
+func (f *File) getSheetMap() map[string]string {
+	maps := make(map[string]string)
+	for idx, name := range f.GetSheetMap() {
+		maps[name] = "xl/worksheets/sheet" + strconv.Itoa(idx) + ".xml"
+	}
+	return maps
+}
+
 // SetSheetBackground provides function to set background picture by given sheet
 // index.
 func (f *File) SetSheetBackground(sheet, picture string) error {
@@ -353,14 +367,14 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
 }
 
 // DeleteSheet provides function to delete worksheet in a workbook by given
-// sheet name. Use this method with caution, which will affect changes in
+// worksheet name. Use this method with caution, which will affect changes in
 // references such as formulas, charts, and so on. If there is any referenced
 // value of the deleted worksheet, it will cause a file error when you open it.
 // This function will be invalid when only the one worksheet is left.
 func (f *File) DeleteSheet(name string) {
 	content := f.workbookReader()
 	for k, v := range content.Sheets.Sheet {
-		if v.Name != name || len(content.Sheets.Sheet) < 2 {
+		if v.Name != trimSheetName(name) || len(content.Sheets.Sheet) < 2 {
 			continue
 		}
 		content.Sheets.Sheet = append(content.Sheets.Sheet[:k], content.Sheets.Sheet[k+1:]...)
@@ -368,18 +382,10 @@ func (f *File) DeleteSheet(name string) {
 		rels := "xl/worksheets/_rels/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml.rels"
 		target := f.deleteSheetFromWorkbookRels(v.ID)
 		f.deleteSheetFromContentTypes(target)
-		_, ok := f.XLSX[sheet]
-		if ok {
-			delete(f.XLSX, sheet)
-		}
-		_, ok = f.XLSX[rels]
-		if ok {
-			delete(f.XLSX, rels)
-		}
-		_, ok = f.Sheet[sheet]
-		if ok {
-			delete(f.Sheet, sheet)
-		}
+		delete(f.sheetMap, name)
+		delete(f.XLSX, sheet)
+		delete(f.XLSX, rels)
+		delete(f.Sheet, sheet)
 		f.SheetCount--
 	}
 }
@@ -416,8 +422,8 @@ func (f *File) deleteSheetFromContentTypes(target string) {
 // workbooks that contain tables, charts or pictures. For Example:
 //
 //    // Sheet1 already exists...
-//    xlsx.NewSheet(2, "sheet2")
-//    err := xlsx.CopySheet(1, 2)
+//    index := xlsx.NewSheet("Sheet2")
+//    err := xlsx.CopySheet(1, index)
 //    if err != nil {
 //        fmt.Println(err)
 //        os.Exit(1)
@@ -432,7 +438,7 @@ func (f *File) CopySheet(from, to int) error {
 }
 
 // copySheet provides function to duplicate a worksheet by gave source and
-// target worksheet index.
+// target worksheet name.
 func (f *File) copySheet(from, to int) {
 	sheet := f.workSheetReader("sheet" + strconv.Itoa(from))
 	worksheet := xlsxWorksheet{}
@@ -484,8 +490,7 @@ func (f *File) SetSheetVisible(name string, visible bool) {
 		}
 	}
 	for k, v := range content.Sheets.Sheet {
-		sheetIndex := k + 1
-		xlsx := f.workSheetReader("sheet" + strconv.Itoa(sheetIndex))
+		xlsx := f.workSheetReader(f.GetSheetMap()[k])
 		tabSelected := false
 		if len(xlsx.SheetViews.SheetView) > 0 {
 			tabSelected = xlsx.SheetViews.SheetView[0].TabSelected
@@ -504,7 +509,7 @@ func parseFormatPanesSet(formatSet string) *formatPanes {
 }
 
 // SetPanes provides function to create and remove freeze panes and split panes
-// by given worksheet index and panes format set.
+// by given worksheet name and panes format set.
 //
 // activePane defines the pane that is active. The possible values for this
 // attribute are defined in the following table:

+ 2 - 3
styles.go

@@ -2218,9 +2218,8 @@ func setCellXfs(style *xlsxStyleSheet, fontID, numFmtID, fillID, borderID int, a
 }
 
 // SetCellStyle provides function to add style attribute for cells by given
-// worksheet sheet index, coordinate area and style ID. Note that diagonalDown
-// and diagonalUp type border should be use same color in the same coordinate
-// area.
+// worksheet name, coordinate area and style ID. Note that diagonalDown and
+// diagonalUp type border should be use same color in the same coordinate area.
 //
 // For example create a borders of cell H9 on Sheet1:
 //

+ 5 - 5
table.go

@@ -82,7 +82,7 @@ func (f *File) countTables() int {
 }
 
 // addSheetTable provides function to add tablePart element to
-// xl/worksheets/sheet%d.xml by given sheet name and relationship index.
+// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
 func (f *File) addSheetTable(sheet string, rID int) {
 	xlsx := f.workSheetReader(sheet)
 	table := &xlsxTablePart{
@@ -95,8 +95,8 @@ func (f *File) addSheetTable(sheet string, rID int) {
 	xlsx.TableParts.TableParts = append(xlsx.TableParts.TableParts, table)
 }
 
-// addTable provides function to add table by given sheet index, coordinate area
-// and format set.
+// addTable provides function to add table by given worksheet name, coordinate
+// area and format set.
 func (f *File) addTable(sheet, tableXML string, hxAxis, hyAxis, vxAxis, vyAxis, i int, formatSet *formatTable) {
 	// Correct the minimum number of rows, the table at least two lines.
 	if hyAxis == vyAxis {
@@ -157,8 +157,8 @@ func parseAutoFilterSet(formatSet string) *formatAutoFilter {
 }
 
 // AutoFilter provides the method to add auto filter in a worksheet by given
-// sheet index, coordinate area and settings. An autofilter in Excel is a way of
-// filtering a 2D range of data based on some simple criteria. For example
+// worksheet name, coordinate area and settings. An autofilter in Excel is a way
+// of filtering a 2D range of data based on some simple criteria. For example
 // applying an autofilter to a cell range A1:D4 in the worksheet 1:
 //
 //    err = xlsx.AutoFilter("Sheet1", "A1", "D4", "")