game_sync/tools/xlsx2proto/xlsx2proto.go

237 lines
6.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 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 // proto数据类型
IsArray bool // 是否数组
IsMap bool // 是否map
IsIndex bool // 是否建立索引
}
type SheetMetaStruct struct {
AbsPath string
FileName string
ProtoName string
Cols []*SheetColumnMetaStruct
}
const (
// xlsx标签
IntType = "(int)"
Int64Type = "(int64)"
StrType = "(str)"
ArrIntType = "(arrint)"
ArrInt64Type = "(arrint64)"
ArrStrType = "(arrstr)"
MapType = "(map)"
// xlsx索引类型,带索引
IntTypeIndex = "(int*)"
Int64TypeIndex = "(int64*)"
StrTypeIndex = "(str*)"
// proto类型
IntTypeProto = "int32"
Int64TypeProto = "int64"
StrTypeProto = "string"
MapProto = "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, "..", "..", "srvdata")
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()
switch {
case strings.HasSuffix(s, IntType):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, IntType), 1, IntTypeProto, false, false, false})
case strings.HasSuffix(s, StrType):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, StrType), 2, StrTypeProto, false, false, false})
case strings.HasSuffix(s, ArrIntType):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ArrIntType), 3, IntTypeProto, true, false, false})
case strings.HasSuffix(s, Int64Type):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, Int64Type), 5, Int64TypeProto, false, false, false})
case strings.HasSuffix(s, ArrInt64Type):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, ArrInt64Type), 6, Int64TypeProto, true, false, false})
case strings.HasSuffix(s, MapType):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, MapType), 7, MapProto, false, true, false})
case strings.HasSuffix(s, IntTypeIndex):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, IntTypeIndex), 1, IntTypeProto, false, false, true})
case strings.HasSuffix(s, Int64TypeIndex):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, Int64TypeIndex), 5, Int64TypeProto, false, false, true})
case strings.HasSuffix(s, StrTypeIndex):
sms.Cols = append(sms.Cols, &SheetColumnMetaStruct{i, strings.TrimSuffix(s, StrTypeIndex), 2, StrTypeProto, false, 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("../../srvdata", 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
}