xmlWorksheet.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package xlsx
  2. import (
  3. "encoding/xml"
  4. "strings"
  5. )
  6. // xlsxWorksheet directly maps the worksheet element in the namespace
  7. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  8. // currently I have not checked it for completeness - it does as much
  9. // as I need.
  10. type xlsxWorksheet struct {
  11. XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
  12. SheetPr xlsxSheetPr `xml:"sheetPr"`
  13. Dimension xlsxDimension `xml:"dimension"`
  14. SheetViews xlsxSheetViews `xml:"sheetViews"`
  15. SheetFormatPr xlsxSheetFormatPr `xml:"sheetFormatPr"`
  16. Cols *xlsxCols `xml:"cols,omitempty"`
  17. SheetData xlsxSheetData `xml:"sheetData"`
  18. DataValidations *xlsxCellDataValidations `xml:"dataValidations"`
  19. AutoFilter *xlsxAutoFilter `xml:"autoFilter,omitempty"`
  20. MergeCells *xlsxMergeCells `xml:"mergeCells,omitempty"`
  21. PrintOptions xlsxPrintOptions `xml:"printOptions"`
  22. PageMargins xlsxPageMargins `xml:"pageMargins"`
  23. PageSetUp xlsxPageSetUp `xml:"pageSetup"`
  24. HeaderFooter xlsxHeaderFooter `xml:"headerFooter"`
  25. }
  26. // xlsxHeaderFooter directly maps the headerFooter element in the namespace
  27. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  28. // currently I have not checked it for completeness - it does as much
  29. // as I need.
  30. type xlsxHeaderFooter struct {
  31. DifferentFirst bool `xml:"differentFirst,attr"`
  32. DifferentOddEven bool `xml:"differentOddEven,attr"`
  33. OddHeader []xlsxOddHeader `xml:"oddHeader"`
  34. OddFooter []xlsxOddFooter `xml:"oddFooter"`
  35. }
  36. // xlsxOddHeader directly maps the oddHeader element in the namespace
  37. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  38. // currently I have not checked it for completeness - it does as much
  39. // as I need.
  40. type xlsxOddHeader struct {
  41. Content string `xml:",chardata"`
  42. }
  43. // xlsxOddFooter directly maps the oddFooter element in the namespace
  44. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  45. // currently I have not checked it for completeness - it does as much
  46. // as I need.
  47. type xlsxOddFooter struct {
  48. Content string `xml:",chardata"`
  49. }
  50. // xlsxPageSetUp directly maps the pageSetup element in the namespace
  51. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  52. // currently I have not checked it for completeness - it does as much
  53. // as I need.
  54. type xlsxPageSetUp struct {
  55. PaperSize string `xml:"paperSize,attr"`
  56. Scale int `xml:"scale,attr"`
  57. FirstPageNumber int `xml:"firstPageNumber,attr"`
  58. FitToWidth int `xml:"fitToWidth,attr"`
  59. FitToHeight int `xml:"fitToHeight,attr"`
  60. PageOrder string `xml:"pageOrder,attr"`
  61. Orientation string `xml:"orientation,attr"`
  62. UsePrinterDefaults bool `xml:"usePrinterDefaults,attr"`
  63. BlackAndWhite bool `xml:"blackAndWhite,attr"`
  64. Draft bool `xml:"draft,attr"`
  65. CellComments string `xml:"cellComments,attr"`
  66. UseFirstPageNumber bool `xml:"useFirstPageNumber,attr"`
  67. HorizontalDPI float32 `xml:"horizontalDpi,attr"`
  68. VerticalDPI float32 `xml:"verticalDpi,attr"`
  69. Copies int `xml:"copies,attr"`
  70. }
  71. // xlsxPrintOptions directly maps the printOptions element in the namespace
  72. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  73. // currently I have not checked it for completeness - it does as much
  74. // as I need.
  75. type xlsxPrintOptions struct {
  76. Headings bool `xml:"headings,attr"`
  77. GridLines bool `xml:"gridLines,attr"`
  78. GridLinesSet bool `xml:"gridLinesSet,attr"`
  79. HorizontalCentered bool `xml:"horizontalCentered,attr"`
  80. VerticalCentered bool `xml:"verticalCentered,attr"`
  81. }
  82. // xlsxPageMargins directly maps the pageMargins element in the namespace
  83. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  84. // currently I have not checked it for completeness - it does as much
  85. // as I need.
  86. type xlsxPageMargins struct {
  87. Left float64 `xml:"left,attr"`
  88. Right float64 `xml:"right,attr"`
  89. Top float64 `xml:"top,attr"`
  90. Bottom float64 `xml:"bottom,attr"`
  91. Header float64 `xml:"header,attr"`
  92. Footer float64 `xml:"footer,attr"`
  93. }
  94. // xlsxSheetFormatPr directly maps the sheetFormatPr element in the namespace
  95. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  96. // currently I have not checked it for completeness - it does as much
  97. // as I need.
  98. type xlsxSheetFormatPr struct {
  99. DefaultColWidth float64 `xml:"defaultColWidth,attr,omitempty"`
  100. DefaultRowHeight float64 `xml:"defaultRowHeight,attr"`
  101. OutlineLevelCol uint8 `xml:"outlineLevelCol,attr,omitempty"`
  102. OutlineLevelRow uint8 `xml:"outlineLevelRow,attr,omitempty"`
  103. }
  104. // xlsxSheetViews directly maps the sheetViews element in the namespace
  105. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  106. // currently I have not checked it for completeness - it does as much
  107. // as I need.
  108. type xlsxSheetViews struct {
  109. SheetView []xlsxSheetView `xml:"sheetView"`
  110. }
  111. // xlsxSheetView directly maps the sheetView element in the namespace
  112. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  113. // currently I have not checked it for completeness - it does as much
  114. // as I need.
  115. type xlsxSheetView struct {
  116. WindowProtection bool `xml:"windowProtection,attr"`
  117. ShowFormulas bool `xml:"showFormulas,attr"`
  118. ShowGridLines bool `xml:"showGridLines,attr"`
  119. ShowRowColHeaders bool `xml:"showRowColHeaders,attr"`
  120. ShowZeros bool `xml:"showZeros,attr"`
  121. RightToLeft bool `xml:"rightToLeft,attr"`
  122. TabSelected bool `xml:"tabSelected,attr"`
  123. ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr"`
  124. DefaultGridColor bool `xml:"defaultGridColor,attr"`
  125. View string `xml:"view,attr"`
  126. TopLeftCell string `xml:"topLeftCell,attr"`
  127. ColorId int `xml:"colorId,attr"`
  128. ZoomScale float64 `xml:"zoomScale,attr"`
  129. ZoomScaleNormal float64 `xml:"zoomScaleNormal,attr"`
  130. ZoomScalePageLayoutView float64 `xml:"zoomScalePageLayoutView,attr"`
  131. WorkbookViewId int `xml:"workbookViewId,attr"`
  132. Pane *xlsxPane `xml:"pane"`
  133. Selection []xlsxSelection `xml:"selection"`
  134. }
  135. // xlsxSelection directly maps the selection element in the namespace
  136. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  137. // currently I have not checked it for completeness - it does as much
  138. // as I need.
  139. type xlsxSelection struct {
  140. Pane string `xml:"pane,attr"`
  141. ActiveCell string `xml:"activeCell,attr"`
  142. ActiveCellId int `xml:"activeCellId,attr"`
  143. SQRef string `xml:"sqref,attr"`
  144. }
  145. // xlsxSelection directly maps the selection element in the namespace
  146. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  147. // currently I have not checked it for completeness - it does as much
  148. // as I need.
  149. type xlsxPane struct {
  150. XSplit float64 `xml:"xSplit,attr"`
  151. YSplit float64 `xml:"ySplit,attr"`
  152. TopLeftCell string `xml:"topLeftCell,attr"`
  153. ActivePane string `xml:"activePane,attr"`
  154. State string `xml:"state,attr"` // Either "split" or "frozen"
  155. }
  156. // xlsxSheetPr directly maps the sheetPr element in the namespace
  157. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  158. // currently I have not checked it for completeness - it does as much
  159. // as I need.
  160. type xlsxSheetPr struct {
  161. FilterMode bool `xml:"filterMode,attr"`
  162. PageSetUpPr []xlsxPageSetUpPr `xml:"pageSetUpPr"`
  163. }
  164. // xlsxPageSetUpPr directly maps the pageSetupPr element in the namespace
  165. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  166. // currently I have not checked it for completeness - it does as much
  167. // as I need.
  168. type xlsxPageSetUpPr struct {
  169. FitToPage bool `xml:"fitToPage,attr"`
  170. }
  171. // xlsxCols directly maps the cols element in the namespace
  172. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  173. // currently I have not checked it for completeness - it does as much
  174. // as I need.
  175. type xlsxCols struct {
  176. Col []xlsxCol `xml:"col"`
  177. }
  178. // xlsxCol directly maps the col element in the namespace
  179. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  180. // currently I have not checked it for completeness - it does as much
  181. // as I need.
  182. type xlsxCol struct {
  183. Collapsed bool `xml:"collapsed,attr"`
  184. Hidden bool `xml:"hidden,attr"`
  185. Max int `xml:"max,attr"`
  186. Min int `xml:"min,attr"`
  187. Style int `xml:"style,attr"`
  188. Width float64 `xml:"width,attr"`
  189. CustomWidth bool `xml:"customWidth,attr,omitempty"`
  190. OutlineLevel uint8 `xml:"outlineLevel,attr,omitempty"`
  191. }
  192. // xlsxDimension directly maps the dimension element in the namespace
  193. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  194. // currently I have not checked it for completeness - it does as much
  195. // as I need.
  196. type xlsxDimension struct {
  197. Ref string `xml:"ref,attr"`
  198. }
  199. // xlsxSheetData directly maps the sheetData element in the namespace
  200. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  201. // currently I have not checked it for completeness - it does as much
  202. // as I need.
  203. type xlsxSheetData struct {
  204. XMLName xml.Name `xml:"sheetData"`
  205. Row []xlsxRow `xml:"row"`
  206. }
  207. // xlsxCellDataValidations excel cell data validation
  208. type xlsxCellDataValidations struct {
  209. DataValidattion []*xlsxCellDataValidation `xml:"dataValidation"`
  210. Count int `xml:"count,attr"`
  211. }
  212. // xlsxCellDataValidation single data validation
  213. type xlsxCellDataValidation struct {
  214. AllowBlank bool `xml:"allowBlank,attr"` // allow empty
  215. ShowInputMessage bool `xml:"showInputMessage,attr"` // 1, true,0,false, select cell, Whether the input message is displayed
  216. ShowErrorMessage bool `xml:"showErrorMessage,attr"` // 1, true,0,false, input error value, Whether the error message is displayed
  217. ErrorStyle *string `xml:"errorStyle,attr"` //error icon style, warning, infomation,stop
  218. ErrorTitle *string `xml:"errorTitle,attr"` // error title
  219. Operator string `xml:"operator,attr,omitempty"` //
  220. Error *string `xml:"error,attr"` // input error value, notice message
  221. PromptTitle *string `xml:"promptTitle,attr"`
  222. Prompt *string `xml:"prompt,attr"`
  223. Type string `xml:"type,attr"` //data type, none,custom,date,decimal,list, textLength,time,whole
  224. Sqref string `xml:"sqref,attr,omitempty"` //Validity of data validation rules, cell and range, eg: A1 OR A1:A20
  225. Formula1 string `xml:"formula1"` // data validation role
  226. Formula2 string `xml:"formula2,omitempty"` //data validation role
  227. minRow int //`xml:"-"`
  228. maxRow int //`xml:"-"`
  229. //minCol int `xml:"-"` //spare
  230. //maxCol int `xml:"-"` //spare
  231. }
  232. // xlsxRow directly maps the row element in the namespace
  233. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  234. // currently I have not checked it for completeness - it does as much
  235. // as I need.
  236. type xlsxRow struct {
  237. R int `xml:"r,attr"`
  238. Spans string `xml:"spans,attr,omitempty"`
  239. Hidden bool `xml:"hidden,attr,omitempty"`
  240. C []xlsxC `xml:"c"`
  241. Ht string `xml:"ht,attr,omitempty"`
  242. CustomHeight bool `xml:"customHeight,attr,omitempty"`
  243. OutlineLevel uint8 `xml:"outlineLevel,attr,omitempty"`
  244. }
  245. type xlsxAutoFilter struct {
  246. Ref string `xml:"ref,attr"`
  247. }
  248. type xlsxMergeCell struct {
  249. Ref string `xml:"ref,attr"` // ref: horiz "A1:C1", vert "B3:B6", both "D3:G4"
  250. }
  251. type xlsxMergeCells struct {
  252. XMLName xml.Name //`xml:"mergeCells,omitempty"`
  253. Count int `xml:"count,attr,omitempty"`
  254. Cells []xlsxMergeCell `xml:"mergeCell,omitempty"`
  255. }
  256. // Return the cartesian extent of a merged cell range from its origin
  257. // cell (the closest merged cell to the to left of the sheet.
  258. func (mc *xlsxMergeCells) getExtent(cellRef string) (int, int, error) {
  259. if mc == nil {
  260. return 0, 0, nil
  261. }
  262. for _, cell := range mc.Cells {
  263. if strings.HasPrefix(cell.Ref, cellRef+":") {
  264. parts := strings.Split(cell.Ref, ":")
  265. startx, starty, err := GetCoordsFromCellIDString(parts[0])
  266. if err != nil {
  267. return -1, -1, err
  268. }
  269. endx, endy, err := GetCoordsFromCellIDString(parts[1])
  270. if err != nil {
  271. return -2, -2, err
  272. }
  273. return endx - startx, endy - starty, nil
  274. }
  275. }
  276. return 0, 0, nil
  277. }
  278. // xlsxC directly maps the c element in the namespace
  279. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  280. // currently I have not checked it for completeness - it does as much
  281. // as I need.
  282. type xlsxC struct {
  283. R string `xml:"r,attr"` // Cell ID, e.g. A1
  284. S int `xml:"s,attr,omitempty"` // Style reference.
  285. T string `xml:"t,attr,omitempty"` // Type.
  286. F *xlsxF `xml:"f,omitempty"` // Formula
  287. V string `xml:"v,omitempty"` // Value
  288. Is *xlsxSI `xml:"is,omitempty"` // Inline String.
  289. }
  290. // xlsxF directly maps the f element in the namespace
  291. // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
  292. // currently I have not checked it for completeness - it does as much
  293. // as I need.
  294. type xlsxF struct {
  295. Content string `xml:",chardata"`
  296. T string `xml:"t,attr,omitempty"` // Formula type
  297. Ref string `xml:"ref,attr,omitempty"` // Shared formula ref
  298. Si int `xml:"si,attr,omitempty"` // Shared formula index
  299. }
  300. // Create a new XLSX Worksheet with default values populated.
  301. // Strictly for internal use only!
  302. func newXlsxWorksheet() (worksheet *xlsxWorksheet) {
  303. worksheet = &xlsxWorksheet{}
  304. worksheet.SheetPr.FilterMode = false
  305. worksheet.SheetPr.PageSetUpPr = make([]xlsxPageSetUpPr, 1)
  306. worksheet.SheetPr.PageSetUpPr[0] = xlsxPageSetUpPr{FitToPage: false}
  307. worksheet.SheetViews.SheetView = make([]xlsxSheetView, 1)
  308. worksheet.SheetViews.SheetView[0] = xlsxSheetView{
  309. ColorId: 64,
  310. DefaultGridColor: true,
  311. RightToLeft: false,
  312. Selection: make([]xlsxSelection, 1),
  313. ShowFormulas: false,
  314. ShowGridLines: true,
  315. ShowOutlineSymbols: true,
  316. ShowRowColHeaders: true,
  317. ShowZeros: true,
  318. TabSelected: false,
  319. TopLeftCell: "A1",
  320. View: "normal",
  321. WindowProtection: false,
  322. WorkbookViewId: 0,
  323. ZoomScale: 100,
  324. ZoomScaleNormal: 100,
  325. ZoomScalePageLayoutView: 100}
  326. worksheet.SheetViews.SheetView[0].Selection[0] = xlsxSelection{
  327. Pane: "topLeft",
  328. ActiveCell: "A1",
  329. ActiveCellId: 0,
  330. SQRef: "A1"}
  331. worksheet.SheetFormatPr.DefaultRowHeight = 12.85
  332. worksheet.PrintOptions.Headings = false
  333. worksheet.PrintOptions.GridLines = false
  334. worksheet.PrintOptions.GridLinesSet = true
  335. worksheet.PrintOptions.HorizontalCentered = false
  336. worksheet.PrintOptions.VerticalCentered = false
  337. worksheet.PageMargins.Left = 0.7875
  338. worksheet.PageMargins.Right = 0.7875
  339. worksheet.PageMargins.Top = 1.05277777777778
  340. worksheet.PageMargins.Bottom = 1.05277777777778
  341. worksheet.PageMargins.Header = 0.7875
  342. worksheet.PageMargins.Footer = 0.7875
  343. worksheet.PageSetUp.PaperSize = "9"
  344. worksheet.PageSetUp.Scale = 100
  345. worksheet.PageSetUp.FirstPageNumber = 1
  346. worksheet.PageSetUp.FitToWidth = 1
  347. worksheet.PageSetUp.FitToHeight = 1
  348. worksheet.PageSetUp.PageOrder = "downThenOver"
  349. worksheet.PageSetUp.Orientation = "portrait"
  350. worksheet.PageSetUp.UsePrinterDefaults = false
  351. worksheet.PageSetUp.BlackAndWhite = false
  352. worksheet.PageSetUp.Draft = false
  353. worksheet.PageSetUp.CellComments = "none"
  354. worksheet.PageSetUp.UseFirstPageNumber = true
  355. worksheet.PageSetUp.HorizontalDPI = 300
  356. worksheet.PageSetUp.VerticalDPI = 300
  357. worksheet.PageSetUp.Copies = 1
  358. worksheet.HeaderFooter.OddHeader = make([]xlsxOddHeader, 1)
  359. worksheet.HeaderFooter.OddHeader[0] = xlsxOddHeader{Content: `&C&"Times New Roman,Regular"&12&A`}
  360. worksheet.HeaderFooter.OddFooter = make([]xlsxOddFooter, 1)
  361. worksheet.HeaderFooter.OddFooter[0] = xlsxOddFooter{Content: `&C&"Times New Roman,Regular"&12Page &P`}
  362. return
  363. }