workbook.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package xlsx
  2. import (
  3. "archive/zip"
  4. "encoding/xml"
  5. "fmt"
  6. "io"
  7. "strings"
  8. )
  9. // xmlxWorkbookRels contains xmlxWorkbookRelations
  10. // which maps sheet id and sheet XML
  11. type xlsxWorkbookRels struct {
  12. Relationships []xlsxWorkbookRelation `xml:"Relationship"`
  13. }
  14. // xmlxWorkbookRelation maps sheet id and xl/worksheets/sheet%d.xml
  15. type xlsxWorkbookRelation struct {
  16. Id string `xml:",attr"`
  17. Target string `xml:",attr"`
  18. }
  19. // xlsxWorkbook directly maps the workbook element from the namespace
  20. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  21. // currently I have not checked it for completeness - it does as much
  22. // as I need.
  23. type xlsxWorkbook struct {
  24. FileVersion xlsxFileVersion `xml:"fileVersion"`
  25. WorkbookPr xlsxWorkbookPr `xml:"workbookPr"`
  26. BookViews xlsxBookViews `xml:"bookViews"`
  27. Sheets xlsxSheets `xml:"sheets"`
  28. DefinedNames xlsxDefinedNames `xml:"definedNames"`
  29. CalcPr xlsxCalcPr `xml:"calcPr"`
  30. }
  31. // xlsxFileVersion directly maps the fileVersion element from the
  32. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  33. // - currently I have not checked it for completeness - it does as
  34. // much as I need.
  35. type xlsxFileVersion struct {
  36. AppName string `xml:"appName,attr"`
  37. LastEdited string `xml:"lastEdited,attr"`
  38. LowestEdited string `xml:"lowestEdited,attr"`
  39. RupBuild string `xml:"rupBuild,attr"`
  40. }
  41. // xlsxWorkbookPr directly maps the workbookPr element from the
  42. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  43. // - currently I have not checked it for completeness - it does as
  44. // much as I need.
  45. type xlsxWorkbookPr struct {
  46. DefaultThemeVersion string `xml:"defaultThemeVersion,attr"`
  47. }
  48. // xlsxBookViews directly maps the bookViews element from the
  49. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  50. // - currently I have not checked it for completeness - it does as
  51. // much as I need.
  52. type xlsxBookViews struct {
  53. WorkBookView []xlsxWorkBookView `xml:"workbookView"`
  54. }
  55. // xlsxWorkBookView directly maps the workbookView element from the
  56. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  57. // - currently I have not checked it for completeness - it does as
  58. // much as I need.
  59. type xlsxWorkBookView struct {
  60. XWindow string `xml:"xWindow,attr"`
  61. YWindow string `xml:"yWindow,attr"`
  62. WindowWidth string `xml:"windowWidth,attr"`
  63. WindowHeight string `xml:"windowHeight,attr"`
  64. }
  65. // xlsxSheets directly maps the sheets element from the namespace
  66. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  67. // currently I have not checked it for completeness - it does as much
  68. // as I need.
  69. type xlsxSheets struct {
  70. Sheet []xlsxSheet `xml:"sheet"`
  71. }
  72. // xlsxSheet directly maps the sheet element from the namespace
  73. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  74. // currently I have not checked it for completeness - it does as much
  75. // as I need.
  76. type xlsxSheet struct {
  77. Name string `xml:"name,attr"`
  78. SheetId string `xml:"sheetId,attr"`
  79. Id string `xml:"id,attr"`
  80. }
  81. // xlsxDefinedNames directly maps the definedNames element from the
  82. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  83. // - currently I have not checked it for completeness - it does as
  84. // much as I need.
  85. type xlsxDefinedNames struct {
  86. DefinedName []xlsxDefinedName `xml:"definedName"`
  87. }
  88. // xlsxDefinedName directly maps the definedName element from the
  89. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  90. // - currently I have not checked it for completeness - it does as
  91. // much as I need.
  92. type xlsxDefinedName struct {
  93. Data string `xml:",chardata"`
  94. Name string `xml:"name,attr"`
  95. LocalSheetID string `xml:"localSheetId,attr"`
  96. }
  97. // xlsxCalcPr directly maps the calcPr element from the namespace
  98. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  99. // currently I have not checked it for completeness - it does as much
  100. // as I need.
  101. type xlsxCalcPr struct {
  102. CalcId string `xml:"calcId,attr"`
  103. }
  104. // getWorksheetFromSheet() is an internal helper function to open a
  105. // sheetN.xml file, refered to by an xlsx.xlsxSheet struct, from the XLSX
  106. // file and unmarshal it an xlsx.xlsxWorksheet struct
  107. func getWorksheetFromSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string) (*xlsxWorksheet, error) {
  108. var rc io.ReadCloser
  109. var decoder *xml.Decoder
  110. var worksheet *xlsxWorksheet
  111. var error error
  112. var sheetName string
  113. worksheet = new(xlsxWorksheet)
  114. sheetName, ok := sheetXMLMap[sheet.Id]
  115. if !ok {
  116. if sheet.SheetId != "" {
  117. sheetName = fmt.Sprintf("sheet%s", sheet.SheetId)
  118. } else {
  119. sheetName = fmt.Sprintf("sheet%s", sheet.Id)
  120. }
  121. }
  122. f, ok := worksheets[sheetName]
  123. if !ok {
  124. // excel created from mac MsExcel,will have a sheets Id as "rId1",
  125. // but has a sheet file named "sheet1" and "_rels/sheet1.xml."
  126. // this work around will open it
  127. for sheetName, f = range worksheets {
  128. //do not want "_rels/sheet1.xml."
  129. if strings.Contains(sheetName, "_") {
  130. continue
  131. }
  132. break
  133. }
  134. if f == nil {
  135. return nil, fmt.Errorf("not found sheet file sheetId:%s", sheet.Id)
  136. }
  137. }
  138. rc, error = f.Open()
  139. if error != nil {
  140. return nil, error
  141. }
  142. decoder = xml.NewDecoder(rc)
  143. error = decoder.Decode(worksheet)
  144. if error != nil {
  145. return nil, error
  146. }
  147. return worksheet, nil
  148. }