File: write.go

package info (click to toggle)
golang-github-tealeg-xlsx 1.0.3%2Bgit20181024.dbf71b6-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 19,088 kB
  • sloc: makefile: 2
file content (112 lines) | stat: -rw-r--r-- 2,636 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package xlsx

import (
	"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())
		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())
		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
}