2022-03-28 07:01:33 +08:00
|
|
|
|
package lib
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"SciencesServer/utils"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/tealeg/xlsx"
|
2022-04-14 18:34:12 +08:00
|
|
|
|
"reflect"
|
|
|
|
|
"strings"
|
2022-03-28 07:01:33 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Excel struct {
|
|
|
|
|
File *xlsx.File
|
|
|
|
|
|
|
|
|
|
name string
|
|
|
|
|
sheet string
|
2022-04-14 18:34:12 +08:00
|
|
|
|
header string
|
2022-03-28 07:01:33 +08:00
|
|
|
|
title []string
|
|
|
|
|
content *ExcelContent
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
body []map[string]string
|
2022-03-28 07:01:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
func WithExcelHeader(header string) OptionExcel {
|
2022-03-28 07:01:33 +08:00
|
|
|
|
return func(excel *Excel) {
|
2022-04-14 18:34:12 +08:00
|
|
|
|
excel.header = header
|
2022-03-28 07:01:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
func WithExcelTitle(title []string) OptionExcel {
|
2022-03-28 07:01:33 +08:00
|
|
|
|
return func(excel *Excel) {
|
2022-04-14 18:34:12 +08:00
|
|
|
|
excel.title = title
|
2022-03-28 07:01:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
func WithExcelContent(content *ExcelContent) OptionExcel {
|
2022-03-28 07:01:33 +08:00
|
|
|
|
return func(excel *Excel) {
|
2022-04-14 18:34:12 +08:00
|
|
|
|
excel.content = content
|
2022-03-28 07:01:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Export 导出
|
|
|
|
|
func (this *Excel) Export() error {
|
|
|
|
|
this.File = xlsx.NewFile()
|
|
|
|
|
sheet, _ := this.File.AddSheet(this.sheet)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
row := new(xlsx.Row)
|
2022-03-28 07:01:33 +08:00
|
|
|
|
cell := new(xlsx.Cell)
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2022-03-28 07:01:33 +08:00
|
|
|
|
}
|
|
|
|
|
if this.title != nil && len(this.title) > 0 {
|
2022-04-14 18:34:12 +08:00
|
|
|
|
row = sheet.AddRow()
|
|
|
|
|
|
2022-03-28 07:01:33 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
// Import 导入
|
|
|
|
|
// @file:文件信息
|
2022-04-14 22:42:09 +08:00
|
|
|
|
// @headers:头部标题数量
|
|
|
|
|
// @sheet:读取的sheet,0:第一页
|
|
|
|
|
func (this *Excel) Import(file string, headers, sheet int) error {
|
2022-04-14 18:34:12 +08:00
|
|
|
|
_file, err := xlsx.OpenFile(file)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2022-04-14 22:42:09 +08:00
|
|
|
|
if len(_file.Sheets) < sheet {
|
|
|
|
|
return errors.New("异常sheet")
|
|
|
|
|
}
|
|
|
|
|
out := make([]map[string]string, 0)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
_sheet := _file.Sheets[sheet]
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
local := 0
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
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()
|
2022-04-14 18:34:12 +08:00
|
|
|
|
}
|
2022-04-14 22:42:09 +08:00
|
|
|
|
out = append(out, _data)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
}
|
|
|
|
|
this.body = out
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
// 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
|
|
|
|
|
//}
|
|
|
|
|
|
2022-03-28 07:01:33 +08:00
|
|
|
|
// 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))
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:34:12 +08:00
|
|
|
|
// Analysis 解析
|
2022-04-14 22:42:09 +08:00
|
|
|
|
func (this *Excel) Analysis(src interface{}) []interface{} {
|
|
|
|
|
if src == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
out := make([]interface{}, 0)
|
|
|
|
|
// 原指针
|
|
|
|
|
_src := reflect.TypeOf(src)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
// 指针类型获取真正type需要调用Elem
|
|
|
|
|
if _src.Kind() == reflect.Ptr {
|
|
|
|
|
_src = _src.Elem()
|
|
|
|
|
}
|
|
|
|
|
for _, val := range this.body {
|
|
|
|
|
tRef := reflect.New(_src)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
fieldNum := tRef.Elem().NumField()
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
for k, v := range val {
|
|
|
|
|
for i := 0; i < fieldNum; i++ {
|
|
|
|
|
// 匹配结构字段名称
|
|
|
|
|
if k != strings.ToLower(tRef.Elem().Type().Field(i).Tag.Get("xlsx")) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
vRef := tRef.Elem().FieldByName(tRef.Elem().Type().Field(i).Name)
|
2022-04-14 18:34:12 +08:00
|
|
|
|
|
2022-04-14 22:42:09 +08:00
|
|
|
|
if !vRef.CanSet() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch vRef.Type().String() {
|
|
|
|
|
case "string":
|
|
|
|
|
vRef.SetString(v)
|
|
|
|
|
break
|
|
|
|
|
case "int", "int32", "int64":
|
|
|
|
|
vRef.SetInt(utils.StringToInt64(v))
|
|
|
|
|
break
|
|
|
|
|
case "uint", "uint32", "uint64":
|
|
|
|
|
vRef.SetUint(utils.StringToUnit64(v))
|
|
|
|
|
break
|
|
|
|
|
case "float", "float32", "float64":
|
|
|
|
|
f, _ := utils.StringToFloat(v)
|
|
|
|
|
vRef.SetFloat(f)
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
2022-04-14 18:34:12 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-14 22:42:09 +08:00
|
|
|
|
out = append(out, tRef.Interface())
|
2022-04-14 18:34:12 +08:00
|
|
|
|
}
|
2022-04-14 22:42:09 +08:00
|
|
|
|
return out
|
2022-04-14 18:34:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-28 07:01:33 +08:00
|
|
|
|
func NewExcel(options ...OptionExcel) *Excel {
|
|
|
|
|
out := new(Excel)
|
|
|
|
|
|
|
|
|
|
for _, opt := range options {
|
|
|
|
|
opt(out)
|
|
|
|
|
}
|
|
|
|
|
return out
|
|
|
|
|
}
|