excel.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package excel
  2. import (
  3. "fmt"
  4. "net/url"
  5. "reflect"
  6. "strconv"
  7. "github.com/gin-gonic/gin"
  8. "github.com/xuri/excelize/v2"
  9. )
  10. type ExcelServer struct {
  11. File *excelize.File
  12. SheetName string // 可定义默认sheet名称
  13. Height float64 // 默认行高度
  14. }
  15. // ExportToPath 导出基本的表格
  16. func (l *ExcelServer) ExportToPath(params []map[string]string, data []map[string]interface{}, path string) (string, error) {
  17. l.Export(params, data)
  18. name := createFileName()
  19. filePath := path + "/" + name
  20. err := l.File.SaveAs(filePath)
  21. return filePath, err
  22. }
  23. // ExportToWeb 导出到浏览器。此处使用的gin框架 其他框架可自行修改ctx
  24. func (l *ExcelServer) ExportToWeb(params []map[string]string, data []map[string]interface{}, c *gin.Context) {
  25. l.Export(params, data)
  26. buffer, _ := l.File.WriteToBuffer()
  27. //设置文件类型
  28. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  29. //设置文件名称
  30. c.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(createFileName()))
  31. _, _ = c.Writer.Write(buffer.Bytes())
  32. }
  33. //设置首行
  34. func (l *ExcelServer) writeTop(params []map[string]string) {
  35. topStyle, _ := l.File.NewStyle(&excelize.Style{
  36. Font: &excelize.Font{Bold: true},
  37. Alignment: &excelize.Alignment{
  38. Horizontal: "center",
  39. Vertical: "center",
  40. },
  41. Protection: nil,
  42. NumFmt: 0,
  43. DecimalPlaces: 0,
  44. CustomNumFmt: nil,
  45. Lang: "",
  46. NegRed: false,
  47. })
  48. var word = 'A'
  49. //首行写入
  50. for _, conf := range params {
  51. title := conf["title"]
  52. width, _ := strconv.ParseFloat(conf["width"], 64)
  53. line := fmt.Sprintf("%c1", word)
  54. //设置标题
  55. _ = l.File.SetCellValue(l.SheetName, line, title)
  56. //列宽
  57. _ = l.File.SetColWidth(l.SheetName, fmt.Sprintf("%c", word), fmt.Sprintf("%c", word), width)
  58. //设置样式
  59. _ = l.File.SetCellStyle(l.SheetName, line, line, topStyle)
  60. word++
  61. }
  62. }
  63. //写入数据
  64. func (l *ExcelServer) writeData(params []map[string]string, data []map[string]interface{}) {
  65. lineStyle, _ := l.File.NewStyle(&excelize.Style{Alignment: &excelize.Alignment{
  66. Horizontal: "center",
  67. Vertical: "center",
  68. }})
  69. //数据写入
  70. var j = 2 //数据开始行数
  71. for i, val := range data {
  72. //设置行高
  73. _ = l.File.SetRowHeight(l.SheetName, i+1, l.Height)
  74. //逐列写入
  75. var word = 'A'
  76. for _, conf := range params {
  77. valKey := conf["key"]
  78. line := fmt.Sprintf("%c%v", word, j)
  79. isNum := conf["is_num"]
  80. //设置值
  81. if isNum != "0" {
  82. valNum := fmt.Sprintf("'%v", val[valKey])
  83. _ = l.File.SetCellValue(l.SheetName, line, valNum)
  84. } else {
  85. _ = l.File.SetCellValue(l.SheetName, line, val[valKey])
  86. }
  87. //设置样式
  88. _ = l.File.SetCellStyle(l.SheetName, line, line, lineStyle)
  89. word++
  90. }
  91. j++
  92. }
  93. //设置行高 尾行
  94. _ = l.File.SetRowHeight(l.SheetName, len(data)+1, l.Height)
  95. }
  96. func (l *ExcelServer) Export(params []map[string]string, data []map[string]interface{}) {
  97. l.writeTop(params)
  98. l.writeData(params, data)
  99. }
  100. // ExportExcelByStruct excel导出(数据源为Struct) []interface{}
  101. func (l *ExcelServer) ExportExcelByStruct(titleList []string, data []interface{}, fileName string, sheetName string, c *gin.Context) error {
  102. l.File.SetSheetName("Sheet1", sheetName)
  103. header := make([]string, 0)
  104. for _, v := range titleList {
  105. header = append(header, v)
  106. }
  107. rowStyleID, _ := l.File.NewStyle(&excelize.Style{
  108. Font: &excelize.Font{
  109. Family: "arial",
  110. Size: 13,
  111. Color: "#666666",
  112. },
  113. Alignment: &excelize.Alignment{
  114. Horizontal: "center",
  115. Vertical: "center",
  116. },
  117. })
  118. _ = l.File.SetSheetRow(sheetName, "A1", &header)
  119. _ = l.File.SetRowHeight("Sheet1", 1, 30)
  120. length := len(titleList)
  121. headStyle := Letter(length)
  122. var lastRow string
  123. var widthRow string
  124. for k, v := range headStyle {
  125. if k == length-1 {
  126. lastRow = fmt.Sprintf("%s1", v)
  127. widthRow = v
  128. }
  129. }
  130. if err := l.File.SetColWidth(sheetName, "A", widthRow, 30); err != nil {
  131. fmt.Print("错误--", err.Error())
  132. }
  133. rowNum := 1
  134. for _, v := range data {
  135. t := reflect.TypeOf(v)
  136. fmt.Print("--ttt--", t.NumField())
  137. value := reflect.ValueOf(v)
  138. row := make([]interface {
  139. }, 0)
  140. for l := 0; l < t.NumField(); l++ {
  141. val := value.Field(l).Interface()
  142. row = append(row, val)
  143. }
  144. rowNum++
  145. err := l.File.SetSheetRow(sheetName, "A"+strconv.Itoa(rowNum), &row)
  146. _ = l.File.SetCellStyle(sheetName, fmt.Sprintf("A%d", rowNum), fmt.Sprintf("%s", lastRow), rowStyleID)
  147. if err != nil {
  148. return err
  149. }
  150. }
  151. disposition := fmt.Sprintf("attachment; filename=%s.xlsx", url.QueryEscape(fileName))
  152. c.Writer.Header().Set("Content-Type", "application/octet-stream")
  153. c.Writer.Header().Set("Content-Disposition", disposition)
  154. c.Writer.Header().Set("Content-Transfer-Encoding", "binary")
  155. c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
  156. return l.File.Write(c.Writer)
  157. }
  158. // Letter 遍历a-z
  159. func Letter(length int) []string {
  160. var str []string
  161. for i := 0; i < length; i++ {
  162. str = append(str, string(rune('A'+i)))
  163. }
  164. return str
  165. }