浏览代码

Fixes #308, refactor `NewSheet()`, `DeleteSheet()`, `SetActiveSheet()` and `GetActiveSheetIndex()`

xuri 7 年之前
父节点
当前提交
e728ff1498
共有 6 个文件被更改,包括 55 次插入58 次删除
  1. 2 1
      col.go
  2. 7 6
      date.go
  3. 二进制
      logo.png
  4. 45 50
      sheet.go
  5. 二进制
      test/Book1.xlsx
  6. 1 1
      xmlWorkbook.go

+ 2 - 1
col.go

@@ -337,7 +337,8 @@ func (f *File) RemoveCol(sheet, column string) {
 	f.adjustHelper(sheet, col, -1, -1)
 }
 
-// completeCol; Completion column element tags of XML in a sheet.
+// completeCol provieds function to completion column element tags of XML in a
+// sheet.
 func completeCol(xlsx *xlsxWorksheet, row, cell int) {
 	buffer := bytes.Buffer{}
 	for r := range xlsx.SheetData.Row {

+ 7 - 6
date.go

@@ -90,12 +90,13 @@ func julianDateToGregorianTime(part1, part2 float64) time.Time {
 	return time.Date(year, time.Month(month), day, hours, minutes, seconds, nanoseconds, time.UTC)
 }
 
-// doTheFliegelAndVanFlandernAlgorithm; By this point generations of programmers have repeated the algorithm sent
-// to the editor of "Communications of the ACM" in 1968 (published in CACM,
-// volume 11, number 10, October 1968, p.657). None of those programmers seems
-// to have found it necessary to explain the constants or variable names set
-// out by Henry F. Fliegel and Thomas C. Van Flandern.  Maybe one day I'll buy
-// that jounal and expand an explanation here - that day is not today.
+// doTheFliegelAndVanFlandernAlgorithm; By this point generations of
+// programmers have repeated the algorithm sent to the editor of
+// "Communications of the ACM" in 1968 (published in CACM, volume 11, number
+// 10, October 1968, p.657). None of those programmers seems to have found it
+// necessary to explain the constants or variable names set out by Henry F.
+// Fliegel and Thomas C. Van Flandern.  Maybe one day I'll buy that jounal and
+// expand an explanation here - that day is not today.
 func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
 	l := jd + 68569
 	n := (4 * l) / 146097

二进制
logo.png


+ 45 - 50
sheet.go

@@ -33,18 +33,27 @@ func (f *File) NewSheet(name string) int {
 	if f.GetSheetIndex(name) != 0 {
 		return f.SheetCount
 	}
+	f.DeleteSheet(name)
 	f.SheetCount++
+	wb := f.workbookReader()
+	sheetID := 0
+	for _, v := range wb.Sheets.Sheet {
+		if v.SheetID > sheetID {
+			sheetID = v.SheetID
+		}
+	}
+	sheetID++
 	// Update docProps/app.xml
 	f.setAppXML()
 	// Update [Content_Types].xml
-	f.setContentTypes(f.SheetCount)
+	f.setContentTypes(sheetID)
 	// Create new sheet /xl/worksheets/sheet%d.xml
-	f.setSheet(f.SheetCount, name)
+	f.setSheet(sheetID, name)
 	// Update xl/_rels/workbook.xml.rels
-	rID := f.addXlsxWorkbookRels(f.SheetCount)
+	rID := f.addXlsxWorkbookRels(sheetID)
 	// Update xl/workbook.xml
-	f.setWorkbook(name, rID)
-	return f.SheetCount
+	f.setWorkbook(name, sheetID, rID)
+	return sheetID
 }
 
 // contentTypesReader provides a function to get the pointer to the
@@ -118,7 +127,8 @@ func trimCell(column []xlsxC) []xlsxC {
 	return col[0:i]
 }
 
-// setContentTypes; Read and update property of contents type of XLSX.
+// setContentTypes provides a function to read and update property of contents
+// type of XLSX.
 func (f *File) setContentTypes(index int) {
 	content := f.contentTypesReader()
 	content.Overrides = append(content.Overrides, xlsxOverride{
@@ -127,7 +137,7 @@ func (f *File) setContentTypes(index int) {
 	})
 }
 
-// setSheet; Update sheet property by given index.
+// setSheet provides a function to update sheet property by given index.
 func (f *File) setSheet(index int, name string) {
 	var xlsx xlsxWorksheet
 	xlsx.Dimension.Ref = "A1"
@@ -141,19 +151,11 @@ func (f *File) setSheet(index int, name string) {
 
 // setWorkbook update workbook property of XLSX. Maximum 31 characters are
 // allowed in sheet title.
-func (f *File) setWorkbook(name string, rid int) {
+func (f *File) setWorkbook(name string, sheetID, rid int) {
 	content := f.workbookReader()
-	rID := 0
-	for _, v := range content.Sheets.Sheet {
-		t, _ := strconv.Atoi(v.SheetID)
-		if t > rID {
-			rID = t
-		}
-	}
-	rID++
 	content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
 		Name:    trimSheetName(name),
-		SheetID: strconv.Itoa(rID),
+		SheetID: sheetID,
 		ID:      "rId" + strconv.Itoa(rid),
 	})
 }
@@ -209,13 +211,13 @@ func (f *File) setAppXML() {
 	f.saveFileList("docProps/app.xml", []byte(templateDocpropsApp))
 }
 
-// replaceRelationshipsNameSpaceBytes; Some tools that read XLSX files have very strict requirements about the
-// structure of the input XML. In particular both Numbers on the Mac and SAS
-// dislike inline XML namespace declarations, or namespace prefixes that don't
-// match the ones that Excel itself uses. This is a problem because the Go XML
-// library doesn't multiple namespace declarations in a single element of a
-// document. This function is a horrible hack to fix that after the XML
-// marshalling is completed.
+// replaceRelationshipsNameSpaceBytes; Some tools that read XLSX files have
+// very strict requirements about the structure of the input XML. In
+// particular both Numbers on the Mac and SAS dislike inline XML namespace
+// declarations, or namespace prefixes that don't match the ones that Excel
+// itself uses. This is a problem because the Go XML library doesn't multiple
+// namespace declarations in a single element of a document. This function is
+// a horrible hack to fix that after the XML marshalling is completed.
 func replaceRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte {
 	oldXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
 	newXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">`)
@@ -230,18 +232,23 @@ func (f *File) SetActiveSheet(index int) {
 	if index < 1 {
 		index = 1
 	}
-	index--
-	content := f.workbookReader()
-	if len(content.BookViews.WorkBookView) > 0 {
-		content.BookViews.WorkBookView[0].ActiveTab = index
-	} else {
-		content.BookViews.WorkBookView = append(content.BookViews.WorkBookView, xlsxWorkBookView{
-			ActiveTab: index,
-		})
+	wb := f.workbookReader()
+	for activeTab, sheet := range wb.Sheets.Sheet {
+		if sheet.SheetID == index {
+			if len(wb.BookViews.WorkBookView) > 0 {
+				wb.BookViews.WorkBookView[0].ActiveTab = activeTab
+			} else {
+				wb.BookViews.WorkBookView = append(wb.BookViews.WorkBookView, xlsxWorkBookView{
+					ActiveTab: activeTab,
+				})
+			}
+		}
 	}
-	index++
 	for idx, name := range f.GetSheetMap() {
 		xlsx := f.workSheetReader(name)
+		if len(xlsx.SheetViews.SheetView) > 0 {
+			xlsx.SheetViews.SheetView[0].TabSelected = false
+		}
 		if index == idx {
 			if len(xlsx.SheetViews.SheetView) > 0 {
 				xlsx.SheetViews.SheetView[0].TabSelected = true
@@ -250,10 +257,6 @@ func (f *File) SetActiveSheet(index int) {
 					TabSelected: true,
 				})
 			}
-		} else {
-			if len(xlsx.SheetViews.SheetView) > 0 {
-				xlsx.SheetViews.SheetView[0].TabSelected = false
-			}
 		}
 	}
 }
@@ -261,21 +264,13 @@ func (f *File) SetActiveSheet(index int) {
 // GetActiveSheetIndex provides a function to get active sheet index of the
 // XLSX. If not found the active sheet will be return integer 0.
 func (f *File) GetActiveSheetIndex() int {
-	buffer := bytes.Buffer{}
-	content := f.workbookReader()
-	for _, v := range content.Sheets.Sheet {
-		xlsx := xlsxWorksheet{}
-		buffer.WriteString("xl/worksheets/sheet")
-		buffer.WriteString(strings.TrimPrefix(v.ID, "rId"))
-		buffer.WriteString(".xml")
-		_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(buffer.String())), &xlsx)
+	for idx, name := range f.GetSheetMap() {
+		xlsx := f.workSheetReader(name)
 		for _, sheetView := range xlsx.SheetViews.SheetView {
 			if sheetView.TabSelected {
-				ID, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
-				return ID
+				return idx
 			}
 		}
-		buffer.Reset()
 	}
 	return 0
 }
@@ -404,8 +399,8 @@ func (f *File) DeleteSheet(name string) {
 	for k, v := range content.Sheets.Sheet {
 		if v.Name == trimSheetName(name) && len(content.Sheets.Sheet) > 1 {
 			content.Sheets.Sheet = append(content.Sheets.Sheet[:k], content.Sheets.Sheet[k+1:]...)
-			sheet := "xl/worksheets/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml"
-			rels := "xl/worksheets/_rels/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml.rels"
+			sheet := "xl/worksheets/sheet" + strconv.Itoa(v.SheetID) + ".xml"
+			rels := "xl/worksheets/_rels/sheet" + strconv.Itoa(v.SheetID) + ".xml.rels"
 			target := f.deleteSheetFromWorkbookRels(v.ID)
 			f.deleteSheetFromContentTypes(target)
 			delete(f.sheetMap, name)

二进制
test/Book1.xlsx


+ 1 - 1
xmlWorkbook.go

@@ -151,7 +151,7 @@ type xlsxSheets struct {
 // not checked it for completeness - it does as much as I need.
 type xlsxSheet struct {
 	Name    string `xml:"name,attr,omitempty"`
-	SheetID string `xml:"sheetId,attr,omitempty"`
+	SheetID int    `xml:"sheetId,attr,omitempty"`
 	ID      string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
 	State   string `xml:"state,attr,omitempty"`
 }