export_exel.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package xvdoc
  2. import (
  3. "bytes"
  4. "fmt"
  5. _ "image/gif"
  6. _ "image/jpeg"
  7. _ "image/png"
  8. "github.com/xuri/excelize/v2"
  9. )
  10. func exportXLSX(mList []Matrix) (res []byte, err error) {
  11. if len(mList) == 0 {
  12. return nil, fmt.Errorf("XVDoc export xlsx error :: expexcted not empty matrix list")
  13. }
  14. // create excelize file and setup sheet name
  15. f := excelize.NewFile()
  16. for index, matrix := range mList {
  17. sName := matrix.Name
  18. if len(sName) == 0 {
  19. sName = fmt.Sprintf("Sheet%v", index)
  20. }
  21. if index == 0 {
  22. f.SetSheetName("Sheet1", sName)
  23. } else {
  24. f.NewSheet(sName)
  25. }
  26. ////////////////
  27. // setup global styles
  28. var sID int
  29. xStyles := make(map[string]int)
  30. for name, style := range matrix.Styles {
  31. var styleRes JSONMap
  32. if styleRes, err = style.Result(matrix.Styles, name); err != nil {
  33. return
  34. }
  35. //fmt.Println("!!!!!!!!!!!!!!", name, string(styleRes.JSON()))
  36. if sID, err = f.NewStyle(string(styleRes.JSON())); err != nil {
  37. return
  38. }
  39. xStyles[name] = sID
  40. }
  41. ////////////////
  42. // setup cells values
  43. var coords, cellName string
  44. for rIndex, row := range matrix.Cells {
  45. for cIndex, cell := range row {
  46. if coords, err = excelize.CoordinatesToCellName(cIndex+1, rIndex+1); err == nil {
  47. if cell != nil {
  48. if cell.Type() == "formula" {
  49. formula := cell.(*CellFormula)
  50. args := make([]string, len(formula.args))
  51. for i, arg := range formula.args {
  52. if arg.aType != argTypeValue {
  53. x, y := arg.Coords(cIndex, rIndex)
  54. if cellName, err = excelize.CoordinatesToCellName(int(x)+1, int(y)+1); err != nil {
  55. return
  56. } else {
  57. args[i] = cellName
  58. }
  59. } else {
  60. args[i] = fmt.Sprint(arg.Value())
  61. }
  62. }
  63. if err = f.SetCellFormula(sName, coords, formula.ReplaceArgs(args)); err != nil {
  64. return
  65. }
  66. } else {
  67. f.SetCellValue(sName, coords, cell.Val())
  68. }
  69. // setup cell styles
  70. if styles := cell.Styles(); len(styles) > 0 {
  71. //fmt.Println("&&&&", styles)
  72. for _, style := range styles {
  73. if sID, check := xStyles[style]; check {
  74. if err = f.SetCellStyle(sName, coords, coords, sID); err != nil {
  75. return
  76. }
  77. }
  78. }
  79. }
  80. }
  81. } else {
  82. return nil, err
  83. }
  84. }
  85. if height, check := matrix.RowsHeight[rIndex]; check {
  86. f.SetRowHeight(sName, rIndex+1, height)
  87. }
  88. }
  89. var c, dc string
  90. // setup rect styles
  91. for _, rect := range matrix.StyleRects {
  92. if c, err = excelize.CoordinatesToCellName(rect.x+1, rect.y+1); err != nil {
  93. return
  94. }
  95. if dc, err = excelize.CoordinatesToCellName(rect.dx+1, rect.dy+1); err != nil {
  96. return
  97. }
  98. for _, style := range rect.styles {
  99. if sID, check := xStyles[style]; check {
  100. if err = f.SetCellStyle(sName, c, dc, sID); err != nil {
  101. return
  102. }
  103. }
  104. }
  105. }
  106. ///////////////////////////////////
  107. // setup images
  108. for _, image := range matrix.Images {
  109. if c, err = excelize.CoordinatesToCellName(image.x+1, image.y+1); err != nil {
  110. return
  111. }
  112. format := ""
  113. if image.format != nil {
  114. format = string(image.format.JSON())
  115. }
  116. if err = f.AddPicture(sName, c, image.path, format); err != nil {
  117. return
  118. }
  119. }
  120. ///////////////////////////////////
  121. // setup columns width
  122. for _, cWidth := range matrix.ColumnsWidth {
  123. if c, err = excelize.ColumnNumberToName(cWidth.x + 1); err != nil {
  124. return
  125. }
  126. if dc, err = excelize.ColumnNumberToName(cWidth.dx + 1); err != nil {
  127. return
  128. }
  129. if err = f.SetColWidth(sName, c, dc, cWidth.width); err != nil {
  130. return
  131. }
  132. }
  133. // setup merges
  134. for _, merge := range matrix.Merges {
  135. if c, err = excelize.CoordinatesToCellName(merge.x+1, merge.y+1); err != nil {
  136. return
  137. }
  138. if dc, err = excelize.CoordinatesToCellName(merge.dx+1, merge.dy+1); err != nil {
  139. return
  140. }
  141. if err = f.MergeCell(sName, c, dc); err != nil {
  142. return
  143. }
  144. }
  145. for _, dropdown := range matrix.Dropdowns {
  146. if c, err = excelize.CoordinatesToCellName(dropdown.x+1, dropdown.y+1); err != nil {
  147. return
  148. }
  149. if dc, err = excelize.CoordinatesToCellName(dropdown.dx+1, dropdown.dy+1); err != nil {
  150. return
  151. }
  152. r := excelize.NewDataValidation(true)
  153. r.Sqref = "A5:A7"
  154. r.Sqref = fmt.Sprintf("%v:%v", c, dc)
  155. r.SetDropList(dropdown.values)
  156. f.AddDataValidation(sName, r)
  157. }
  158. ///////////////////////////////////
  159. }
  160. //r := excelize.NewDataValidation(true)
  161. //r.Sqref = "A5:A7"
  162. //r.SetDropList([]string{"10", "30", "50"})
  163. //f.AddDataValidation("xv-test", r)
  164. // setup result data
  165. var buf bytes.Buffer
  166. f.Write(&buf)
  167. return buf.Bytes(), nil
  168. }