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
 ```
 
-### 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
 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
 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.
 
@@ -131,7 +131,7 @@ func main() {
 }
 ```
 
-### Add picture to XLSX file
+### Add picture to spreadsheet file
 
 ```go
 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,
 // relationship type, target and target mode.
 func (f *File) addRels(relPath, relType, target, targetMode string) int {
+	var uniqPart = map[string]string{
+		SourceRelationshipSharedStrings: "/xl/sharedStrings.xml",
+	}
 	rels := f.relsReader(relPath)
 	if rels == nil {
 		rels = &xlsxRelationships{}
 	}
 	var rID int
-	for _, rel := range rels.Relationships {
+	for idx, rel := range rels.Relationships {
 		ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
 		if ID > rID {
 			rID = ID
 		}
+		if relType == rel.Type {
+			if partName, ok := uniqPart[rel.Type]; ok {
+				rels.Relationships[idx].Target = partName
+				return rID
+			}
+		}
 	}
 	rID++
 	var ID bytes.Buffer

+ 6 - 6
excelize_test.go

@@ -22,7 +22,7 @@ import (
 )
 
 func TestOpenFile(t *testing.T) {
-	// Test update a XLSX file.
+	// Test update the spreadsheet file.
 	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
 	assert.NoError(t, err)
 
@@ -154,11 +154,11 @@ func TestOpenFile(t *testing.T) {
 	// Test read cell value with given axis large than exists row.
 	_, err = f.GetCellValue("Sheet2", "E231")
 	assert.NoError(t, err)
-	// Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index.
+	// Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index.
 	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")
-	// 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)
 	// Test get worksheet map of workbook.
 	f.GetSheetMap()
@@ -261,7 +261,7 @@ func TestBrokenFile(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"))
 		if assert.Error(t, err) {
 			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) {
-	// Test create a XLSX file.
+	// Test create a spreadsheet file.
 	f := NewFile()
 	f.NewSheet("Sheet1")
 	f.NewSheet("XLSXSheet2")

+ 9 - 1
lib.go

@@ -26,10 +26,18 @@ import (
 // filesystem.
 func ReadZipReader(r *zip.Reader) (map[string][]byte, int, 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))
 	worksheets := 0
 	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
 		}
 		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)
 }
 
-// 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
 // document currently.
 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
-// 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) {
 	var (
 		wsDr            *xlsxWsDr

+ 0 - 4
rows.go

@@ -282,10 +282,6 @@ func (f *File) sharedStringsReader() *xlsxSST {
 	if f.SharedStrings == nil {
 		var sharedStrings xlsxSST
 		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))).
 			Decode(&sharedStrings); err != nil && err != io.EOF {
 			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.
-// 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 {
 	// Check if the worksheet already exists
 	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
-// type of XLSX.
+// type of the spreadsheet.
 func (f *File) setContentTypes(partName, contentType string) {
 	content := f.contentTypesReader()
 	content.Overrides = append(content.Overrides, xlsxOverride{
@@ -174,8 +175,8 @@ func (f *File) setSheet(index int, name string) {
 	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) {
 	content := f.workbookReader()
 	content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
@@ -204,9 +205,9 @@ func (f *File) setAppXML() {
 	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 {
 	oldXmlns := stringToBytes(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`)
 	newXmlns := stringToBytes("r")
@@ -263,7 +264,7 @@ 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.
+// spreadsheet. If not found the active sheet will be return integer 0.
 func (f *File) GetActiveSheetIndex() (index int) {
 	var sheetID = f.getActiveSheetID()
 	wb := f.workbookReader()
@@ -278,7 +279,7 @@ func (f *File) GetActiveSheetIndex() (index int) {
 }
 
 // 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 {
 	wb := f.workbookReader()
 	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 {
 	wb := f.workbookReader()
 	if wb == nil || ID < 1 {
@@ -341,9 +342,9 @@ func (f *File) GetSheetName(index int) (name string) {
 	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 {
 	var ID = -1
 	for sheetID, sheet := range f.GetSheetMap() {