Przeglądaj źródła

fmt.Stringer interface support in WriteSlice & WriteStruct

ivnivnch 10 lat temu
rodzic
commit
53181919fb
2 zmienionych plików z 74 dodań i 32 usunięć
  1. 35 28
      write.go
  2. 39 4
      write_test.go

+ 35 - 28
write.go

@@ -1,6 +1,9 @@
 package xlsx
 
-import "reflect"
+import (
+	"fmt"
+	"reflect"
+)
 
 // 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,
@@ -24,25 +27,29 @@ func (r *Row) WriteSlice(e interface{}, cols int) int {
 
 	var setCell func(reflect.Value)
 	setCell = func(val reflect.Value) {
-		switch val.Kind() { // underlying type of slice
-		case reflect.String:
+		switch t := val.Interface().(type) {
+		case int, int8, int16, int32:
 			cell := r.AddCell()
-			cell.SetString(val.Interface().(string))
-		case reflect.Int, reflect.Int8,
-			reflect.Int16, reflect.Int32:
+			cell.SetInt(t.(int))
+		case int64:
 			cell := r.AddCell()
-			cell.SetInt(val.Interface().(int))
-		case reflect.Int64:
+			cell.SetInt64(t)
+		case string:
 			cell := r.AddCell()
-			cell.SetInt64(val.Interface().(int64))
-		case reflect.Bool:
+			cell.SetString(t)
+		case float32, float64:
 			cell := r.AddCell()
-			cell.SetBool(val.Interface().(bool))
-		case reflect.Float64, reflect.Float32:
+			cell.SetFloat(t.(float64))
+		case bool:
 			cell := r.AddCell()
-			cell.SetFloat(val.Interface().(float64))
-		case reflect.Interface:
-			setCell(reflect.ValueOf(val.Interface()))
+			cell.SetBool(t)
+		case fmt.Stringer:
+			cell := r.AddCell()
+			cell.SetString(t.String())
+		default:
+			if val.Kind() == reflect.Interface {
+				setCell(reflect.ValueOf(t))
+			}
 		}
 	}
 
@@ -74,21 +81,21 @@ func (r *Row) WriteStruct(e interface{}, cols int) int {
 
 	var k int
 	for i := 0; i < n; i, k = i+1, k+1 {
-		f := v.Field(i).Kind()
 		cell := r.AddCell()
 
-		switch f {
-		case reflect.Int, reflect.Int8,
-			reflect.Int16, reflect.Int32:
-			cell.SetInt(v.Field(i).Interface().(int))
-		case reflect.Int64:
-			cell.SetInt64(v.Field(i).Interface().(int64))
-		case reflect.String:
-			cell.SetString(v.Field(i).Interface().(string))
-		case reflect.Float64, reflect.Float32:
-			cell.SetFloat(v.Field(i).Interface().(float64))
-		case reflect.Bool:
-			cell.SetBool(v.Field(i).Interface().(bool))
+		switch t := v.Field(i).Interface().(type) {
+		case int, int8, int16, int32:
+			cell.SetInt(t.(int))
+		case int64:
+			cell.SetInt64(t)
+		case string:
+			cell.SetString(t)
+		case float32, float64:
+			cell.SetFloat(t.(float64))
+		case bool:
+			cell.SetBool(t)
+		case fmt.Stringer:
+			cell.SetString(t.String())
 		default:
 			k-- // nothing set so reset to previous
 		}

+ 39 - 4
write_test.go

@@ -8,6 +8,17 @@ type WriteSuite struct{}
 
 var _ = Suite(&WriteSuite{})
 
+type testStringerImpl struct {
+	Value string
+}
+
+func (this testStringerImpl) String() string {
+	return this.Value
+}
+func (this *testStringerImpl) Set(val string) {
+	this.Value = val
+}
+
 // Test if we can write a struct to a row
 func (r *RowSuite) TestWriteStruct(c *C) {
 	var f *File
@@ -15,16 +26,20 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 	sheet, _ := f.AddSheet("Test1")
 	row := sheet.AddRow()
 	type e struct {
-		FirstName string
-		Age       int
-		GPA       float64
-		LikesPHP  bool
+		FirstName   string
+		Age         int
+		GPA         float64
+		LikesPHP    bool
+		Stringer    testStringerImpl
+		StringerPtr *testStringerImpl
 	}
 	testStruct := e{
 		"Eric",
 		20,
 		3.94,
 		false,
+		testStringerImpl{"Stringer"},
+		&testStringerImpl{"Pointer to Stringer"},
 	}
 	row.WriteStruct(&testStruct, -1)
 	c.Assert(row, NotNil)
@@ -33,11 +48,15 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 	c1, e1 := row.Cells[1].Int()
 	c2, e2 := row.Cells[2].Float()
 	c3 := row.Cells[3].Bool()
+	c4 := row.Cells[4].String()
+	c5 := row.Cells[5].String()
 
 	c.Assert(c0, Equals, "Eric")
 	c.Assert(c1, Equals, 20)
 	c.Assert(c2, Equals, 3.94)
 	c.Assert(c3, Equals, false)
+	c.Assert(c4, Equals, "Stringer")
+	c.Assert(c5, Equals, "Pointer to Stringer")
 
 	c.Assert(e1, Equals, nil)
 	c.Assert(e2, Equals, nil)
@@ -54,6 +73,8 @@ func (r *RowSuite) TestWriteSlice(c *C) {
 	type floatA []float64
 	type boolA []bool
 	type interfaceA []interface{}
+	type stringerA []testStringerImpl
+	type stringerPtrA []*testStringerImpl
 
 	s0 := strA{"Eric"}
 	row0 := sheet.AddRow()
@@ -99,4 +120,18 @@ func (r *RowSuite) TestWriteSlice(c *C) {
 	c.Assert(c42, Equals, 3.94)
 	c43 := row4.Cells[3].Bool()
 	c.Assert(c43, Equals, true)
+
+	s5 := stringerA{testStringerImpl{"Stringer"}}
+	row5 := sheet.AddRow()
+	row5.WriteSlice(&s5, -1)
+	c.Assert(row5, NotNil)
+	c5 := row5.Cells[0].String()
+	c.Assert(c5, Equals, "Stringer")
+
+	s6 := stringerPtrA{&testStringerImpl{"Pointer to Stringer"}}
+	row6 := sheet.AddRow()
+	row6.WriteSlice(&s6, -1)
+	c.Assert(row6, NotNil)
+	c6 := row6.Cells[0].String()
+	c.Assert(c6, Equals, "Pointer to Stringer")
 }