xmlWorkbook.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package xlsx
  2. import (
  3. "archive/zip"
  4. "encoding/xml"
  5. "fmt"
  6. "io"
  7. )
  8. const (
  9. // sheet state values as defined by
  10. // http://msdn.microsoft.com/en-us/library/office/documentformat.openxml.spreadsheet.sheetstatevalues.aspx
  11. sheetStateVisible = "visible"
  12. sheetStateHidden = "hidden"
  13. sheetStateVeryHidden = "veryHidden"
  14. )
  15. // xmlxWorkbookRels contains xmlxWorkbookRelations
  16. // which maps sheet id and sheet XML
  17. type xlsxWorkbookRels struct {
  18. XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/relationships Relationships"`
  19. Relationships []xlsxWorkbookRelation `xml:"Relationship"`
  20. }
  21. // xmlxWorkbookRelation maps sheet id and xl/worksheets/sheet%d.xml
  22. type xlsxWorkbookRelation struct {
  23. Id string `xml:",attr"`
  24. Target string `xml:",attr"`
  25. Type string `xml:",attr"`
  26. }
  27. // xlsxWorkbook directly maps the workbook element from the namespace
  28. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  29. // currently I have not checked it for completeness - it does as much
  30. // as I need.
  31. type xlsxWorkbook struct {
  32. XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main workbook"`
  33. FileVersion xlsxFileVersion `xml:"fileVersion"`
  34. WorkbookPr xlsxWorkbookPr `xml:"workbookPr"`
  35. WorkbookProtection xlsxWorkbookProtection `xml:"workbookProtection"`
  36. BookViews xlsxBookViews `xml:"bookViews"`
  37. Sheets xlsxSheets `xml:"sheets"`
  38. DefinedNames xlsxDefinedNames `xml:"definedNames"`
  39. CalcPr xlsxCalcPr `xml:"calcPr"`
  40. }
  41. // xlsxWorkbookProtection directly maps the workbookProtection 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 xlsxWorkbookProtection struct {
  46. // We don't need this, yet.
  47. }
  48. // xlsxFileVersion directly maps the fileVersion 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 xlsxFileVersion struct {
  53. AppName string `xml:"appName,attr,omitempty"`
  54. LastEdited string `xml:"lastEdited,attr,omitempty"`
  55. LowestEdited string `xml:"lowestEdited,attr,omitempty"`
  56. RupBuild string `xml:"rupBuild,attr,omitempty"`
  57. }
  58. // xlsxWorkbookPr directly maps the workbookPr element from the
  59. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  60. // - currently I have not checked it for completeness - it does as
  61. // much as I need.
  62. type xlsxWorkbookPr struct {
  63. DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
  64. BackupFile bool `xml:"backupFile,attr,omitempty"`
  65. ShowObjects string `xml:"showObjects,attr,omitempty"`
  66. Date1904 bool `xml:"date1904,attr"`
  67. }
  68. // xlsxBookViews directly maps the bookViews element from the
  69. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  70. // - currently I have not checked it for completeness - it does as
  71. // much as I need.
  72. type xlsxBookViews struct {
  73. WorkBookView []xlsxWorkBookView `xml:"workbookView"`
  74. }
  75. // xlsxWorkBookView directly maps the workbookView element from the
  76. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  77. // - currently I have not checked it for completeness - it does as
  78. // much as I need.
  79. type xlsxWorkBookView struct {
  80. ActiveTab int `xml:"activeTab,attr,omitempty"`
  81. FirstSheet int `xml:"firstSheet,attr,omitempty"`
  82. ShowHorizontalScroll bool `xml:"showHorizontalScroll,attr,omitempty"`
  83. ShowVerticalScroll bool `xml:"showVerticalScroll,attr,omitempty"`
  84. ShowSheetTabs bool `xml:"showSheetTabs,attr,omitempty"`
  85. TabRatio int `xml:"tabRatio,attr,omitempty"`
  86. WindowHeight int `xml:"windowHeight,attr,omitempty"`
  87. WindowWidth int `xml:"windowWidth,attr,omitempty"`
  88. XWindow string `xml:"xWindow,attr,omitempty"`
  89. YWindow string `xml:"yWindow,attr,omitempty"`
  90. }
  91. // xlsxSheets directly maps the sheets element from the namespace
  92. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  93. // currently I have not checked it for completeness - it does as much
  94. // as I need.
  95. type xlsxSheets struct {
  96. Sheet []xlsxSheet `xml:"sheet"`
  97. }
  98. // xlsxSheet directly maps the sheet element from the namespace
  99. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  100. // currently I have not checked it for completeness - it does as much
  101. // as I need.
  102. type xlsxSheet struct {
  103. Name string `xml:"name,attr,omitempty"`
  104. SheetId string `xml:"sheetId,attr,omitempty"`
  105. Id string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
  106. State string `xml:"state,attr,omitempty"`
  107. }
  108. // xlsxDefinedNames directly maps the definedNames element from the
  109. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  110. // - currently I have not checked it for completeness - it does as
  111. // much as I need.
  112. type xlsxDefinedNames struct {
  113. DefinedName []xlsxDefinedName `xml:"definedName"`
  114. }
  115. // xlsxDefinedName directly maps the definedName element from the
  116. // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
  117. // - currently I have not checked it for completeness - it does as
  118. // much as I need.
  119. // for a descriptions of the attributes see
  120. // https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.spreadsheet.definedname.aspx
  121. type xlsxDefinedName struct {
  122. Data string `xml:",chardata"`
  123. Name string `xml:"name,attr"`
  124. Comment string `xml:"comment,attr,omitempty"`
  125. CustomMenu string `xml:"customMenu,attr,omitempty"`
  126. Description string `xml:"description,attr,omitempty"`
  127. Help string `xml:"help,attr,omitempty"`
  128. ShortcutKey string `xml:"shortcutKey,attr,omitempty"`
  129. StatusBar string `xml:"statusBar,attr,omitempty"`
  130. LocalSheetID int `xml:"localSheetId,attr,omitempty"`
  131. FunctionGroupID int `xml:"functionGroupId,attr,omitempty"`
  132. Function bool `xml:"function,attr,omitempty"`
  133. Hidden bool `xml:"hidden,attr,omitempty"`
  134. VbProcedure bool `xml:"vbProcedure,attr,omitempty"`
  135. PublishToServer bool `xml:"publishToServer,attr,omitempty"`
  136. WorkbookParameter bool `xml:"workbookParameter,attr,omitempty"`
  137. Xlm bool `xml:"xml,attr,omitempty"`
  138. }
  139. // xlsxCalcPr directly maps the calcPr element from the namespace
  140. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  141. // currently I have not checked it for completeness - it does as much
  142. // as I need.
  143. type xlsxCalcPr struct {
  144. CalcId string `xml:"calcId,attr,omitempty"`
  145. IterateCount int `xml:"iterateCount,attr,omitempty"`
  146. RefMode string `xml:"refMode,attr,omitempty"`
  147. Iterate bool `xml:"iterate,attr,omitempty"`
  148. IterateDelta float64 `xml:"iterateDelta,attr,omitempty"`
  149. }
  150. // Helper function to lookup the file corresponding to a xlsxSheet object in the worksheets map
  151. func worksheetFileForSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string) *zip.File {
  152. sheetName, ok := sheetXMLMap[sheet.Id]
  153. if !ok {
  154. if sheet.SheetId != "" {
  155. sheetName = fmt.Sprintf("sheet%s", sheet.SheetId)
  156. } else {
  157. sheetName = fmt.Sprintf("sheet%s", sheet.Id)
  158. }
  159. }
  160. return worksheets[sheetName]
  161. }
  162. // getWorksheetFromSheet() is an internal helper function to open a
  163. // sheetN.xml file, referred to by an xlsx.xlsxSheet struct, from the XLSX
  164. // file and unmarshal it an xlsx.xlsxWorksheet struct
  165. func getWorksheetFromSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string, rowLimit int) (*xlsxWorksheet, error) {
  166. var r io.Reader
  167. var decoder *xml.Decoder
  168. var worksheet *xlsxWorksheet
  169. var err error
  170. worksheet = new(xlsxWorksheet)
  171. f := worksheetFileForSheet(sheet, worksheets, sheetXMLMap)
  172. if f == nil {
  173. return nil, fmt.Errorf("Unable to find sheet '%s'", sheet)
  174. }
  175. if rc, err := f.Open(); err != nil {
  176. return nil, err
  177. } else {
  178. defer rc.Close()
  179. r = rc
  180. }
  181. if rowLimit != NoRowLimit {
  182. r, err = truncateSheetXML(r, rowLimit)
  183. if err != nil {
  184. return nil, err
  185. }
  186. }
  187. decoder = xml.NewDecoder(r)
  188. err = decoder.Decode(worksheet)
  189. if err != nil {
  190. return nil, err
  191. }
  192. return worksheet, nil
  193. }