write.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package xlsx
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "reflect"
  6. "time"
  7. )
  8. // Writes an array to row r. Accepts a pointer to array type 'e',
  9. // and writes the number of columns to write, 'cols'. If 'cols' is < 0,
  10. // the entire array will be written if possible. Returns -1 if the 'e'
  11. // doesn't point to an array, otherwise the number of columns written.
  12. func (r *Row) WriteSlice(e interface{}, cols int) int {
  13. if cols == 0 {
  14. return cols
  15. }
  16. // make sure 'e' is a Ptr to Slice
  17. v := reflect.ValueOf(e)
  18. if v.Kind() != reflect.Ptr {
  19. return -1
  20. }
  21. v = v.Elem()
  22. if v.Kind() != reflect.Slice {
  23. return -1
  24. }
  25. // it's a slice, so open up its values
  26. n := v.Len()
  27. if cols < n && cols > 0 {
  28. n = cols
  29. }
  30. var setCell func(reflect.Value)
  31. setCell = func(val reflect.Value) {
  32. switch t := val.Interface().(type) {
  33. case time.Time:
  34. cell := r.AddCell()
  35. cell.SetValue(t)
  36. case fmt.Stringer: // check Stringer first
  37. cell := r.AddCell()
  38. cell.SetString(t.String())
  39. case sql.NullString: // check null sql types nulls = ''
  40. cell := r.AddCell()
  41. if cell.SetString(``); t.Valid {
  42. cell.SetValue(t.String)
  43. }
  44. case sql.NullBool:
  45. cell := r.AddCell()
  46. if cell.SetString(``); t.Valid {
  47. cell.SetBool(t.Bool)
  48. }
  49. case sql.NullInt64:
  50. cell := r.AddCell()
  51. if cell.SetString(``); t.Valid {
  52. cell.SetValue(t.Int64)
  53. }
  54. case sql.NullFloat64:
  55. cell := r.AddCell()
  56. if cell.SetString(``); t.Valid {
  57. cell.SetValue(t.Float64)
  58. }
  59. default:
  60. switch val.Kind() { // underlying type of slice
  61. case reflect.String, reflect.Int, reflect.Int8,
  62. reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, reflect.Float32:
  63. cell := r.AddCell()
  64. cell.SetValue(val.Interface())
  65. case reflect.Bool:
  66. cell := r.AddCell()
  67. cell.SetBool(t.(bool))
  68. case reflect.Interface:
  69. setCell(reflect.ValueOf(t))
  70. }
  71. }
  72. }
  73. var i int
  74. for i = 0; i < n; i++ {
  75. setCell(v.Index(i))
  76. }
  77. return i
  78. }
  79. // Writes a struct to row r. Accepts a pointer to struct type 'e',
  80. // and the number of columns to write, `cols`. If 'cols' is < 0,
  81. // the entire struct will be written if possible. Returns -1 if the 'e'
  82. // doesn't point to a struct, otherwise the number of columns written
  83. func (r *Row) WriteStruct(e interface{}, cols int) int {
  84. if cols == 0 {
  85. return cols
  86. }
  87. v := reflect.ValueOf(e).Elem()
  88. if v.Kind() != reflect.Struct {
  89. return -1 // bail if it's not a struct
  90. }
  91. n := v.NumField() // number of fields in struct
  92. if cols < n && cols > 0 {
  93. n = cols
  94. }
  95. var k int
  96. for i := 0; i < n; i, k = i+1, k+1 {
  97. f := v.Field(i)
  98. switch t := f.Interface().(type) {
  99. case time.Time:
  100. cell := r.AddCell()
  101. cell.SetValue(t)
  102. case fmt.Stringer: // check Stringer first
  103. cell := r.AddCell()
  104. cell.SetString(t.String())
  105. case sql.NullString: // check null sql types nulls = ''
  106. cell := r.AddCell()
  107. if cell.SetString(``); t.Valid {
  108. cell.SetValue(t.String)
  109. }
  110. case sql.NullBool:
  111. cell := r.AddCell()
  112. if cell.SetString(``); t.Valid {
  113. cell.SetBool(t.Bool)
  114. }
  115. case sql.NullInt64:
  116. cell := r.AddCell()
  117. if cell.SetString(``); t.Valid {
  118. cell.SetValue(t.Int64)
  119. }
  120. case sql.NullFloat64:
  121. cell := r.AddCell()
  122. if cell.SetString(``); t.Valid {
  123. cell.SetValue(t.Float64)
  124. }
  125. default:
  126. switch f.Kind() {
  127. case reflect.String, reflect.Int, reflect.Int8,
  128. reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, reflect.Float32:
  129. cell := r.AddCell()
  130. cell.SetValue(f.Interface())
  131. case reflect.Bool:
  132. cell := r.AddCell()
  133. cell.SetBool(t.(bool))
  134. default:
  135. k-- // nothing set so reset to previous
  136. }
  137. }
  138. }
  139. return k
  140. }