소스 검색

Prevent workbooks with chartsheets from causing panics

Chartsheets are in the sheets listing but are not included in the file
map. Before, this would cause a panic when an attempt is made to open
a nil file. Now, chartsheets are skipped until there's better support
for them.
Brian Smith 10 년 전
부모
커밋
8921c11e37
2개의 변경된 파일28개의 추가작업 그리고 12개의 파일을 삭제
  1. 12 3
      lib.go
  2. 16 9
      xmlWorkbook.go

+ 12 - 3
lib.go

@@ -589,7 +589,16 @@ func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]strin
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 	file.Date1904 = workbook.WorkbookPr.Date1904
 	file.Date1904 = workbook.WorkbookPr.Date1904
-	sheetCount = len(workbook.Sheets.Sheet)
+
+	// Only try and read sheets that have corresponding files.
+	// Notably this excludes chartsheets don't right now
+	var workbookSheets []xlsxSheet
+	for _, sheet := range workbook.Sheets.Sheet {
+		if f := worksheetFileForSheet(sheet, file.worksheets, sheetXMLMap); f != nil {
+			workbookSheets = append(workbookSheets, sheet)
+		}
+	}
+	sheetCount = len(workbookSheets)
 	sheetsByName := make(map[string]*Sheet, sheetCount)
 	sheetsByName := make(map[string]*Sheet, sheetCount)
 	sheets := make([]*Sheet, sheetCount)
 	sheets := make([]*Sheet, sheetCount)
 	sheetChan := make(chan *indexedSheet, sheetCount)
 	sheetChan := make(chan *indexedSheet, sheetCount)
@@ -604,7 +613,7 @@ func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]strin
 			}
 			}
 		}()
 		}()
 		err = nil
 		err = nil
-		for i, rawsheet := range workbook.Sheets.Sheet {
+		for i, rawsheet := range workbookSheets {
 			readSheetFromFile(sheetChan, i, rawsheet, file, sheetXMLMap)
 			readSheetFromFile(sheetChan, i, rawsheet, file, sheetXMLMap)
 		}
 		}
 	}()
 	}()
@@ -614,7 +623,7 @@ func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]strin
 		if sheet.Error != nil {
 		if sheet.Error != nil {
 			return nil, nil, sheet.Error
 			return nil, nil, sheet.Error
 		}
 		}
-		sheetName := workbook.Sheets.Sheet[sheet.Index].Name
+		sheetName := workbookSheets[sheet.Index].Name
 		sheetsByName[sheetName] = sheet.Sheet
 		sheetsByName[sheetName] = sheet.Sheet
 		sheet.Sheet.Name = sheetName
 		sheet.Sheet.Name = sheetName
 		sheets[sheet.Index] = sheet.Sheet
 		sheets[sheet.Index] = sheet.Sheet

+ 16 - 9
xmlWorkbook.go

@@ -148,6 +148,19 @@ type xlsxCalcPr struct {
 	IterateDelta float64 `xml:"iterateDelta,attr,omitempty"`
 	IterateDelta float64 `xml:"iterateDelta,attr,omitempty"`
 }
 }
 
 
+// Helper function to lookup the file corresponding to a xlsxSheet object in the worksheets map
+func worksheetFileForSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string) *zip.File {
+	sheetName, ok := sheetXMLMap[sheet.Id]
+	if !ok {
+		if sheet.SheetId != "" {
+			sheetName = fmt.Sprintf("sheet%s", sheet.SheetId)
+		} else {
+			sheetName = fmt.Sprintf("sheet%s", sheet.Id)
+		}
+	}
+	return worksheets[sheetName]
+}
+
 // getWorksheetFromSheet() is an internal helper function to open a
 // getWorksheetFromSheet() is an internal helper function to open a
 // sheetN.xml file, refered to by an xlsx.xlsxSheet struct, from the XLSX
 // sheetN.xml file, refered to by an xlsx.xlsxSheet struct, from the XLSX
 // file and unmarshal it an xlsx.xlsxWorksheet struct
 // file and unmarshal it an xlsx.xlsxWorksheet struct
@@ -156,18 +169,12 @@ func getWorksheetFromSheet(sheet xlsxSheet, worksheets map[string]*zip.File, she
 	var decoder *xml.Decoder
 	var decoder *xml.Decoder
 	var worksheet *xlsxWorksheet
 	var worksheet *xlsxWorksheet
 	var error error
 	var error error
-	var sheetName string
 	worksheet = new(xlsxWorksheet)
 	worksheet = new(xlsxWorksheet)
 
 
-	sheetName, ok := sheetXMLMap[sheet.Id]
-	if !ok {
-		if sheet.SheetId != "" {
-			sheetName = fmt.Sprintf("sheet%s", sheet.SheetId)
-		} else {
-			sheetName = fmt.Sprintf("sheet%s", sheet.Id)
-		}
+	f := worksheetFileForSheet(sheet, worksheets, sheetXMLMap)
+	if f == nil {
+		return nil, fmt.Errorf("Unable to find sheet '%s'", sheet)
 	}
 	}
-	f := worksheets[sheetName]
 	rc, error = f.Open()
 	rc, error = f.Open()
 	if error != nil {
 	if error != nil {
 		return nil, error
 		return nil, error