public/xlsx2proto/xlsx2proto.go

225 lines
5.8 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 main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/tealeg/xlsx"
)
var XlsxFiles = make(map[string]string)
var templates *template.Template
type SheetColumnMetaStruct struct {
ColIndex int
ColName string
ColType int
CTString string
IsArray bool
IsMap bool
}
type SheetMetaStruct struct {
AbsPath string
FileName string
ProtoName string
Cols []*SheetColumnMetaStruct
}
const (
INTTYPE string = "(int)"
INT64TYPE string = "(int64)"
STRTYPE = "(str)"
ARRINTTYPE = "(arrint)"
ARRINT64TYPE = "(arrint64)"
ARRSTRTYPE = "(arrstr)"
INTTYPE_PROTO = "int32"
INT64TYPE_PROTO = "int64"
STRTYPE_PROTO = "string"
MAPTYPE string = "(map)"
MAP_PROTO = "map"
)
func Init() {
var err error
wd, err := os.Getwd()
if err != nil {
return
}
protoAbsPath := filepath.Join(wd, "..", "protocol")
err = os.MkdirAll(protoAbsPath, os.ModePerm)
if err != nil {
return
}
xlsxAbsPath := filepath.Join(wd, "..", "xlsx")
var fis []os.DirEntry
fis, err = os.ReadDir(xlsxAbsPath)
if err != nil {
return
}
srvDataAbsPath := filepath.Join(wd, "..", "code")
err = os.MkdirAll(srvDataAbsPath, os.ModePerm)
if err != nil {
return
}
for _, v := range fis {
if !v.IsDir() {
if !strings.HasSuffix(v.Name(), ".xlsx") {
continue
}
pfAbs := filepath.Join(xlsxAbsPath, v.Name())
XlsxFiles[v.Name()] = pfAbs
}
}
pattern := filepath.Join(wd, "templ", "*.templ")
funcMap := template.FuncMap{
"inc": func(n int) int {
n++
return n
},
}
//fmt.Println("templ目录", pattern)
templates, err = template.Must(template.New("mytempl").Funcs(funcMap).ParseGlob(pattern)).Parse("")
}
func main() {
Init()
smsMap := make(map[string]*SheetMetaStruct)
for xlsxFileName, xlsxFilePath := range XlsxFiles {
xlsxFile, err := xlsx.OpenFile(xlsxFilePath)
if err != nil {
fmt.Println("excel file open error:", err, " filePath:", xlsxFilePath)
continue
}
for _, sheet := range xlsxFile.Sheets {
sms := &SheetMetaStruct{
AbsPath: xlsxFilePath,
FileName: xlsxFileName,
ProtoName: strings.TrimSuffix(xlsxFileName, ".xlsx"),
Cols: make([]*SheetColumnMetaStruct, 0, sheet.MaxCol)}
for _, row := range sheet.Rows {
for i, cell := range row.Cells {
s := cell.String()
if strings.HasSuffix(s, INTTYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, INTTYPE), 1, INTTYPE_PROTO, false, false})
} else if strings.HasSuffix(s, STRTYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, STRTYPE), 2, STRTYPE_PROTO, false, false})
} else if strings.HasSuffix(s, ARRINTTYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRINTTYPE), 3, INTTYPE_PROTO, true, false})
} else if strings.HasSuffix(s, ARRSTRTYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRSTRTYPE), 4, STRTYPE_PROTO, true, false})
} else if strings.HasSuffix(s, INT64TYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, INT64TYPE), 5, INT64TYPE_PROTO, false, false})
} else if strings.HasSuffix(s, ARRINT64TYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ARRINT64TYPE), 6, INT64TYPE_PROTO, true, false})
} else if strings.HasSuffix(s, MAPTYPE) {
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, MAPTYPE), 7, MAP_PROTO, false, true})
}
}
break //only fetch first row
}
smsMap[sms.ProtoName] = sms
break //only fetch first sheet
}
}
geneProto(smsMap)
}
func geneProto(xlsxs map[string]*SheetMetaStruct) {
if xlsxs == nil {
return
}
geneAgcHelper(xlsxs) //生成go代码 xlsx转二进制文件.json,.dat
geneDataStructProto(xlsxs) //生成xlsx转protobuf结构文件(pbdata.proto)
for _, val := range xlsxs {
genGoDataMgr(val) // 生成Go对象文件
}
}
// geneAgcHelper 生成go代码读取xlsx数据
func geneAgcHelper(xlsxs map[string]*SheetMetaStruct) {
dm := map[string]interface{}{
"data": xlsxs,
"opath": filepath.Join("..", "data"),
"isMapCol": isMapColumn(xlsxs),
}
outputHelper := bytes.NewBuffer(nil)
err := templates.ExecuteTemplate(outputHelper, "agc", dm)
if err != nil {
fmt.Println("geneProto ExecuteTemplate error:", err)
return
}
helperGoFile := filepath.Join("..", "xlsx2binary", "agc.go")
err = os.WriteFile(helperGoFile, outputHelper.Bytes(), os.ModePerm)
if err != nil {
fmt.Println("geneProto WriteFile error:", err)
return
}
}
// geneDataStructProto 生成xlsx的proto文件
func geneDataStructProto(xlsxs map[string]*SheetMetaStruct) {
outputHelper := bytes.NewBuffer(nil)
err := templates.ExecuteTemplate(outputHelper, "gpb", xlsxs)
if err != nil {
fmt.Println("geneDataStructProto ExecuteTemplate error:", err)
return
}
protoFile := "../protocol/server/pbdata.proto"
err = os.WriteFile(protoFile, outputHelper.Bytes(), os.ModePerm)
if err != nil {
fmt.Println("geneDataStructProto error:", err)
}
}
// genGoDataMgr 生成go代码读取.dat文件数据
func genGoDataMgr(sms *SheetMetaStruct) {
if sms == nil {
return
}
outputHelper := bytes.NewBuffer(nil)
err := templates.ExecuteTemplate(outputHelper, "gpb_mgr", sms)
if err != nil {
fmt.Println("genGoDataMgr ExecuteTemplate error:", err)
return
}
opath := filepath.Join("../code", strings.ToLower(fmt.Sprintf("%v.go", sms.ProtoName)))
err = os.WriteFile(opath, outputHelper.Bytes(), os.ModePerm)
if err != nil {
fmt.Println("genGoDataMgr WriteFile error:", err)
return
}
}
func isMapColumn(xlsxs map[string]*SheetMetaStruct) bool {
for _, sheet := range xlsxs {
for _, col := range sheet.Cols {
if col.IsMap {
return true
}
}
}
return false
}