将excel内容解析到golang struct

excel映射解析Golang

工具库地址:excelize360-mapping-struct gitee

_

接触到了一个excel批量导入的需求,网上找了下对于excel的数据的验证解析实在是没找到什么好的工具,找到个360开源库,发现结合需求实现起来还是有些麻烦,毕竟excel千变万化,加上数据还需要做各种校验,但万变不离其宗,回归到代码语言本身上来,分析下数据结构,最好的方式还是映射绑定数据到结构体struct,让编码开发也更加友好。
golang 基于excelize360实现的excel解析工具库,通过结构体字段tag实现映射数据到结构体,并加入了一些预期的错误格式,可根据实际运用情况加入更多错误模板,具体使用方式clone本仓库代码,可直接在本地运行调试。

支持的tag标签

tag属性说明
mapping将数据进行转义,一般数据表格中都是以明文输入输出数据,但在实际代码业务中只用0或1表示状态的场景。例:mapping(已完成:1,未完成:2)
unique标识唯一性,在同列中唯一。例:unique(true)
date时间格式化,该属性分两部分,第一个参数:该单元格的时间日期格式(注意该格式非在数据表格中明文显示的格式,要查看该单元格在excel中的时间格式设置);第二个参数:将转化到的格式。例:date(01-02-06,2006-01-02)
name指定该属性所在字段绑定的excel列名称,一般情况下数据表格都会指定每一列代表的含义,该属性十分重要,也是映射数据的主要参考依据,需要保持excel列名跟name属性保持一致,例:name(*名称)

以上tag属性统一作用在 excel 标签下,如某个字段需要绑定多个属性,属性间用 “;” 分隔。
结构体定义示例:

type Project struct {
	Name       string      `json:"project_name" excel:"name(*名称);unique(true)"`
	StartTime  *string     `json:"start_time" excel:"name(开始时间);date(01-02-06,2006-01-02)"`
	Status     int         `json:"Status" excel:"name(状态);mapping(已完成:1,未完成:2)"`
	Statistics *Statistics `json:"statistics"`
	Result     struct {
		Count *int `json:"count" excel:"name(总数)"`
	} `json:"result"`
	Time time.Time `json:"time"`
}

type Statistics struct {
	Num int `json:"num" excel:"name(数量)"`
}

自定义验证接口

工具内置一个接口,可根据需求选择性实现该接口。

type MappingStruct interface {
	ExcelRowProcess(res *Result) error
}

通过已经绑定execl标签的结构体实现接口,可对每一行数据(其实就是可以把该结构体看作是每一行数据的模板,数据进行映射操作时每一行映射完都会调用一次该接口)进行自定义校验或进行数据改值(每一行数据都会自动创建新的指针指向并复制初始指针传入的内容)等操作,说明:如果在实现的接口中需要事务性的操作,可以将相关存储引擎通过初始指针进行传递。

接口实现示例:

func (p *Project) ExcelRowProcess(res *excel.Result) error {
	log.Println(p.Statistics.Num, *p.Result.Count)
	valid := validation.Validation{}
	valid.Match(p.Name, regexp.MustCompile("^[-_a-zA-Z一-龥]{1,64}$"), strconv.Itoa(excel.ParamUnqualified))
	for _, err := range valid.Errors {
		errType, _ := strconv.Atoi(err.Key)
		res.AddError(errType, "名称")
	}
	return nil
}
p := new(Project)
p.Time = time.Now() //每一行数据都可复用
processor, err := excel.NewProcessor(p, true)
if err != nil {
    log.Println(err.Error())
    return
}

NewProcessor: new一个处理器,第二个参数表示是否开启验证,为false的话,自定义的验证就不会被调用了。
接口提供返回error参数,注意如果返回参数不为空,解析会立马停止,并返回该错误,一般在致命错误下返回该错误,一般的验证错误可见下边数据行验证错误的说明。

Result——内置的错误处理工具与数据映射结果处理

result提供了四个方法,可在实现自定义验证接口中与映射解析返回的结果参数获取该对象进行方法调取。

方法名称说明
AddError主要用于自定义验证接口中,可结合下边介绍错误处理模板添加行错误,提供了一个错误码(错误格式的编码)参数与错误格式化值参数,类似golang中fmt.Sprintf 方法
HasError用于数据解析后,判断excel解析结果是否存在错误,返回错误列表,错误列表由行号+错误信息集合组成,标识了哪一行数据产生了哪些错误
List返回当前已经完成解析数据行的集合,注意返回类型是一个[]interface{}
Format将已经完成解析数据行的集合通过json序列化反序列化方法在解析到指定的对象中

数据行验证错误

数据解析过程中会对每一行数据进行解析检验,发现不符合要求的数据单元,并不会立即结束解析,而是会将所有行的错误进行整合,最终将错误结果以 行号+错误信息集合 当作一项放入到错误集合中返回最终结果。

内部验证错误

内部验证错误主要与excel格式的错误或预期定义错误息息相关,错误集合介绍如下:

格式组成说明
%s[%s]不可重复列名[列值]unique属性,在做列唯一性校验时提示的错误
%s单元格格式错误列名date属性,excel设置的单元格时间与结构体date属性第一个参数不一致时提示的错误
%s单元格存在非法输入列名mapping属性,当单元格输入的值不在mapping定义的转义列表中时提示的错误
%s单元格非法输入,参数非bool类型值列名单元格输入的值与结构体对应字段类型不一致输出的错误
%s单元格非法输入,参数非整形数值列名单元格输入的值与结构体对应字段类型不一致输出的错误
%s单元格非法输入,参数非浮点型数值列名单元格输入的值与结构体对应字段类型不一致输出的错误

自定义错误

自定义错误工具也定义了一些可直接使用的模板,也可根据实际需求自定义,在自定义的验证接口中使用,接口已有错误模板如下:

错误码格式组成说明
ParamCannotBeEmpty%s参数不可为空自定义(例:res.AddError(excel.ParamCannotBeEmpty, "名称"))适用参数空值
ParamUnqualified%s参数格式不正确自定义适用正则校验
AlreadyExists%s已存在自定义适用判断已存在
NotExist%s不存在自定义适用判断不存在
NotInConfigurationItems%s不在配置项中自定义适用输入的数据不在指定的集合中
TimeFormatError%s时间格式错误自定义适用时间格式错误
DataOutsideExpectedLimits%s数据不在预期限制范围自定义适用数据在一定范围内的校验
ParamInvalid%s参数验证失败自定义适用没有具体定义的错误

自定义错误格式模板信息,直接在工具文件头部已列出的模板下进行添加即可。

const (
	ParamError = iota
	ParamInvalid
	ParamUnqualified
	AlreadyExists
	NotExist
	NotInConfigurationItems
	TimeFormatError
	DataOutsideExpectedLimits
	ParamCannotBeEmpty
)

var errFormatList = map[int]excelErr{
	ParamCannotBeEmpty:        {"%s参数不可为空"},
	ParamUnqualified:          {"%s参数格式不正确"},
	AlreadyExists:             {"%s已存在"},
	NotExist:                  {"%s不存在"},
	NotInConfigurationItems:   {"%s不在配置项中"},
	TimeFormatError:           {"%s时间格式错误"},
	DataOutsideExpectedLimits: {"%s数据不在预期限制范围"},
	ParamInvalid:              {"%s参数验证失败"},
}

其他具体实现以及更多详细使用方式 main 方法中已经实现

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
回答: 在Go语言中,struct是一种数据类型,用于定义自定义的复合数据结构。struct可以包含多个字段,每个字段都有自己的类型和名称。可以使用struct关键字来定义一个struct类型,并在大括号内定义字段。\[1\]在struct中,还可以使用内嵌结构体的方式来组织数据。内嵌结构体是指在一个结构体中嵌入另一个结构体作为其字段。这样可以实现结构体的组合和复用。\[2\]在使用struct时,可以使用简洁的语法格式来创建和初始化结构体变量。可以使用结构体类型名加大括号的方式来创建一个结构体变量,并为每个字段赋值。也可以使用键值对的方式来指定字段的值。\[3\] #### 引用[.reference_title] - *1* *3* [Golang 结构体](https://blog.csdn.net/weixin_47243236/article/details/122028539)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Golang 入门 : 结构体(struct)](https://blog.csdn.net/weixin_30753873/article/details/97302216)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值