Files
2022-04-15 09:13:57 +08:00

288 lines
5.7 KiB
Go
Raw Permalink 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]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头部标题数量
// @sheet读取的sheet0第一页
func (this *Excel) Import(file string, headers, sheet int) error {
_file, err := xlsx.OpenFile(file)
if err != nil {
return err
}
if len(_file.Sheets) < sheet {
return errors.New("异常sheet")
}
out := make([]map[string]string, 0)
_sheet := _file.Sheets[sheet]
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()
}
out = append(out, _data)
}
this.body = out
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 解析
// @dist标识对象
func (this *Excel) Analysis(dist interface{}) []interface{} {
if dist == nil {
return nil
}
out := make([]interface{}, len(this.body))
// 原指针
_dist := reflect.TypeOf(dist)
// 指针类型获取真正type需要调用Elem
if _dist.Kind() == reflect.Ptr {
_dist = _dist.Elem()
}
for key, val := range this.body {
tRef := reflect.New(_dist)
fieldNum := tRef.Elem().NumField()
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)
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
}
}
}
out[key] = tRef.Interface()
}
return out
}
func NewExcel(options ...OptionExcel) *Excel {
out := new(Excel)
for _, opt := range options {
opt(out)
}
return out
}