Files
2022-04-14 18:34:12 +08:00

232 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}