export_exel.go 5.0 KB

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