内容简介:项目架构:Echo+Gorm+excelize依赖开源项目:开源项目中文文档:
项目架构:Echo+Gorm+excelize
依赖开源项目: github.com/360EntSecGroup-Skylar/excelize
开源项目中文文档: https://xuri.me/excelize/zh-hans/
excel模板
image.png
func ImportAccountByExcel(c echo.Context) error {
//文件地址
path := c.FormValue("path")
if path == "" {
return utils.ErrorNull(c, "请上传excel文件")
}
path = strings.TrimLeft(path, "/")
if flag, _ := utils.PathExists(path); !flag {
return utils.ErrorNull(c, "未找到excel文件")
}
//path := "files/excel/account_template_test.xlsx"
//excel表
sheetName := "Sheet1"
xlsx, err := excelize.OpenFile(path)
if err != nil {
return utils.ErrorNull(c, fmt.Sprintf("打开excel失败,error:%s", err.Error()))
}
//excel错误样式,黄色背景
style, _ := xlsx.NewStyle(`{"border":[{"type":"left","color":"000000","style":1},{"type":"top","color":"000000","style":1},{"type":"bottom","color":"000000","style":1},{"type":"right","color":"000000","style":1}],"fill":{"type":"pattern","color":["#ffeb00"],"pattern":1},"alignment":{"horizontal":"left","ident":1,"vertical":"center","wrap_text":true}}`)
//sheet名称
rows := xlsx.GetRows(sheetName)
var ip = c.RealIP()
var now = time.Now()
var partyId int64 = 1
var account *model.Account
var accountInfo *model.AccountInfo
var dateStr, tempStr string
var errorMap = map[int]interface{}{}
var errorMsg []string
var org model.PartyOrg
var partyPost model.PartyPost
//模板错误
if len(rows) <= 2 {
return utils.ErrorNull(c, "excel格式错误或无有效数据")
}
//无有效数据
if len(rows[2]) < 25 {
return utils.ErrorNull(c, "excel格式错误或无有效数据")
}
for rIndex, row := range rows {
//跳过提示行、标题行
if rIndex != 0 && rIndex != 1 {
errorMsg = []string{}
accountInfo = new(model.AccountInfo)
account = new(model.Account)
//姓名
account.FullName = utils.Trim(row[0])
if account.FullName == "" {
errorMsg = append(errorMsg, "姓名不能为空")
} else if len(account.FullName) >= 50 {
errorMsg = append(errorMsg, "姓名字符过长")
}
//性别
account.Gender = utils.Trim(row[1])
if account.Gender == "" {
errorMsg = append(errorMsg, "性别为必填项")
} else if account.Gender != enum.GENDER_MALE && account.Gender != enum.GENDER_FEMALE {
errorMsg = append(errorMsg, "性别错误,值范围:男、女")
}
//手机号
account.Mobile = utils.Trim(row[2])
if account.Mobile == "" {
errorMsg = append(errorMsg, "手机号码为必填项")
} else if !utils.IsMobile(account.Mobile) {
errorMsg = append(errorMsg, "手机号码格式错误")
}
account.Name = account.Mobile
//出生日期
dateStr = utils.Trim(row[3])
account.DateOfBirth, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "出生日期格式错误")
}
//在岗状态
accountInfo.WorkStatus = utils.Trim(row[4])
switch accountInfo.WorkStatus {
case "在岗", "待聘人员", "农民工", "停薪留职", "排休人员", "离退休", "其他", "":
break
default:
errorMsg = append(errorMsg, "在岗状态错误,值范围:在岗, 待聘人员, 农民工, 停薪留职, 排休人员, 离退休, 其他")
break
}
//民族
accountInfo.Nation = utils.Trim(row[5])
if len(accountInfo.Nation) > 50 {
errorMsg = append(errorMsg, "民族字符串过长")
}
//籍贯
accountInfo.NativePlace = utils.Trim(row[6])
if len(accountInfo.Nation) > 100 {
errorMsg = append(errorMsg, "籍贯字符串过长")
}
//身份证
accountInfo.Idcard = utils.Trim(row[7])
if accountInfo.Idcard != "" {
if len(accountInfo.Idcard) != 15 && len(accountInfo.Idcard) != 18 {
errorMsg = append(errorMsg, "身份证格式错误仅,支持15、18位")
}
}
//学历
accountInfo.Education = utils.Trim(row[8])
switch accountInfo.Education {
case "博士", "硕士", "本科", "专科", "高中及以下", "":
break
default:
errorMsg = append(errorMsg, "学历错误,值范围:博士,硕士,本科,专科,高中及以下")
break
}
//人员类型
accountInfo.PersonnelType = utils.Trim(row[9])
if accountInfo.PersonnelType != "" {
switch accountInfo.PersonnelType {
case "正式党员", "预备党员", "":
break
default:
errorMsg = append(errorMsg, "学历错误,值范围:正式党员,预备党员")
break
}
}
//党支部
tempStr = utils.Trim(row[10])
if tempStr != "" {
org, err = GetPartyOrgByName(partyId, tempStr)
if err != nil {
errorMsg = append(errorMsg, "党支部不存在")
} else {
account.OrgId = org.ID
}
} else {
errorMsg = append(errorMsg, "党支部为必填项")
}
//党内职务
tempStr = utils.Trim(row[11])
if tempStr != "" {
partyPost, err = GetPartyPostByName(partyId, tempStr)
if err != nil {
errorMsg = append(errorMsg, "党内职务不存在")
} else {
accountInfo.PartyPostId = partyPost.ID
}
}
//转为预备党员日期
dateStr = utils.Trim(row[12])
accountInfo.TurnPreparePartyDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "转为预备党员日期格式错误")
}
//转为正式党员日期
dateStr = utils.Trim(row[13])
accountInfo.TurnPartyDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "转为正式党员日期格式错误")
}
//工作岗位
accountInfo.Post = utils.Trim(row[14])
if len(accountInfo.Post) >= 50 {
errorMsg = append(errorMsg, "工作岗位字符过长")
}
//税后工资
tempStr = utils.Trim(row[15])
if tempStr != "" {
accountInfo.AfterTaxWages, err = convert.ToFloat64(utils.Trim(row[15]))
if err != nil || accountInfo.AfterTaxWages < 0 {
errorMsg = append(errorMsg, "税后工资格式错误")
}
}
//固定电话
accountInfo.Phone = utils.Trim(row[16])
if len(accountInfo.Phone) >= 30 {
errorMsg = append(errorMsg, "固定电话字符过长")
}
//家庭地址
accountInfo.HomeAddress = utils.Trim(row[17])
if len(accountInfo.HomeAddress) >= 255 {
errorMsg = append(errorMsg, "家庭地址字符过长")
}
//党籍状态
accountInfo.PartyStatus = utils.Trim(row[18])
switch accountInfo.PartyStatus {
case "正常", "异常", "":
break
default:
errorMsg = append(errorMsg, "党籍状态错误,值范围:正常、异常")
break
}
//是否为失联党员
accountInfo.PartyLostStatus = utils.Trim(row[19])
switch accountInfo.PartyLostStatus {
case "是", "否", "":
break
default:
errorMsg = append(errorMsg, "是否为失联党员错误,值范围:是、否")
break
}
//失去联系的日期
dateStr = utils.Trim(row[20])
accountInfo.PartyLostDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "失去联系的日期格式错误")
}
//是否为流动党员
accountInfo.PartyFlowStatus = utils.Trim(row[21])
switch accountInfo.PartyFlowStatus {
case "是", "否", "":
break
default:
errorMsg = append(errorMsg, "是否为流动党员错误,值范围:是、否")
break
}
//外出流向
accountInfo.OutgoingFlow = utils.Trim(row[22])
if len(accountInfo.OutgoingFlow) >= 500 {
errorMsg = append(errorMsg, "外出流向字符过长")
}
//申请入党日期
dateStr = utils.Trim(row[23])
accountInfo.PartyApplyDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "申请入党日期格式错误")
}
//列为积极分子日期
dateStr = utils.Trim(row[24])
accountInfo.PartyActivistDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "列为积极分子日期格式错误")
}
//列为发展对象日期
dateStr = utils.Trim(row[25])
accountInfo.PartyDevelopDate, err = utils.ParseExcelDate(dateStr)
if err != nil {
errorMsg = append(errorMsg, "列为发展对象日期格式错误")
}
//判断手机号码是否存在
acc, _ := GetAccountByMobile(account.Mobile)
if acc.ID > 0 {
errorMsg = append(errorMsg, "手机号码已存在")
}
if len(errorMsg) > 0 {
//错误记录
xlsx.SetCellDefault(sheetName, fmt.Sprintf("AA%v", rIndex+1), strings.Join(errorMsg, ";\r\n"))
errorMap[rIndex] = errorMsg
} else {
//添加的默认数据
account.ID = utils.ID()
account.Status = enum.NORMAL
account.CTime = &now
account.UTime = account.CTime
account.PartyId = partyId
account.Ip = ip
accountInfo.ID = utils.ID()
accountInfo.AccountId = account.ID
//数据保存
if err := saveImportAccount(account, accountInfo); err != nil {
//保存失败错误处理
errorMsg = append(errorMsg, err.Error())
xlsx.SetCellDefault(sheetName, fmt.Sprintf("AA%v", rIndex+1), strings.Join(errorMsg, ";\r\n"))
errorMap[rIndex] = errorMsg
}
}
//如果有错误,将背景设为警示颜色
if len(errorMsg) > 0 {
xlsx.SetCellStyle(sheetName, fmt.Sprintf("A%v", rIndex+1), fmt.Sprintf("AA%v", rIndex+1), style)
}
fmt.Println("-------------------------------------------------------------------------------------------")
}
}
if len(errorMap) > 0 {
//固定的标题栏位置
xlsx.SetCellDefault(sheetName, "AA2", "错误说明")
xlsx.Save()
return utils.Confirm(c, "导入数据异常,请下载excel根据最后一列的错误说明进行修改调整", fmt.Sprintf("%s", path))
}
//需要自己处理返回
return utils.SuccessNull(c, "导入成功")
}
func saveImportAccount(account *model.Account, accountInfo *model.AccountInfo) error {
//保存事务
tx := global.DB.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if tx.Error != nil {
global.Log.Error("tx error:%v", tx.Error.Error())
return errors.New(fmt.Sprintf("初始化事务失败:%s", tx.Error.Error()))
}
if err := tx.Create(&account).Error; err != nil {
tx.Rollback()
global.Log.Error("tx create account error:%v", err)
return errors.New(fmt.Sprintf("导入党员失败:%s", err.Error()))
}
if err := tx.Create(&accountInfo).Error; err != nil {
tx.Rollback()
global.Log.Error("tx create accountInfo error:%v", err)
return errors.New(fmt.Sprintf("导入党员详细信息失败:%s", err.Error()))
}
if err := tx.Commit().Error; err != nil {
global.Log.Error("commit error:%v", err)
return errors.New(fmt.Sprintf("保存党员失败:%s", err.Error()))
}
return nil
}
//去除前后所有空格、空字符串、制表符
func Trim(str string) string {
if str == "" {
return ""
}
return strings.TrimSpace(strings.TrimPrefix(str, string('\uFEFF')))
}
//已处理数字型日期
func ParseExcelDate(date string) (d *time.Time, err error) {
if date != "" {
var date2 time.Time
if !IsValidNumber(date) {
date2, err = ParseDate(date)
if err != nil {
return
}
d = &date2
return
} else {
date2, err = ParseDate("1900-1-1")
if err != nil {
return
}
days := convert.MustInt(date)
date2 = date2.AddDate(0, 0, days-2)
d = &date2
return
}
}
return
}
//字符串日期转换
func ParseDate(date string) (time.Time, error) {
date = strings.Replace(date, "/", "-", -1)
date = strings.Replace(date, ".", "-", -1)
date = strings.Replace(date, "-0", "-", -1)
local, _ := time.LoadLocation("Local")
return time.ParseInLocation("2006-1-2", date, local)
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 专访倍赛CEO杜霖:数据标注行业的内在逻辑
- Label Studio多媒体数据标注工具[5星推荐]
- 商汤开源利用无标注数据大幅提高精度的人脸识别算法
- Google发布Fluid Annotation,数据标注速度提高三倍!
- 无需标注,这个AI能在大量数据中一眼识别欺诈攻击
- 史上最强GAN被谷歌超越:标注数据少用90%,造假效果却更逼真
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Out of their Minds
Dennis Shasha、Cathy Lazere / Springer / 1998-07-02 / USD 16.00
This best-selling book is now available in an inexpensive softcover format. Imagine living during the Renaissance and being able to interview that eras greatest scientists about their inspirations, di......一起来看看 《Out of their Minds》 这本书的介绍吧!