Go语言gin框架项目:按模板导出excel并在网页端下载,并将此接口完成swagger的配置

news2025/1/18 4:51:04

1.需求

甲方的需求是以这种格式导出一个开工通知单

前端页面是这个样子:

 前端勾选一部分部室,后端根据勾选的这些部室名称进行查询,将查询到的部室主任名字填充到表格对应的位置中,另外将前端传过来的信息都填充到表格的指定位置

先展示一下最后导出的结果:

2.解决方法思路

1.前端以form-data表单形式传过来数据,后端使用gin框架的PostForm方法接收参数,并将参数填充到指定位置

2.前端传过来一些部室,后端对这些部室进行判断,通过部室名去查找部室主任,并将部室主任填充到对应的位置

3.导出excel所使用的库excelize:

go get github.com/xuri/excelize/v2

3.源码及结果展示

1.项目结构

 

2.在网页端下载excel文件(源码)

package file

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func ExcelDown(ctx *gin.Context, filepath string, filename string) {
	ctx.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
	ctx.Writer.Header().Add("Content-Type", "application/msexcel")
	ctx.File(filepath)
}

3.导出excel文件

1.如何配置swagger还有导出excel的步骤和逻辑都有写的很清楚,具体看代码注释

package controller

import (
	"fmt"
	"ginEssential/common"
	"ginEssential/file"
	"ginEssential/model"
	"ginEssential/response"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"strings"
	"time"
)

//导出开工通知单excel

//	@Summary		导出开工通知单excel
//	@Description	输入信息进行导出
//	@Tags			开工通知管理
//	@Accept			multipart/form-data
//	@Produce		application/msexcel
//	@Param			informNumber	formData	string	true	"通知单编号"
//	@Param			projectName		formData	string	true	"项目名称"
//	@Param			designPhase		formData	string	true	"设计阶段"
//	@Param			projectNumber	formData	string	true	"工程编码"
//	@Param			startTime		formData	string	true	"开始时间"
//	@Param			completionTime	formData	string	true	"完成时间"
//	@Param			designBasis		formData	string	true	"设计依据"
//	@Param			departments		formData	string	true	"专业部室"
//	@Param			remark			formData	string	true	"备注"
//	@Param			technology		formData	string	true	"技保部"
//	@Router			/informs/excel [post]
func InformExcel(ctx *gin.Context) {

	DB := common.GetDB()

	//创建一个新的工作簿
	f := excelize.NewFile()
	//声明工作表的名称
	sheetName := "开工通知单"
	f.SetSheetName("Sheet1", sheetName)
	//往表里面添加数据
	//获取当前时间,填在表头
	now := time.Now()
	currentDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	nowDate := currentDate.Format("2006-1-2")
	//获取通知单编号
	informNumber := ctx.PostForm("informNumber")
	//获取项目名称
	projectName := ctx.PostForm("projectName")
	//获取设计阶段
	designPhase := ctx.PostForm("designPhase")
	//获取工程编码
	projectNumber := ctx.PostForm("projectNumber")
	//获取开始时间
	startTime := ctx.PostForm("startTime")
	//获取完成时间
	completionTime := ctx.PostForm("completionTime")
	//获取设计依据
	designBasis := ctx.PostForm("designBasis")
	//获取前端传来了哪些专业部室
	departments := ctx.PostForm("departments")
	fmt.Println(departments)
	//判断里面有哪些部室
	var department model.Department
	//判断里面有没有规划室
	if strings.Contains(departments, "规划室") {
		//根据规划室查询室主任
		if err := DB.Where("department_name = ?", "规划室").First(&department).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	planDirector := department.DepartmentDirector

	var department1 model.Department
	if strings.Contains(departments, "电气室") {
		if err := DB.Where("department_name = ?", "电气室").First(&department1).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	electricalDirector := department1.DepartmentDirector

	var department2 model.Department
	if strings.Contains(departments, "输电室") {
		if err := DB.Where("department_name = ?", "输电室").First(&department2).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	transmissionDirector := department2.DepartmentDirector

	var department3 model.Department
	if strings.Contains(departments, "土建室") {
		if err := DB.Where("department_name = ?", "土建室").First(&department3).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	constructDirector := department3.DepartmentDirector

	var department4 model.Department
	if strings.Contains(departments, "配电室") {
		if err := DB.Where("department_name = ?", "配电室").First(&department4).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	distributeDirector := department4.DepartmentDirector

	var department5 model.Department
	if strings.Contains(departments, "技经室") {
		if err := DB.Where("department_name = ?", "技经室").First(&department5).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	technologyDirector := department5.DepartmentDirector

	var department6 model.Department
	if strings.Contains(departments, "评审室") {
		if err := DB.Where("department_name = ?", "评审室").First(&department6).Error; err != nil {
			response.Fail(ctx, "部门不存在!", nil)
			return
		}
	}
	evaluateDirector := department6.DepartmentDirector

	//获取备注
	remark := ctx.PostForm("remark")
	//获取技保部
	technology := ctx.PostForm("technology")

	data := [][]interface{}{
		{"工程项目开工通知单"},
		{"时间:", nowDate, nil, nil, nil, "编号:", informNumber, nil, nil},
		{"工程名称", projectName, nil, nil},
		{"设计阶段", designPhase, nil, nil, nil, "工程编码", projectNumber, nil},
		{"工程计划", "开始时间", startTime, nil, nil, "完成时间", completionTime, nil},
		{"设计依据", designBasis, nil},
		{nil, "规划室", nil, nil, nil, "室主任", planDirector, nil},
		{nil, "电气室", nil, nil, nil, "室主任", electricalDirector, nil},
		{nil, "输电室", nil, nil, nil, "室主任", transmissionDirector, nil},
		{"专业部室", "土建室", nil, nil, nil, "室主任", constructDirector, nil},
		{nil, "配电室", nil, nil, nil, "室主任", distributeDirector, nil},
		{nil, "技经室", nil, nil, nil, "室主任", technologyDirector, nil},
		{nil, "评审室", nil, nil, nil, "室主任", evaluateDirector, nil},
		{"备注", remark, nil},
		{"技保部", technology, nil},
	}
	//遍历这个二维数组
	for i, row := range data {
		//按列赋值时,需要指定起始存储坐标
		startCell, err := excelize.JoinCellName("A", i+1)
		if err != nil {
			fmt.Println(err)
			return
		}
		if err := f.SetSheetRow(sheetName, startCell, &row); err != nil {
			fmt.Println(err)
			return
		}
	}
	//合并单元格
	mergeCellRanges := [][]string{
		{"A1", "I1"},
		{"B2", "E2"},
		{"G2", "I2"},
		{"B3", "I3"},
		{"B4", "E4"},
		{"G4", "I4"},
		{"C5", "E5"},
		{"G5", "I5"},
		{"B6", "I6"},
		{"C7", "E7"},
		{"G7", "I7"},
		{"C8", "E8"},
		{"G8", "I8"},
		{"C9", "E9"},
		{"G9", "I9"},
		{"C10", "E10"},
		{"G10", "I10"},
		{"C11", "E11"},
		{"G11", "I11"},
		{"C12", "E12"},
		{"G12", "I12"},
		{"C13", "E13"},
		{"G13", "I13"},
		{"B14", "I14"},
		{"B15", "I15"},
		{"A7", "A9"},
		{"A11", "A13"},
	}
	for _, ranges := range mergeCellRanges {
		if err := f.MergeCell(sheetName, ranges[0], ranges[1]); err != nil {
			fmt.Println(err)
			return
		}
	}
	//创建格式,居中对齐
	style1, err := f.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{Horizontal: "center"},
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	//将样式应用到具体的单元格中
	if f.SetCellStyle(sheetName, "A1", "I15", style1); err != nil {
		fmt.Println(err)
		return
	}
	//保存生成的excel
	//用当前时间来给文件命名
	currentTime1 := time.Now().Format("20060102-150405")
	kai := "start"
	filename := kai + currentTime1 + ".xlsx"
	filepath := "Book1.xlsx"
	err5 := f.SaveAs(filepath)
	// 按照给定路径保存excel
	if err5 != nil {
		response.Fail(ctx, "导出失败", nil)
	} else {
		//下载
		file.ExcelDown(ctx, filepath, filename)
	}
}

 2.参数传递以及结果展示:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/556887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4.1 一级存储结构

本节介绍 GPU 上的一级缓存结构,重点介绍统一的 L1 数据缓存和暂存器“共享内存”,以及它们如何与计算核心交互。 我们还简要讨论了 L1 纹理缓存的典型微架构。 我们包括对纹理缓存的讨论,虽然它在 GPU 计算应用程序中的使用有限,…

前端GC垃圾回收机制

js中的管理是自动的,对象不再被引用时就是垃圾,不能从根上访问时也是垃圾。 能够访问到的对象就是可达对象(引用,作用域链),可达的标准就是从根触发是否能够被找到,根可以理解为是全局变量。 …

【机器学习】 - 作业7: 某闯关类手游用户流失预测

课程链接: 清华大学驭风计划 代码仓库:Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的,其分为四门课,包括: 机器学习(张敏教授) , 深度学习(胡晓林教授), 计算…

并发和线程

并行和并发 1.并行跟并发有什么区别? 从操作系统的角度来看,线程是CPU分配的最小单位。 并行就是同一时刻,两个线程都在执行。这就要求有两个CPU去分别执行两个线程。 并发就是同一时刻,只有一个执行,但是一个时间段…

详解HTTPS加密过程

目录 前言 HTTPS是什么 HTTPS的工作过程 引入对称加密 引入非对称加密 引入证书 总结 前言 对于HTTP上篇文章已经做了详细的解释了。众所周知,HTTPS要比HTTP要安全,但是为什么HTTPS要比HTTP安全呢? 这篇文章主要研究HTTPS的加密机制…

操作系统-X18 linux日志审计

Linux日志审计 在unix/类unix(Linux)系统中,日志是内核(内存)的一部分。 用于记录系统、程序运行中发生的各种事件 通过阅读日志,有助于诊断和解决系统故障 日志文件的分类 ①内核及系统日志 由系统sysl…

队列及其实现

目录 一&#xff1a;队列 1.队列的概念及结构 2.队列的实现 <1>.初始化队列 <2>.队尾入队列 <3>.队头出队列 <4>.获取队列头部元素 <5>.获取队列队尾元素 <6>.获取队列中有效元素个数 <7>.销毁队列 二&#xff1a;完整代…

如何完全卸载IDEA

工欲善其事必先利其器&#xff0c;我们在用idea的时候&#xff0c;idea的环境出现了莫名其妙的问题&#xff0c;怎么也找不到问题原因。有时候也可能是安装了不知名VB脚本&#xff0c;给系统装了一大堆的环境变量(如下图所示)&#xff0c;这个时候你可以试着把idea卸载重新安装…

Jetpack Compose UI预览

Android开发 Jetpack_Compose_2 UI预览Preview 前言 在学习jetpack compose如何编写ui之前&#xff0c;我认为还是应该先了解与Android studio配合的UI预览Preview。 这样就可以立刻看到UI效果&#xff0c;从而方便后续学习验证代码。 所需依赖 implementation "androidx…

CAPL(vTESTStudio) - 自动创建带有时间戳的报告和log

目录 getLocalTime - 获取本地时间函数 代码示例 获取当前时间并形成格式:"2023_05_22_23_20_18"

Qt中的坐标系

Qt中的坐标系 Qt中的坐标系与win10上画图工具的联系 上面这个图片的水印挡住了重要信息,然后又截了一张,显然,画图工具的像素就是Qt中的坐标系,所以,以后查坐标系直接打开Qt:画笔位置所显示的像素就是Qt的坐标!!! 再总结一下: 好奇:win10上的画图工具是qt写的吗? 答: 不是…

【SpringCloud】Nacos

文章目录 一、Nacos1、安装2、服务注册和发现3、服务分级存储模型4、负载均衡策略--NacosRule5、服务实例的权重设置 一、Nacos 1、安装 官网&#xff1a;https://nacos.io/zh-cn/ 下载 Github主页: https://github.com/alibaba/nacos Github的Release下载页: https://githu…

linux命令行如何查看命令帮助信息

一&#xff0c;简介 “授之以鱼不如授之以渔”&#xff0c;我们再学习linux命令的时候&#xff0c;想查看某个命令的详细说明&#xff0c;有哪些方法呢&#xff1f;本文来介绍一下如何在命令行查找命令的帮助信息。 二&#xff0c;linux命令格式介绍 Linux命令一般由三部分组…

【深度学习】- 作业1: Softmax实现手写数字识别

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

【深度学习】 - 作业7: 图像超分辨率重建

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

Linux网络编程—Day10

Linux服务器程序规范 Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端&#xff0c;因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程&#xff08;PID为1的进程&#xff09;&#xff1b;Linux服务器程序通常有一套日志系统&#…

Android 11.0 系统设置显示主菜单添加屏幕旋转菜单实现旋转屏幕功能

1.前言 在android11.0的系统rom定制化开发中,在对系统设置进行定制开发中,有产品需求要求增加 旋转屏幕功能的菜单,就是在点击旋转屏幕菜单后弹窗显示旋转0度,旋转 90度,旋转180度, 旋转270度针对不同分辨率的无重力感应的大屏设备的屏幕旋转功能的实现, 接下来就来分析…

chatgpt赋能Python-python_dill

Python dill - 更高效&#xff0c;更强大的对象序列化工具 在Python编程中&#xff0c;对象序列化是一个非常常见的操作&#xff0c;它将Python对象转换为可以存储或传输的格式。Python默认提供了pickle模块来实现序列化&#xff0c;但是pickle存在一些限制&#xff0c;比如无…

usb摄像头驱动-core层usb设备的注册

usb摄像头驱动-core层driver.c 文章目录 usb摄像头驱动-core层driver.cusb_bus_typeusb_device_matchusb_uevent usb_register_driver 在ubuntu中接入罗技c920摄像头打印的信息如下&#xff1a; 在内核中&#xff0c;/driver/usb/core/driver.c 文件扮演了 USB 核心驱动程序管…

复现ms17-010漏洞

复现ms17-010 复现条件环境操作效果 让我们来看看“hkl”在干嘛 复现 条件 1.靶机必须为win8以下。 2.靶机必须同攻击机处于相同网段&#xff08;即倒数第二位相同&#xff09;。 3.靶机的445端口必须要开启。 环境 虚拟机kali为攻击机&#xff0c;win7虚拟机为靶机。 kali…