# -*- 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_JSON_TYPE = "json" STRING_JSON_ARRAY_TYPE = "array" 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" JSON_WORD = "(LUA)" excel_dir = "./Excel" generate_json_dir = "../../server/cfg/data" generate_json_lang_dir = "./win7-x64/GameConfig/Serve" server_cfg_data_dir = "../../server/cfg/data" 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 == "": if value_type==INT_TYPE or value_type==FLOAT_TYPE or value_type==UINI_TYPE: return 0 if value_type==INT_LSIT_TYPE or value_type==UINT_LSIT_TYPE or value_type==LONG_LSIT_TYPE or value_type==FLOAT_LIST_TYPE: return[] if "[]" in value_type: return [] return "" 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_JSON_TYPE or value_type == STRING_JSON_ARRAY_TYPE: return value # elif value_type == STRING_LAN_TYPE: # value = value.encode("utf8") # lang_key = str(value).replace("#", "") # return json_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_json_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_json(table) def obj_to_json(obj): return json.dumps(obj,indent=4) def excel_to_json_file(excel_path, json_path, isLanguage): if not os.path.exists(excel_path): print("excel not exists.", excel_path) return try: json_data = excel_to_json_data(excel_path, isLanguage) f = open(json_path, "w", encoding="UTF-8", newline="\n") f.write(json_data) f.close() except: print(excel_path + " 配置错误,检查该表") exit(-1) def excel_list_to_json_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) if temp_excel_prefix in name: continue excel_file_path = file_path + os.sep + name json_file_name = name[:name.find(excel_suffix)] json_dir = generate_json_dir if name == "LanguageDesc.xlsx": json_dir = generate_json_lang_dir if json_file_name in alone_save_excel: print("need alone save", name) json_file_dir = json_dir + os.sep + json_file_name if not os.path.exists(json_file_dir): os.mkdir(json_file_dir) json_file_path = json_dir + os.sep + json_file_name + os.sep + json_file_name + ".json" else: tmpName=name[:name.find(excel_suffix)] if "Desc" not in tmpName: tmpName+="Desc" json_file_path = json_dir + os.sep + tmpName + ".json" is_language = name == "LanguageDesc.xlsx" excel_to_json_file(excel_file_path, json_file_path, is_language) if __name__ == "__main__": if not os.path.exists(generate_json_dir): os.makedirs(generate_json_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_json_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_json_dir, file_name) if os.path.isdir(file_path): shutil.rmtree(file_path) else: os.remove(file_path) if not os.path.exists(generate_json_lang_dir): os.makedirs(generate_json_lang_dir) config_file = open(config_file_name) configs = json.load(config_file) # print(configs) config_file.close() #默认目录xls文件转lua文件 excel_list_to_json_file(excel_dir) #区域目录xls文件覆盖,重新生成json文件 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_json_file(region_file_path)