Files
chat-deploy/pkg/common/xlsx/main.go
kim.dev.6789 b7f8db7d08 复制项目
2026-01-14 22:35:45 +08:00

116 lines
2.3 KiB
Go

package xlsx
import (
"errors"
"github.com/xuri/excelize/v2"
"io"
"reflect"
)
func ParseSheet(file *excelize.File, v interface{}) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr {
return errors.New("not ptr")
}
val = val.Elem()
if val.Kind() != reflect.Slice {
return errors.New("not slice")
}
itemType := val.Type().Elem()
if itemType.Kind() != reflect.Struct {
return errors.New("not struct")
}
newItemValue := func() reflect.Value {
return reflect.New(itemType).Elem()
}
putItem := func(v reflect.Value) {
val.Set(reflect.Append(val, v))
}
var sheetName string
if s, ok := newItemValue().Interface().(SheetName); ok {
sheetName = s.SheetName()
} else {
sheetName = itemType.Name()
}
if sheetIndex, err := file.GetSheetIndex(sheetName); err != nil {
return err
} else if sheetIndex < 0 {
return nil
}
fieldIndex := make(map[string]int)
for i := 0; i < itemType.NumField(); i++ {
field := itemType.Field(i)
alias := field.Tag.Get("column")
switch alias {
case "":
fieldIndex[field.Name] = i
case "-":
continue
default:
fieldIndex[alias] = i
}
}
if len(fieldIndex) == 0 {
return errors.New("empty column struct")
}
sheetIndex := make(map[string]int)
for i := 1; ; i++ {
name, err := file.GetCellValue(sheetName, GetAxis(i, 1))
if err != nil {
return err
}
if name == "" {
break
}
if _, ok := fieldIndex[name]; ok {
sheetIndex[name] = i
}
}
if len(sheetIndex) == 0 {
return errors.New("sheet column empty")
}
for i := 2; ; i++ {
var (
notEmpty int
item = newItemValue()
)
for column, index := range sheetIndex {
s, err := file.GetCellValue(sheetName, GetAxis(index, i))
if err != nil {
return err
}
if s == "" {
continue
}
notEmpty++
if err = String2Value(s, item.Field(fieldIndex[column])); err != nil {
return err
}
}
if notEmpty > 0 {
putItem(item)
} else {
break
}
}
return nil
}
func ParseAll(r io.Reader, models ...interface{}) error {
if len(models) == 0 {
return errors.New("empty models")
}
file, err := excelize.OpenReader(r)
if err != nil {
return err
}
defer file.Close()
for i := 0; i < len(models); i++ {
if err := ParseSheet(file, models[i]); err != nil {
return err
}
}
return nil
}