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 相关文章推荐
Go语言操作数据库及其常规操作的示例代码
Apr 21 Golang
Golang 正则匹配效率详解
Apr 25 Golang
golang 实现两个结构体复制字段
Apr 28 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
May 05 Golang
浅谈golang 中time.After释放的问题
May 05 Golang
Go 在 MongoDB 中常用查询与修改的操作
May 07 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
golang语言指针操作
Apr 14 Golang
详解Go语言中Get/Post请求测试
Jun 01 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
php中如何防止表单的重复提交
2013/08/02 PHP
PHP获取一年有几周以及每周开始日期和结束日期
2015/08/06 PHP
PHP定时执行任务的3种方法详解
2015/12/21 PHP
php实现学生管理系统
2020/03/21 PHP
超强多功能php绿色集成环境详解
2017/01/25 PHP
PHP的mysqli_rollback()函数讲解
2019/01/23 PHP
RSA实现JS前端加密与PHP后端解密功能示例
2019/08/05 PHP
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
详解AngularJS Filter(过滤器)用法
2015/12/28 Javascript
Bootstrap+jfinal退出系统弹出确认框的实现方法
2016/05/30 Javascript
JavaScript中数据类型转换总结
2016/12/25 Javascript
jQuery点击导航栏选中更换样式的实现代码
2017/01/23 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
解决nodejs的npm命令无反应的问题
2018/05/17 NodeJs
微信小程序网络请求封装示例
2018/07/24 Javascript
Vue.js构建你的第一个包并在NPM上发布的方法步骤
2019/05/01 Javascript
vue+Element实现搜索关键字高亮功能
2019/05/28 Javascript
jquery实现两个div中的元素相互拖动的方法分析
2020/04/05 jQuery
Vue实现简易购物车页面
2020/12/30 Vue.js
python 控制语句
2011/11/03 Python
python算法表示概念扫盲教程
2017/04/13 Python
python随机取list中的元素方法
2018/04/08 Python
Python 调用PIL库失败的解决方法
2019/01/08 Python
基于Python检测动态物体颜色过程解析
2019/12/04 Python
python3通过qq邮箱发送邮件以及附件
2020/05/20 Python
详解pandas.DataFrame.plot() 画图函数
2020/06/14 Python
python 实现aes256加密
2020/11/27 Python
在Ubuntu中安装并配置Pycharm教程的实现方法
2021/01/06 Python
利用CSS3实现毛玻璃效果示例源码
2016/09/25 HTML / CSS
Book Depository欧盟:一家领先的国际图书零售商
2019/05/21 全球购物
大学毕业自我鉴定范文
2014/02/03 职场文书
成语的广告词
2014/03/19 职场文书
电气自动化求职信
2014/06/24 职场文书
2014年十一国庆节爱国演讲稿
2014/09/23 职场文书
2015年小学总务工作总结
2015/07/21 职场文书
mysql联合索引的使用规则
2021/06/23 MySQL