export.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package excel
  2. import (
  3. "github.com/xuri/excelize/v2"
  4. "strconv"
  5. )
  6. const maxCharCount = 26
  7. var DefaultColumnWidth float64 = 20
  8. type ColumnOption struct {
  9. Field string
  10. Comment string
  11. Width float64
  12. }
  13. func Export(sheetName, filepath string, columns []ColumnOption, rows []map[string]any) error {
  14. f := excelize.NewFile()
  15. sheetIndex, err := f.NewSheet(sheetName)
  16. if err != nil {
  17. return err
  18. }
  19. _ = f.DeleteSheet("Sheet1")
  20. _ = f.SetColWidth(sheetName, "A", string(byte('A'+len(columns)-1)), DefaultColumnWidth)
  21. contentStyle, _ := f.NewStyle(&excelize.Style{
  22. Alignment: &excelize.Alignment{
  23. Horizontal: "center",
  24. Vertical: "center",
  25. WrapText: true,
  26. },
  27. })
  28. titleStyle, _ := f.NewStyle(&excelize.Style{
  29. Alignment: &excelize.Alignment{
  30. Horizontal: "center",
  31. Vertical: "center",
  32. WrapText: true,
  33. },
  34. Font: &excelize.Font{
  35. Bold: true,
  36. Size: 14,
  37. },
  38. })
  39. maxColumnRowNameLen := 1 + len(strconv.Itoa(len(rows)))
  40. columnCount := len(columns)
  41. if columnCount > maxCharCount {
  42. maxColumnRowNameLen++
  43. } else if columnCount > maxCharCount*maxCharCount {
  44. maxColumnRowNameLen += 2
  45. }
  46. //标题
  47. type columnItem struct {
  48. RowName []byte
  49. FieldName string
  50. }
  51. columnNames := make([]columnItem, 0)
  52. for index, column := range columns {
  53. columnName := getColumnName(index, maxColumnRowNameLen)
  54. if column.Width > 0 {
  55. _ = f.SetColWidth(sheetName, string(columnName), string(columnName), column.Width)
  56. }
  57. columnNames = append(columnNames, columnItem{FieldName: column.Field, RowName: columnName})
  58. rowName := getColumnRowName(columnName, 1)
  59. err := f.SetCellValue(sheetName, rowName, column.Comment)
  60. if err != nil {
  61. return err
  62. }
  63. _ = f.SetCellStyle(sheetName, rowName, rowName, titleStyle)
  64. }
  65. //正文
  66. for rowIndex, row := range rows {
  67. for _, item := range columnNames {
  68. rowName := getColumnRowName(item.RowName, rowIndex+2)
  69. err := f.SetCellValue(sheetName, rowName, row[item.FieldName])
  70. if err != nil {
  71. return err
  72. }
  73. _ = f.SetCellStyle(sheetName, rowName, rowName, contentStyle)
  74. }
  75. }
  76. f.SetActiveSheet(sheetIndex)
  77. err = f.SaveAs(filepath)
  78. if err != nil {
  79. return err
  80. }
  81. return nil
  82. }
  83. func getColumnName(column, maxColumnRowNameLen int) []byte {
  84. const A = 'A'
  85. if column < maxCharCount {
  86. slice := make([]byte, 0, maxColumnRowNameLen)
  87. return append(slice, byte(A+column))
  88. } else {
  89. return append(getColumnName(column/maxCharCount-1, maxColumnRowNameLen), byte(A+column%maxCharCount))
  90. }
  91. }
  92. func getColumnRowName(columnName []byte, rowIndex int) (columnRowName string) {
  93. l := len(columnName)
  94. columnName = strconv.AppendInt(columnName, int64(rowIndex), 10)
  95. columnRowName = string(columnName)
  96. columnName = columnName[:l]
  97. return
  98. }