Golang是如何操作excel的?
关键术语介绍
为了方便开源库的快速上手,我们先来了解 excel 中的几个关键术语,如下图所示,①为sheet,也就是表格中的页签;②为row,代表 excel 中的一行;③为cell,代表 excel 中的一个单元格。
正常情况下,创建一个表格的基本流程是打开 wps 点击新建,这时会默认创建一个 sheet,然后在该 sheet 中的第一行填写表头,接下来根据表头逐行填充内容,最后将文件另存为到硬盘的某个位置。这与 Golang 开源库创建 excel 的流程基本相同,下面演示一个极简表格的创建。
创建表格
创建表格前需要先引入 excel 库,我们以比较热门的 tealeg/xlsx 库为例。
go get github.com/tealeg/xlsx
首先创建一个空文件,拿到文件句柄。
file := xlsx.NewFile()
创建一个名为人员信息收集
的 sheet。
sheet, err := file.AddSheet("人员信息收集")
if err != nil {
panic(err.Error())
}
然后为该 sheet 创建一行,这行作为我们的表头。
row := sheet.AddRow()
在该行中创建一个单元格。
cell := row.AddCell()
现在给单元格填充内容,因为是表头,暂且叫姓名
。
cell.Value = "姓名"
如何创建第二个单元格呢?原理相同,此处 cell 变量已定义,再创建新单元格只需赋值即可。
cell = row.AddCell()
cell.Value = "性别"
表头已经设置好了,可以开始创建第二行来填充内容了,方式与上述无差别。
row = sheet.AddRow()
cell = row.AddCell()
cell.Value = "张三"
cell = row.AddCell()
cell.Value = "男"
表格设置完成后,将该文件保存,文件名可自定义。
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
跑起来后,可以发现目录中多了一个 demo.xlsx 文件,打开预览内容如下,达到了预期效果。
文件源码
package main
import "github.com/tealeg/xlsx"
func main() {
file := xlsx.NewFile()
sheet, err := file.AddSheet("人员信息收集")
if err != nil {
panic(err.Error())
}
row := sheet.AddRow()
cell := row.AddCell()
cell.Value = "姓名"
cell = row.AddCell()
cell.Value = "性别"
row = sheet.AddRow()
cell = row.AddCell()
cell.Value = "张三"
cell = row.AddCell()
cell.Value = "男"
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
}
读取表格
表格的读取比创建简单很多,依然以上文创建的文件为例。
output, err := xlsx.FileToSlice("demo.xlsx")
if err != nil {
panic(err.Error())
}
只需将文件路径传入上述方法,即可自动读取并返回一个三维切片,我们来读取第一个 sheet 的第二行中的第一个单元格。
log.Println(output[0][1][1]) //Output: 男
由此一来就非常容易遍历了。
for rowIndex, row := range output[0] {
for cellIndex, cell := range row {
log.Println(fmt.Sprintf("第%d行,第%d个单元格:%s", rowIndex+1, cellIndex+1, cell))
}
}
2020/10/11 16:15:29 第1行,第1个单元格:姓名
2020/10/11 16:15:29 第1行,第2个单元格:性别
2020/10/11 16:15:29 第2行,第1个单元格:张三
2020/10/11 16:15:29 第2行,第2个单元格:男
文件源码
package main
import (
"fmt"
"github.com/tealeg/xlsx"
"log"
)
func main() {
output, err := xlsx.FileToSlice("demo.xlsx")
if err != nil {
panic(err.Error())
}
log.Println(output[0][1][1])
for rowIndex, row := range output[0] {
for cellIndex, cell := range row {
log.Println(fmt.Sprintf("第%d行,第%d个单元格:%s", rowIndex+1, cellIndex+1, cell))
}
}
}
修改表格
只是读取表格内容可能在特定场景下无法满足需求,有时候需要对表格内容进行更改。
file, err := xlsx.OpenFile("demo.xlsx")
if err != nil {
panic(err.Error())
}
修改表格之前依然需要先读取文件,只是这次并没有直接将其转化为三维切片。拿到文件句柄后,可以直接修改某一行的内容。
file.Sheets[0].Rows[1].Cells[0].Value = "李四"
上述代码将第二行的张三改为了李四,但这还没有结束,接下来需要将文件重新保存。
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
打开文件预览,可以看到已经成功将张三改为了李四。
文件源码
package main
import "github.com/tealeg/xlsx"
func main() {
file, err := xlsx.OpenFile("demo.xlsx")
if err != nil {
panic(err.Error())
}
file.Sheets[0].Rows[1].Cells[0].Value = "李四"
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
}
样式设置
该开源库不仅支持内容的编辑,还支持表格的样式设置,样式统一由结构体 Style 来负责。
type Style struct {
Border Border
Fill Fill
Font Font
ApplyBorder bool
ApplyFill bool
ApplyFont bool
ApplyAlignment bool
Alignment Alignment
NamedStyleIndex *int
}
拿上述生成的文件为例,假如我要将姓名所在单元格居中,首先要实例化样式对象。
style := xlsx.NewStyle()
赋值居中属性。
style.Alignment = xlsx.Alignment{
Horizontal: "center",
Vertical: "center",
}
给第一行第一个单元格设置样式。
file.Sheets[0].Rows[0].Cells[0].SetStyle(style)
与修改表格处理逻辑相同,最后保存文件。
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
打开预览,可以看到文字已经上下左右居中。
同理,可以修改文字颜色和背景,同样通过 style 的属性来设置。
style.Font.Color = xlsx.RGB_Dark_Red
style.Fill.BgColor = xlsx.RGB_Dark_Green
其他还有很多属性可以设置,比如合并单元格、字体、大小等等,大家可以自行测试。
文件源码
package main
import "github.com/tealeg/xlsx"
func main() {
file, err := xlsx.OpenFile("demo.xlsx")
if err != nil {
panic(err.Error())
}
style := xlsx.NewStyle()
style.Font.Color = xlsx.RGB_Dark_Red
style.Fill.BgColor = xlsx.RGB_Dark_Green
style.Alignment = xlsx.Alignment{
Horizontal: "center",
Vertical: "center",
}
file.Sheets[0].Rows[0].Cells[0].SetStyle(style)
err = file.Save("demo.xlsx")
if err != nil {
panic(err.Error())
}
}
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(七)图片上传功能
- 黑客比程序员牛在哪?
- oracle工具集初探(r4笔记第8天)
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(二)Log4j讲解与整合
- 京东JData算法大赛-高潜用户购买意向预测(github源码)
- 巧用linux命令做图片下载器(r4笔记第7天)
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(五)结合MockMvc进行服务端的单元测试
- 关于order by中的数据排序(r4笔记第6天)
- 深度学习CTPN+CRNN模型实现图片内文字的定位与识别(OCR)
- Markdown语法讲解及MWeb使用教程
- 通过Linu命令实现屏幕录制和回放(r4笔记第5天)
- 用keras对国产剧评论文本的情感进行预测
- python常用可视化技巧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 你不知道的 node 爬虫原来这么简单
- 带货直播系统源码中,商品详情页是如何搭建起来的
- 基于飞桨复现CVPR 2020 GhostNet的全程解析
- 【即时通信IM】红包消息如何构建?
- YOLOv4损失函数全面解析
- Pandas进阶修炼120题,给你深度和广度的船新体验
- 5万字、97 张图总结操作系统核心知识点
- C++核心准则CP.100:不要使用无锁编程方式,除非绝对必要
- 神了,Excel的这个操作我今天才知道
- DataFrame(7):DataFrame运算——逻辑运算
- 高性能网关设计实践
- LASSO回归姊妹篇:R语言实现岭回归分析
- 学了这个,三歪再也不想写各种setter了
- 使用 GitLab CI 与 Argo CD 进行 GitOps 实践
- Java 语言中十大“坑爹”功能!