123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- package xlsx
- import (
- "database/sql"
- "fmt"
- "reflect"
- "time"
- )
- // Writes an array to row r. Accepts a pointer to array type 'e',
- // and writes the number of columns to write, 'cols'. If 'cols' is < 0,
- // the entire array will be written if possible. Returns -1 if the 'e'
- // doesn't point to an array, otherwise the number of columns written.
- func (r *Row) WriteSlice(e interface{}, cols int) int {
- if cols == 0 {
- return cols
- }
- // make sure 'e' is a Ptr to Slice
- v := reflect.ValueOf(e)
- if v.Kind() != reflect.Ptr {
- return -1
- }
- v = v.Elem()
- if v.Kind() != reflect.Slice {
- return -1
- }
- // it's a slice, so open up its values
- n := v.Len()
- if cols < n && cols > 0 {
- n = cols
- }
- var setCell func(reflect.Value)
- setCell = func(val reflect.Value) {
- switch t := val.Interface().(type) {
- case time.Time:
- cell := r.AddCell()
- cell.SetValue(t)
- case fmt.Stringer: // check Stringer first
- cell := r.AddCell()
- cell.SetString(t.String())
- case sql.NullString: // check null sql types nulls = ''
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.String)
- }
- case sql.NullBool:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetBool(t.Bool)
- }
- case sql.NullInt64:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.Int64)
- }
- case sql.NullFloat64:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.Float64)
- }
- default:
- switch val.Kind() { // underlying type of slice
- case reflect.String, reflect.Int, reflect.Int8,
- reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, reflect.Float32:
- cell := r.AddCell()
- cell.SetValue(val.Interface())
- case reflect.Bool:
- cell := r.AddCell()
- cell.SetBool(t.(bool))
- case reflect.Interface:
- setCell(reflect.ValueOf(t))
- }
- }
- }
- var i int
- for i = 0; i < n; i++ {
- setCell(v.Index(i))
- }
- return i
- }
- // Writes a struct to row r. Accepts a pointer to struct type 'e',
- // and the number of columns to write, `cols`. If 'cols' is < 0,
- // the entire struct will be written if possible. Returns -1 if the 'e'
- // doesn't point to a struct, otherwise the number of columns written
- func (r *Row) WriteStruct(e interface{}, cols int) int {
- if cols == 0 {
- return cols
- }
- v := reflect.ValueOf(e).Elem()
- if v.Kind() != reflect.Struct {
- return -1 // bail if it's not a struct
- }
- n := v.NumField() // number of fields in struct
- if cols < n && cols > 0 {
- n = cols
- }
- var k int
- for i := 0; i < n; i, k = i+1, k+1 {
- f := v.Field(i)
- switch t := f.Interface().(type) {
- case time.Time:
- cell := r.AddCell()
- cell.SetValue(t)
- case fmt.Stringer: // check Stringer first
- cell := r.AddCell()
- cell.SetString(t.String())
- case sql.NullString: // check null sql types nulls = ''
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.String)
- }
- case sql.NullBool:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetBool(t.Bool)
- }
- case sql.NullInt64:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.Int64)
- }
- case sql.NullFloat64:
- cell := r.AddCell()
- if cell.SetString(``); t.Valid {
- cell.SetValue(t.Float64)
- }
- default:
- switch f.Kind() {
- case reflect.String, reflect.Int, reflect.Int8,
- reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64, reflect.Float32:
- cell := r.AddCell()
- cell.SetValue(f.Interface())
- case reflect.Bool:
- cell := r.AddCell()
- cell.SetBool(t.(bool))
- default:
- k-- // nothing set so reset to previous
- }
- }
- }
- return k
- }
|