write.go 2.7 KB

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