Go 语言 Excel 表格转成 Struct

- 最近用go语言的Excelize包实现xlsx读取发现一点问题。当xlsx末尾列数据为空时(下图中红框部分),如果存入到像[]string切片或者数组内,Go语言数组这种会自动忽略右边的空值,会出现行的长度不一致(比如第14行列数为4,15行列数为3,第18行直接没数据)。这比python的pandas难用多了,现总结有几种方法:1.修改原数据(在列末尾添加一个全是一样特殊字符的结束列或者把空cell用特殊字符填充),好处是数据都是对齐,缺点是费时费力。2.代码调整(2.1用数组方式接收字段,接收后需要判断该字段是否空,空就用一个特殊字符替代,然后插入数据库内 2.2用反射的方式实现,用结构体存储,字段为空也不影响)。综合优缺点,开始用2.2方法实现

 

image

包的导入

import (
"fmt"
"github.com/xuri/excelize/v2"
"reflect"
"strconv"
"strings"
)
// 定义结构体 TableColumn, “xlsx"是自定义标签
type TableColumn struct {
Classification string `json:"classification" xlsx:"分类"`
TagNumber string `json:"tagNumber" xlsx:"标签序号"`
FirstlyLabel string `json:"firstlyLabel" xlsx:"一级标签"`
SecondaryLabel string `json:"secondaryLabel" xlsx:"二级标签"`
TertiaryLabel string `json:"tertiaryLabel" xlsx:"三级标签"`
}
// 按行读取数据
func getRows(fileName string) [][]string {
file, err := excelize.OpenFile(fileName)
if err != nil {
panic(err)
}
defer file.Close()
rows, err := file.GetRows(file.GetSheetList()[0], excelize.Options{})
if err != nil {
panic(err)
}
return rows
}
// 初始化 标签序列 对应的 结构体字段 顺序
func initTag2FieldIdx(v interface{}, tagKey string) map[string]int {
u := reflect.TypeOf(v)
numField := u.NumField()
tag2fieldIndex := map[string]int{}
for i := 0; i < numField; i++ {
f := u.Field(i)
tagValue, ok := f.Tag.Lookup(tagKey)
if ok {
tag2fieldIndex[tagValue] = i
} else {
continue
}
}
return tag2fieldIndex
}
// 将 行数据 按照反射的方式转为结构体 TableColumn
func rowsToTableColumns(rows [][]string, tag2fieldIndex map[string]int) []*TableColumn {
var data []*TableColumn
// 默认第一行对应tag
head := rows[0]
for _, row := range rows[1:] {
tbCol := &TableColumn{}
rv := reflect.ValueOf(tbCol).Elem()
for i := 0; i < len(row); i++ {
colCell := row[i]
// 通过 tag 取到结构体字段下标
fieldIndex, ok := tag2fieldIndex[head[i]]
if !ok {
continue
}
colCell = strings.Trim(colCell, " ")
// 通过字段下标找到字段放射对象
v := rv.Field(fieldIndex)
// 根据字段的类型,选择适合的赋值方法
switch v.Kind() {
case reflect.String:
value := colCell
v.SetString(value)
case reflect.Int64, reflect.Int32:
value, err := strconv.Atoi(colCell)
if err != nil {
panic(err)
}
v.SetInt(int64(value))
case reflect.Float64:
value, err := strconv.ParseFloat(colCell, 64)
if err != nil {
panic(err)
}
v.SetFloat(value)
}
}
data = append(data, tbCol)
}
return data
}
func main() {
initTag2FieldIdx := initTag2FieldIdx(TableColumn{}, "xlsx")
rows := getRows("excel/test.xlsx")
tbCols := rowsToTableColumns(rows, initTag2FieldIdx)
for _, s := range tbCols {
fmt.Printf("%+v\n", s)
}
}

结果:
image

参考:

1. 小试牛刀:Go 反射帮我把 Excel 转成 Struct - Zioyi - 博客园 (cnblogs.com)

posted @   落樱纷飞  阅读(272)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示