2023-04-03 11:04:31 +08:00

496 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#-*- 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