Files
NetworkAuth/utils/excel/excel.go

122 lines
2.8 KiB
Go
Raw Normal View History

2026-03-18 21:51:17 +08:00
package excel
import (
"fmt"
"io"
"reflect"
"time"
"github.com/xuri/excelize/v2"
)
// ExportData 导出数据配置
type ExportData struct {
Headers []string // 表头显示名称列表
Fields []string // 对应结构体字段名或Map键名
Data interface{} // 数据源(必须是切片类型)
Sheet string // 工作表名称,默认为 Sheet1
}
// Export 生成Excel文件
func Export(config ExportData) (*excelize.File, error) {
f := excelize.NewFile()
sheet := config.Sheet
if sheet == "" {
sheet = "Sheet1"
}
// 如果不是默认Sheet1则创建新Sheet
index, err := f.NewSheet(sheet)
if err != nil {
return nil, err
}
// 设置表头
for i, header := range config.Headers {
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
f.SetCellValue(sheet, cell, header)
}
// 设置表头样式(加粗、背景色)
style, _ := f.NewStyle(&excelize.Style{
Font: &excelize.Font{Bold: true},
Fill: excelize.Fill{Type: "pattern", Color: []string{"#E0E0E0"}, Pattern: 1},
})
f.SetRowStyle(sheet, 1, 1, style)
// 处理数据
val := reflect.ValueOf(config.Data)
if val.Kind() != reflect.Slice {
return nil, fmt.Errorf("data must be a slice")
}
for i := 0; i < val.Len(); i++ {
item := val.Index(i)
// 如果是指针,获取其指向的值
if item.Kind() == reflect.Ptr {
item = item.Elem()
}
rowNum := i + 2 // 从第2行开始第1行是表头
for j, field := range config.Fields {
cellName, _ := excelize.CoordinatesToCellName(j+1, rowNum)
var cellValue interface{}
// 尝试从结构体或Map中获取值
if item.Kind() == reflect.Struct {
fieldVal := item.FieldByName(field)
if fieldVal.IsValid() {
cellValue = fieldVal.Interface()
}
} else if item.Kind() == reflect.Map {
key := reflect.ValueOf(field)
mapVal := item.MapIndex(key)
if mapVal.IsValid() {
cellValue = mapVal.Interface()
}
}
// 特殊类型处理
switch v := cellValue.(type) {
case time.Time:
if !v.IsZero() {
f.SetCellValue(sheet, cellName, v.Format("2006-01-02 15:04:05"))
}
case *time.Time:
if v != nil && !v.IsZero() {
f.SetCellValue(sheet, cellName, v.Format("2006-01-02 15:04:05"))
}
default:
f.SetCellValue(sheet, cellName, v)
}
}
}
f.SetActiveSheet(index)
// 如果创建了新Sheet且名字不叫Sheet1删除默认的Sheet1
if sheet != "Sheet1" {
f.DeleteSheet("Sheet1")
}
return f, nil
}
// Parse 读取Excel文件内容返回二维字符串数组
func Parse(r io.Reader) ([][]string, error) {
f, err := excelize.OpenReader(r)
if err != nil {
return nil, err
}
defer f.Close()
// 获取第一个工作表
sheet := f.GetSheetName(0)
rows, err := f.GetRows(sheet)
if err != nil {
return nil, err
}
return rows, nil
}