Go结合Gin导出Mysql数据到Excel表格


Posted in Golang onAugust 05, 2022

1、实现目标

Golang 使用excelize 导出表格到浏览器下载或者保存到本地。
后续导入的话也会写到这里

2、使用的库

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、项目目录

go-excel
├─ app
│  ├─ excelize
│  │  └─ excelize.go
│  ├─ model
│  │  └─ sysUser.go
│  └─ service
│     └─ userService.go
├─ common
│  └─ mysql.go
├─ go.mod
├─ go.sum
├─ main.go
└─ setting.json

4、主要代码编写

gin还不会老师们可以看:https://blog.csdn.net/bei_FengBoby/article/details/124847078
读取配置文件是用的viper

4.1、excelize.go(主要工具类)

ExportExcelByStruct 函数 是从网络上直接copy的,研究他这个写法花了好一会儿,所以也写上去了,提供大家学习

import (
	"fmt"
	"math/rand"
	"net/url"
	"reflect"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
)

var (
	defaultSheetName = "Sheet1" //默认Sheet名称
	defaultHeight    = 25.0     //默认行高度
)

type lzExcelExport struct {
	file      *excelize.File
	sheetName string //可定义默认sheet名称
}

func NewMyExcel() *lzExcelExport {
	return &lzExcelExport{file: createFile(), sheetName: defaultSheetName}
}

//导出基本的表格
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
}

//导出到浏览器。此处使用的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()
	//设置文件类型
	c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
	//设置文件名称
	c.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(createFileName()))
	_, _ = c.Writer.Write(buffer.Bytes())
}

//设置首行
func (l *lzExcelExport) writeTop(params []map[string]string) {
	topStyle, _ := l.file.NewStyle(`{"font":{"bold":true},"alignment":{"horizontal":"center","vertical":"center"}}`)
	var word = 'A'
	//首行写入
	for _, conf := range params {
		title := conf["title"]
		width, _ := strconv.ParseFloat(conf["width"], 64)
		line := fmt.Sprintf("%c1", word)
		//设置标题
		_ = l.file.SetCellValue(l.sheetName, line, title)
		//列宽
		_ = l.file.SetColWidth(l.sheetName, fmt.Sprintf("%c", word), fmt.Sprintf("%c", word), width)
		//设置样式
		_ = l.file.SetCellStyle(l.sheetName, line, line, topStyle)
		word++
	}
}

//写入数据
func (l *lzExcelExport) writeData(params []map[string]string, data []map[string]interface{}) {
	lineStyle, _ := l.file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}}`)
	//数据写入
	var j = 2 //数据开始行数
	for i, val := range data {
		//设置行高
		_ = l.file.SetRowHeight(l.sheetName, i+1, defaultHeight)
		//逐列写入
		var word = 'A'
		for _, conf := range params {
			valKey := conf["key"]
			line := fmt.Sprintf("%c%v", word, j)
			isNum := conf["is_num"]

			//设置值
			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])
			}

			//设置样式
			_ = l.file.SetCellStyle(l.sheetName, line, line, lineStyle)
			word++
		}
		j++
	}
	//设置行高 尾行
	_ = 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()
	// 创建一个默认工作表
	sheetName := defaultSheetName
	index := f.NewSheet(sheetName)
	// 设置工作簿的默认工作表
	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导出(数据源为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("错误--", 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(接受请求)

其中导出的函数都已经测试是ok的,可以直接用,数据改成自己的就好,
注意的事项里面我也写了,避雷!!

import (
	"go-excel/app/excelize"
	"go-excel/app/model"
	config "go-excel/common"
	"github.com/gin-gonic/gin"
)



//获取所有用户数据-excel
func GetAllUserExportToWeb(ctx *gin.Context) {
	var users []model.TUser
	db := config.GetDB()
	db.Find(&users)

	//定义首行标题
	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",
	})

	//填充数据
	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盘
	ex.ExportToPath(dataKey, data, "D:/")
}

//excel 导出
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 {
		//这里最好新建一个struct 和titles一致,不然users里面的多余的字段也会写进去
		datas = append(datas, model.TUser{
			ID:       v.ID,
			Username: v.Username,
			Remark:   v.Remark,
		})
	}
	ex.ExportExcelByStruct(titles, datas, "用户数据", "用户", ctx)
}

4.2、测试结果

GetAllUserExportToWeb

Go结合Gin导出Mysql数据到Excel表格

GetUserExcelByMap

Go结合Gin导出Mysql数据到Excel表格

5、文档代码地址

https://gitee.com/hjx_RuGuoYunZhiDao/strom-huang-go.git —go-excel目录

到此这篇关于Go结合Gin导出Mysql数据到Excel表格的文章就介绍到这了,更多相关Go 导出Mysql数据到Excel内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
golang中切片copy复制和等号复制的区别介绍
Apr 27 Golang
golang中的空slice案例
Apr 27 Golang
golang 生成对应的数据表struct定义操作
Apr 28 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
聊聊golang中多个defer的执行顺序
May 08 Golang
go语言使用Casbin实现角色的权限控制
Jun 26 Golang
修改并编译golang源码的操作步骤
Jul 25 Golang
golang内置函数len的小技巧
Jul 25 Golang
Go 语言中 20 个占位符的整理
Oct 16 Golang
Golang 字符串的常见操作
Apr 19 Golang
go goth封装第三方认证库示例详解
Aug 14 Golang
GO中sync包自由控制并发示例详解
Aug 05 #Golang
Go语言编译原理之源码调试
Aug 05 #Golang
Go语言编译原理之变量捕获
Aug 05 #Golang
在ubuntu下安装go开发环境的全过程
Aug 05 #Golang
Go语言测试库testify使用学习
Jul 23 #Golang
Go语言怎么使用变长参数函数
Jul 15 #Golang
Go微服务项目配置文件的定义和读取示例详解
Jun 21 #Golang
You might like
解决MySQL中文输出变成问号的问题
2008/06/05 PHP
php数组函数序列之array_values() 获取数组元素值的函数与方法
2011/10/30 PHP
Apache中php.ini的设置方法
2013/02/28 PHP
基于PHP CURL获取邮箱地址的详解
2013/06/03 PHP
浅析php变量作用域的一些问题
2013/08/08 PHP
PHP从零开始打造自己的MVC框架之路由类实现方法分析
2019/06/03 PHP
Javascript new关键字的玄机 以及其它
2010/08/25 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
JavaScript编写Chrome扩展实现与浏览器的交互及时间通知
2016/05/16 Javascript
jquery实现瀑布流效果 jquery下拉加载新数据
2016/12/12 Javascript
jQuery学习笔记之入门
2016/12/14 Javascript
JS对象创建的几种方式整理
2017/02/28 Javascript
浅谈webpack编译vue项目生成的代码探索
2017/12/11 Javascript
通过js动态创建标签,并设置属性方法
2018/02/24 Javascript
vue 实现websocket发送消息并实时接收消息
2019/12/09 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
2020/05/06 Javascript
Vue按时间段查询数据组件使用详解
2020/08/21 Javascript
如何在vue中使用kindeditor富文本编辑器
2020/12/19 Vue.js
python读取Android permission文件
2013/11/01 Python
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
Python虚拟环境Virtualenv使用教程
2015/05/18 Python
Python实现LRU算法的2种方法
2015/06/24 Python
python实现简单购物商城
2016/05/21 Python
Python找出list中最常出现元素的方法
2016/06/14 Python
python3基于OpenCV实现证件照背景替换
2018/07/18 Python
用Python去除图像的黑色或白色背景实例
2019/12/12 Python
无惧面试,带你搞懂python 装饰器
2020/08/17 Python
世界上最大的汽车共享网站:Zipcar
2017/01/14 全球购物
shell的种类有哪些
2015/04/15 面试题
造价工程师个人求职信
2013/09/21 职场文书
大学生关于奋斗的演讲稿
2014/01/09 职场文书
三年级学生评语
2014/04/23 职场文书
团委竞选演讲稿
2014/04/24 职场文书
2014流动人口计划生育工作总结
2014/12/20 职场文书
无婚姻登记记录证明
2015/06/18 职场文书
Python趣味实战之手把手教你实现举牌小人生成器
2021/06/07 Python