1 Star 0 Fork 0

心灵波动 / excel2cfg

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
excel2cfg.py 34.63 KB
一键复制 编辑 原始数据 按行查看 历史
心灵波动 提交于 2021-07-07 14:38 . first
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
#!/usr/bin/python
# -*- coding: utf-8 -*-
# 这段代码主要的功能是把excel表格转换成utf-8格式的json文件
# lastdate:2011-8-15 14:21 version 1.1
"""
https://github.com/zdhsoft/excel2json
pip install pyinstaller
pyinstaller -F excel2json.py
"""
import os
import sys
import codecs
from shutil import copy
import json
import xlrd # http://pypi.python.org/pypi/xlrd
from collections import OrderedDict
from enum import Enum
import types
import argparse
import datetime
import hashlib
import platform;
from colorama import Fore, Back, Style, init
# 缓存目录的路径
CACHE_PATH = "__cache"
# 客户端输出目录
ClientPath = "Client"
# 服务器端输出目录
ServerPath = "Server"
# 字段名所在行
FIELD_ROW = 0
# 数据类型所在行
TYPE_ROW = 1
# 数据类别所在行
CATEGORY_ROW = 2
# 数据开始行
DATA_ROW = 4
# 导出分类
CATEGORY_UNKNOW = 0
CATEGORY_CLIENT = 1
CATEGORY_SERVER = 2
CATEGORY_BOTH = 3
class CategoryType(Enum):
UNKNOW = 0
CLIENT = 1
SERVER = 2
BOTH = 3
AccessCategoryType = {'C': CategoryType.CLIENT, 'S': CategoryType.SERVER, 'C&S': CategoryType.BOTH}
def is_in_category_type(t1, t2):
if t1 == 'C' and (t2 == 'C' or t2 == 'C&S'):
return True
if t1 == 'S' and (t2 == 'S' or t2 == 'C&S'):
return True
return False
# 数据类型枚举
class DataType(Enum):
NONE = 0
INT = 1
FLOAT = 2
BOOL = 3
STRING = 4
ARRAY = 5
OBJECT = 6
AccessDataType = {'int': DataType.INT, 'float': DataType.FLOAT, 'bool': DataType.BOOL,'string': DataType.STRING,'array': DataType.ARRAY, 'object': DataType.OBJECT}
# 字符串转类型枚举
def convertDataType(colType):
if not colType in AccessDataType:
return DataType.NONE
return AccessDataType[colType]
# 表格类型
class TabType(Enum):
NONE = 0
TAB_ARRAY = 1 # array类型
TAB_MAP = 2 # map类型
TAB_KV = 3 # kv类型
AccessTabType = {'array': TabType.TAB_ARRAY, 'map': TabType.TAB_MAP, 'kv': TabType.TAB_KV}
# 导出类型
class ExportType(Enum):
NONE = 0
JSON = 1
LUA = 2
TS = 3
AccessExportType = {'.json': ExportType.JSON, '.lua': ExportType.LUA, '.ts': ExportType.TS}
# 校验导出类型是否合法
def check_export(suffix):
pass
# kv 类型默认导出列
DefaultKVFields = {'key':0,'value':1,'type':2,'required':3,'desc':4}
def hump2underline(hump_str):
"""
驼峰形式字符串转成下划线形式
:param hump_str: 驼峰形式字符串
:return: 字母全小写的下划线形式字符串
"""
# 匹配正则,匹配小写字母和大写字母的分界位置
p = re.compile(r'([a-z]|\d)([A-Z])')
# 这里第二个参数使用了正则分组的后向引用
sub = re.sub(p, r'\1_\2', hump_str).lower()
return sub
def underline2hump(underline_str):
"""
下划线形式字符串转成驼峰形式
:param underline_str: 下划线形式字符串
:return: 驼峰形式字符串
"""
# 这里re.sub()函数第二个替换参数用到了一个匿名回调函数,回调函数的参数x为一个匹配对象,返回值为一个处理后的字符串
sub = re.sub(r'(_\w)', lambda x: x.group(1)[1].upper(), underline_str)
return sub
def json_hump2underline(hump_json_str):
"""
把一个json字符串中的所有字段名都从驼峰形式替换成下划线形式。
注意点:因为考虑到json可能具有多层嵌套的复杂结构,所以这里直接采用正则文本替换的方式进行处理,而不是采用把json转成字典再进行处理的方式
:param hump_json_str: 字段名为驼峰形式的json字符串
:return: 字段名为下划线形式的json字符串
"""
# 从json字符串中匹配字段名的正则
# 注:这里的字段名只考虑由英文字母、数字、下划线组成
attr_ptn = re.compile(r'"\s*(\w+)\s*"\s*:')
# 使用hump2underline函数作为re.sub函数第二个参数的回调函数
sub = re.sub(attr_ptn, lambda x: '"' + hump2underline(x.group(1)) + '" :', hump_json_str)
return sub
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, obj)
# 打印错误
def printError(errStr):
print (Back.BLUE + "**************************************************")
print (Fore.RED + errStr)
print (Back.BLUE + "**************************************************")
# 获取文件md5
def getFileMD5(filePath):
if not (os.path.exists(filePath)):
return ""
srcFile = open(filePath, "rb")
srcData = srcFile.read()
srcFile.close()
m = hashlib.md5()
m.update(srcData)
return m.hexdigest()
# 删除文件
def removeFile(filePath):
if os.path.exists(filePath):
os.remove(filePath)
# 拷贝文件
def copyFile(src, dst):
removeFile(dst)
copy(src, dst)
def spaceString(layer):
lua_str = ""
for i in range(0, layer):
lua_str += '\t'
return lua_str
def objToLuaString(data, layer=0):
d_type = type(data)
if d_type is list:
lua_str = "{\n"
lua_str += spaceString(layer+1)
for i in range(0, len(data)):
lua_str += ("[" + str(i+1) + "] = ")
lua_str += dicToLuaString(data[i], layer+1)
if i < len(data)-1:
lua_str += ','
lua_str += '\n'
lua_str += spaceString(layer)
lua_str += '}'
return lua_str
elif d_type is dict:
lua_str = ''
lua_str += "{\n"
data_len = len(data)
data_count = 0
for k, v in data.items():
data_count += 1
lua_str += spaceString(layer+1)
if type(k) is int:
lua_str += '[' + str(k) + ']'
else:
lua_str += '["' + str(k) + '"]'
lua_str += ' = '
try:
lua_str += dicToLuaString(v, layer + 1)
if data_count < data_len:
lua_str += ',\n'
except :
print('error in ', k, v)
raise
lua_str += '\n'
lua_str += spaceString(layer)
lua_str += '}'
return lua_str
else:
print(d_type, 'is error')
return None
def dicToLuaString(data, layer=0):
d_type = type(data)
if d_type is type(None):
return 'nil'
elif d_type is bytes or d_type is str or d_type is str:
return "'" + data + "'"
elif d_type is bool:
if data:
return 'true'
else:
return 'false'
elif d_type is int or d_type is int or d_type is float:
return str(data)
elif d_type is list:
lua_str = "{\n"
lua_str += spaceString(layer+1)
for i in range(0, len(data)):
lua_str += ("[" + str(i+1) + "] = ")
lua_str += dicToLuaString(data[i], layer+1)
if i < len(data)-1:
lua_str += ','
lua_str += '\n'
lua_str += spaceString(layer)
lua_str += '}'
return lua_str
elif d_type is dict:
lua_str = ''
lua_str += "\n"
lua_str += spaceString(layer)
lua_str += "{\n"
data_len = len(data)
data_count = 0
for k, v in data.items():
data_count += 1
lua_str += spaceString(layer+1)
if type(k) is int:
lua_str += '[' + str(k) + ']'
else:
lua_str += '["' + str(k) + '"]'
lua_str += ' = '
try:
lua_str += dicToLuaString(v, layer + 1)
if data_count < data_len:
lua_str += ',\n'
except e:
print ('error in ', k, v)
raise
lua_str += '\n'
lua_str += spaceString(layer)
lua_str += '}'
return lua_str
else:
print(d_type, 'is error')
return None
def IsJson(strValue):
try:
obj = json.loads(strValue, encoding='utf-8')
d_type = type(obj)
if d_type is list:
return True
elif d_type is dict:
return True
return False
except ValueError:
return False
return False
def IsInt(strValue):
try:
int(strValue)
except ValueError:
return False
return True
def IsFloat(strValue):
try:
float(strValue)
except ValueError:
return False
return True
def FloatToString(aFloat):
if type(aFloat) != float:
return u""
strTemp = str(aFloat)
strList = strTemp.split(".")
if len(strList) == 1:
return strTemp
else:
if strList[1] == "0":
return u""+strList[0]
else:
return u""+strTemp
def ParseExtType(paramExtType):
strList = paramExtType.split(":")
retType = {}
if len(strList) == 2:
retType["key"] = strList[0]
retType["type"] = strList[1]
else:
retType["key"] = ""
retType["type"] = ""
return retType
# 查找第1个非要求的字符串的下标
def findFirstNot(str, begin, substr):
for i in range(begin, len(str)):
if substr.find(str[i]) == -1:
return i
return -1
# 解析filter字符串,返回变量数组
def parseFilterKey(filter):
ret = []
begin = 0
while True:
index = filter.find("$", begin)
if index >= 0:
index += 1
end = findFirstNot(
filter, index, "1234567890abcdefghijklmnopqrstuvwxyz_ABC DEFGHIJKLMNOPQRSTUVWXYZ")
key = filter[index:end]
ret.append(key)
begin = end
else:
return ret
# 读取字段列表
def readFields(paramFields):
# mapField = {}
mapField = OrderedDict()
strList = paramFields.split(",")
i = 0
for f in strList:
mapField[f] = i
i += 1
return mapField
# def CellToString(paramCell):
# strCellValue = u""
# if type(paramCell) == unicode:
# strCellValue = paramCell
# elif type(paramCell) == float:
# strCellValue = FloatToString(paramCell)
# else:
# strCellValue = str(paramCell)
# return strCellValue
def IsEmptyLine(paramTable, paramRow, paramFieldCount):
linecnt = 0
for i in range(paramFieldCount-1):
v = paramTable.cell_value(paramRow, i)
if type(v) == str:
v = v
elif type(v) == float:
v = FloatToString(v)
else:
v = str(v)
linecnt += len(v)
if linecnt > 0:
return False
if linecnt == 0:
return True
else:
return False
def IsEmptyGrid(data):
if len(str(data)) == 0:
return True
else:
return False
# 数据解析
def DealData(dataType, data):
if data == "null":
return True, data
ok = False
strValue = u""
if dataType == DataType.INT:
# 值为空,返回默认值
if IsEmptyGrid(data):
return True, u"0"
# 这里读进来的整形 带.0
if type(data) != float:
return ok, strValue
strValue = FloatToString(data)
if IsInt(strValue) == False:
return ok, strValue
strValue = str(strValue)
elif dataType == DataType.FLOAT:
# 值为空,返回默认值
if IsEmptyGrid(data):
return True, u"0"
if type(data) != float:
return ok, strValue
strValue = FloatToString(data)
elif dataType == DataType.BOOL:
# 值为空,返回默认值
if IsEmptyGrid(data):
return True, u"false"
if data == 0:
strValue = u"false"
elif data == 1:
strValue = u"true"
else:
return ok, strValue
elif dataType == DataType.STRING:
# 值为空,返回默认值
if type(data) == "":
return True, u"\"\""
if type(data) == float:
data = FloatToString(data)
if type(data) != str:
return ok, strValue
# strValue = data.replace(u"\\", u"\\\\").replace(u"\"", u"\\\"")
# strValue = strValue.replace(u"\n", u"")
strValue = "\"" + data + u"\""
elif dataType == DataType.ARRAY:
ok = True
strValue = json.dumps(json.loads(data, object_pairs_hook=OrderedDict))
elif dataType == DataType.OBJECT:
obj = data.replace(u"\\", u"")
if IsJson(obj) == False:
return ok, strValue
strValue = obj
else:
return ok, strValue
return True, strValue
# 表格转array
def table2Array(srcPath, category, table, filename, suffix, mapTable, desc):
# 如果有缓存文件则使用缓存文件
md5 = getFileMD5(srcPath)
cacheFile = os.path.join(CACHE_PATH, filename + "_" + md5 + suffix)
dstFilePath = ""
if category == "C":
dstFilePath = os.path.join(ClientPath, filename + suffix)
else:
dstFilePath = os.path.join(ServerPath, filename + suffix)
if os.path.exists(cacheFile):
copy(cacheFile, dstFilePath)
print("copy cache file " + filename + suffix + " to dist dir ")
return True
nrows = table.nrows
ncols = table.ncols
# 头部加上"[\n"
json_str = u"[\n"
rs = 0
for r in range(DATA_ROW, nrows):
if IsEmptyLine(table, r, ncols): # 跳过空行
continue
strTmp = u"\t{ "
i = 0
for c in range(ncols):
# 根据列名校验是否是要导出的列
title = table.cell_value(FIELD_ROW, c)
title = title.replace(u"\n", u"").replace(u"\"", u"").replace(u" ", u"")
if not title in mapTable:
continue
# 校验列的数据类型
dataType = DataType.INT
colType = table.cell_value(TYPE_ROW, c).replace(u" ", "")
if "array" in colType:
dataType = DataType.ARRAY
elif "map" in colType:
dataType = DataType.MAP
else:
if not colType in AccessDataType:
printError(u"错误 Table2Array data type error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title + "type:" + colType)
sys.exit(1)
else:
dataType = AccessDataType[colType]
# 取数据
data = table.cell_value(r, c)
# 数据校验转换
ok, strValue = DealData(dataType, data)
if ok == False:
printError(u"错误 data format error on make " + filename +"row:" + str(r+1) + "col:" + str(c+1) + "title:" + title)
sys.exit(1)
if i > 0:
strTmp += u", " + u"\"" + title + u"\":" + strValue
else:
strTmp += u"" + u"\"" + title + u"\":" + strValue
i += 1
# 当前行结束
strTmp += u" }"
if rs > 0: # 不是第1行
strTmp = ",\n" + strTmp
rs += 1
json_str += strTmp
# 尾部加上"\n]"
json_str += u"\n]"
json_str += u"\n"
# 打开输出文件
dir = os.path.dirname(dstFilePath)
if dir and not os.path.exists(dir):
os.makedirs(dir)
f = codecs.open(dstFilePath, "w", "utf-8")
if suffix == ".json":
f.write(json.dumps(json.loads(json_str, object_pairs_hook=OrderedDict),
ensure_ascii=False, indent=4).replace(u"\\\\", u"\\"))
elif suffix == ".lua":
if len(desc) > 0:
f.write("--[[\n")
f.write(str(desc))
f.write("\n]]--\n")
f.write("return " + objToLuaString(json.loads(json_str)))
f.close()
# 备份一份缓存文件
copyFile(dstFilePath, cacheFile)
print("Create ", dstFilePath, " OK")
return
# 表格转map
def table2Map(srcPath, category, table, filename, suffix, mapTable, desc):
# 如果有缓存文件则使用缓存文件
md5 = getFileMD5(srcPath)
cacheFile = os.path.join(CACHE_PATH, filename + "_" + md5 + suffix)
dstFilePath = ""
if category == "C":
dstFilePath = os.path.join(ClientPath, filename + suffix)
else:
dstFilePath = os.path.join(ServerPath, filename + suffix)
if os.path.exists(cacheFile):
copy(cacheFile, dstFilePath)
print("copy cache file " + filename + suffix + " to dist dir ")
return True
nrows = table.nrows
ncols = table.ncols
json_str = u"{\n"
keyIndex = 0
rs = 0
for r in range(DATA_ROW, nrows):
if IsEmptyLine(table, r, ncols):
continue # 跳过空行
i = 0
keyValue = table.cell_value(r, keyIndex)
if type(keyValue) == float:
keyValue = FloatToString(keyValue)
else:
keyValue = str(keyValue)
strTmp = u"\t\""+str(keyValue) + "\": { "
for c in range(ncols):
# 根据列名校验是否是要导出的列
title = table.cell_value(FIELD_ROW, c)
title = title.replace(u"\n", u"").replace(u"\"", u"").replace(u" ", u"")
# 校验是否是要导出的列
if not title in mapTable:
continue
# 校验列的数据类型
dataType = DataType.INT
colType = table.cell_value(TYPE_ROW, c).replace(u" ", u"")
if "array" in colType:
dataType = DataType.ARRAY
elif "map" in colType:
dataType = DataType.MAP
else:
if not colType in AccessDataType:
printError(u"错误 Table2Map data type error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title + "type:" + colType)
sys.exit(1)
else:
dataType = AccessDataType[colType]
# 取数据
data = table.cell_value(r, c)
# 数据校验转换
ok, strValue = DealData(dataType, data)
if ok == False:
printError(u"错误 data format error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title)
sys.exit(1)
if i > 0:
delm = u", "
else:
delm = u""
strTmp += delm + u"\"" + title + u"\":" + strValue
i += 1
strTmp += u" }"
if rs > 0: # 不是第1行
strTmp = u",\n" + strTmp
rs += 1
json_str += strTmp
json_str += u"\n}"
json_str += u"\n"
# 打开输出文件
dir = os.path.dirname(dstFilePath)
if dir and not os.path.exists(dir):
os.makedirs(dir)
f = codecs.open(dstFilePath, "w", "utf-8")
if suffix == ".json":
f.write(json.dumps(json.loads(json_str, object_pairs_hook=OrderedDict),
ensure_ascii=False, indent=4).replace(u"\\\\", u"\\"))
elif suffix == ".lua":
if len(desc) > 0:
f.write("--[[\n")
f.write(str(desc))
f.write("\n]]--\n")
f.write("return " + objToLuaString(json.loads(json_str)))
f.close()
# 备份一份缓存文件
copyFile(dstFilePath, cacheFile)
print ("Create ", dstFilePath, " OK")
return
# 表格转key:value 表,2列(key:value) 或 3列(key:value:type)
def table2KeyValue(srcPath, category, table, filename, suffix, fields, desc):
# 如果有缓存文件则使用缓存文件
md5 = getFileMD5(srcPath)
cacheFile = os.path.join(CACHE_PATH, filename + "_" + md5 + suffix)
dstFilePath = ""
if category == "C":
dstFilePath = os.path.join(ClientPath, filename + suffix)
else:
dstFilePath = os.path.join(ServerPath, filename + suffix)
if os.path.exists(cacheFile):
copy(cacheFile, dstFilePath)
print("copy cache file " + filename + suffix + " to dist dir ")
return True
# 校验要导出的列的个数
if not (len(fields) == 2 or len(fields) == 5):
return False
nrows = table.nrows # 行数
ncols = table.ncols # 列数
hasMap = (len(fields) > 0)
json_str = u"{\n"
# for k,v in fields.items():
# pass
# 计算要导出的列索引
colMap = OrderedDict()
for c in range(ncols):
# 根据列名校验是否是要导出的列
title = table.cell_value(FIELD_ROW, c)
title = title.replace(u"\n", u"").replace( u"\"", u"").replace(u" ", u"")
if not title in fields:
continue
colMap[fields[title]] = c
result = OrderedDict()
rs = 0
for r in range(DATA_ROW, nrows):
if IsEmptyLine(table, r, ncols): # 跳过空行
continue
# 取出key
# i = 0
keyValue = table.cell_value(r, colMap[0])
if len(keyValue) <= 0:
continue
# 取value 值
data = table.cell_value(r, colMap[1])
# 取出value 类型
colType = table.cell_value(TYPE_ROW, colMap[1]).replace(u" ", u"")
if len(colMap) >= 3:
colType = table.cell_value(r, colMap[2])
dataType = convertDataType(colType)
if dataType == DataType.NONE:
printError(u"错误 Table2KeyValue data type error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title + "type:" + colType)
sys.exit(1)
return
# 数据校验转换
ok, strValue = DealData(dataType, data)
if ok == False:
printError(u"错误 data format error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title)
sys.exit(1)
# 拼接字符串
strTmp = u"\t\""+keyValue + "\":" + strValue
if rs > 0: # 不是第1行
strTmp = u",\n" + strTmp
rs += 1
json_str += strTmp
json_str += u"\n}"
json_str += u"\n"
# 打开输出文件
dir = os.path.dirname(dstFilePath)
if dir and not os.path.exists(dir):
os.makedirs(dir)
f = codecs.open(dstFilePath, "w", "utf-8")
if suffix == ".json":
f.write(json.dumps(json.loads(json_str, object_pairs_hook=OrderedDict), ensure_ascii=False, indent=4).replace(u"\\\\", u"\\"))
elif suffix == ".lua":
if len(desc) > 0:
f.write("--[[\n")
f.write(str(desc))
f.write("\n]]--\n")
f.write("return " + objToLuaString(json.loads(json_str)))
f.close()
# 备份一份缓存文件
copyFile(dstFilePath, cacheFile)
print("Create ", dstFilePath, " OK")
return
def convertAttributeType(attributeType):
if(attributeType == "int" or attributeType == "float"):
return "number"
else:
return attributeType
# 表格转typescript
def table2TypeScript(table, filename, suffix, mapTable, desc):
nrows = table.nrows
ncols = table.ncols
hasMap = (len(mapTable) > 0)
json_str = u"export namespace " + filename.replace(".ts", "") + " {\n"
json_str += u"\texport class Data {\n"
# 处理基础属性
for index in range(ncols):
note = table.cell_value(0, index)
attribute = table.cell_value(2, index).replace(u" ", u"")
if not attribute in mapTable:
continue
attributeType = table.cell_value(1, index).replace(u" ", u"")
if "array" in attributeType:
strList = attributeType.split("|")
json_str += (u"\t\t//" + note.replace(u"\t",
"").replace(u"\n", "").replace(u" ", "") + u"\n")
json_str += (u"\t\t" + attribute + ": " +
json.loads(strList[1])["Type"] + u";\n\n")
else:
json_str += (u"\t\t//" + note.replace(u"\t",
"").replace(u"\n", "").replace(u" ", "") + u"\n")
json_str += (u"\t\t" + attribute + ": " +
convertAttributeType(attributeType) + u";\n\n")
json_str += u"\t};\n\n"
# 处理非基础属性
for index in range(ncols):
note = table.cell_value(0, index)
attribute = table.cell_value(2, index).replace(u" ", u"")
if not attribute in mapTable:
continue
attributeType = table.cell_value(1, index).replace(u" ", u"")
if "array" in attributeType:
strList = attributeType.split("|")
jsonMap = json.loads(strList[1])
classType = ""
for key in jsonMap:
if key != "Type":
classType = key
break
# 处理类名
json_str += u"\texport class " + classType + "{\n"
# 处理属性
for key in jsonMap[classType]:
json_str += u"\t\t" + key + ": " + \
jsonMap[classType][key] + ";\n"
# 花括号收尾
json_str += u"\t};\n\n"
json_str += u"\tconst dataList: Data[] = [\n"
for r in range(3, nrows):
if IsEmptyLine(table, r, ncols): # 跳过空行
continue
# # 过滤不需要的行
# if len(filter) > 0:
# dic = {}
# for c in range(ncols):
# key = table.cell_value(2, c).replace(u" ", u"")
# value = table.cell_value(r, c)
# dic[key] = value
# if (eval(filter, {}, dic)) == False:
# continue
json_str += u"\t\t{\n"
for c in range(ncols):
# 根据列名校验是否是要导出的列
title = table.cell_value(2, c).replace(u" ", u"")
title = title.replace(u"\n", u"").replace(u"\"", u"")
if hasMap:
if not title in mapTable:
continue
else:
title = mapTable[title]
# 校验列的数据类型
dataType = DataType.INT
colType = table.cell_value(1, c)
if "array" in colType:
dataType = DataType.ARRAY
elif "map" in colType:
dataType = DataType.MAP
else:
if not colType in AccessDataType:
print(Back.BLUE + "**************************************************")
print(Fore.RED + u"错误 Table2TypeScript data type error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title + "type:" + colType)
print (Back.BLUE + "**************************************************")
sys.exit(1)
else:
dataType = AccessDataType[colType]
# 取数据
data = table.cell_value(r, c)
# 数据校验转换
ok, strValue = DealData(dataType, data)
if ok == False:
print(Back.BLUE + "**************************************************")
print(Fore.RED + u"错误 data format error on make " + filename + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title)
print(Back.BLUE + "**************************************************")
sys.exit(1)
json_str += u"\t\t\t" + title + u": " + strValue + u",\n"
# 当前行结束
json_str += u"\t\t},\n"
json_str += u"\t];\n\n"
json_str += u"\texport const map: Map<number, Data> = new Map<number, Data>();\n"
json_str += u"\tfor (const data of dataList) {\n"
json_str += u"\t\tmap.set(data.id, data)\n"
json_str += u"\t};\n\n"
json_str += u"\texport const getValueWithID = function (id: number) {\n"
json_str += u"\t\treturn map.get(id);\n"
json_str += u"\t}\n\n"
json_str += u"\texport const getSize = function () {\n"
json_str += u"\t\treturn dataList.length;\n"
json_str += u"\t}\n"
json_str += u"};"
# 打开输出文件
dir = os.path.dirname(filename)
if dir and not os.path.exists(dir):
os.makedirs(dir)
f = codecs.open(filename, "w", "utf-8")
f.write(json_str)
f.close()
print("Create ", filename, " OK")
return
# 根据表的结构推断表类型
def parse_tab():
pass
# 解析单个tab标签页
def gen_tab(srcPath, category, tabType, destTable, destFileName, suffix, fields, strDesc):
if suffix == ".json" or suffix == ".lua":
if tabType == TabType.TAB_ARRAY:
table2Array(srcPath, category, destTable, destFileName, suffix, fields, strDesc)
elif tabType == TabType.TAB_MAP:
table2Map(srcPath, category, destTable, destFileName, suffix, fields, strDesc)
elif tabType == TabType.TAB_KV:
table2KeyValue(srcPath, category, destTable, destFileName, suffix, fields, strDesc)
else:
printError(u"错误 type only support key:array,key:map,key:value format " + destFileName)
sys.exit(1)
return False
elif suffix == ".ts":
table2TypeScript(destTable, destFileName, suffix, fields, strDesc)
else:
printError(u"错误 only support (json, lua, ts), conf format " + destFileName)
sys.exit(1)
return False
return True
pass
# 解析单个excel
def gen_file(srcPath, export_category, export_suffix):
# 校验是否有tablelist
# 打开excel表
book = xlrd.open_workbook(srcPath)
# 检测表是否是空的
sheetNames = book.sheet_names()
if len(sheetNames) == 0:
print("这是一张空的表: " + srcPath)
return True
if "tablelist" in sheetNames:
# 读取 tablelist 导出配置页
sheet = book.sheet_by_name(u"tablelist")
for r in range(sheet.nrows-2):
# 读目的table名(filename)
destTableName = sheet.cell_value(r+2, 0)
if destTableName not in sheetNames:
printError(u"错误 export type not exist " + destFileName + " tab:" + destTableName)
return False
# 读输出文件名及文件扩展名
destFileName = sheet.cell_value(r+2, 2)
mainFile = destFileName[:destFileName.rfind(".")]
suffix = destFileName[destFileName.rfind("."):].lower()
if suffix not in AccessExportType:
printError(u"错误 export type not exist " + destFileName + " tab:" + destTableName + " suffix:" + suffix)
return False
# 读导出的列(fields)
strUseFields = sheet.cell_value(r+2, 3)
fields = readFields(strUseFields)
# 读导出分类 C、S、C&S
category = sheet.cell_value(r+2, 4)
if export_category != category:
continue # 与导出的类型不相符
# 读tab类型(type)
strExtType = sheet.cell_value(r+2, 5)
if strExtType not in AccessTabType:
continue
tabType = AccessTabType[strExtType]
# 读出描述
strDesc = sheet.cell_value(r+1, 6)
print ("\nCreate " + destTableName + " ==> " + destFileName + " Starting...")
# 读取目的table数据
destTable = book.sheet_by_name(destTableName)
# 单个标签页生成
if not gen_tab(srcPath, category, tabType, destTable, mainFile, suffix, fields, strDesc):
return False
pass
else:
for sheetName in sheetNames:
mainFile = sheetName
suffix = export_suffix
fields = OrderedDict()
strDesc = ""
tabType = TabType.TAB_ARRAY
category = export_category
destTable = book.sheet_by_name(sheetName)
i = 0
for c in range(destTable.ncols):
# 根据列名校验是否是要导出的列
title = destTable.cell_value(FIELD_ROW, c)
title = title.replace(u"\n", u"").replace(u"\"", u"").replace(u" ", u"")
category = destTable.cell_value(CATEGORY_ROW, c).replace(u" ", u"")
if not is_in_category_type(export_category, category):
continue
fields[title] = i
i += 1
pass
title = destTable.cell_value(FIELD_ROW, 0).replace(u"\n", u"").replace(u"\"", u"").replace(u" ", u"")
colType = destTable.cell_value(TYPE_ROW, 0).replace(u" ", u"")
dataType = convertDataType(colType)
if dataType == DataType.NONE:
printError(u"错误 Table2KeyValue data type error on make " + srcPath + "row:" + str(r+1) + "col:" + str(c+1) + "title:" + title + "type:" + colType)
sys.exit(1)
if title == 'key' and dataType == DataType.STRING and len(fields) == 5:
tabType = TabType.TAB_KV
if title == 'id' and dataType == DataType.STRING and len(fields) > 2:
tabType = TabType.TAB_MAP
# 单个标签页生成
if not gen_tab(srcPath, export_category, tabType, destTable, mainFile, suffix, fields, strDesc):
return False
return True
pass
# 入口
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument('--input', type=str)
parser.add_argument('--output', type=str)
parser.add_argument('--category', type=str)
parser.add_argument('--suffix', type=str)
args = parser.parse_args()
input_path = args.input # 输入路径
output_path = args.output # 输出路径
category = args.category # 导出分类 C || S
suffix = args.suffix # 导出扩展名 .json || .lua || .ts
if category not in AccessCategoryType:
printError(u"错误 args category invalid " + category)
sys.exit(1)
categoryType = AccessCategoryType[category]
if categoryType == CategoryType.BOTH:
printError(u"错误 args category invalid " + category)
sys.exit(1)
if suffix not in AccessExportType:
printError(u"错误 args suffix invalid " + suffix)
sys.exit(1)
# 创建缓存目录
if not os.path.exists(CACHE_PATH):
os.makedirs(CACHE_PATH)
# 创建输出目录
ClientPath = os.path.join(output_path, ClientPath)
ServerPath = os.path.join(output_path, ServerPath)
if not os.path.exists(ClientPath):
os.makedirs(ClientPath)
if not os.path.exists(ServerPath):
os.makedirs(ServerPath)
# 遍历所有文件
bSuccessed = True
for path, dirs, files in os.walk(input_path):
for f in files:
srcPath = os.path.join(path, f)
mainName = os.path.splitext(f)[0]
extName = os.path.splitext(f)[1].lower()
if (extName == ".xlsx" or extName == ".xls") and mainName[0] != '~':
if not gen_file(srcPath, category, suffix):
bSuccessed = False
break
if bSuccessed:
print(Fore.GREEN + u"导出成功")
else:
print(Fore.RED + "导出失败!!!!!!!!!!!!")
Python
1
https://gitee.com/uzt/excel2cfg.git
git@gitee.com:uzt/excel2cfg.git
uzt
excel2cfg
excel2cfg
master

搜索帮助