脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go结合反射将结构体转换成Excel的过程详解

Go结合反射将结构体转换成Excel的过程详解

2022-10-14 11:49范闲 Golang

这篇文章主要介绍了Go结合反射将结构体转换成Excel的过程详解,大概思路是在Go的结构体中每个属性打上一个excel标签,利用反射获取标签中的内容,作为表格的Header,需要的朋友可以参考下

Excel中的一些概念

Go结合反射将结构体转换成Excel的过程详解

一个excel文件中可以包含多个sheet,一个sheet可以理解成一个表格

表格的每一行称为 Row

表格的每一行中的任意一个单元格称为 Cell

使用tealeg操作Excel

安装tealeg

?
1
go get github.com/tealeg/xlsx

使用tealeg新建一个表格

tealeg提供了傻瓜式API,主要流程为创建一个Sheet,在Sheet中添加Row,然后在Row中添加每个单元格的值,最终持久化到磁盘。

?
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
func TestTealeg(t *testing.T) {
    excel := xlsx.NewFile()
 
    // 新建一个sheet
    sheet, err := excel.AddSheet("Sheet1")
    if err != nil {
        t.Fatal(err)
    }
 
    // 创建首行
    headerRow := sheet.AddRow()
 
    // 设置行高
    headerRow.SetHeightCM(0.5)
 
    // 填充行中的单元格
    headerRow.AddCell().Value = "姓名"
    headerRow.AddCell().Value = "年龄"
 
    valList := [][]string{
        {"张三", "13"},
        {"李四", "14"},
        {"王五", "15"},
    }
 
    for _, line := range valList {
        row := sheet.AddRow()
        row.SetHeightCM(0.5)
        for _, v := range line {
            row.AddCell().Value = v
        }
    }
 
    // 持久化到磁盘
    if err := excel.Save("username.xlsx"); err != nil {
        t.Fatal(err)
    }
}

执行这个Test用例后,在项目的当前文件夹中会出现一个username.xlsx的表格,内容和前面介绍的excel概念中使用的表格是一个。

Go结合反射将结构体转换成Excel

  • 大概思路是在Go的结构体中每个属性打上一个excel标签
  • 利用反射获取标签中的内容,作为表格的Header
  • 利用反射获取Go结构体中的属性的值,组成一个map,key为从标签中excel反射获取的值,val为结构体属性具体的值,map的伪代码如下:map[excelTag]strucVal 类型为map[string]string
  • 如果一个array或者slice中的结构体需要转换成excel,那么只需要将每个元素转换成第 3 步提到的map作为一行,组成一个[]map[excelTag]strucVal然后遍历这个切片,追加到表格中即可。

反射获取每个Struct中的Tag

?
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
func getStructTagList(v interface{}, tag string) []string {
    var resList []string
    if v == nil {
        return resList
    }
    var item interface{}
    switch reflect.TypeOf(v).Kind() {
    case reflect.Slice, reflect.Array:
        values := reflect.ValueOf(v)
        if values.Len() == 0 {
            return resList
        }
        item = values.Index(0).Interface()
    case reflect.Struct:
        item = reflect.ValueOf(v).Interface()
    default:
        panic(fmt.Sprintf("type %v not support", reflect.TypeOf(v).Kind()))
    }
    typeOf := reflect.TypeOf(item)
    fieldNum := typeOf.NumField()
    for i := 0; i < fieldNum; i++ {
        resList = append(resList, typeOf.Field(i).Tag.Get(tag))
    }
    return resList
}

通过反射将结构体的值转换成map[excelTag]strucVal

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func getTagValMap(v interface{}, tag string) map[string]string {
    resMap := make(map[string]string)
    if v == nil {
        return resMap
    }
    typeOf := reflect.TypeOf(v)
    fieldNum := typeOf.NumField()
    for i := 0; i < fieldNum; i++ {
        structField := typeOf.Field(i)
        tagValue := structField.Tag.Get(tag)
        val := reflect.ValueOf(v).FieldByName(structField.Name)
        resMap[tagValue] = fmt.Sprintf("%v", val.Interface())
    }
    return resMap
}

利用反射将一个Silce,Array或者Struct转换成[]map[excelTag]strucVal

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func struct2MapTagList(v interface{}, tag string) []map[string]string {
    var resList []map[string]string
    switch reflect.TypeOf(v).Kind() {
    case reflect.Slice, reflect.Array:
        values := reflect.ValueOf(v)
        for i := 0; i < values.Len(); i++ {
            resList = append(resList, getTagValMap(values.Index(i).Interface(), tag))
        }
        break
    case reflect.Struct:
        val := reflect.ValueOf(v).Interface()
        resList = append(resList, getTagValMap(val, tag))
        break
    default:
        panic(fmt.Sprintf("type %v not support", reflect.TypeOf(v).Kind()))
    }
    return resList
}

通过tealeg将[]map[excelTag]strucVal转换成Excel

通过上面两步,已经可以将一个结构体,切片或者list转换成了一个[]map[excelTag]strucVal类型的切片,下面我们只需要调用tealeg转换成excel

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func Struct2Xlsx(v interface{}) (*xlsx.File, error) {
    var tag = "excel"
    tagList := getStructTagList(v, tag)
    mapTagList := struct2MapTagList(v, tag)
    excelFile := xlsx.NewFile()
    sheet, err := excelFile.AddSheet("Sheet1")
    if err != nil {
        return nil, err
    }
    headerRow := sheet.AddRow()
    for _, tagVal := range tagList {
        headerRow.SetHeightCM(0.5)
        headerRow.AddCell().Value = tagVal
    }
    for _, mapTagVal := range mapTagList {
        row := sheet.AddRow()
        for _, tagVal := range tagList {
            row.SetHeightCM(0.5)
            row.AddCell().Value = mapTagVal[tagVal]
        }
    }
    return excelFile, nil
}

运行测试用例验证

?
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
type Username struct {
    Name string `excel:"姓名"`
    Age  int    `excel:"年龄"`
}
 
func TestStruct2Excet(t *testing.T) {
    var data = []Username{
        {
            Name: "张三",
            Age:  13,
        },
        {
            Name: "李四",
            Age:  14,
        },
        {
            Name: "王五",
            Age:  15,
        },
    }
    excel, err := Struct2Xlsx(data)
    if err != nil {
        t.Fatal(err)
    }
    if err := excel.Save("username.xlsx"); err != nil {
        t.Fatal(err)
    }
}

测试运行成功后,会在项目目录创建一个username.xlsx的文件,这个文件就是我们的结构体转换成excel的结果

到此这篇关于Go结合反射将结构体转换成Excel的过程详解的文章就介绍到这了,更多相关Go结构体转换成Exce内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7106508948299055112

延伸 · 阅读

精彩推荐
  • GolangGo 实现 WebSockets和什么是 WebSockets

    Go 实现 WebSockets和什么是 WebSockets

    这篇文章主要介绍了Go 实现 WebSockets和什么是 WebSockets,WebSockets 是构建实时应用程序的第一大解决方案,在线游戏、即时通讯、跟踪应用程序等,下文相关...

    宇宙之一粟11842022-09-28
  • Golang深入Golang中的sync.Pool详解

    深入Golang中的sync.Pool详解

    这篇文章主要介绍了深入Golang中的sync.Pool详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    sunsky30311992021-05-27
  • Golang一篇文章教会你Go语言基础之结构体反射

    一篇文章教会你Go语言基础之结构体反射

    本篇从主要讲述Go反射结构体的相关知识:反射在结构体中的应用,如何单独反射结构体字段信息,ValueOf其他操作,如何放射结构体绑定的方法。 ...

    Go语言进阶学习5512020-12-20
  • Golanggolang协程池模拟实现群发邮件功能

    golang协程池模拟实现群发邮件功能

    这篇文章主要介绍了golang协程池模拟实现群发邮件功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    陶士涵9372021-06-15
  • Golang深入理解Golang的单元测试和性能测试

    深入理解Golang的单元测试和性能测试

    Go语言提供了强大的测试工具,下面这篇文章主要给大家介绍了关于Golang单元测试和性能测试的相关资料,文中通过示例代码给大家详细介绍了单元测试和...

    shenlanzifa5352020-05-08
  • GolangGo语言中的Array、Slice、Map和Set使用详解

    Go语言中的Array、Slice、Map和Set使用详解

    这篇文章主要介绍了Go语言中的Array、Slice、Map和Set使用详解,本文给出了它们的创建、使用、多维等代码实例,需要的朋友可以参考下 ...

    junjie5632020-04-09
  • GolangGo语言基本的语法和内置数据类型初探

    Go语言基本的语法和内置数据类型初探

    这篇文章主要介绍了Go语言基本的语法和内置数据类型,是golang入门学习中的基础知识,需要的朋友可以参考下 ...

    脚本之家3882020-04-28
  • Golang深入理解go slice结构

    深入理解go slice结构

    这篇文章主要介绍了go slice结构,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧...

    好吃吗8462021-11-13