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如何去除多余空白字符(含制表符)
Apr 25 Golang
Go语言带缓冲的通道实现
Apr 26 Golang
Go语言中的UTF-8实现
Apr 26 Golang
goland 设置project gopath的操作
May 06 Golang
Golang 实现获取当前函数名称和文件行号等操作
May 08 Golang
golang fmt格式“占位符”的实例用法详解
Jul 04 Golang
入门学习Go的基本语法
Jul 07 Golang
详解Golang如何优雅的终止一个服务
Mar 21 Golang
Golang使用Panic与Recover进行错误捕获
Mar 22 Golang
Golang原生rpc(rpc服务端源码解读)
Apr 07 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Golang 字符串的常见操作
Apr 19 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截取中文字符串的问题
2006/07/12 PHP
PHP 计算代码执行耗时的代码修正网上普遍错误
2011/05/14 PHP
基于php权限分配的实现代码
2013/04/28 PHP
PHP数学运算函数大汇总(经典值得收藏)
2016/04/01 PHP
php计算给定日期所在周的开始日期和结束日期示例
2017/02/06 PHP
php 算法之实现相对路径的实例
2017/10/17 PHP
php微信开发之关键词回复功能
2018/06/13 PHP
Aster vs Newbee BO5 第三场2.19
2021/03/10 DOTA
prototype.js的Ajax对象
2006/09/23 Javascript
Jquery post传递数组方法实现思路及代码
2013/04/28 Javascript
Javascript玩转继承(二)
2014/05/08 Javascript
详解JavaScript基于面向对象之继承实例
2015/12/16 Javascript
js动态生成form 并用ajax方式提交的实现方法
2016/09/09 Javascript
JavaScript实现图片瀑布流和底部刷新
2017/01/02 Javascript
使用Fullpage插件快速开发整屏翻页的页面
2017/09/13 Javascript
BootStrap TreeView使用实例详解
2017/11/01 Javascript
vuex 使用文档小结篇
2018/01/11 Javascript
Vue.js的复用组件开发流程完整记录
2018/11/29 Javascript
[33:23]VG vs Pain 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python获取当前计算机cpu数量的方法
2015/04/18 Python
详解Python的Django框架中的templates设置
2015/05/11 Python
利用Python实现Windows下的鼠标键盘模拟的实例代码
2017/07/13 Python
Python random模块用法解析及简单示例
2017/12/18 Python
python回调函数中使用多线程的方法
2017/12/25 Python
Pandas GroupBy对象 索引与迭代方法
2018/11/16 Python
解决运行出现'dict' object has no attribute 'has_key'问题
2020/07/15 Python
python如何利用paramiko执行服务器命令
2020/11/07 Python
意大利体育用品网上商城:Nencini Sport
2016/08/18 全球购物
英国高端食品和葡萄酒超市:Waitrose
2016/08/23 全球购物
你经历的项目中的SCM配置项主要有哪些?什么是配置项?
2013/11/04 面试题
医药销售求职信范文
2014/02/01 职场文书
中国梦演讲稿范文
2014/08/28 职场文书
高中军训的心得体会
2014/09/01 职场文书
工伤认定行政答辩状
2015/05/22 职场文书
2019年幼儿园管理条例范本!
2019/07/17 职场文书
JavaScript与JQuery框架基础入门教程
2021/07/15 Javascript