内容简介:项目架构: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%,造假效果却更逼真
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。