123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- # -*- coding: utf-8 -*-
- '''
- 一、支持的表头
- 单值Key-Value形式的:【KV】、【MAP】;即第2行是key,第3行是类型,第5行是value
- 如:{a=1, b=3, ...}
- 单值Key-Value形式的:【K-V】;即第1列是key,第2列是类型,第4列是value
- 如:{a=1, b=3, ...}
- 对象列表形式的:【V】;即第1列
- 如:{1, 2, 3, ...}
- 对象Key-Value形式的:【M】;
- 如:{[1]={a=1, b=3, ...}, [2]={a=1, b=3, ...}}
- 单值列表形式的:【LIST】、【L】。
- 如:{{a=1, b=3, ...}, {a=1, b=3, ...}}
- 推荐使用:
- 单值Key-Value形式的:【K-V】
- 对象列表形式的:【V】
- 对象Key-Value形式的:【M】
- 单值列表形式的:【L】
- 二、支持的数据类型:
- 整数:int;
- 整数字符串:intstring;
- 布尔值:bool、boolean。为true的值:"TRUE"、"true"、"T"、"1"、1:
- 字符串:text、string;
- 浮点型:double、float;
- lua表达式:table、lua;
- 如:{{id=101,count=2222}}
- 其它:直接用文本输出。
- '''
- import os
- import sys
- import commands
- import json
- import shutil
- import ConfigParser
- import json
- import math
- from optparse import OptionParser
- from xlrd import open_workbook
- reload(sys)
- sys.setdefaultencoding('utf-8')
- class ConfigParserEx(ConfigParser.ConfigParser):
- def __init__(self,defaults=None):
- ConfigParser.ConfigParser.__init__(self,defaults=None)
- def optionxform(self, optionstr):
- return optionstr
- def load_config(path):
- ''' 读取配置表
- '''
- config = ConfigParserEx()
- config.read(path)
- return config
- kSpace = " "
- class ExcaleToLuaClass(object):
- def __init__(self):
- self.currentPyPath = sys.path[0]
- self.configPath = None
- self.errorMap = []
- def start(self):
- print("开始转换...")
- print("++++ 检查参数...")
- ok = self.check_arguments()
- if ok:
- print("---- 检查参数正确!!!")
- else:
- print("---- 检查参数错误!!!")
- return
- print("++++ 加载配置...")
- ok = self.load_arguments_config()
- if ok:
- print("---- 加载配置正确!!!")
- else:
- print("---- 加载配置错误!!!")
- return
- print("++++ 转换...")
- ok = self.loop_exchange()
- if ok:
- print("---- 转换正确!!!")
- else:
- print("---- 转换错误!!!")
- return
- for errorName in self.errorMap:
- print(json.dumps("\033[31m---- 错误配置:" + errorName + "\033[0m").decode("unicode-escape"))
- def check_arguments(self):
- ''' 检查参数
- '''
- parser = OptionParser()
- parser.add_option("-s", action="store", type="string", dest="source", help="source path")
- parser.add_option("-l", action="store", type="string", dest="list", help="source subdirectory list")
- parser.add_option("-o", action="store", type ="string", dest="output", help="output path")
- parser.add_option("-t", action="store", type ="string", dest="type", help="type")
- # 不必输入,固定是输出json格式
- # parser.add_option("--json", action="store_true", dest="outputJson", help="output json")
- (options, args) = parser.parse_args()
- ok = True
- sourcePath = options.source
- if options.source == None:
- ok = False
- print("-s config path is not set")
- subListStr = options.list
- subList = [""]
- if options.list != None:
- subList = str.split(subListStr, ",")
- outputPath = options.output
- if options.output == None:
- #如果输出目录没有写,则在源目录中新建一个output目录作为输出目录
- outputPath = os.path.join(cur_path, "out")
- onlyClient = False
- if options.type == "c":
- onlyClient = True
- else:
- onlyClient = False
- onlyServer = False
- if options.type == "s":
- onlyServer = True
- else:
- onlyServer = False
- outputJson = True # options.outputJson
- print "sourcePath", sourcePath
- print "subList", subList
- print "outputPath", outputPath
- if outputJson:
- print "输出 json格式"
- else:
- print "输出 lua格式"
- if not os.path.exists(outputPath):
- os.makedirs(outputPath)
- self.excelRootPath = sourcePath
- self.excelDirList = subList
- self.jsonRootPath = outputPath
- if onlyClient:
- self.mode = "CLIENT"
- elif onlyServer:
- self.mode = "SERVER"
- else:
- self.mode = "ALL"
- self.outputJson = outputJson
- return True
- def load_arguments_config(self):
- ''' 加载参数
- '''
- return True
- def loop_exchange(self):
- ''' 循环转换
- '''
- excelRootPath = self.excelRootPath
- excelDirList = self.excelDirList
- jsonRootPath = self.jsonRootPath
- mode = self.mode
- oneJson = {}
- for i in range(0, len(excelDirList)):
- excelDir = excelDirList[i]
- sourcePath = os.path.join(excelRootPath, excelDir)
- outputPath = os.path.join(jsonRootPath)
- if not os.path.exists(outputPath):
- os.makedirs(outputPath)
- dirList = []
- # 填充所有目录和文件名称
- for dirpath, dirnames, filenames in os.walk(sourcePath):
- for filename in filenames:
- dirList.append(os.path.join(dirpath, filename))
- # 过滤文件
- for filePath in dirList:
- name, ext = os.path.splitext(filePath)
- if ext == ".xlsx":
- if name.find("~$") < 0 and name.find(".~") < 0:
- # 批量创建
- self.excel2lua(filePath, outputPath, mode, oneJson)
- jsonStr = json.dumps(oneJson, sort_keys=True, separators=(',', ':'), ensure_ascii=False)
- jsonStr = jsonStr.decode("utf-8")
- outputFilePath = os.path.join(outputPath, "AllConfig.json")
- output = open(outputFilePath , "w")
- output.write(jsonStr)
- output.close()
- return True
- # 生成lua文件
- def excel2lua(self, filePath, outputPath, mode, oneJson):
- ''' 转换
- '''
- excelData = self.openExecl(filePath)
- # 遍历所有的sheet
- for sheet in excelData.sheets():
- name = sheet.name
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- #row 1 作为lua表的属性用
- row_1 = sheet.row_values(0)
- dataMode = row_1[0]
- excelMode = row_1[1]
- if dataMode == "" or excelMode == "":
- # self.errorMap.append(filePath)
- continue
- if mode != "ALL":
- if mode == "CLIENT" and (excelMode != "CLIENT" and excelMode != "ALL"):
- # 只需要导出客户端需要的,该表不是客户端需要的,过掉
- continue
- elif mode == "SERVER" and (excelMode != "SERVER" and excelMode != "ALL"):
- # 只需要导出客户端需要的,该表不是客户端需要的,过掉
- continue
- outputFilePath = os.path.join(outputPath, name + ".lua")
- if dataMode == "K-V":
- self.outputColKeyValue(sheet, outputFilePath)
- elif dataMode == "V":
- self.outputList(sheet, outputFilePath)
- elif dataMode == "M":
- self.outputObjMap(sheet, outputFilePath)
- elif dataMode == "L":
- self.outputObjList(sheet, outputFilePath)
- # 下面是兼容旧版本的标签
- elif dataMode == "KV" or dataMode == "MAP":
- self.outputKeyValue(sheet, outputFilePath)
- elif dataMode == "LIST":
- self.outputObjList(sheet, outputFilePath)
- else:
- continue
- if self.outputJson:
- jsonData = self.lua2json(outputPath, name)
- oneJson[name] = jsonData
- # lua转json
- def lua2json(self, outputPath, name):
- cmdFormat = 'lua -e \" \
- local cjson = require([[cjson]]); \
- package.path = [[{0}/?.lua;]] .. package.path; \
- local function updateKey(tab) \
- if type(tab) ~= [[table]] then \
- return tab; \
- end \
- local count = 0; \
- for key, value in pairs(tab) do \
- count = count + 1; \
- end \
- local ret = {{}}; \
- if count == #tab then \
- for i, value in ipairs(tab) do \
- ret[i] = updateKey(value); \
- end \
- else \
- for key, value in pairs(tab) do \
- ret[tostring(key)] = updateKey(value); \
- end \
- end \
- return ret; \
- end \
- local fileName = [[{1}]]; \
- local config = require(fileName); \
- config = updateKey(config); \
- local jsonStr = cjson.encode(config); \
- print(jsonStr); \
- \"'
- cmd = cmdFormat.format(outputPath, name)
- content = commands.getoutput(cmd)
- data = json.loads(content)
- luaOutputFilePath = os.path.join(outputPath, name + ".lua")
- os.remove(luaOutputFilePath)
- return data
- # 打开execl
- def openExecl(self, filePath):
- try:
- print("openExecl file name : " + filePath)
- data = open_workbook(filePath)
- return data
- except Exception,e:
- print "openExecl error:" + str(e)
- def cellValue(self, value, typeStr):
- ret = ""
- if value == "":
- return ""
- if value == "无" and typeStr != "text":
- return ""
- if typeStr == "int":
- retInt = float(value)
- ret = str(int(math.floor(retInt + 0.5)))
- elif typeStr == "intstring":
- if type(value) == type(0.1):
- retInt = float(value)
- ret = "\'" + str(int(math.floor(retInt + 0.5))) + "\'"
- else:
- ret = "\'" + str(value) + "\'"
- elif typeStr == "bool" or typeStr == "boolean":
- if value == "TRUE" or value == "true" or value == "T" or value == "1" or value == 1:
- ret = "true"
- else:
- ret = "false"
- elif typeStr == "text" or typeStr == "string":
- ret = "\'" + str(value) + "\'"
- elif typeStr == "double" or typeStr == "float":
- ret = str(value)
- elif typeStr == "table" or typeStr == "lua":
- ret = str(value)
- else:
- ret = str(value)
- return ret
- # 以Map形式输出 {a=1, b=3, ...}
- def outputColKeyValue(self, sheet, outputFilePath):
- name = sheet.name
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- output = open(outputFilePath, "w")
- output.write("local root = {")
- # 从第2行开始读
- start_rr = 1
- #第一行需要特殊处理
- firstLine = True
- for x in xrange(start_rr, nrows):
- onRow = sheet.row_values(x)
- keyStr = onRow[0]
- # 忽略key是空的列
- if keyStr == "":
- continue
- valueType = onRow[1]
- value = onRow[3]
- valueStr = self.cellValue(value, valueType)
- # 忽略空值的属性
- if valueStr == "":
- continue
- if firstLine:
- output.write("\n" + kSpace + keyStr + " = " + valueStr)
- firstLine = False
- else:
- output.write(",\n" + kSpace + keyStr + " = " + valueStr)
- output.write("\n}\nreturn root")
- output.close()
- # 以List形式输出 {1, 2, 3, ...}
- def outputList(self, sheet, outputFilePath):
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- # 第3行是数据类型的声明
- typeRow = sheet.row_values(2)
- # 因为是list,就一个类型
- valueType = typeRow[0]
- output = open(outputFilePath, "w")
- output.write("local root = {")
- # 从第5行开始读
- start_rr = 4
- #第一行需要特殊处理
- firstLine = True
- for x in xrange(start_rr, nrows):
- onRow = sheet.row_values(x)
- value = onRow[0]
- valueStr = self.cellValue(value, valueType)
- if firstLine:
- output.write("\n" + kSpace + valueStr)
- firstLine = False
- else:
- output.write(",\n" + kSpace + valueStr)
- output.write("\n}\nreturn root")
- output.close()
- # 以Map形式输出 {[1]={a=1, b=3, ...}, [2]={a=1, b=3, ...}}
- def outputObjMap(self, sheet, outputFilePath):
- name = sheet.name
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- # 支持合并单元格
- merge = {}
- for (rlow, rhigh, clow, chigh) in sheet.merged_cells:
- for r in xrange(rlow, rhigh):
- if not merge.get(r):
- merge[r] = {}
- for c in xrange(clow, chigh):
- merge[r][c] = sheet.row_values(rlow)[clow]
- #第1行的第3个单元格声明哪个作为key
- row_1 = sheet.row_values(0)
- key = row_1[2]
- # 第2行是key名称
- keyRow = sheet.row_values(1)
- # 第3行是数据类型的声明
- typeRow = sheet.row_values(2)
- output = open(outputFilePath, "w")
- output.write("local root = {")
- # 从第0列开始读
- start_cc = 0
- # 从第5行开始读
- start_rr = 4
- #第一行需要特殊处理
- firstLine = True
- for x in xrange(start_rr, nrows):
- objStr = "{"
- keyValue = ""
- # 读取一行
- oneRow = sheet.row_values(x)
- mergeRow = merge.get(x)
- # 第一个属性需要特殊处理
- firstProperty = True
- for cc in xrange(start_cc, ncols):
- keyStr = keyRow[cc]
- # 忽略key是空的列
- if keyStr == "":
- continue
- value = oneRow[cc]
- valueType = typeRow[cc]
- if mergeRow:
- mergeCell = mergeRow.get(cc)
- if mergeCell != None:
- value = mergeCell
- value = self.cellValue(value, valueType)
- if value == "":
- continue
- if firstProperty:
- objStr = objStr + "\n" + kSpace + kSpace + keyStr + " = " + value
- firstProperty = False
- else:
- objStr = objStr + ",\n" + kSpace + kSpace + keyStr + " = " + value
- if keyStr == key:
- keyValue = value
- if firstLine:
- objStr = "\n" + kSpace + "[" + keyValue + "] = " + objStr + "\n" + kSpace + "}"
- firstLine = False
- else:
- objStr = ",\n" + kSpace + "[" + keyValue + "] = " + objStr + "\n" + kSpace + "}"
- output.write(objStr)
- output.write("\n}\nreturn root")
- output.close()
- # 以Map形式输出 {{a=1, b=3, ...}, {a=1, b=3, ...}}
- def outputObjList(self, sheet, outputFilePath):
- name = sheet.name
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- # 支持合并单元格
- merge = {}
- for (rlow, rhigh, clow, chigh) in sheet.merged_cells:
- for r in xrange(rlow, rhigh):
- if not merge.get(r):
- merge[r] = {}
- for c in xrange(clow, chigh):
- merge[r][c] = sheet.row_values(rlow)[clow]
- # 第2行是key名称
- keyRow = sheet.row_values(1)
- # 第3行是数据类型的声明
- typeRow = sheet.row_values(2)
- output = open(outputFilePath, "w")
- output.write("local root = {")
- # 从第0列开始读
- start_cc = 0
- # 从第5行开始读
- start_rr = 4
- #第一行需要特殊处理
- firstLine = True
- for x in xrange(start_rr, nrows):
- if firstLine:
- output.write("\n" + kSpace + "{")
- firstLine = False
- else:
- output.write(",\n" + kSpace + "{")
- # 读取一行
- onRow = sheet.row_values(x)
- mergeRow = merge.get(x)
- # 第一个属性需要特殊处理
- firstProperty = True
- for cc in xrange(start_cc, ncols):
- keyStr = keyRow[cc]
- # 忽略key是空的列
- if keyStr == "":
- continue
- value = onRow[cc]
- valueType = typeRow[cc]
- if mergeRow:
- mergeCell = mergeRow.get(cc)
- if mergeCell != None:
- value = mergeCell
- valueStr = self.cellValue(value, valueType)
- # 忽略空值的属性
- if valueStr == "":
- continue
- if firstProperty:
- output.write("\n" + kSpace + kSpace + keyStr + " = " + valueStr)
- firstProperty = False
- else:
- output.write(",\n" + kSpace + kSpace + keyStr + " = " + valueStr)
- output.write("\n" + kSpace + "}")
- output.write("\n}\nreturn root")
- output.close()
- # 以Map形式输出 {a=1, b=3, ...}
- def outputKeyValue(self, sheet, outputFilePath):
- name = sheet.name
- nrows = sheet.nrows
- ncols = sheet.ncols
- #print(nrows, ncols)#行列数
- # 支持合并单元格
- merge = {}
- for (rlow, rhigh, clow, chigh) in sheet.merged_cells:
- for r in xrange(rlow, rhigh):
- if not merge.get(r):
- merge[r] = {}
- for c in xrange(clow, chigh):
- merge[r][c] = sheet.row_values(rlow)[clow]
- # 第2行是key名称
- keyRow = sheet.row_values(1)
- # 第3行是数据类型的声明
- typeRow = sheet.row_values(2)
- # 第3行是值
- valueRow = sheet.row_values(4)
- mergeRow = merge.get(4)
- output = open(outputFilePath, "w")
- output.write("local root = {")
- # 从第0列开始读
- start_cc = 0
- #第一行需要特殊处理
- firstLine = True
- for cc in xrange(start_cc, ncols):
- keyStr = keyRow[cc]
- # 忽略key是空的列
- if keyStr == "":
- continue
- value = valueRow[cc]
- valueType = typeRow[cc]
- if mergeRow:
- mergeCell = mergeRow.get(cc)
- if mergeCell != None:
- value = mergeCell
- valueStr = self.cellValue(value, valueType)
- # 忽略空值的属性
- if valueStr == "":
- continue
- if firstLine:
- output.write("\n" + kSpace + keyStr + " = " + valueStr)
- firstLine = False
- else:
- output.write(",\n" + kSpace + keyStr + " = " + valueStr)
- output.write("\n}\nreturn root")
- output.close()
- def main():
- ExcaleToLuaClass().start()
- if __name__ == '__main__':
- main()
|