当前位置: 首页 > 工具软件 > Excelize > 使用案例 >

Golang操作Excel的模块Excelize学习总结

贝阳泽
2023-12-01

读取Excel的数据,转换成Golang中的数据类型

这个案例主要是读取excel中单元格的数据

打开指定的文件(TMP_01.xlsx),读取文件内容,并输出为go的数据格式

  • 打开已存在的文件
    func OpenFile(filename string, opt ...Options) (*File, error)
  • 按行读取所有的数据
    func (f *File) GetRows(sheet string) ([][]string, error)
  • 按行读取数据,用于循环读取每一行
    func (f *File) Rows(sheet string) (*Rows, error)
    func (rows *Rows) Next() bool
    func (rows *Rows) Columns() ([]string, error)
rows,err := file.Rows("Sheet1")
if err != nil {
    fmt.Println(err)
    return
}
for rows.Next(){
    s,err := rows.Columns
    if err != nil {
        fmt.Println(err)
        return 
    }
    fmt.Println(s)  // 字符串切片,一行的所有数据
}
  • 按行读取数据,用于循环读取每一行 与rows方法类似
    func (f *File) Cols(sheet string) (*Cols, error)
    func (cols *Cols) Next() bool
    func (cols *Cols) Rows() ([]string, error)

  • 指定单元格的值
    func (f *File) GetCellValue(sheet, axis string) (string, error)

  • 指定单元格的公式
    func (f *File) GetCellFormula(sheet, axis string) (string, error)

  • 指定单元格的链接

HYPERLINK 创建的链接只能通过获取公式得到

func (f *File) GetCellHyperLink(sheet, axis string) (bool, string, error)

  • 获取合并单元格
    func (f *File) GetMergeCells(sheet string) ([]MergeCell, error)
  • 获取合并单元格的开始单元格
    func (m *MergeCell) GetStartAxis() string
  • 合并单元格的结束单元格
    func (m *MergeCell) GetEndAxis() string
  • 合并单元格的值
    func (m *MergeCell) GetCellValue() string

合并单元格范围内的所有单元格的值都是一样的,也可以直接使用 GetCellValue 获取值

代码:main.go

package main

import (
	"fmt"
	"strconv"

	"github.com/xuri/excelize/v2"
)

func main() {
	f, err := excelize.OpenFile("../excel_files/TMP_01.xlsx")
	if err != nil {
		fmt.Println("打开文件失败,错误信息:", err)
		return
	}
	// 指定sheet页数据
	fmt.Println("step1")
	rows, err := f.GetRows("基础的表格")
	if err != nil {
		fmt.Println("获取行信息失败,错误信息:", err)
		return
	}
	// 输出为切片类型
	fmt.Println(rows)
	// 注意:输出的是切片,当前行有多少列数据切片的长度就是几,就是说每一行的数据个数与整个表格的没有关系
	fmt.Printf("按行获取的数据类型是:%T\n", rows)

	// 输出为map
	var users []map[string]interface{}
	// 表头数据
	var columns []string = rows[0]

	for _, row := range rows[1:] {
		user := make(map[string]interface{}, 1)
		for idx, col := range columns {
			if len(row)-1 < idx {
				user[col] = ""
			} else {
				user[col] = row[idx]
				// fmt.Printf("当前单元格的数据类型是%T\n", row[idx]) // 所有的都默认是string
			}
		}
		users = append(users, user)
	}

	fmt.Println(users)
	fmt.Printf("数据类型是 %T\n", users)

	var users2 = make([]User, 0)
	for _, row := range rows[1:] {
		if len(row) < 4 {
			row = append(row, make([]string, 4-len(row))...)
		}
		u := new(User)
		u.Name = row[0]
		u.Gender = row[1]
		age, err := strconv.ParseUint(row[2], 10, 8)
		if err != nil {
			fmt.Println(err)
			return
		}
		u.Age = uint8(age)
		u.Worker = row[3]
		users2 = append(users2, *u)
	}
	fmt.Println(users2)

	// 按行获取数据
	fmt.Println("step2")
	r, err := f.Rows("基础的表格")
	if err != nil {
		fmt.Println(err)
	}

	// 按行循环取数据
	for r.Next() {
		s, err := r.Columns()
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println(s, len(s))
	}

	// 按列获取数据
	fmt.Println("step3")
	cols, err := f.GetCols("基础的表格")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(cols)

	// 某一列去重  性别列示例
	cols1 := DeduplicateSlices(cols[1][1:])
	fmt.Println(cols1)

	// 按列获取数据
	cols2, err := f.Cols("基础的表格")
	if err != nil {
		fmt.Println(err)
		return
	}
	// 循环获取每一列的数
	for cols2.Next() {
		r, err := cols2.Rows()
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(r)
	}

	fmt.Println("step4")
	// 获取指定单元格的数据
	s, err := f.GetCellValue("基础的表格", "A1")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(s)

	// 获取单元格的公式
	formula1, err := f.GetCellFormula("sheet2", "C1")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(formula1)
	formula2, _ := f.GetCellFormula("sheet2", "C2")
	fmt.Println(formula2)
	fmt.Println(f.GetCellValue("sheet2", "C2"))
	formula3, _ := f.GetCellFormula("sheet2", "C3")
	fmt.Println(formula3)
	formula4, _ := f.GetCellFormula("sheet2", "C4") // 没有公式就为空
	fmt.Println(formula4)
	formula5, _ := f.GetCellFormula("sheet2", "C5")
	fmt.Println(formula5)

	// 指定单元格的链接 返回的第一个值是判断是否是链接,第二个值是链接的目标位置,第三个是错误
	ok, target, err := f.GetCellHyperLink("sheet2", "D1")
	fmt.Println(ok, target, err)
	if err != nil || !ok {
		fmt.Println(err)
	}
	fmt.Println(target)

	fmt.Println(f.GetCellHyperLink("sheet2", "A1"))
	fmt.Println(f.GetCellHyperLink("sheet2", "D2")) // 不适用于使用HYPERLINK 公式创建的链接
	fmt.Println(f.GetCellFormula("sheet2", "D2"))   // HYPERLINK 创建的链接只能通过获取公式得到

	// 获取合并单元格
	fmt.Println("step5")
	merge_cells, err := f.GetMergeCells("sheet2")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(merge_cells)
	for _, c := range merge_cells {
		fmt.Println(c.GetStartAxis()) // 合并单元格开始的单元格
		fmt.Println(c.GetEndAxis())   // 合并单元格结束的单元格
		fmt.Println(c.GetCellValue()) // 合并单元格的值
	}
	fmt.Println(f.GetCellValue("sheet2", "A9")) // 合并单元格的所有单元格的值都一样
	fmt.Println(f.GetCellValue("sheet2", "B9"))
}

代码: func.go

package main

type User struct {
	Name   string `json:"name"`
	Gender string `json:"gender"`
	Age    uint8  `json:"age"`
	Worker string `json:"worker"`
}

func NewUser(name string, gender string, age uint8, worker string) *User {
	return &User{
		Name:   name,
		Age:    age,
		Gender: gender,
		Worker: worker,
	}
}

func (u *User) Work() string {
	return u.Name + "目前正在从事" + u.Worker
}

// 根据中文名称获取对应的英文名称
func GetColName(col string) (t string) {
	switch col {
	case "姓名":
		t = "Name"
	case "性别":
		t = "Gender"
	case "工作":
		t = "Worker"
	case "年龄":
		t = "Age"
	}
	return
}

// 切片去重
func DeduplicateSlices(slices []string) []string {

	var tmp_map = make(map[string]uint)
	for _, str := range slices {
		_, ok := tmp_map[str]
		if !ok {
			tmp_map[str] = 1
			continue
		}
		tmp_map[str] += 1
	}
	rst := make([]string, 0)
	for idx := range tmp_map {
		rst = append(rst, idx)
	}
	return rst
}

更多API请移驾作者大佬的文档 : https://xuri.me/excelize/zh-hans/
作者大佬的视频 : https://www.bilibili.com/video/BV1hU4y1F7wQ

 类似资料: