今天出一个专题教程
如何使用go语言操作excel
背景是
我需要对表格中的数据先做一个筛选,然后按照聚合统计,重点分析其中的几个数据
接入我们自己的一些系统然后继续分析
然后发现这样的操作,具有相当高的重复性,我就在想能不能
写一个通用的脚本来实现这个操作
go读取excel
xlsx文件读取
xlsx本质上是压缩包,这个大家应该都知道吧
可以把xlsx文件改个名,比如xxx.zip,然后解压,你就能得到这些东西

实际上这些工具就是去解析其中的xml文件,然后拿到对应数据的
- 通过文件名读取
func read1() {
file, err := xlsx.OpenFile("0126可疑ip.xlsx")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
fmt.Println(file.Sheet)
}
- 通过字节数组读取
func read2() {
byteData, err := os.ReadFile("0126可疑ip.xlsx")
if err != nil {
fmt.Println("读取文件失败", err)
return
}
file, err := xlsx.OpenBinary(byteData)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
fmt.Println(file.Sheet)
}
- 通过readerAt接口读取
一般用于封装
func read3() {
file, err := os.Open("0126可疑ip.xlsx")
if err != nil {
fmt.Println("打开文件失败", err)
return
}
info, _ := file.Stat()
xFile, err := xlsx.OpenReaderAt(file, info.Size())
if err != nil {
fmt.Println("Error opening file:", err)
return
}
fmt.Println(xFile.Sheet)
}
补充:为什么xlsx需要io.ReaderAt接口,而不是io.Reader接口
| 特性 | io.Reader |
io.ReaderAt |
|---|---|---|
| 读取方式 | 顺序读取 | 随机访问(可以从任意位置读取) |
| 数据源状态 | 读取后数据会从流中移除(破坏性读取) | 读取后数据源不变(非破坏性读取) |
| 适用场景 | 流式数据(如网络流、文件流) | 大文件、需要随机访问的场景 |
| 性能 | 适合小文件或流式处理 | 适合大文件或需要分块读取的场景 |
| 是否支持回溯 | 不支持(除非结合Seek) |
支持(可以随时读取任意位置) |
数据读取
- 先确定哪一个sheet
- 然后读行
- 然后遍历每一列
func readData() {
file, err := xlsx.OpenFile("0126可疑ip.xlsx")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
sheet := file.Sheets[0]
for _, row := range sheet.Rows {
for _, cell := range row.Cells {
fmt.Printf("%v \t", cell.Value)
}
fmt.Println()
}
}
数据读取实战练习
读取0126可疑ip.xlsx,将其中的top10攻击ip拿出来,显示出攻击ip和攻击次数
func readData1() {
file, err := xlsx.OpenFile("0126可疑ip.xlsx")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
sheet := file.Sheets[0]
// 获取去重之后的ip
var uniqueIPMap = map[string]int{}
for _, row := range sheet.Rows[1:] {
ip := row.Cells[1].String()
_, ok := uniqueIPMap[ip]
if ok {
uniqueIPMap[ip]++
} else {
uniqueIPMap[ip] = 1
}
}
type IPData struct {
IP string
Count int
}
var uniqueIPList []IPData
for s, i := range uniqueIPMap {
uniqueIPList = append(uniqueIPList, IPData{
IP: s,
Count: i,
})
}
sort.Slice(uniqueIPList, func(i, j int) bool {
return uniqueIPList[i].Count > uniqueIPList[j].Count
})
for _, info := range uniqueIPList[:10] {
fmt.Println(info.IP, info.Count)
}
}
go写入excel
- 创建sheet
- 创建row
- 创建column
func write() {
file := xlsx.NewFile()
sheet, _ := file.AddSheet("sheet1")
var headers = []string{
"时间",
"攻击IP",
"攻击次数",
}
headerRow := sheet.AddRow()
for _, header := range headers {
headerRow.AddCell().Value = header
}
font := xlsx.NewFont(12, "Calibra")
style := xlsx.NewStyle()
style.Font = *font
for i := 0; i < 10; i++ {
row := sheet.AddRow()
row.AddCell().Value = time.Now().Format("2006-01-02")
cell := row.AddCell()
cell.SetString(fmt.Sprintf("192.168.100.%d", i+1))
cell.SetStyle(style)
row.AddCell().SetInt(i + 1)
}
err := file.Save("xxx.xlsx")
fmt.Println(err)
}