write.go 3.0 KB

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