496 lines
19 KiB
Python
496 lines
19 KiB
Python
#-*- 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
|
||
|