Go結(jié)合Gin導(dǎo)出Mysql數(shù)據(jù)到Excel表格
1、實(shí)現(xiàn)目標(biāo)
Golang 使用excelize 導(dǎo)出表格到瀏覽器下載或者保存到本地。
后續(xù)導(dǎo)入的話也會(huì)寫(xiě)到這里
2、使用的庫(kù)
go get github.com/xuri/excelize/v2
Git地址:
https://github.com/qax-os/excelize
文檔地址:
https://xuri.me/excelize/zh-hans/base/installation.html#install
3、項(xiàng)目目錄
go-excel ├─ app │ ├─ excelize │ │ └─ excelize.go │ ├─ model │ │ └─ sysUser.go │ └─ service │ └─ userService.go ├─ common │ └─ mysql.go ├─ go.mod ├─ go.sum ├─ main.go └─ setting.json
4、主要代碼編寫(xiě)
gin還不會(huì)老師們可以看:https://blog.csdn.net/bei_FengBoby/article/details/124847078
讀取配置文件是用的viper
4.1、excelize.go(主要工具類)
ExportExcelByStruct 函數(shù) 是從網(wǎng)絡(luò)上直接copy的,研究他這個(gè)寫(xiě)法花了好一會(huì)兒,所以也寫(xiě)上去了,提供大家學(xué)習(xí)
import ( "fmt" "math/rand" "net/url" "reflect" "strconv" "time" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" ) var ( defaultSheetName = "Sheet1" //默認(rèn)Sheet名稱 defaultHeight = 25.0 //默認(rèn)行高度 ) type lzExcelExport struct { file *excelize.File sheetName string //可定義默認(rèn)sheet名稱 } func NewMyExcel() *lzExcelExport { return &lzExcelExport{file: createFile(), sheetName: defaultSheetName} } //導(dǎo)出基本的表格 func (l *lzExcelExport) ExportToPath(params []map[string]string, data []map[string]interface{}, path string) (string, error) { l.export(params, data) name := createFileName() filePath := path + "/" + name err := l.file.SaveAs(filePath) return filePath, err } //導(dǎo)出到瀏覽器。此處使用的gin框架 其他框架可自行修改ctx func (l *lzExcelExport) ExportToWeb(params []map[string]string, data []map[string]interface{}, c *gin.Context) { l.export(params, data) buffer, _ := l.file.WriteToBuffer() //設(shè)置文件類型 c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8") //設(shè)置文件名稱 c.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(createFileName())) _, _ = c.Writer.Write(buffer.Bytes()) } //設(shè)置首行 func (l *lzExcelExport) writeTop(params []map[string]string) { topStyle, _ := l.file.NewStyle(`{"font":{"bold":true},"alignment":{"horizontal":"center","vertical":"center"}}`) var word = 'A' //首行寫(xiě)入 for _, conf := range params { title := conf["title"] width, _ := strconv.ParseFloat(conf["width"], 64) line := fmt.Sprintf("%c1", word) //設(shè)置標(biāo)題 _ = l.file.SetCellValue(l.sheetName, line, title) //列寬 _ = l.file.SetColWidth(l.sheetName, fmt.Sprintf("%c", word), fmt.Sprintf("%c", word), width) //設(shè)置樣式 _ = l.file.SetCellStyle(l.sheetName, line, line, topStyle) word++ } } //寫(xiě)入數(shù)據(jù) func (l *lzExcelExport) writeData(params []map[string]string, data []map[string]interface{}) { lineStyle, _ := l.file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}}`) //數(shù)據(jù)寫(xiě)入 var j = 2 //數(shù)據(jù)開(kāi)始行數(shù) for i, val := range data { //設(shè)置行高 _ = l.file.SetRowHeight(l.sheetName, i+1, defaultHeight) //逐列寫(xiě)入 var word = 'A' for _, conf := range params { valKey := conf["key"] line := fmt.Sprintf("%c%v", word, j) isNum := conf["is_num"] //設(shè)置值 if isNum != "0" { valNum := fmt.Sprintf("'%v", val[valKey]) _ = l.file.SetCellValue(l.sheetName, line, valNum) } else { _ = l.file.SetCellValue(l.sheetName, line, val[valKey]) } //設(shè)置樣式 _ = l.file.SetCellStyle(l.sheetName, line, line, lineStyle) word++ } j++ } //設(shè)置行高 尾行 _ = l.file.SetRowHeight(l.sheetName, len(data)+1, defaultHeight) } func (l *lzExcelExport) export(params []map[string]string, data []map[string]interface{}) { l.writeTop(params) l.writeData(params, data) } func createFile() *excelize.File { f := excelize.NewFile() // 創(chuàng)建一個(gè)默認(rèn)工作表 sheetName := defaultSheetName index := f.NewSheet(sheetName) // 設(shè)置工作簿的默認(rèn)工作表 f.SetActiveSheet(index) return f } func createFileName() string { name := time.Now().Format("2006-01-02-15-04-05") rand.Seed(time.Now().UnixNano()) return fmt.Sprintf("excle-%v-%v.xlsx", name, rand.Int63n(time.Now().Unix())) } //excel導(dǎo)出(數(shù)據(jù)源為Struct) []interface{} func (l *lzExcelExport) ExportExcelByStruct(titleList []string, data []interface{}, fileName string, sheetName string, c *gin.Context) error { l.file.SetSheetName("Sheet1", sheetName) header := make([]string, 0) for _, v := range titleList { header = append(header, v) } rowStyleID, _ := l.file.NewStyle(`{"font":{"color":"#666666","size":13,"family":"arial"},"alignment":{"vertical":"center","horizontal":"center"}}`) _ = l.file.SetSheetRow(sheetName, "A1", &header) _ = l.file.SetRowHeight("Sheet1", 1, 30) length := len(titleList) headStyle := Letter(length) var lastRow string var widthRow string for k, v := range headStyle { if k == length-1 { lastRow = fmt.Sprintf("%s1", v) widthRow = v } } if err := l.file.SetColWidth(sheetName, "A", widthRow, 30); err != nil { fmt.Print("錯(cuò)誤--", err.Error()) } rowNum := 1 for _, v := range data { t := reflect.TypeOf(v) fmt.Print("--ttt--", t.NumField()) value := reflect.ValueOf(v) row := make([]interface { }, 0) for l := 0; l < t.NumField(); l++ { val := value.Field(l).Interface() row = append(row, val) } rowNum++ err := l.file.SetSheetRow(sheetName, "A"+strconv.Itoa(rowNum), &row) _ = l.file.SetCellStyle(sheetName, fmt.Sprintf("A%d", rowNum), fmt.Sprintf("%s", lastRow), rowStyleID) if err != nil { return err } } disposition := fmt.Sprintf("attachment; filename=%s.xlsx", url.QueryEscape(fileName)) c.Writer.Header().Set("Content-Type", "application/octet-stream") c.Writer.Header().Set("Content-Disposition", disposition) c.Writer.Header().Set("Content-Transfer-Encoding", "binary") c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") return l.file.Write(c.Writer) } // Letter 遍歷a-z func Letter(length int) []string { var str []string for i := 0; i < length; i++ { str = append(str, string(rune('A'+i))) } return str }
4.2、userService.go(接受請(qǐng)求)
其中導(dǎo)出的函數(shù)都已經(jīng)測(cè)試是ok的,可以直接用,數(shù)據(jù)改成自己的就好,
注意的事項(xiàng)里面我也寫(xiě)了,避雷??!
import ( "go-excel/app/excelize" "go-excel/app/model" config "go-excel/common" "github.com/gin-gonic/gin" ) //獲取所有用戶數(shù)據(jù)-excel func GetAllUserExportToWeb(ctx *gin.Context) { var users []model.TUser db := config.GetDB() db.Find(&users) //定義首行標(biāo)題 dataKey := make([]map[string]string, 0) dataKey = append(dataKey, map[string]string{ "key": "id", "title": "索引", "width": "20", "is_num": "0", }) dataKey = append(dataKey, map[string]string{ "key": "username", "title": "用戶名", "width": "20", "is_num": "0", }) dataKey = append(dataKey, map[string]string{ "key": "remark", "title": "備注", "width": "20", "is_num": "0", }) //填充數(shù)據(jù) data := make([]map[string]interface{}, 0) if len(users) > 0 { for _, v := range users { data = append(data, map[string]interface{}{ "id": v.ID, "username": v.Username, "remark": v.Remark, }) } } ex := excelize.NewMyExcel() // ex.ExportToWeb(dataKey, data, ctx) //保存到D盤(pán) ex.ExportToPath(dataKey, data, "D:/") } //excel 導(dǎo)出 func GetUserExcelByMap(ctx *gin.Context) { var users []model.TUser db := config.GetDB() db.Find(&users) titles := []string{"ID", "用戶名", "備注"} ex := excelize.NewMyExcel() var datas []interface{} for _, v := range users { //這里最好新建一個(gè)struct 和titles一致,不然users里面的多余的字段也會(huì)寫(xiě)進(jìn)去 datas = append(datas, model.TUser{ ID: v.ID, Username: v.Username, Remark: v.Remark, }) } ex.ExportExcelByStruct(titles, datas, "用戶數(shù)據(jù)", "用戶", ctx) }
4.2、測(cè)試結(jié)果
GetAllUserExportToWeb
GetUserExcelByMap
5、文檔代碼地址
https://gitee.com/hjx_RuGuoYunZhiDao/strom-huang-go.git —go-excel目錄
到此這篇關(guān)于Go結(jié)合Gin導(dǎo)出Mysql數(shù)據(jù)到Excel表格的文章就介紹到這了,更多相關(guān)Go 導(dǎo)出Mysql數(shù)據(jù)到Excel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang 定時(shí)任務(wù)方面time.Sleep和time.Tick的優(yōu)劣對(duì)比分析
這篇文章主要介紹了golang 定時(shí)任務(wù)方面time.Sleep和time.Tick的優(yōu)劣對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05一文帶你玩轉(zhuǎn)Golang Prometheus Eexporter開(kāi)發(fā)
本文分兩大塊,一是搞清楚prometheus四種類型的指標(biāo)Counter,Gauge,Histogram,Summary用golang語(yǔ)言如何構(gòu)造這4種類型對(duì)應(yīng)的指標(biāo),二是搞清楚修改指標(biāo)值的場(chǎng)景和方式,感興趣的可以了解一下2023-02-02解決golang時(shí)間字符串轉(zhuǎn)time.Time的坑
這篇文章主要介紹了解決golang時(shí)間字符串轉(zhuǎn)time.Time的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04go語(yǔ)言實(shí)戰(zhàn)之實(shí)現(xiàn)比特幣地址校驗(yàn)步驟
這篇文章主要介紹了go語(yǔ)言實(shí)戰(zhàn)之實(shí)現(xiàn)比特幣地址校驗(yàn)步驟,利用生產(chǎn)的隨機(jī)數(shù)采用橢圓加密算法生成公鑰,具體步驟實(shí)例代碼請(qǐng)參考下本文2021-05-05