export.go 2.6 KB

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