write.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. // Writes a struct to row r. Accepts a pointer to struct type 'e',
  59. // and the number of columns to write, `cols`. If 'cols' is < 0,
  60. // the entire struct will be written if possible. Returns -1 if the 'e'
  61. // doesn't point to a struct, otherwise the number of columns written
  62. func (r *Row) WriteStruct(e interface{}, cols int) int {
  63. if cols == 0 {
  64. return cols
  65. }
  66. v := reflect.ValueOf(e).Elem()
  67. if v.Kind() != reflect.Struct {
  68. return -1 // bail if it's not a struct
  69. }
  70. n := v.NumField() // number of fields in struct
  71. if cols < n && cols > 0 {
  72. n = cols
  73. }
  74. var k int
  75. for i := 0; i < n; i, k = i+1, k+1 {
  76. f := v.Field(i)
  77. switch t := f.Interface().(type) {
  78. case time.Time:
  79. cell := r.AddCell()
  80. cell.SetValue(t)
  81. case fmt.Stringer: // check Stringer first
  82. cell := r.AddCell()
  83. cell.SetString(t.String())
  84. default:
  85. switch f.Kind() {
  86. case reflect.String, reflect.Int, reflect.Int8,
  87. reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, reflect.Float32:
  88. cell := r.AddCell()
  89. cell.SetValue(f.Interface())
  90. case reflect.Bool:
  91. cell := r.AddCell()
  92. cell.SetBool(t.(bool))
  93. default:
  94. k-- // nothing set so reset to previous
  95. }
  96. }
  97. }
  98. return k
  99. }