Browse Source

support case-sensitive doc parts to improve compatibility

xuri 5 years ago
parent
commit
49257c5918
7 changed files with 50 additions and 36 deletions
  1. 6 6
      README.md
  2. 10 1
      excelize.go
  3. 6 6
      excelize_test.go
  4. 9 1
      lib.go
  5. 2 2
      picture.go
  6. 0 4
      rows.go
  7. 17 16
      sheet.go

+ 6 - 6
README.md

@@ -29,9 +29,9 @@ go get github.com/360EntSecGroup-Skylar/excelize
 go get github.com/360EntSecGroup-Skylar/excelize/v2
 go get github.com/360EntSecGroup-Skylar/excelize/v2
 ```
 ```
 
 
-### Create XLSX file
+### Create spreadsheet
 
 
-Here is a minimal example usage that will create XLSX file.
+Here is a minimal example usage that will create spreadsheet file.
 
 
 ```go
 ```go
 package main
 package main
@@ -58,9 +58,9 @@ func main() {
 }
 }
 ```
 ```
 
 
-### Reading XLSX file
+### Reading spreadsheet
 
 
-The following constitutes the bare to read a XLSX document.
+The following constitutes the bare to read a spreadsheet document.
 
 
 ```go
 ```go
 package main
 package main
@@ -95,7 +95,7 @@ func main() {
 }
 }
 ```
 ```
 
 
-### Add chart to XLSX file
+### Add chart to spreadsheet file
 
 
 With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all.
 With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all.
 
 
@@ -131,7 +131,7 @@ func main() {
 }
 }
 ```
 ```
 
 
-### Add picture to XLSX file
+### Add picture to spreadsheet file
 
 
 ```go
 ```go
 package main
 package main

+ 10 - 1
excelize.go

@@ -220,16 +220,25 @@ func checkSheet(xlsx *xlsxWorksheet) {
 // addRels provides a function to add relationships by given XML path,
 // addRels provides a function to add relationships by given XML path,
 // relationship type, target and target mode.
 // relationship type, target and target mode.
 func (f *File) addRels(relPath, relType, target, targetMode string) int {
 func (f *File) addRels(relPath, relType, target, targetMode string) int {
+	var uniqPart = map[string]string{
+		SourceRelationshipSharedStrings: "/xl/sharedStrings.xml",
+	}
 	rels := f.relsReader(relPath)
 	rels := f.relsReader(relPath)
 	if rels == nil {
 	if rels == nil {
 		rels = &xlsxRelationships{}
 		rels = &xlsxRelationships{}
 	}
 	}
 	var rID int
 	var rID int
-	for _, rel := range rels.Relationships {
+	for idx, rel := range rels.Relationships {
 		ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
 		ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
 		if ID > rID {
 		if ID > rID {
 			rID = ID
 			rID = ID
 		}
 		}
+		if relType == rel.Type {
+			if partName, ok := uniqPart[rel.Type]; ok {
+				rels.Relationships[idx].Target = partName
+				return rID
+			}
+		}
 	}
 	}
 	rID++
 	rID++
 	var ID bytes.Buffer
 	var ID bytes.Buffer

+ 6 - 6
excelize_test.go

@@ -22,7 +22,7 @@ import (
 )
 )
 
 
 func TestOpenFile(t *testing.T) {
 func TestOpenFile(t *testing.T) {
-	// Test update a XLSX file.
+	// Test update the spreadsheet file.
 	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
 	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
 	assert.NoError(t, err)
 	assert.NoError(t, err)
 
 
@@ -154,11 +154,11 @@ func TestOpenFile(t *testing.T) {
 	// Test read cell value with given axis large than exists row.
 	// Test read cell value with given axis large than exists row.
 	_, err = f.GetCellValue("Sheet2", "E231")
 	_, err = f.GetCellValue("Sheet2", "E231")
 	assert.NoError(t, err)
 	assert.NoError(t, err)
-	// Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index.
+	// Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index.
 	f.GetSheetName(f.GetActiveSheetIndex())
 	f.GetSheetName(f.GetActiveSheetIndex())
-	// Test get worksheet index of XLSX by given worksheet name.
+	// Test get worksheet index of spreadsheet by given worksheet name.
 	f.GetSheetIndex("Sheet1")
 	f.GetSheetIndex("Sheet1")
-	// Test get worksheet name of XLSX by given invalid worksheet index.
+	// Test get worksheet name of spreadsheet by given invalid worksheet index.
 	f.GetSheetName(4)
 	f.GetSheetName(4)
 	// Test get worksheet map of workbook.
 	// Test get worksheet map of workbook.
 	f.GetSheetMap()
 	f.GetSheetMap()
@@ -261,7 +261,7 @@ func TestBrokenFile(t *testing.T) {
 	})
 	})
 
 
 	t.Run("OpenNotExistsFile", func(t *testing.T) {
 	t.Run("OpenNotExistsFile", func(t *testing.T) {
-		// Test open a XLSX file with given illegal path.
+		// Test open a spreadsheet file with given illegal path.
 		_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
 		_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
 		if assert.Error(t, err) {
 		if assert.Error(t, err) {
 			assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
 			assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
@@ -270,7 +270,7 @@ func TestBrokenFile(t *testing.T) {
 }
 }
 
 
 func TestNewFile(t *testing.T) {
 func TestNewFile(t *testing.T) {
-	// Test create a XLSX file.
+	// Test create a spreadsheet file.
 	f := NewFile()
 	f := NewFile()
 	f.NewSheet("Sheet1")
 	f.NewSheet("Sheet1")
 	f.NewSheet("XLSXSheet2")
 	f.NewSheet("XLSXSheet2")

+ 9 - 1
lib.go

@@ -26,10 +26,18 @@ import (
 // filesystem.
 // filesystem.
 func ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
 func ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
 	var err error
 	var err error
+	var docPart = map[string]string{
+		"[content_types].xml":  "[Content_Types].xml",
+		"xl/sharedstrings.xml": "xl/sharedStrings.xml",
+	}
 	fileList := make(map[string][]byte, len(r.File))
 	fileList := make(map[string][]byte, len(r.File))
 	worksheets := 0
 	worksheets := 0
 	for _, v := range r.File {
 	for _, v := range r.File {
-		if fileList[v.Name], err = readFile(v); err != nil {
+		fileName := v.Name
+		if partName, ok := docPart[strings.ToLower(v.Name)]; ok {
+			fileName = partName
+		}
+		if fileList[fileName], err = readFile(v); err != nil {
 			return nil, 0, err
 			return nil, 0, err
 		}
 		}
 		if strings.HasPrefix(v.Name, "xl/worksheets/sheet") {
 		if strings.HasPrefix(v.Name, "xl/worksheets/sheet") {

+ 2 - 2
picture.go

@@ -474,7 +474,7 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
 	return f.getPicture(row, col, drawingXML, drawingRelationships)
 	return f.getPicture(row, col, drawingXML, drawingRelationships)
 }
 }
 
 
-// DeletePicture provides a function to delete charts in XLSX by given
+// DeletePicture provides a function to delete charts in spreadsheet by given
 // worksheet and cell name. Note that the image file won't be deleted from the
 // worksheet and cell name. Note that the image file won't be deleted from the
 // document currently.
 // document currently.
 func (f *File) DeletePicture(sheet, cell string) (err error) {
 func (f *File) DeletePicture(sheet, cell string) (err error) {
@@ -496,7 +496,7 @@ func (f *File) DeletePicture(sheet, cell string) (err error) {
 }
 }
 
 
 // getPicture provides a function to get picture base name and raw content
 // getPicture provides a function to get picture base name and raw content
-// embed in XLSX by given coordinates and drawing relationships.
+// embed in spreadsheet by given coordinates and drawing relationships.
 func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string) (ret string, buf []byte, err error) {
 func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string) (ret string, buf []byte, err error) {
 	var (
 	var (
 		wsDr            *xlsxWsDr
 		wsDr            *xlsxWsDr

+ 0 - 4
rows.go

@@ -282,10 +282,6 @@ func (f *File) sharedStringsReader() *xlsxSST {
 	if f.SharedStrings == nil {
 	if f.SharedStrings == nil {
 		var sharedStrings xlsxSST
 		var sharedStrings xlsxSST
 		ss := f.readXML("xl/sharedStrings.xml")
 		ss := f.readXML("xl/sharedStrings.xml")
-		if len(ss) == 0 {
-			ss = f.readXML("xl/SharedStrings.xml")
-			delete(f.XLSX, "xl/SharedStrings.xml")
-		}
 		if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))).
 		if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))).
 			Decode(&sharedStrings); err != nil && err != io.EOF {
 			Decode(&sharedStrings); err != nil && err != io.EOF {
 			log.Printf("xml decode error: %s", err)
 			log.Printf("xml decode error: %s", err)

+ 17 - 16
sheet.go

@@ -32,8 +32,9 @@ import (
 )
 )
 
 
 // NewSheet provides function to create a new sheet by given worksheet name.
 // NewSheet provides function to create a new sheet by given worksheet name.
-// When creating a new XLSX file, the default sheet will be created. Returns
-// the number of sheets in the workbook (file) after appending the new sheet.
+// When creating a new spreadsheet file, the default worksheet will be
+// created. Returns the number of sheets in the workbook (file) after
+// appending the new sheet.
 func (f *File) NewSheet(name string) int {
 func (f *File) NewSheet(name string) int {
 	// Check if the worksheet already exists
 	// Check if the worksheet already exists
 	if f.GetSheetIndex(name) != -1 {
 	if f.GetSheetIndex(name) != -1 {
@@ -152,7 +153,7 @@ func trimCell(column []xlsxC) []xlsxC {
 }
 }
 
 
 // setContentTypes provides a function to read and update property of contents
 // setContentTypes provides a function to read and update property of contents
-// type of XLSX.
+// type of the spreadsheet.
 func (f *File) setContentTypes(partName, contentType string) {
 func (f *File) setContentTypes(partName, contentType string) {
 	content := f.contentTypesReader()
 	content := f.contentTypesReader()
 	content.Overrides = append(content.Overrides, xlsxOverride{
 	content.Overrides = append(content.Overrides, xlsxOverride{
@@ -174,8 +175,8 @@ func (f *File) setSheet(index int, name string) {
 	f.Sheet[path] = &xlsx
 	f.Sheet[path] = &xlsx
 }
 }
 
 
-// setWorkbook update workbook property of XLSX. Maximum 31 characters are
-// allowed in sheet title.
+// setWorkbook update workbook property of the spreadsheet. Maximum 31
+// characters are allowed in sheet title.
 func (f *File) setWorkbook(name string, sheetID, rid int) {
 func (f *File) setWorkbook(name string, sheetID, rid int) {
 	content := f.workbookReader()
 	content := f.workbookReader()
 	content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
 	content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
@@ -204,9 +205,9 @@ func (f *File) setAppXML() {
 	f.saveFileList("docProps/app.xml", []byte(templateDocpropsApp))
 	f.saveFileList("docProps/app.xml", []byte(templateDocpropsApp))
 }
 }
 
 
-// replaceRelationshipsBytes; Some tools that read XLSX files have very strict
-// requirements about the structure of the input XML. This function is a
-// horrible hack to fix that after the XML marshalling is completed.
+// replaceRelationshipsBytes; Some tools that read spreadsheet files have very
+// strict requirements about the structure of the input XML. This function is
+// a horrible hack to fix that after the XML marshalling is completed.
 func replaceRelationshipsBytes(content []byte) []byte {
 func replaceRelationshipsBytes(content []byte) []byte {
 	oldXmlns := stringToBytes(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`)
 	oldXmlns := stringToBytes(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`)
 	newXmlns := stringToBytes("r")
 	newXmlns := stringToBytes("r")
@@ -263,7 +264,7 @@ func (f *File) SetActiveSheet(index int) {
 }
 }
 
 
 // GetActiveSheetIndex provides a function to get active sheet index of the
 // GetActiveSheetIndex provides a function to get active sheet index of the
-// XLSX. If not found the active sheet will be return integer 0.
+// spreadsheet. If not found the active sheet will be return integer 0.
 func (f *File) GetActiveSheetIndex() (index int) {
 func (f *File) GetActiveSheetIndex() (index int) {
 	var sheetID = f.getActiveSheetID()
 	var sheetID = f.getActiveSheetID()
 	wb := f.workbookReader()
 	wb := f.workbookReader()
@@ -278,7 +279,7 @@ func (f *File) GetActiveSheetIndex() (index int) {
 }
 }
 
 
 // getActiveSheetID provides a function to get active sheet index of the
 // getActiveSheetID provides a function to get active sheet index of the
-// XLSX. If not found the active sheet will be return integer 0.
+// spreadsheet. If not found the active sheet will be return integer 0.
 func (f *File) getActiveSheetID() int {
 func (f *File) getActiveSheetID() int {
 	wb := f.workbookReader()
 	wb := f.workbookReader()
 	if wb != nil {
 	if wb != nil {
@@ -313,9 +314,9 @@ func (f *File) SetSheetName(oldName, newName string) {
 	}
 	}
 }
 }
 
 
-// getSheetNameByID provides a function to get worksheet name of XLSX by given
-// worksheet ID. If given sheet ID is invalid, will return an empty
-// string.
+// getSheetNameByID provides a function to get worksheet name of the
+// spreadsheet by given worksheet ID. If given sheet ID is invalid, will
+// return an empty string.
 func (f *File) getSheetNameByID(ID int) string {
 func (f *File) getSheetNameByID(ID int) string {
 	wb := f.workbookReader()
 	wb := f.workbookReader()
 	if wb == nil || ID < 1 {
 	if wb == nil || ID < 1 {
@@ -341,9 +342,9 @@ func (f *File) GetSheetName(index int) (name string) {
 	return
 	return
 }
 }
 
 
-// getSheetID provides a function to get worksheet ID of XLSX by given
-// sheet name. If given worksheet name is invalid, will return an integer type
-// value -1.
+// getSheetID provides a function to get worksheet ID of the spreadsheet by
+// given sheet name. If given worksheet name is invalid, will return an
+// integer type value -1.
 func (f *File) getSheetID(name string) int {
 func (f *File) getSheetID(name string) int {
 	var ID = -1
 	var ID = -1
 	for sheetID, sheet := range f.GetSheetMap() {
 	for sheetID, sheet := range f.GetSheetMap() {