package lib import ( "SciencesServer/utils" "errors" "fmt" "github.com/tealeg/xlsx" "reflect" "strings" ) type Excel struct { File *xlsx.File name string sheet string header string title []string content *ExcelContent body map[string][]map[string]string } type ExcelContent struct { Kind ExcelContentKind Content []interface{} } type ExcelContentKind int const ( ExcelContentKindForStruct ExcelContentKind = iota + 1 ExcelContentKindForSlice ExcelContentKindForText ) type OptionExcel func(excel *Excel) func WithExcelName(name string) OptionExcel { return func(excel *Excel) { excel.name = name } } func WithExcelSheet(sheet string) OptionExcel { return func(excel *Excel) { excel.sheet = sheet } } func WithExcelHeader(header string) OptionExcel { return func(excel *Excel) { excel.header = header } } func WithExcelTitle(title []string) OptionExcel { return func(excel *Excel) { excel.title = title } } func WithExcelContent(content *ExcelContent) OptionExcel { return func(excel *Excel) { excel.content = content } } // Export 导出 func (this *Excel) Export() error { this.File = xlsx.NewFile() sheet, _ := this.File.AddSheet(this.sheet) row := new(xlsx.Row) cell := new(xlsx.Cell) style := xlsx.NewStyle() style.Alignment = xlsx.Alignment{ Horizontal: "center", Vertical: "center", } if this.header != "" { row = sheet.AddRow() row.SetHeight(28.0) cell = row.AddCell() cell.HMerge = 1 // 横向合并 //cell.VMerge = 1 // 纵向合并 cell.Value = this.header cell.SetStyle(style) if this.title != nil && len(this.title) > 0 { cell.HMerge = len(this.title) - 1 } } if this.title != nil && len(this.title) > 0 { row = sheet.AddRow() for _, v := range this.title { cell = row.AddCell() cell.Value = v } } if this.content != nil { for _, v := range this.content.Content { row = sheet.AddRow() if this.content.Kind == ExcelContentKindForStruct { row.WriteStruct(v, -1) continue } if this.content.Kind == ExcelContentKindForSlice { row.WriteSlice(v, -1) continue } for i := 0; i < len(this.title); i++ { cell = row.AddCell() // TODO:存在不同类型,请自行加判断 switch v.(type) { case []string: cell.Value = v.([]string)[i] break case []int: cell.Value = fmt.Sprintf("%v", v.([]int)[i]) break case []interface{}: cell.Value = fmt.Sprintf("%v", v.([]interface{})[i]) break default: return errors.New("未知数据类型") } } } } return nil } // Import 导入 // @file:文件信息 // @headers:标题数量 func (this *Excel) Import(file string, headers int) error { _file, err := xlsx.OpenFile(file) if err != nil { return err } out := make(map[string][]map[string]string, 0) // 循环Sheet for _, sheet := range _file.Sheets { data := make([]map[string]string, 0) local := 0 if headers > 0 { local += headers } for i := local + 1; i < len(sheet.Rows); i++ { body := sheet.Rows[i].Cells _data := make(map[string]string, 0) for key, cell := range sheet.Rows[local].Cells { _data[cell.String()] = body[key].String() } data = append(data, _data) } out[sheet.Name] = data } this.body = out return nil } // Save 保存 func (this *Excel) Save(path string) error { return this.File.Save(this.name + ".xlsx") isExist, err := utils.PathExists(path) if err != nil { return err } if !isExist { if err = utils.MkdirAll(path); err != nil { return err } } fmt.Printf("%s/%s.xlsx", path, this.name) return nil //return this.Save(fmt.Sprintf("%s\%s.xlsx", path, this.name)) } // Analysis 解析 func (this *Excel) Analysis(sheet string, src interface{}) error { for k, v := range this.body["专家信息"][0] { tRef := reflect.TypeOf(src).Elem() fieldNum := tRef.NumField() for i := 0; i < fieldNum; i++ { // 匹配结构字段名称 if k != strings.ToLower(tRef.Field(i).Tag.Get("xlsx")) { continue } vRef := reflect.ValueOf(src).Elem().FieldByName(tRef.Field(i).Name) if !vRef.CanSet() { continue } switch vRef.Type().String() { case "string": vRef.SetString(v) break case "int", "int64": vRef.SetInt(utils.StringToInt64(v)) break case "uint", "uint64": vRef.SetUint(utils.StringToUnit64(v)) break } } } return nil } func NewExcel(options ...OptionExcel) *Excel { out := new(Excel) for _, opt := range options { opt(out) } return out }