【Go】excelize库实现excel导入导出封装(三),基于excel模板导出excel

news2024/9/28 3:24:17

前言

大家好,这里是符华~

关于excelize库实现excel导入导出封装,我已经写了两篇了,我想要的功能基本已经实现了,现在还差一个模板导出,这篇文章就来讲讲如何实现用模板导出excel。

前两篇:

【Go】excelize库实现excel导入导出封装(一),自定义导出样式、隔行背景色、自适应行高、动态导出指定列、动态更改表头

【Go】excelize库实现excel导入导出封装(二),基于map、多个sheet、多级表头、树形结构表头导出,横向、纵向合并单元格导出


根据模板导出excel,在开发中也是经常会遇到的一种导出方式。一想到模板导出,我自然而然就想到了Java里的 easypoi 框架。easypoi 呢在Java里面也是一个操作excel使用率很高的框架,然后这个框架的模板导出呢,是有设定模板指令的,就是下面这种:

在这里插入图片描述

用的时候就是这样:

在这里插入图片描述

填充数据就是把数据放到map里面,map的key对应模板里面设置的字段名(比如 name、sfz 这几个字段名),map的value就是我们要导出的结果值。

然后呢我就想,Go里面用模板导出应该也是用模板指令的吧?但是呢其实在 excelize 库中,它并不支持类似的模板指令,这么看来 excelize 库好像不支持用模板导出?那有啥办法可以实现这个功能?


欸嘿,还真有,只不过这个模板导出呢就和 excelize 没啥关系了,但因为是自己封装导入导出,那我就干脆把这个模板导出也一起封装进来、一起放到这个专栏系列里面了。

实现

excelize 虽然没有模板指令,但是Go标准库中的 text/templatehtml/template 包提供了强大的模板功能,所以我们本篇文章的实现也是基于 html/template 来实现的。

html/template 的模板指令和 easypoi 的模板指令有点类似,但细节上还是有很大差异的,具体使用用法可以看看这篇文章:Go语言标准库之html/template详解 。

我们可以使用 text/templatehtml/template 来解析模板,但是需要注意的是,这两个库并不能直接解析excel模板,它们只能解析文本格式的文件,不能解析二进制格式的文件。

所以用的时候,我们准备好了一个excel模板时,还需要将这个excel文件另存为xml文件。

有了xml文件也不能直接用,有些地方的数据可能需要处理一下,比如遍历list的时候,需要将 range 遍历放到正确的位置。

检查好之后,再使用 template.ParseFiles 函数解析这个xml文件,接下来就可以填充数据了。填充好后,将渲染模板并输出为excel文件。

准备模板

我们先准备好excel模板

在这里插入图片描述

然后再另存为xml文件

在这里插入图片描述

拿到xml文件后,先不要急着解析,先格式化一下进行检查,如果数据太多,我们按照关键字搜索

在这里插入图片描述

错误的位置:

在这里插入图片描述

改正的位置:

在这里插入图片描述

在这里插入图片描述

按照上面的方法检查并改正好之后,保存好,这样我们就可以开始解析这个xml模板了。

开始

// 模板导出
func ExportTemplate() {
	// 准备结构体数据
	var list = []Test{
		{"fuhua", "符华", "fuhua@123.com", "太虚剑派", false, "1", 1},
		{"baiye", "白夜", "baiye@123.com", "天命科技有限公司", false, "2", 1},
		{"chiling", "炽翎", "chiling@123.com", "太虚剑派", false, "2", 2},
		{"yunmo", "云墨", "yunmo@123.com", "太虚剑派", false, "1", 2},
		{"yuelun", "月轮", "yuelun@123.com", "天命科技有限公司", false, "1", 1},
		{"xunyu", "迅羽", "xunyu@123.com", "天命科技有限公司", true, "2", 124},
	}
	// 准备map数据
	data := map[string]any{
		"name":     "符华",
		"sex":      "女",
		"birthday": "2000-10-01",
		"jg":       "广东省",
		"sfz":      "123456789111111111",
		"gzdw":     "天命科技",
		"email":    "fuhua@123.com",
		"phone":    "13188888888",
		"workList": []map[string]any{
			{"date": "2019-01-01~2020-10-01", "unit": "逐火之蛾", "post": "普通员工", "sfzz": "否"},
			{"date": "2020-10-20~2022-09-15", "unit": "太虚剑派", "post": "CEO", "sfzz": "否"},
			{"date": "2022-10-01~至今", "unit": "天命科技", "post": "经理", "sfzz": "是"},
		},
		"list": list,
	}
	templatePath := "template\\测试模板导出.xml" // 模板路径
	outPath := "C:\\Users\\Administrator\\Desktop\\output.xlsx" // 输出路径
	err := excel.TemplateExport(templatePath, outPath, data)
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println("导出成功!")
	// 将excel下载到浏览器,第一个参数是模板路径、第二个参数是下载的文件名称(要带上后缀)、第三个参数是模板数据、第四个参数是http响应
	// excel.DownLoadByTemplate(templatePath,"output.xlsx",data,res)
}

excel 包下的 TemplateExport 函数:

// TemplateExport 基于excel的模板导出
func TemplateExport(templatePath, outPath string, data map[string]interface{}) error {
	// 解析模板
	tmpl, err := template.ParseFiles(templatePath)
	if err != nil {
		return errors.New("模板解析失败:" + err.Error())
	}
	// 创建输出文件
	file, err := os.Create(outPath)
	if err != nil {
		return errors.New("创建输出文件失败:" + err.Error())
	}
	defer file.Close()
	// 渲染模板并输出结果
	err = tmpl.Execute(file, data)
	if err != nil {
		return errors.New("模板数据渲染失败:" + err.Error())
	}
	return nil
}

excel 包下的 DownLoadByTemplate 函数:

// 根据模板下载文件:templatePath 模板路径,fileName 文件名称(需要加上后缀名),data 模板数据
func DownLoadByTemplate(templatePath, fileName string, data map[string]interface{}, res http.ResponseWriter) {
	// 解析模板
	tmpl, err := template.ParseFiles(templatePath)
	if err != nil {
		http.Error(res, "模板解析失败:"+err.Error(), http.StatusInternalServerError)
		return
	}
	// 设置响应头
	res.Header().Set("Content-Type", "text/html; charset=UTF-8")
	res.Header().Set("Content-Type", "application/octet-stream")
	res.Header().Set("Content-Disposition", "attachment; filename="+fileName)
	res.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
	// 渲染模板并输出结果
	err = tmpl.Execute(res, data)
	if err != nil {
		http.Error(res, "模板数据渲染失败:"+err.Error(), http.StatusInternalServerError)
	}
}

导出结果:

在这里插入图片描述

这样子我们就实现了根据模板导出excel辣~

最后

这里是 源码

如果大家觉得本篇文章或专栏对你有所帮助或者觉得写得还可以的话,欢迎大家多多给博主 点赞关注 支持一下哦😘下载源码的时候顺便给博主点个Star😘你动动手指就是对我莫大的鼓励🥰

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

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

相关文章

Linux-->进程概念

文章目录 进程进程概念操作系统管理进程描述进程-PCB组织进程task_strcut 查看Linux下进程信息通过系统文件查看通过命令查看 通过系统调用获取进程标示符通过系统调用frok创建进程fork的使用进程状态运行阻塞挂起Linux下具体的进程状态 前台进程和后台进程kill僵尸进程孤儿进程…

VGAN实现视网膜图像血管分割(基于pytorch)

背景介绍 VGAN(Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks)出自2018年的一篇论文,尝试使用生成性对抗网络实现视网膜血管分割的任务,原论文地址:https://arxiv.org/abs/1706.0931…

automa插件使用的一些实战经验2

automa的工程还是要经常导出备份,因为经常出现突然模块消失的情况。 1 滑动分页条件区分 传统的页面都是有分页标签,这样你很容易知道,应该用分页来做。但是现在手机端的应用基本都是上滑就可以分页,再混合式开发的环境下&#xf…

【模块系列】STM32BMP280

前言 最进想练习下I2C的应用,手上好有BMP280也没用过,就看着机翻手册和原版手册,开始嘎嘎写库函数了。库的命名应该还1是比较规范了吧,就是手册对于最终值的计算方式很迷糊,所以现在也不能保证有可靠性啊,大…

SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!

SSM整合 1.1 流程分析1.2 整合配置步骤1:创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步骤9:创建Web项目入口配…

力扣日记1.13-【二叉树篇】669. 修剪二叉搜索树

力扣日记:【二叉树篇】669. 修剪二叉搜索树 日期:2023.1.13 参考:代码随想录、力扣 669. 修剪二叉搜索树 题目描述 难度:中等 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树…

1992年-2020年ESA_CCI土地覆盖数据介绍、下载与数据分享

数据介绍 ESA CCI Land Cover是欧洲空间局(European Space Agency,ESA)的一个项目,其目标是生成全球土地覆盖的高质量、一致性和长期的时间序列数据,分辨率大约为300米。 该项目是ESA气候变化计划(Climate…

Linux中安装字体

问题说明 wps 安装后打开文件部分字体出现乱码,原因主要是linux中缺少windows中的相关字体,只要从windows电脑中的字体拷贝到linux系统中并安装就能解决问题 对ubuntu 和manjora有效。 安装字体 字体下载地址可参考附录 在 Linux 中,一次…

强化学习应用(五):基于Q-learning的无人机物流路径规划研究(提供Python代码)

一、Q-learning简介 Q-learning是一种强化学习算法,用于解决基于马尔可夫决策过程(MDP)的问题。它通过学习一个价值函数来指导智能体在环境中做出决策,以最大化累积奖励。 Q-learning算法的核心思想是通过不断更新一个称为Q值的…

机器人模仿学习之动作分块ACT算法的代码剖析、部署训练

前言 本文最早是属于《斯坦福Mobile ALOHA背后的关键技术:动作分块ACT算法的原理解析》的第二、第三部分,涉及到动作分块ACT的代码剖析与部署训练 但因为想把ACT的代码逐行剖析的更细致些,加之为避免上一篇文章太过于长,故把动作…

使用Nginx作为反向代理服务器在Linux中的最佳实践

在Linux环境下,Nginx因其高效性能、稳定性以及丰富的功能集而广泛用于作为反向代理服务器。以下是在Linux中使用Nginx作为反向代理服务器的最佳实践: 1. 安装与配置 首先,确保你的Linux发行版已经安装了Nginx。大多数Linux发行版都提供了Ng…

【上分日记】第369场周赛(分类讨论 + 数学 + 前缀和)

文章目录 前言正文1.3000. 对角线最长的矩形的面积2.3001. 捕获黑皇后需要的最少移动次数3.3002. 移除后集合的最多元素数3.3003. 执行操作后的最大分割数量 总结尾序 前言 终于考完试了,考了四天,也耽搁了四天,这就赶紧来补这场周赛的题了&a…

java求链表中倒数第k个结点

下面我用两种方法求解: 第一种方法:通常我们做这种题就是求出链表的长度length,然后呢length-k的值就是我们要从链表头部走几步就可以了,代码解释: public class Solution {public class ListNode {int val;ListNode…

Star 8K+,使用.NET开发的开源NoSQL数据库

LiteDB 是一个轻量级、快速、易用的 .NET NoSQL 嵌入式数据库,完全用 C# 托管代码开发,并且是免费和开源的。它非常适合在移动应用(Xamarin iOS/Android)和小型的桌面/Web 应用中使用。 主要特点 简单易用的 API,类似…

信号量机制

1965年,由荷兰学者迪科斯彻Dijkstra提出(P、V分别代表荷兰语的Proberen (test)和Verhogen (increment))、是一种卓有成效的进程同步机制。 信号量-软件解决方案: 保证两个或多个代码…

Javascript jQuery简介

✨前言✨ 1.如果代码对您有帮助 欢迎点赞👍收藏⭐哟 后面如有问题可以私信评论哟🗒️ 2.博主后面将持续更新哟😘🎉本章目录🎉 🥝一.jQuery简介🥥二.JQeury常用API🍇1.jQeury选择…

c JPEG编码,此程序没有处现MCU中亮度分量的排序

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> //v4l2 头文件 #include <strin…

UE5蓝图-脚部IK

引擎版本&#xff1a;UE5.2 脚部IK做不做的区别&#xff1a; 图1是没有做脚步IK&#xff0c;我们的角色一部分的脚像是浮在半空中&#xff0c;图2是做了脚步IK&#xff0c;我们的角色就是一部分在地上&#xff0c;一部分在物体上。从上面的两个图可以看出&#xff0c;制作脚步…

Leetcode 剑指 Offer II 061. 查找和最小的 K 对数字

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k…

[oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算

和python玩耍 &#x1f94a; Python 回忆 上次 了解shell环境中的命令 命令作用whoami显示当前用户名pwd显示当前文件夹ls列出当前文件夹下的内容python3仿佛进入大于号黑洞 这python3 怎么玩啊&#xff01;&#x1f620; 说好的python教程呢&#xff1f;&#x1f914; 运…