mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
122 lines
2.8 KiB
Go
122 lines
2.8 KiB
Go
|
|
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
|
|||
|
|
}
|