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

目录
  • Excel中的一些概念
  • 使用tealeg操作Excel
  • 安装tealeg
  • 使用tealeg新建一个表格
  • Go结合反射将结构体转换成Excel
  • 反射获取每个Struct中的Tag
  • 通过反射将结构体的值转换成map[excelTag]strucVal
  • 利用反射将一个Silce,Array或者Struct转换成[]map[excelTag]strucVal
  • 通过tealeg将[]map[excelTag]strucVal转换成Excel
  • 运行测试用例验证

Excel中的一些概念

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

表格的每一行称为 Row

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

使用tealeg操作Excel

安装tealeg

go get github.com/tealeg/xlsx

使用tealeg新建一个表格

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

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

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

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

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

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
}

运行测试用例验证

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • go语言通过反射创建结构体、赋值、并调用对应的操作

    我就废话不多说了,大家还是直接看代码吧~ package main import ( "fmt" "reflect" "testing" ) type Call struct { Num1 int Num2 int } func (call Call) GetSub(name string){ fmt.Printf("%v 完成了减法运算,%v - %v = %v \n", name, call.Num1, call.Num2

  • Go 结构体、数组、字典和 json 字符串的相互转换方法

    Go 语言中 encoding/json 包可以很方便的将结构体.数组.字典转换为 json 字符串. 引用 import "encoding/json" 解析语法 // v 传入结构体.数组等实例变量 // []byte 字节数组 // error 可能会有的错误 func Marshal(v interface{}) ([]byte, error) 反解析 // []byte 字节数组 // v 传入结构体.数组等实例变量的指针地址 // error 可能会有的错误 func Un

  • go语言通过反射获取和设置结构体字段值的方法

    本文实例讲述了go语言通过反射获取和设置结构体字段值的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: type MyStruct struct {         N int } n := MyStruct{ 1 } // get immutable := reflect.ValueOf(n) val := immutable.FieldByName("N").Int() fmt.Printf("N=%d\n", val) // prints

  • 浅谈Go语言中的结构体struct & 接口Interface & 反射

    结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struct类型理解为类,可以定义方法,和函数定义有些许区别: struct类型是值类型. struct定义 type User struct { Name string Age int32 mess string } var user User var user1 *User = &User{} var user2 *User = new(User) struct使用 下面示例中user1和

  • golang 如何用反射reflect操作结构体

    背景 需要遍历结构体的所有field 对于exported的field, 动态set这个field的value 对于unexported的field, 通过强行取址的方法来获取该值(tricky?) 思路 下面的代码实现了从一个strct ptr对一个包外结构体进行取值的操作,这种场合在笔者需要用到反射的场合中出现比较多 simpleStrtuctField 函数接受一个结构体指针,因为最后希望改变其值,所以传参必须是指针.然后解引用. 接下来遍历结构体的每个field, exported字段是

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

    目录 Excel中的一些概念 使用tealeg操作Excel 安装tealeg 使用tealeg新建一个表格 Go结合反射将结构体转换成Excel 反射获取每个Struct中的Tag 通过反射将结构体的值转换成map[excelTag]strucVal 利用反射将一个Silce,Array或者Struct转换成[]map[excelTag]strucVal 通过tealeg将[]map[excelTag]strucVal转换成Excel 运行测试用例验证 Excel中的一些概念 一个excel文

  • 用python把ipynb文件转换成pdf文件过程详解

    这两天一直在做课件,我个人一直不太喜欢PPT这个东西--能不用就不用,我个人特别崇尚极简风. 谁让我们是程序员呢,所以就爱上了Jupyter写课件,讲道理markdown也是个非常不错的写书格式啊. 安装Jupyter其实非常简单,你会python就应该会用jupyter,起码简单的 pip install jupyter, jupyter notebook 要会对伐- 好那接下来就是使用jupyter了,启动jupyter后,使用浏览器访问相应IP:Port就可以使用了.没错,jupyter就

  • python把ipynb文件转换成pdf文件过程详解

    这两天一直在做课件,我个人一直不太喜欢PPT这个东西--能不用就不用,我个人特别崇尚极简风. 谁让我们是程序员呢,所以就爱上了Jupyter写课件,讲道理markdown也是个非常不错的写书格式啊. 安装Jupyter其实非常简单,你会python就应该会用jupyter,起码简单的 pip install jupyter, jupyter notebook 要会对伐- 好那接下来就是使用jupyter了,启动jupyter后,使用浏览器访问相应IP:Port就可以使用了.没错,jupyter就

  • C语言结构体数组的定义和使用详解

    目录 介绍 结构体数组定义时初始化 补充 介绍 一个结构体变量可以存放一个学生的一组信息,可是如果有 10 个学生呢?难道要定义 10 个结构体变量吗?难道上面的程序要复制和粘贴 10 次吗? 很明显不可能,这时就要使用数组.结构体中也有数组,称为结构体数组.它与前面讲的数值型数组几乎是一模一样的,只不过需要注意的是,结构体数组的每一个元素都是一个结构体类型的变量,都包含结构体中所有的成员项. 定义结构体数组的方法很简单,同定义结构体变量是一样的,只不过将变量改成数组.或者说同前面介绍的普通数组

  • Python深度学习之Keras模型转换成ONNX模型流程详解

    目录 从Keras转换成PB模型 从PB模型转换成ONNX模型 改变现有的ONNX模型精度 部署ONNX 模型 总结 从Keras转换成PB模型 请注意,如果直接使用Keras2ONNX进行模型转换大概率会出现报错,这里笔者曾经进行过不同的尝试,最后都失败了. 所以笔者的推荐的情况是:首先将Keras模型转换为TensorFlow PB模型. 那么通过tf.keras.models.load_model()这个函数将模型进行加载,前提是你有一个基于h5格式或者hdf5格式的模型文件,最后再通过改

  • php实现将二维关联数组转换成字符串的方法详解

    本文实例讲述了php实现将二维关联数组转换成字符串的方法.分享给大家供大家参考,具体如下: 需求 项目中遇到了二维关联数组转字符串的问题,查阅相关资料,写了如下程序,并且能过滤重复的关键字. 举例,php的二维数组如下: $name = array( "self" => "wangzhengyi", "student" => array( "chenshan", "xiaolingang" ),

  • 深入分析C语言中结构体指针的定义与引用详解

    指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员:[例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出. 复制代码 代码如下: #include <stdlib.h> /*使用m a l l o c (

  • C++结构体struct和类class区别详解

    之前因为都在忙着毕业的开题答辩与投稿论文的事宜,一直没有时间更新这个系列的文章.师弟看了上一篇雾中风景的文章,希望我继续把这个系列的文章写下去.坦白说,C++的特性很多,这也不是教学指南的文章,我会选取一些自己在学习C++过程之中值得探讨的问题和大家聊一聊,来抛砖引玉.好的,今天先放点开胃菜,和大家聊聊struct与class关键字. 1.struct关键字: 在C++语言作为C语言的一个超集,是兼容C语言的所有语法规则的.C语言是我学习的第一门编程语言,我自然对于其中的语法规则十分熟悉,C语言

  • asp.net开发sql server转换成oracle的方法详解

    前言 因为前段时间我们公司项目 要把sql server 转oracle,发现网上这方面的资料较少,所以在这里分享一下心得,也记录一下问题,下面话不多说了,来一起看看详细的介绍: 开始我研究了一段时间 然后下载了 oracle 11g 版本 和 PL/SQL(客户端) 和sql server 不同的是 oracle 没有自己的客户端 需要用第三方的软件运行 PL/SQL 就是一个 sqldeveloper 也是一个,PL/SQL 我觉得比较稳定一点.但是2个都安装的话 刚好互补了 oracle

  • Golang 利用反射对结构体优雅排序的操作方法

    最近开始实习,工作技术栈主要Python和Golang,目前的任务把Python模块重构为GO模块,然后出现了一个问题,就是要将一个结构体按结构体中各个字段进行排序,然后写入Redis,对于Pyhon来说for循环就能解决,但是对于Go语言来说,每一次排序都要写一个比较函数,写出来的代码太丑,非常长,代码结构是一致,只是比较字段不一样而已,个人无法接受啊,网上搜索也没搜索到合适解决方法,所以自己想了一个解决方法来优雅排序. 比较函数: func reflectCmp(i, j interface

随机推荐