From c0299db2f52bed8ab2e2cbd3cdad4f32a9e9aab5 Mon Sep 17 00:00:00 2001 From: VIVIMAN Date: Fri, 28 Jan 2022 01:00:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20Golang=20=E5=AF=BC?= =?UTF-8?q?=E5=87=BAexcel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../go_to_excel/go_to_checkExcel/main.go | 394 ++++++++++++++++++ .../data_func/go_to_excel/go_to_main/main.go | 16 +- .../go_to_excel/go_to_main_style/main.go | 172 ++++++++ .../go_to_excel/go_to_mc/query_all/main.go | 243 +++++++++++ .../go_to_json/{demo => demo01}/demo.go | 0 .../go_to_json/{demo1 => demo02}/demo.go | 0 .../data_func/go_to_json/demo03/main.go | 42 ++ .../data_func/go_to_orm/go_to_gom/main.go | 35 ++ golang_learn/go.mod | 4 +- golang_learn/go.sum | 20 +- 10 files changed, 918 insertions(+), 8 deletions(-) create mode 100644 golang_learn/data_func/go_to_excel/go_to_checkExcel/main.go create mode 100644 golang_learn/data_func/go_to_excel/go_to_main_style/main.go create mode 100644 golang_learn/data_func/go_to_excel/go_to_mc/query_all/main.go rename golang_learn/data_func/go_to_json/{demo => demo01}/demo.go (100%) rename golang_learn/data_func/go_to_json/{demo1 => demo02}/demo.go (100%) create mode 100644 golang_learn/data_func/go_to_json/demo03/main.go create mode 100644 golang_learn/data_func/go_to_orm/go_to_gom/main.go diff --git a/golang_learn/data_func/go_to_excel/go_to_checkExcel/main.go b/golang_learn/data_func/go_to_excel/go_to_checkExcel/main.go new file mode 100644 index 0000000..5dca6e3 --- /dev/null +++ b/golang_learn/data_func/go_to_excel/go_to_checkExcel/main.go @@ -0,0 +1,394 @@ +package main + +/*import ( + "fmt" + "github.com/360EntSecGroup-Skylar/excelize" + "strings" + "time" +) + +func main() { + +} +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 IsValidNumber(date string) bool { + +} + +//字符串日期转换 +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) +}*/ diff --git a/golang_learn/data_func/go_to_excel/go_to_main/main.go b/golang_learn/data_func/go_to_excel/go_to_main/main.go index c25853c..afa6061 100644 --- a/golang_learn/data_func/go_to_excel/go_to_main/main.go +++ b/golang_learn/data_func/go_to_excel/go_to_main/main.go @@ -4,12 +4,26 @@ package main * 推荐:使用方式,写的输出excel文件 **/ import ( - // "github.com/360EntSecGroup-Skylar/excelize/v2" + "fmt" "github.com/360EntSecGroup-Skylar/excelize" "strconv" ) func main() { + headers := []string{"用户名", "性别", "年龄"} + values := [][]interface{}{ + {"测试", 1, "男"}, + {"ggr1", 2, "男"}, + } + f, _ := ExportExcel("Sheet1", headers, values) + err := f.SaveAs("test.xlsx") + fmt.Sprintln(err) + + // 文件名使用英文,否则会中文乱码 + //fileName = "test.xlxs" + //w.Header().Add("Content-Type", "application/octet-stream") + //w.Header().Add("Content-Disposition", "attachment; filename="+fileName) + //w.Header().Add("Content-Transfer-Encoding", "binary") } diff --git a/golang_learn/data_func/go_to_excel/go_to_main_style/main.go b/golang_learn/data_func/go_to_excel/go_to_main_style/main.go new file mode 100644 index 0000000..f6d745c --- /dev/null +++ b/golang_learn/data_func/go_to_excel/go_to_main_style/main.go @@ -0,0 +1,172 @@ +package main + +import ( + "fmt" + + "github.com/xuri/excelize/v2" +) + +func main() { + // wb := excelize.NewFile() + wb, err := excelize.OpenFile("../excel_files/TMP_05.xlsx") + if err != nil { + fmt.Println(err) + return + } + sheetName := wb.GetSheetName(wb.GetActiveSheetIndex()) + + sty_idx, err := wb.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + { + Type: "right", // top bottom left right diagonalDown diagonalUp 中的一个 + Color: "#000000", // 十六进制的颜色编码 + Style: 2, // 0-13 有对应的样式 + }, + { + Type: "left", + Color: "#000000", + Style: 2, + }, + { + Type: "top", + Color: "#000000", + Style: 2, + }, + { + Type: "bottom", + Color: "#000000", + Style: 2, + }, + }, Fill: excelize.Fill{ + Type: "gradient", // gradient 渐变色 pattern 填充图案 + // Pattern: 1, // 填充样式 当类型是 pattern 0-18 填充图案 1 实体填充 + // Color: []string{"#FF0000"}, // 当Type = pattern 时,只有一个 + Color: []string{"#00F700", "#00F700"}, + Shading: 1, // 类型是 gradient 使用 0-5 横向(每种颜色横向分布) 纵向 对角向上 对角向下 有外向内 由内向外 + }, Font: &excelize.Font{ + Bold: true, + // Italic: false, + // Underline: "single", + Size: 14, + Family: "宋体", + // Strike: true, // 删除线 + Color: "#0000FF", + }, Alignment: &excelize.Alignment{ + Horizontal: "center", // 水平对齐方式 center left right fill(填充) justify(两端对齐) centerContinuous(跨列居中) distributed(分散对齐) + Vertical: "center", // 垂直对齐方式 center top justify distributed + // Indent: 1, // 缩进 只要有值就变成了左对齐 + 缩进 + // TextRotation: 30, // 旋转 + // RelativeIndent: 10, // 好像没啥用 + // ReadingOrder: 0, // 不知道怎么设置 + // JustifyLastLine: true, // 两端分散对齐,只有 水平对齐 为 distributed 时 设置true 才有效 + // WrapText: true, // 自动换行 + // ShrinkToFit: true, // 缩小字体以填充单元格 + }, Protection: &excelize.Protection{ + Hidden: true, // 貌似没啥用 + Locked: true, // 貌似没啥用 + }, NumFmt: 0, // 内置的数字格式样式 0-638 常用的 0-58 配合lang使用,因为语言不同样式不同 具体的样式参照文档 + Lang: "zh-cn", // zh-cn 中文 + DecimalPlaces: 2, // 小数位数 只有NumFmt是 2-11 有效 + // CustomNumFmt: "",// 自定义样式 是指针,只能通过变量的方式 + NegRed: true, // 不知道具体的含义 + }) + if err != nil { + fmt.Println(err) + } + + if err := wb.SetCellStyle(sheetName, "A1", "B3", sty_idx); err != nil { + fmt.Println(err) + return + } + + // 除了以Go语言的方式传参外,还支持JSON格式的传参 + // 边框样式 + border_sty, err := wb.NewStyle(`{"border":[ + {"type":"top","color":"#000000","style":1}, + {"type":"left","color":"#000000","style":1}, + {"type":"right","color":"#000000","style":1}, + {"type":"bottom","color":"#000000","style":1} + ]}`) + if err != nil { + fmt.Println(err) + } + + if err := wb.SetCellStyle(sheetName, "D2", "G10", border_sty); err != nil { + fmt.Println(err) + } + // 字体样式 + // 链接的字体样式 下划线 + 蓝色 + font_link_sty, err := wb.NewStyle(`{"font":{"underline":"single","size":12,"color":"#0000FF","family":"仿宋"}}`) + if err != nil { + fmt.Println(err) + } + fmt.Println(font_link_sty) + if err := wb.SetCellValue(sheetName, "F6", "这是链接"); err != nil { + fmt.Println(err) + } + + if err := wb.SetCellHyperLink(sheetName, "F6", "Sheet1!A1", "Location"); err != nil { + fmt.Println(err) + } + + if err := wb.SetCellStyle(sheetName, "F6", "F6", font_link_sty); err != nil { + fmt.Println(err) + } + + styleIdx, err := wb.GetCellStyle(sheetName, "F6") + if err != nil { + fmt.Println(err) + } + + fmt.Println(styleIdx) + + // 对齐方式 + Al_style, err := wb.NewStyle(`{"alignment":{ + "horizontal":"center", + "vertical":"center" + }}`) + if err != nil { + fmt.Println(err) + } + if err := wb.SetCellStyle(sheetName, "F6", "F6", Al_style); err != nil { + fmt.Println(err) + } + + // 多个样式设置在同一个单元格,后面的会覆盖前面的 + + link_sty, err := wb.NewStyle(`{ + "border":[ + {"type":"top","color":"#000000","style":1}, + {"type":"left","color":"#000000","style":1}, + {"type":"right","color":"#000000","style":1}, + {"type":"bottom","color":"#000000","style":1} + ], + "font":{ + "underline":"single", + "size":12, + "color":"#0000FF", + "family":"仿宋" + }, + "alignment":{ + "horizontal":"center", + "vertical":"center" + } + }`) + + if err != nil { + fmt.Println(err) + } + if err := wb.SetCellStyle(sheetName, "D11", "D11", link_sty); err != nil { + fmt.Println(err) + } + + if err := wb.SetCellValue(sheetName, "D11", "这是链接"); err != nil { + fmt.Println(err) + } + + if err := wb.SetCellHyperLink(sheetName, "D11", "http://www.baidu.com", "External"); err != nil { + fmt.Println(err) + } + wb.Save() + // wb.SaveAs("../excel_files/TMP_05.xlsx") +} diff --git a/golang_learn/data_func/go_to_excel/go_to_mc/query_all/main.go b/golang_learn/data_func/go_to_excel/go_to_mc/query_all/main.go new file mode 100644 index 0000000..7a41736 --- /dev/null +++ b/golang_learn/data_func/go_to_excel/go_to_mc/query_all/main.go @@ -0,0 +1,243 @@ +package main + +import ( + "database/sql" + "encoding/json" + "fmt" + "github.com/360EntSecGroup-Skylar/excelize" + _ "github.com/go-sql-driver/mysql" + "log" + "strconv" + "strings" + "time" +) + +const sheetName = `全部数据` +const fileName = `公务员系统数据-` +const fileType = `.xlsx` +const linkStr = `root:admin@tcp(127.0.0.1:35017)/hy_qggwy?charset=utf8` +const sqlStr = `SELECT concat(code_type,code_value),code_name FROM CODE_VALUE where code_type in('%s') union SELECT concat(code_type,code_value),code_name3 FROM CODE_VALUE where code_type='ZB01'` + +var CodeValueMap = make(map[string]string) +var allObj = make([][]interface{}, 200) + +func main() { + db, _ := sql.Open("mysql", linkStr) + codes, headers, types, headWidth, yrYhsLen, err := getInit() + if err { + return + } + QueryMap(db, fmt.Sprintf(sqlStr, strings.Join(types, "','")), CodeValueMap) + log.Print("输出内容:", headers) + log.Print("输出内容:", codes) + log.Print("输出内容:", CodeValueMap) + + allObj = [][]interface{}{} + ii := make([]interface{}, yrYhsLen, yrYhsLen) + for i := 0; i < yrYhsLen; i++ { + ii[i] = "测试" + } + allObj = append(allObj, ii) + ii = make([]interface{}, yrYhsLen, yrYhsLen) + for i := 0; i < yrYhsLen; i++ { + ii[i] = "输出内容输出内容输出内容" + } + allObj = append(allObj, ii) + log.Print("输出内容:", allObj) + getExcelFile(headers, headWidth, allObj) +} + +// getInit 初始化 JSON 对象,获取猎头 +func getInit() ([]string, []string, []string, []float64, int, bool) { + var yrYhs []YrYh + //读取的数据为json格式,需要进行解码 + err := json.Unmarshal([]byte(yryh), &yrYhs) + if err != nil { + log.Fatal("发生异常:", err) + return nil, nil, nil, nil, 0, true + } + yrYhsLen := len(yrYhs) + types := make([]string, yrYhsLen, yrYhsLen) // 输出类型 + codes := make([]string, yrYhsLen, yrYhsLen) // 输出信息项 + headers := make([]string, yrYhsLen, yrYhsLen) // 输出列名 + headWidth := make([]float64, yrYhsLen, yrYhsLen) // 输出列名 + for i1, i2 := range yrYhs { + codes[i1] = i2.Code + headers[i1] = i2.Name + headWidth[i1] = i2.Width + if i2.Type != "" && i2.Type != "DATE" && i2.Type != "ZB01" { + types[i1] = i2.Type + } + } + return codes, headers, types, headWidth, yrYhsLen, false +} + +func getExcelFile(headers []string, headWidth []float64, values [][]interface{}) { + f, _ := ExportExcel(sheetName, headers, headWidth, values) + _ = f.SaveAs(fileName + time.Now().Format("2006102150405") + fileType) +} + +// maxCharCount 最多26个字符A-Z +const maxCharCount = 26 + +// ExportExcel 导出Excel文件 +// sheetName 工作表名称, 注意这里不要取sheet1这种名字,否则导致文件打开时发生部分错误。 +// headers 列名切片, 表头 +// rows 数据切片,是一个二维数组 +func ExportExcel(sheetName string, headers []string, headWidth []float64, rows [][]interface{}) (*excelize.File, error) { + f := excelize.NewFile() + style, _ := f.NewStyle(`{ + "border":[ + {"type":"top","color":"#000000","style":1}, + {"type":"left","color":"#000000","style":1}, + {"type":"right","color":"#000000","style":1}, + {"type":"bottom","color":"#000000","style":1} + ], + "font":{"size":12,"color":"#000000","family":"仿宋"}, + "alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, + "fill":{"type":"gradient","shading":0,"color":["#FFFF00","#FFFF00"]} + }`) + sheetIndex := f.NewSheet(sheetName) + maxColumnRowNameLen := 1 + len(strconv.Itoa(len(rows))) + columnCount := len(headers) + if columnCount > maxCharCount { + maxColumnRowNameLen++ + } else if columnCount > maxCharCount*maxCharCount { + maxColumnRowNameLen += 2 + } + columnNames := make([][]byte, 0, columnCount) + f.SetRowHeight(sheetName, 1, 80) // 设置行高 + for i, header := range headers { + columnName := getColumnName(i, maxColumnRowNameLen) + columnNames = append(columnNames, columnName) + // 初始化excel表头,这里的index从1开始要注意 + curColumnName := getColumnRowName(columnName, 1) + f.SetColWidth(sheetName, toCharStr(i+1), toCharStr(i+1), headWidth[i]) + f.SetCellValue(sheetName, curColumnName, header) + f.SetCellStyle(sheetName, curColumnName, curColumnName, style) // 设置单元格样式 + } + for rowIndex, row := range rows { + for columnIndex, columnName := range columnNames { + // 从第二行开始 + f.SetCellValue(sheetName, getColumnRowName(columnName, rowIndex+2), row[columnIndex]) + } + } + f.SetActiveSheet(sheetIndex) + return f, nil +} + +// getColumnName 生成列名 +// Excel的列名规则是从A-Z往后排;超过Z以后用两个字母表示,比如AA,AB,AC;两个字母不够以后用三个字母表示,比如AAA,AAB,AAC +// 这里做数字到列名的映射:0 -> A, 1 -> B, 2 -> C +// maxColumnRowNameLen 表示名称框的最大长度,假设数据是10行,1000列,则最后一个名称框是J1000(如果有表头,则是J1001),是4位 +// 这里根据 maxColumnRowNameLen 生成切片,后面生成名称框的时候可以复用这个切片,而无需扩容 +func getColumnName(column, maxColumnRowNameLen int) []byte { + const A = 'A' + if column < maxCharCount { + // 第一次就分配好切片的容量 + slice := make([]byte, 0, maxColumnRowNameLen) + return append(slice, byte(A+column)) + } else { + // 递归生成类似AA,AB,AAA,AAB这种形式的列名 + return append(getColumnName(column/maxCharCount-1, maxColumnRowNameLen), byte(A+column%maxCharCount)) + } +} + +// getColumnRowName 生成名称框 +// Excel的名称框是用A1,A2,B1,B2来表示的,这里需要传入前一步生成的列名切片,然后直接加上行索引来生成名称框,就无需每次分配内存 +func getColumnRowName(columnName []byte, rowIndex int) (columnRowName string) { + l := len(columnName) + columnName = strconv.AppendInt(columnName, int64(rowIndex), 10) + columnRowName = string(columnName) + // 将列名恢复回去 + columnName = columnName[:l] + return +} + +// 获取表数据 +func QueryMap(db *sql.DB, sqlStr string, m map[string]string) { + rows, _ := db.Query(sqlStr) + defer rows.Close() + columns, _ := rows.Columns() + for rows.Next() { + _ = rows.Scan(&columns[0], &columns[1]) + m[columns[0]] = columns[1] + } +} + +func has(v1 dept, vs []*dept) bool { + var has bool + has = false + for _, v2 := range vs { + v3 := *v2 + if v1.Pid+v1.Id == v3.Pid { + has = true + break + } + } + return has + +} + +func makeTree(vs []*dept, node *dept) { + fmt.Println("the node value in maketree is:", *node) + childs := findChild(node, vs) + fmt.Println(" the child we got is :", childs) + for _, child := range childs { + fmt.Println("in the childs's for loop, the child's address here is:", &child) + node.Child = append(node.Child, child) + fmt.Println("in the child's for loop, after append the child is:", child) + if has(*child, vs) { + fmt.Println("i am in if has") + fmt.Println("the child in if has is:", *child) + fmt.Println("the child in if has 's address is:", child) + makeTree(vs, child) + } + } + +} + +func findChild(v *dept, vs []*dept) (ret []*dept) { + for _, v2 := range vs { + if v.Pid+v.Id == v2.Pid { + ret = append(ret, v2) + } + } + return +} + +// 数字转字母 +func toCharStr(i int) string { + return string('A' - 1 + i) +} + +type YrYh struct { + Name string `json:"name"` + Code string `json:"code"` + Type string `json:"type"` + Width float64 `json:"width"` +} + +var yryh = `[ + {"name":"姓名","code":"a01.a0101","type":"","width":11}, + {"name":"性别","code":"a01.a0104","type":"GB2261","width":8}, + {"name":"民族","code":"a01.a0117","type":"GB3304","width":8}, + {"name":"出生日期","code":"a01.a0107","type":"DATE","width":12}, + {"name":"参加工作时间","code":"a01.a0134","type":"DATE","width":13}, + {"name":"入党时间","code":"a01.a0140","type":"","width":12}, + {"name":"工作单位及职务全称","code":"a01.a0192a","type":"","width":20}, + {"name":"职务层次","code":"a01.a0221","type":"ZB09","width":12}, + {"name":"任职务层次时间","code":"a01.a0288","type":"DATE","width":15}, + {"name":"职级","code":"a01.a0192e","type":"ZB148","width":12}, + {"name":"任职级时间","code":"a01.a0192c","type":"DATE","width":12}, + {"name":"任相当层次职务职级时间","code":"a01.a0192x","type":"DATE","width":15}, + {"name":"最高学历","code":"a01.zgxl","type":"","width":15}, + {"name":"籍贯","code":"a01.a0111","type":"ZB01","width":12} +]` + +// 树结构 +type dept struct { + Id string `json:"id"` + Pid string `json:"pid"` + Child []*dept `json:"child"` +} diff --git a/golang_learn/data_func/go_to_json/demo/demo.go b/golang_learn/data_func/go_to_json/demo01/demo.go similarity index 100% rename from golang_learn/data_func/go_to_json/demo/demo.go rename to golang_learn/data_func/go_to_json/demo01/demo.go diff --git a/golang_learn/data_func/go_to_json/demo1/demo.go b/golang_learn/data_func/go_to_json/demo02/demo.go similarity index 100% rename from golang_learn/data_func/go_to_json/demo1/demo.go rename to golang_learn/data_func/go_to_json/demo02/demo.go diff --git a/golang_learn/data_func/go_to_json/demo03/main.go b/golang_learn/data_func/go_to_json/demo03/main.go new file mode 100644 index 0000000..7456590 --- /dev/null +++ b/golang_learn/data_func/go_to_json/demo03/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "encoding/json" + "log" +) + +func main() { + var yrYhs []YrYh + //读取的数据为json格式,需要进行解码 + err := json.Unmarshal([]byte(yryh), &yrYhs) + if err != nil { + log.Fatal("发生异常:", err) + return + } + for _, i2 := range yrYhs { + log.Print("输出内容:", i2) + } +} + +type YrYh struct { + Name string `json:"name"` + Code string `json:"code"` + Type string `json:"type"` +} + +var yryh = `[ + {"name":"姓名","code":"a0101","type":""}, + {"name":"性别","code":"a0104","type":"GB2261"}, + {"name":"民族","code":"a0117","type":"GB3304"}, + {"name":"出生日期","code":"a0107","type":"DATE"}, + {"name":"参加工作时间","code":"a0134","type":"DATE"}, + {"name":"入党时间","code":"a0140","type":""}, + {"name":"工作单位及职务全称","code":"a0192a","type":""}, + {"name":"职务层次","code":"a0221","type":"ZB09"}, + {"name":"任职务层次时间","code":"a0288","type":"DATE"}, + {"name":"职级","code":"a0192e","type":"ZB148"}, + {"name":"任职级时间","code":"a0192c","type":"DATE"}, + {"name":"任相当层次职务职级时间","code":"a0192x","type":"DATE"}, + {"name":"最高学历","code":"zgxl","type":""}, + {"name":"籍贯","code":"a0111","type":"ZB01"} +]` diff --git a/golang_learn/data_func/go_to_orm/go_to_gom/main.go b/golang_learn/data_func/go_to_orm/go_to_gom/main.go new file mode 100644 index 0000000..05450af --- /dev/null +++ b/golang_learn/data_func/go_to_orm/go_to_gom/main.go @@ -0,0 +1,35 @@ +package main + +//func main() { +// var funcs []func(db *gorm.DB) error +// for _, user := range prugs { +// funcs = append(funcs, func(db *gorm.DB) error { +// execSQL := "" +// return db.Exec(execSQL, value...).Error +// }) +// } +// +// if err := global.Tx(funcs...); err != nil { +// global.Log.Error("err:%s", err.Error()) +// return err +// } +//} + +//func Tx(funcs ...func(db *gorm.DB) error) (err error) { +// tx := DB.Begin() +// defer func() { +// if r := recover(); r != nil { +// tx.Rollback() +// err = fmt.Errorf("%v", err) +// } +// }() +// for _, f := range funcs { +// err = f(tx) +// if err != nil { +// tx.Rollback() +// return +// } +// } +// err = tx.Commit().Error +// return +//} diff --git a/golang_learn/go.mod b/golang_learn/go.mod index fed65bc..baf69ac 100644 --- a/golang_learn/go.mod +++ b/golang_learn/go.mod @@ -30,10 +30,10 @@ require ( github.com/spf13/viper v1.8.1 github.com/tidwall/gjson v1.13.0 github.com/tidwall/sjson v1.2.4 + github.com/xuri/excelize/v2 v2.5.0 github.com/yeka/zip v0.0.0-20180914125537-d046722c6feb - golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/exp/errors v0.0.0-20210715201039-d37aa40e8013 - golang.org/x/image v0.0.0-20201208152932-35266b937fa6 + golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e golang.org/x/text v0.3.6 gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect diff --git a/golang_learn/go.sum b/golang_learn/go.sum index 1ecc7be..380b57c 100644 --- a/golang_learn/go.sum +++ b/golang_learn/go.sum @@ -267,6 +267,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI= +github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= +github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= +github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= @@ -317,6 +321,10 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc= github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= +github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o= +github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/excelize/v2 v2.5.0 h1:nDDVfX0qaDuGjAvb+5zTd0Bxxoqa1Ffv9B4kiE23PTM= +github.com/xuri/excelize/v2 v2.5.0/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A= github.com/yeka/zip v0.0.0-20180914125537-d046722c6feb h1:OJYP70YMddlmGq//EPLj8Vw2uJXmrA+cGSPhXTDpn2E= github.com/yeka/zip v0.0.0-20180914125537-d046722c6feb/go.mod h1:9BnoKCcgJ/+SLhfAXj15352hTOuVmG5Gzo8xNRINfqI= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -344,8 +352,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -362,8 +370,8 @@ golang.org/x/exp/errors v0.0.0-20210715201039-d37aa40e8013/go.mod h1:YgqsNsAu4fT golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -424,8 +432,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -495,6 +504,7 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=