# -*- coding: UTF-8 -*- import xlrd import os import shutil import re import sys import json from functools import cmp_to_key INT_KEY_TYPE = "int_key" UINT_KEY_TYPE = "uint_key" STRING_KEY_TYPE = "string_key" INT_TYPE = "int" FLOAT_TYPE = "float" UINI_TYPE = "uint" STRING_TYPE = "string" STRING_LAN_TYPE = "string_lan" STRING_LUA_TYPE = "string_lua" STRING_LIST_TYPE = "string[]" INT_LSIT_TYPE = "int[]" UINT_LSIT_TYPE = "uint[]" LONG_LSIT_TYPE = "long[]" FLOAT_LIST_TYPE = "float[]" LONG_TYPE = "long" NONE_TYPE = "none" LUA_WORD = "(LUA)" excel_dir = "./Excel" generate_lua_dir = "../../client/pandora/Assets/Lua/Desc" generate_lua_lang_dir = "../../client/pandora/Assets/Lua/Desc/LanguageDesc" excel_suffix = ".xlsx" temp_excel_prefix = "~$" alone_save_excel = [ ] excel_config_file = "ClientExcelConfig.json" excel_self_config_file = "./selfExcelConfig/ClientExcelConfig.json" class FirstColumn: def __init__(self, key): self._rawKey = key self._key = key self._list_count = 1 self._list_index = 0 self._inew_table = 0 self.parse() def parse(self): match = re.match(r"(\w+)_(\d+)_(\d+)", self._key) if match: self._key = match.group(1) self._list_count = int(match.group(2)) self._list_index = int(match.group(3)) match2 = re.match(r"(\w+)_(\d+)_(\w+)",self._key) if match2: self._key = match2.group(1) self._list_index = int(match2.group(2)) self._list_key = match2.group(3) self._inew_table = 1 def get_key(self): return self._key def get_list_key(self): return self._list_key def is_list(self): return self._list_count > 1 def get_list_index(self): return self._list_index def is_newtable(self): return self._inew_table > 0 def get_cell_value(value_type, value,key=None): if value is None or value == "": return "nil" elif value_type == INT_KEY_TYPE or value_type == INT_TYPE or value_type == UINT_KEY_TYPE or value_type == UINI_TYPE or value_type == LONG_TYPE: return int(round(float(value))) elif value_type.startswith(INT_LSIT_TYPE): # if type(value) is str: # value = value.encode("utf8") value = str(value) value = value.replace(',',';') value = value.split(';') value = [int(round(float(x))) for x in value] return value elif value_type.startswith(UINT_LSIT_TYPE): # if type(value) is str: # value = value.encode("utf8") value = str(value) value = value.replace(',',';') value = value.split(';') value = [int(round(float(x))) for x in value] return value elif value_type.startswith(LONG_LSIT_TYPE): # if type(value) is str: # value = value.encode("utf8") value = str(value) value = value.replace(',',';') value = value.split(';') value = [int(round(float(x))) for x in value] return value elif value_type.startswith(FLOAT_LIST_TYPE): # if type(value) is str: # value = value.encode("utf8") value = str(value) value = value.replace(',',';') value = value.split(';') value = [float(x) for x in value] return value elif value_type == FLOAT_TYPE: return float(value) elif value_type.startswith(STRING_LIST_TYPE): # if type(value) is str: # value = value.encode("utf8") value = str(value) value = value.replace(',',';') value = value.split(';') value = [x.strip() for x in value] return value elif value_type == STRING_KEY_TYPE or value_type == STRING_TYPE or value_type == STRING_LAN_TYPE: # if type(value) is str or type(value) is str: # value = value.encode("utf8") value = str(value) #语言表 value = value.replace("\n", "\\n") value = value.replace("\"", "\\\"") value = value.replace("", "%s") value = value.replace("", "%s") value = value.replace("", "%s") value = value.replace("", "%s") return value elif value_type == STRING_LUA_TYPE: return LUA_WORD+str(value) # elif value_type == STRING_LAN_TYPE: # value = value.encode("utf8") # lang_key = str(value).replace("#", "") # return LUA_WORD+"GM and GM.Lang(\"%s\") or \"%s\"" % (lang_key, lang_key) return None def sort_spell_skin_show(table): items = [] for key in table: items.append(table[key]) def sort_method(item1,item2): if item1["spellId"] < item2["spellId"]: return -1 elif item1["spellId"] > item2["spellId"]: return 1 else: if item1["skinIndex"] < item2["skinIndex"]: return -1 elif item1["skinIndex"] > item2["skinIndex"]: return 1 else: if item1.get("layer") != "nil": if item1["layer"] < item2["layer"]: return -1 else: return 1 else: return 0 sorted_items = sorted(items,key = cmp_to_key(sort_method)) return sorted_items def excel_to_lua_data(path, isLanguage): excel_data = {} xml_data = xlrd.open_workbook(path) # 打开xls文件 sheet = xml_data.sheets()[0] # 打开第一张表 # 先判断key的数量 row_num = sheet.nrows # 获取表的行数 col_num = sheet.ncols # 获取表的列数 row_key_values = sheet.row_values(0) # 获取表的第一行的所有数据 row_type_values = sheet.row_values(1) # 获取表的第二行的所有数据 row_cs_values = sheet.row_values(2) # 获取表的第三行的所有数据 row_desc_values = sheet.row_values(3) # 获取表的第四行的所有数据 index_list = [] # 需要导出的列索引 key_list_map = {} # 所有key_value的列表 key_list = [] # key的列表 for i in range(0, col_num): key_value = row_key_values[i] type_value = row_type_values[i] cs_value = row_cs_values[i] if type_value == INT_KEY_TYPE or type_value == UINT_KEY_TYPE or type_value == STRING_KEY_TYPE: key_list.append(key_value) if key_value not in key_list_map: key_list_map[key_value] = [] for row in range(4, row_num): try: key_list_map[key_value].append(get_cell_value(type_value, sheet.row_values(row)[i])) except: print("error file:" + path + ",key:" + key_value + ",row:" + str(row)) sys.exit() #忽略的部分列 if key_value != NONE_TYPE and cs_value != "skip" and cs_value.find("c") != -1: if isLanguage: if type_value != STRING_KEY_TYPE: index_list.append(i) else: index_list.append(i) def set_row_value(row, obj): row_values = sheet.row_values(row) for i in index_list: first_column = FirstColumn(row_key_values[i]) column_key = first_column.get_key() try: #数组单独处理 if first_column.is_list(): if column_key not in obj: obj[column_key] = {} obj[column_key][first_column.get_list_index()+1] = get_cell_value(row_type_values[i], row_values[i]) elif first_column.is_newtable(): if column_key not in obj: obj[column_key] = {} if (first_column.get_list_index()+1) not in obj[column_key]: obj[column_key][first_column.get_list_index()+1] = {} obj[column_key][first_column.get_list_index()+1][first_column.get_list_key()] = get_cell_value(row_type_values[i], row_values[i]) else: obj[column_key] = get_cell_value(row_type_values[i], row_values[i]) except: print("error file:" + str(path) + ",key:" + str(column_key), ",row:" + str(row)) sys.exit() table = {} if len(key_list) == 2: #暂时只支持2个key row_index = 0 for row in range(4, row_num): first_key = key_list_map[key_list[0]][row_index] second_key = key_list_map[key_list[1]][row_index] row_index = row_index + 1 if first_key == "" or first_key == "nil" or second_key == "" or second_key == "nil": print("%s key is nil,row:%d" % (path, row)) continue if first_key not in table: table[first_key] = {} if second_key not in table[first_key]: table[first_key][second_key] = {} obj = table[first_key][second_key] set_row_value(row, obj) elif len(key_list) <= 1: #没有key或者单个key row_index = 0 row_key_list = None if len(key_list) > 0: row_key_list = key_list_map[key_list[0]] for row in range(4, row_num): row_index = row_index + 1 row_key = row_index if not (row_key_list is None): row_key = row_key_list[row_index-1] if row_key == "nil" or row_key == "": print("%s key is nil,row:%d" % (path, row)) continue if row_key not in table: table[row_key] = {} obj = table[row_key] set_row_value(row, obj) file_name = os.path.basename(path) if file_name == "SpellActionSkinShowDesc.xlsx": try: table = sort_spell_skin_show(table) except Exception as e: print(e) return obj_to_lua(table) ####################################################################### def value_tostring(value): value_type = type(value) if value_type is str: value = str(value) value_type = type(value) if value is None: return "nil" if value_type == str: if value == "" or value == "nil": return "nil" if value.find(LUA_WORD, 0, len(LUA_WORD)) == -1: return "\"%s\"" % value else: return value.replace(LUA_WORD, "") elif value_type == bool: if value: return "true" else: return "false" else: return value def key_tostring(key): key_type = type(key) if key_type == int: return "[%d]" % key elif key_type == str: return key def obj_to_lua(obj): result = [] def _encode_to_lua(value, key, indent): if value is None: return key_type = type(key) if key_type != str and key_type != int: return value_type = type(value) if value_type == list or value_type == dict: result.append("%s%s = {" % (indent, key_tostring(key))) indent2 = indent + "\t" if value_type == list: for i in range(len(value)): _encode_to_lua(value[i], i + 1, indent2) elif value_type == dict: for k in list(value.keys()): _encode_to_lua(value[k], k, indent2) if indent == "": result.append("%s}" % (indent)) else: result.append("%s}," % (indent)) else: valueStr = value_tostring(value) if valueStr != "nil": result.append("%s%s = %s," % (indent, key_tostring(key), valueStr)) _encode_to_lua(obj, "local M", "") result.append("return M") return "\n".join(result) def excel_to_lua_file(excel_path, lua_path, isLanguage): if not os.path.exists(excel_path): print("excel not exists.", excel_path) return try: lua_data = excel_to_lua_data(excel_path, isLanguage) f = open(lua_path, "w", encoding="UTF-8",newline="\n") f.write(lua_data) f.close() except: print(excel_path+" 配置错误,检查该表") exit(-1) def excel_list_to_lua_file(file_path): excel_names = os.listdir(file_path) for name in excel_names: if name in configs['included'] and name.endswith(excel_suffix) and not name.startswith(temp_excel_prefix): print(name) excel_file_path = file_path + os.sep + name lua_file_name = name[:name.find(excel_suffix)] lua_dir = generate_lua_dir if name == "LanguageDesc.xlsx": lua_dir = generate_lua_lang_dir if lua_file_name in alone_save_excel: print("need alone save",name) lua_file_dir = lua_dir + os.sep + lua_file_name if not os.path.exists(lua_file_dir): os.mkdir(lua_file_dir) lua_file_path = lua_dir + os.sep + lua_file_name + os.sep + lua_file_name + ".lua" else: lua_file_path = lua_dir + os.sep + name[:name.find(excel_suffix)] + ".lua" is_language = name == "LanguageDesc.xlsx" excel_to_lua_file(excel_file_path, lua_file_path, is_language) if __name__ == "__main__": if not os.path.exists(generate_lua_dir): os.makedirs(generate_lua_dir) change_region_dir="" #需要替换的区域目录 clean_old_file = True config_file_name = excel_config_file if (len(sys.argv) > 1 and sys.argv[1] == "self" ): config_file_name = excel_self_config_file clean_old_file = False elif (len(sys.argv) > 2 and sys.argv[1] == "region" ): change_region_dir=sys.argv[2] #需要替换的区域目录 if clean_old_file: for file_name in os.listdir(generate_lua_dir): if not file_name.startswith("SpellShowDesc") and not file_name.startswith("QuestEventDesc") and not file_name.startswith("DramaDesc") and not file_name.startswith("WorldDesc"): file_path = os.path.join(generate_lua_dir, file_name) if os.path.isdir(file_path): shutil.rmtree(file_path) else: os.remove(file_path) if not os.path.exists(generate_lua_lang_dir): os.makedirs(generate_lua_lang_dir) config_file = open(config_file_name) configs = json.load(config_file) # print(configs) config_file.close() #默认目录xls文件转lua文件 excel_list_to_lua_file(excel_dir) #区域目录xls文件覆盖,重新生成lua文件 if change_region_dir != "" : region_file_path = excel_dir + os.sep + change_region_dir if not os.path.exists(region_file_path): print(region_file_path+" 目录不存在") exit(-1) print(region_file_path+" 目录文件进行覆盖处理") excel_list_to_lua_file(region_file_path)