excel.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package common
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "strconv"
  7. "strings"
  8. "github.com/360EntSecGroup-Skylar/excelize/v2"
  9. )
  10. // #################
  11. // excel 对外接口 , demo 可以见test
  12. // #################
  13. type Excel interface {
  14. WriteSheet(sheetName string, sheetHeader []string, writer RowWriter) error // 写入sheet
  15. FlushWrite(writer io.Writer) error // 写出去
  16. GetSheetList() []string // 获取sheet-list
  17. ReadSheet(sheetName string) ([][]string, error) // 读取sheet
  18. }
  19. type Row interface {
  20. Write(v interface{}) // 每写入一个数据,ColumnIndex()就会+1, 推荐v为字符串类型
  21. ColumnIndex() int // 获取当前列所在的index,从0开始 (索引从0开始,主要是为了和数组对应起来)
  22. RowIndex() int // 获取当前行所在的index,从0开始 (索引从0开始,主要是为了和数组对应起来)
  23. }
  24. type RowWriter func(r Row) (hasNext bool) // 是否还要写入下一行
  25. // #################
  26. // 360 excel 实现
  27. // #################
  28. type _360Excel struct {
  29. *excelize.File
  30. }
  31. func NewWriter360Excel() Excel {
  32. file := excelize.NewFile()
  33. return &_360Excel{
  34. File: file,
  35. }
  36. }
  37. func NewReader360Excel(reader io.Reader) (Excel, error) {
  38. excel := new(_360Excel)
  39. r, err := excelize.OpenReader(reader)
  40. if err != nil {
  41. return nil, err
  42. }
  43. excel.File = r
  44. return excel, nil
  45. }
  46. type row struct {
  47. *excelize.File // out
  48. columnNum int // 第几列,0开始
  49. rowNum int // 第几行,excel的行数,从1开始,如果写了header从2开始
  50. offset int // 行的偏移量
  51. sheetName string // sheet_name
  52. err error // 运行中间的异常
  53. builder strings.Builder
  54. }
  55. func newRow(f *excelize.File, sheetName string, startRowNum int) *row {
  56. return &row{
  57. File: f,
  58. sheetName: sheetName,
  59. rowNum: startRowNum,
  60. offset: startRowNum, // row偏差
  61. columnNum: 1, // 初始化为1
  62. }
  63. }
  64. func (r *row) Write(v interface{}) {
  65. if r.err != nil {
  66. return
  67. }
  68. columnName, err := excelize.ColumnNumberToName(r.columnNum)
  69. if err != nil {
  70. r.err = err
  71. return
  72. }
  73. r.builder.WriteString(columnName)
  74. r.builder.WriteString(rowNumberName(r.rowNum))
  75. if err := r.SetCellValue(r.sheetName, r.builder.String(), v); err != nil {
  76. r.err = err
  77. return
  78. }
  79. // end handler
  80. r.builder.Reset()
  81. r.columnNum++
  82. }
  83. func (r *row) ColumnIndex() int {
  84. return r.columnNum - 1 // 偏差
  85. }
  86. func (r *row) RowIndex() int {
  87. return r.rowNum - r.offset // 偏差
  88. }
  89. func (r *row) increaseRow() {
  90. r.rowNum++
  91. r.columnNum = 1
  92. }
  93. func (e *_360Excel) FlushWrite(writer io.Writer) error {
  94. e.DeleteSheet("Sheet1")
  95. e.SetActiveSheet(0)
  96. return e.Write(writer)
  97. }
  98. func rowNumberName(rowNum int) string {
  99. return strconv.Itoa(rowNum)
  100. }
  101. // excel的index都是从1开始,和传统计数都有偏差!
  102. func (e *_360Excel) WriteSheet(sheetName string, sheetHeader []string, writer RowWriter) (err error) {
  103. // 抓取recover
  104. defer func() {
  105. if rerr := recover(); rerr != nil {
  106. err = errors.New(fmt.Sprintf("%+v", rerr))
  107. }
  108. }()
  109. // 校验,默认会有一个sheet1,所以不能和他使用的一样,因此需要最后删除
  110. if sheetName == "" || sheetName == "Sheet1" {
  111. return errors.New("sheetName不能为空或为Sheet1")
  112. }
  113. // 初始化 sheet
  114. e.NewSheet(sheetName)
  115. var (
  116. rowNum = 1 // excel的行是从1开始计数
  117. hasHeader = sheetHeader != nil && len(sheetHeader) > 0 // 是否有header
  118. )
  119. // header A1 B1 C1 D1 ... 写header
  120. for index, title := range sheetHeader {
  121. columnNumberName, err := excelize.ColumnNumberToName(index + 1) // excel列从A开始
  122. if err != nil {
  123. return err
  124. }
  125. if err := e.SetCellStr(sheetName, columnNumberName+rowNumberName(rowNum), title); err != nil {
  126. return err
  127. }
  128. }
  129. // row ++
  130. if hasHeader {
  131. rowNum++
  132. }
  133. row := newRow(e.File, sheetName, rowNum)
  134. // 循环写
  135. for writer(row) {
  136. if err := row.err; err != nil {
  137. return err
  138. }
  139. row.increaseRow()
  140. }
  141. return nil
  142. }
  143. func (e *_360Excel) GetSheetList() []string {
  144. return e.File.GetSheetList()
  145. }
  146. func (e *_360Excel) ReadSheet(sheetName string) ([][]string, error) {
  147. result, err := e.GetRows(sheetName)
  148. if err != nil {
  149. return nil, err
  150. }
  151. return result, nil
  152. }