#-*- coding: UTF-8 -*- import xlrd import re import util import platform import os TAB = " " def get_file_name_length(file_path): return len(util.get_file_name(file_path)) #type = 1 lua type = 2 hrl type = 3 erl def write_file(string, type, path): file_path = path["file_path"] folder_path = path["folder_path"] dump_path = path["dump_path"] tmp = get_file_name_length(file_path) + 4 if len(file_path) - tmp - len(folder_path) > 1: relative_file_path = file_path[len(folder_path)+1:len(file_path)-tmp] #相对路径。生成树形目录 else: relative_file_path = "" excel_name = util.get_file_name(file_path) if type == 1: s = "lua" dump_name = (excel_name.lower()) + ".lua" elif type == 2: s = "hrl" dump_name = "config_" + util.to_lower(excel_name) + ".hrl" elif type == 3: s = "erl" dump_name = "config_" + util.to_lower(excel_name) + ".erl" elif type == 4: s = "map" dump_name = "cfg_" + excel_name + ".erl" base_path = dump_path + util.SPLIT_STR if not os.path.isdir(base_path): os.makedirs(base_path) if relative_file_path != "": paths = relative_file_path.split(util.SPLIT_STR) for i in range(len(paths)): if platform.system() == "Windows": base_path = base_path + util.SPLIT_STR + paths[i] else: base_path = base_path + paths[i] + "/" if not os.path.isdir(base_path): os.makedirs(base_path) f = open(base_path + dump_name, "w") f.write(string) f.close() else: f = open(dump_path + util.SPLIT_STR + dump_name, "w") f.write(string) f.close() def to_lua_by_row(row_list, config_sheet, main_key_index, key_data, value_row): lua_list = [] row_obj = {} for index in range(len(key_data)): # if index == main_key_index: # continue # 只导出前端需要的列 if key_data[index]["key_color"] == 2 or key_data[index]["key_color"] == False: continue # 忽略非必须导出并且内容为空的cell if key_data[index]["key_must"] == False and value_row[index] == "": continue key_value = key_data[index]["key_name"] key_type = key_data[index]["key_type"] # lua_list.append(TAB + "[\"" + key_value + "\"] = ") value_row_list, row_obj[key_value] = get_value_list(config_sheet, value_row[index], key_type, 0, key_data[index]["is_array"], key_data[index]["key_must"]) if index != main_key_index: lua_list.append(TAB + "[\"" + key_value + "\"] = ") # value_row_list.append(",\n") lua_list.append("".join(value_row_list)) lua_list.append(",\n") row_list.append(row_obj) return ''.join(lua_list) def write_to_lua(data_sheet, config_sheet, file_name, path): file_name_lower = file_name.lower() key_data = data_sheet["key_data"] main_key_index = data_sheet["main_key_index"] value_data = data_sheet["value_data"] row_list = [] lua_list = [] lua_list.append("local " + file_name_lower + " = {}\n") for row in range(len(value_data)): main_key_value = get_cell_value_by_type(value_data[row][main_key_index], key_data[main_key_index]["key_type"]) lua_list.append(file_name_lower + "[" + str(main_key_value) + "] = {\n") row_value = to_lua_by_row(row_list, config_sheet, main_key_index, key_data, value_data[row]) lua_list.append(row_value + "}\n") lua_list.append("return " + file_name_lower) write_file(''.join(lua_list), 1, path) return row_list def init_rule(excel_data): rules = [] for sheet_name in excel_data.sheet_names(): if sheet_name == "rule": break else: return rules data = excel_data.sheet_by_name("rule") nrows = data.nrows ncols = data.ncols for i in range(nrows): if data.cell(i, 0).value == "": break rule_value_list = [] for j in range(ncols): value = data.cell(i, j).value if value == "": break rule_value_list.append(value) rules.append(rule_value_list) return rules def read_config_sheet(excel_data): config_data = {} for sheet_name in excel_data.sheet_names(): if sheet_name == "config": break else: return None data = excel_data.sheet_by_name("config") nrows = data.nrows ncols = data.ncols for i in range(nrows): key_value = data.cell(i, 0).value if key_value == "": continue config_data[key_value] = [] for j in range(1, ncols): value = data.cell(i, j).value if value == "": continue if value != "": variable_obj = {} array = value.split(":") xy = data.cell_xf_index(i, j) index_color = excel_data.xf_list colortype = index_color[xy].background.pattern_colour_index must = util.get_color_type(colortype) variable_obj["variable_name"] = array[0] variable_obj["variable_type"] = array[1] variable_obj["is_must"] = must config_data[key_value].append(variable_obj) return config_data def read_data_sheet(excel_data): data = excel_data.sheet_by_index(0) nrows = data.nrows ncols = data.ncols key_row_index = 0 type_row_index = 0 value_row_index = 0 flag = 0 name_rows = None type_rows = None for row in range(nrows): rowvalue = data.row_values(row) tmp = unicode(rowvalue[0]) if not re.search(r"^//", tmp) and re.search(r"^\S", tmp): if flag == 0: key_row_index = row name_rows = rowvalue flag = 1 else: type_row_index = row value_row_index = row + 1 type_rows = rowvalue break if name_rows is None or type_rows is None: return None max_col = len(name_rows) for col in range(len(name_rows), 1, -1): if name_rows[col-1] != "": max_col = col break key_data = [] main_key_index = None for col in range(max_col): key_obj = {} if name_rows[col] != "": is_key = util.is_key(name_rows[col]) else: is_key = False if is_key: if main_key_index is None: main_key_index = col key_obj["key_name"] = name_rows[col][1:] else: key_obj["key_name"] = name_rows[col] key_obj["key_type"] = type_rows[col] if type_rows[col] != "": key_obj["is_array"] = util.is_array(type_rows[col]) else: key_obj["is_array"] = False index_color = excel_data.xf_list xy = data.cell_xf_index(key_row_index, col) colortype = index_color[xy].background.pattern_colour_index color = util.get_color_type(colortype) key_obj["key_color"] = color xy = data.cell_xf_index(type_row_index, col) colortype = index_color[xy].background.pattern_colour_index must = util.get_color_type(colortype) key_obj["key_must"] = must key_data.append(key_obj) if main_key_index is None: main_key_index = 0 value_data = [] for row in range(value_row_index, nrows): if data.cell(row, 0).value == "": continue row_data = [] value_data.append(row_data) for col in range(max_col): row_data.append(data.cell(row, col).value) main_data = {} main_data["key_data"] = key_data main_data["main_key_index"] = main_key_index main_data["value_data"] = value_data return main_data def check_item_extra_rule(obj, variable_list, index, variable_value, operator): if isinstance(obj, dict): if len(variable_list) >= index + 1: if obj.has_key(variable_list[index]): return check_item_extra_rule(obj[variable_list[index]], variable_list, index + 1, variable_value, operator) elif isinstance(obj, list): # 如果筛选rule是某个数组里的某个属性,那么这个数组里只要有一个元素满足条件,rule就算成立 check_rule = False for i in range(len(obj)): if check_item_extra_rule(obj[i], variable_list, index, variable_value, operator): check_rule = True break return check_rule else: if operator == "==": if variable_value != obj: return False elif operator == "!=": if variable_value == obj: return False return True def get_item(dict_or_list, obj, variable_list, index, type_list, type_value, operator): if isinstance(obj, dict): check_result = False # 额外的筛选rule if type_list is not None: if len(type_list) == index + 1: if check_item_extra_rule(obj, type_list, index, type_value, operator): check_result = True else: return elif variable_list[index] != type_list[index]: if check_item_extra_rule(obj, type_list, index, type_value, operator): check_result = True else: return if len(variable_list) >= index + 1: if obj.has_key(variable_list[index]): # 如果为true说明已经判断过rule并且通过,后面就不用再判断rule if check_result: get_item(dict_or_list, obj[variable_list[index]], variable_list, index + 1, None, type_value, operator) else: get_item(dict_or_list, obj[variable_list[index]], variable_list, index + 1, type_list, type_value, operator) elif isinstance(obj, list): for i in range(len(obj)): get_item(dict_or_list, obj[i], variable_list, index, type_list, type_value, operator) else: if isinstance(dict_or_list, dict): dict_or_list[str(obj)] = 1 elif isinstance(dict_or_list, list): dict_or_list.append(str(obj)) def get_item_value(excel_obj, dict_or_list, keys, types): key_list = keys.split(".") main_key_index = excel_obj["data_sheet"]["main_key_index"] key_data = excel_obj["data_sheet"]["key_data"] rows = excel_obj["rows"] # 如果有额外的筛选规则 type_list = None type_value = None operator = "==" if types: m = re.search(r"==|!=", types) if m is not None: operator = str(m.group()) tmp = types.split(operator) type_value = tmp[1] type_list = tmp[0].split(".") for i in range(len(rows)): if rows[i].has_key(key_list[0]): if isinstance(dict_or_list, list): row_list = [] get_item(row_list, rows[i], key_list, 0, type_list, type_value, operator) dict_or_list.append(row_list) else: get_item(dict_or_list, rows[i], key_list, 0, type_list, type_value, operator) return dict_or_list def get_item_value_dict(excel_obj, keys, types=False): return get_item_value(excel_obj, {}, keys, types) def get_item_value_list(excel_obj, keys, types=False): return get_item_value(excel_obj, [], keys, types) def get_main_key(excel_obj): return excel_obj["data_sheet"]["main_key_index"] def get_value_data(excel_obj): return excel_obj["data_sheet"]["value_data"] def get_rules(excel_obj): return excel_obj["rules"] def get_value_list(config_sheet, cell_value, key_type, deep, is_array, is_must): check_cell_value(cell_value, key_type, is_array, is_must) value_row_list = [] value_row_obj = None if is_array: key_type = key_type[1:-1] if config_sheet is not None and config_sheet.has_key(key_type): value_row_list, value_row_obj = get_value_with_config(config_sheet, cell_value, config_sheet[key_type], deep, is_array, is_must) else: value_row_list, value_row_obj = cell_value_to_lua_string(key_type, cell_value[1:-1], deep, is_array, is_must) else: if config_sheet is not None and config_sheet.has_key(key_type): value_row_list, value_row_obj = get_value_with_config(config_sheet, cell_value, config_sheet[key_type], deep, is_array, is_must) else: value_row_list, value_row_obj = cell_value_to_lua_string(key_type, cell_value, deep, is_array, is_must) return value_row_list, value_row_obj def get_value_with_config(config_sheet, cell_value, config_data, deep, is_array, is_must): value_list = [] value_obj = None if is_array: strings = util.split_string(cell_value[1:-1]) value_list.append(deep*TAB + "{") first_item = True value_obj = [] for i in range(len(strings)): value_obj2 = {} strings2 = util.split_string(strings[i][1:-1]) # 为了和上一版本的脚本导出后的结果一模一样而做的处理 if first_item == True: first_item = False else: value_list.append(",") value_list.append("\n" + (deep+2)*TAB + "{\n") first_item_strings2 = True for j in range(len(strings2)): if (not config_data[j]["is_must"]) and (strings2[j] == "" or strings2[j] == "NULL" or strings2[j] == "null"): continue variable_type = config_data[j]["variable_type"] variable_type_is_array = util.is_array(variable_type) # 为了和上一版本的脚本导出后的结果一模一样而做的处理 if first_item_strings2 == True: first_item_strings2 = False else: value_list.append(",\n") value_list.append((deep+3)*TAB + "[\"" + config_data[j]["variable_name"] + "\"] = ") value_row_list, obj = get_value_list(config_sheet, strings2[j], variable_type, deep + 2, variable_type_is_array, is_must) value_obj2[str(config_data[j]["variable_name"])] = obj value_list.append("".join(value_row_list)) value_obj.append(value_obj2) value_list.append("\n" + (deep+2)*TAB + "}") value_list.append("\n" + (deep+1)*TAB + "}") else: strings = util.split_string(cell_value[1:-1]) value_list.append("{\n") first_item = True value_obj = {} for i in range(len(strings)): variable_type = config_data[i]["variable_type"] variable_type_is_array = util.is_array(variable_type) # 为了和上一版本的脚本导出后的结果一模一样而做的处理 if first_item == True: first_item = False else: value_list.append(",\n") value_list.append((deep+2)*TAB + "[\"" + config_data[i]["variable_name"] + "\"] = ") value_row_list, obj = get_value_list(config_sheet, strings[i], variable_type, deep, variable_type_is_array, is_must) value_obj[str(config_data[i]["variable_name"])] = obj value_list.append("".join(value_row_list)) value_list.append("\n" + (deep+1)*TAB + "}") return value_list, value_obj def cell_value_to_lua_string(key_type, cell_value, deep, is_array, is_must): value_list = [] value_obj = None if is_array: value_obj = [] strings = util.split_string(cell_value) value_list.append("{\n") first_item = True for i in range(len(strings)): # 为了和上一版本的脚本导出后的结果一模一样而做的处理 if first_item == True: first_item = False else: value_list.append(",\n") value_list.append((deep+2)*TAB) value = get_cell_value_by_type(strings[i], key_type) value_obj.append(value) value_list.append(value) value_list.append("\n" + (deep+1)*TAB + "}") else: value = get_cell_value_by_type(cell_value, key_type) value_obj = value value_list.append(value) return value_list, value_obj def get_cell_value_by_type(value, value_type): if value_type == "string" or value_type == "atom": value = str(value) if value[0] == "\"" or value[0] == "\“": if value[-1] != "\"": raise EOFError(u"引号填写有误") value = value[1:-1] value = "\"" + value + "\"" elif value_type == "int" or value_type == "int32": value = str(int(value)) else: value = str(value) return value def check_cell_value(value, value_type, is_array, is_must): if is_array or (not util.is_base(value_type)): if (not is_must) and (value == "" or value == "NULL" or value == "null"): return if is_array: if value[0] != "[" or value[-1] != "]": raise EOFError(u"数组缺括号") else: if value[0] != "{" or value[-1] != "}": raise EOFError(u"复合类型缺括号") else: if is_must and value == "": raise EOFError(u"缺少必填项") if value_type == "string" or value_type == "atom": value = str(value) if value[-1] == "\"" and value[0] != "\"": raise EOFError(u"引号填写有误") if value[0] == "\"" or value[0] == "\“": if value[-1] != "\"": raise EOFError(u"引号填写有误") elif value_type == "int" or value_type == "int32": try: if abs(int(value) - float(value)) > 1e-5: raise EOFError(u"整数类型填写有误") except: raise EOFError(u"整数类型填写有误") elif value_type == "float": try: float(value) except: raise EOFError(u"浮点型填写有误") def convert(path): excel_data = xlrd.open_workbook(path["file_path"], formatting_info=True) file_name = util.get_file_name(path["file_path"]) config_sheet = read_config_sheet(excel_data) data_sheet = read_data_sheet(excel_data) rules = init_rule(excel_data) rows = write_to_lua(data_sheet, config_sheet, file_name, path) excel_data.release_resources() del excel_data excel_obj = dict() excel_obj["file_name"] = os.path.basename(path["file_path"]) excel_obj["file_path"] = path["file_path"] excel_obj["data_sheet"] = data_sheet excel_obj["rows"] = rows excel_obj["rules"] = rules print "convert " + file_name + " finish" return excel_obj