From da8277b3b3282f2a228f448949902b68543cf301 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 7 Nov 2025 17:20:30 +0800 Subject: [PATCH] bugfix --- docs/dbtable.md | 43 ++++++++++++ setup.cfg | 1 + xls2ddl/json2xlsx.py | 162 +++++++++++++++++++++++++++++++++++++++++++ xls2ddl/xlsxData.py | 6 +- 4 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 docs/dbtable.md create mode 100644 xls2ddl/json2xlsx.py diff --git a/docs/dbtable.md b/docs/dbtable.md new file mode 100644 index 0000000..7aefcda --- /dev/null +++ b/docs/dbtable.md @@ -0,0 +1,43 @@ +# 数据库表定义规范 + +数据库表用一个json格式文件或数据来定义,具体规范如下 +{ + "name" + "title" + "primary" + "catelog" # 可选项:entity relation dimession indication + "fields":[ # 字段 + { + "name" + "title" + "type" #可选项有:str char short long llong date time timestamp float double ddouble decimal text + "length" + "dec" + "nullable" # 可选项:yes no + "default" + "comments" # 注释 + } + ] + "indexes":[ + { + "name" # 每个索引一个,idxname不能重复一个表中 + "idxtype" # unique or index + "idxfields" # 字段名或字段名数组[f1,f1] + } + ] + “codes":[ # 如果一个字段数据可以从其他表中获得,可以通过下面的模式定义选择输入逻辑 + { + "field" # 字段的名字 + "table" # 数据来源表 + "valuefield" # 数据来源表值字段 + "textfield" # 数据来源表显示字段 + "cond" # 检索条件 + } + ] +] +说明: +id字段全部使用str 32类型 +字典中的length:如果type是str char float double ddouble decimal中的一个,则必为>0的数字 +字典中的dec: 如果type是float double ddouble decimal中的一个,则必须是>0的数字 + + diff --git a/setup.cfg b/setup.cfg index ade0b80..262544e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,4 +17,5 @@ install_requires = console_scripts = xls2ddl = xls2ddl.xls2ddl:main xls2ui = xls2ddl.xls2ui:main + json2xlsx = xls2ddl.json2xlsx diff --git a/xls2ddl/json2xlsx.py b/xls2ddl/json2xlsx.py new file mode 100644 index 0000000..885a90c --- /dev/null +++ b/xls2ddl/json2xlsx.py @@ -0,0 +1,162 @@ +import json +import os +from openpyxl import Workbook + +def save_table_json_to_xlsx(table_json, output_dir="."): + """ + 将数据库表定义的 JSON 数据写入 .xlsx 文件 + :param table_json: 字典,符合数据库表定义规范的 JSON 数据 + :param output_dir: 输出目录 + """ + # 提取表名作为文件名 + table_name = table_json.get("name") + if not table_name: + raise ValueError("JSON 中缺少 'name' 字段") + + filename = f"{table_name}.xlsx" + filepath = os.path.join(output_dir, filename) + + # 创建工作簿 + wb = Workbook() + + # --- summary sheet --- + ws_summary = wb.active + ws_summary.title = "summary" + summary_headers = ["name", "title", "primary", "catelog"] + ws_summary.append(summary_headers) + ws_summary.append([ + table_json.get("name", ""), + table_json.get("title", ""), + table_json.get("primary", ""), + table_json.get("catelog", "") + ]) + + # --- fields sheet --- + ws_fields = wb.create_sheet("fields") + field_headers = ["name", "title", "type", "length", "dec", "nullable", "default", "comments"] + ws_fields.append(field_headers) + for field in table_json.get("fields", []): + row = [ + field.get("name", ""), + field.get("title", ""), + field.get("type", ""), + field.get("length", ""), + field.get("dec", ""), + field.get("nullable", ""), + field.get("default", ""), + field.get("comments", "") + ] + ws_fields.append(row) + + # --- indexes sheet --- + ws_indexes = wb.create_sheet("indexes") + index_headers = ["name", "idxtype", "idxfields"] + ws_indexes.append(index_headers) + for idx in table_json.get("indexes", []): + idxfields = idx.get("idxfields") + # 如果 idxfields 是列表,转成字符串形式 f1,f2;否则保持原样 + idxfields_str = ",".join(idxfields) if isinstance(idxfields, list) else str(idxfields) + ws_indexes.append([ + idx.get("name", ""), + idx.get("idxtype", ""), + idxfields_str + ]) + + # --- codes sheet --- + ws_codes = wb.create_sheet("codes") + code_headers = ["field", "table", "valuefield", "textfield", "cond"] + ws_codes.append(code_headers) + for code in table_json.get("codes", []): + ws_codes.append([ + code.get("field", ""), + code.get("table", ""), + code.get("valuefield", ""), + code.get("textfield", ""), + code.get("cond", "") + ]) + + # 保存文件 + wb.save(filepath) + print(f"✅ 已生成文件: {filepath}") + + +# ====================== +# 使用示例 +# ====================== + +if __name__ == "__main__": + import os, sys + import codecs + import json + if len(sys.argv) < 2: + print(f'{sys.argv[0] dbtable_json_file ...') + sys.exit(1) + for a in sys.argv[1:]: + with open(a, 'r', encoding='utf-8') as file: + content = file.read() + data = json.loads(content) + if not isinstance(data, list): + data = [data] + for d in data: + save_table_json_to_xlsx(d) + """ + # 示例 JSON 数据 + sample_json = { + "name": "user_info", + "title": "用户信息表", + "primary": "id", + "catelog": "entity", + "fields": [ + { + "name": "id", + "title": "用户ID", + "type": "str", + "length": 32, + "nullable": "no", + "comments": "主键,32位字符串" + }, + { + "name": "age", + "title": "年龄", + "type": "short", + "nullable": "yes", + "default": 0, + "comments": "用户年龄" + }, + { + "name": "salary", + "title": "月薪", + "type": "decimal", + "length": 10, + "dec": 2, + "nullable": "yes", + "default": "0.00", + "comments": "精确到分" + } + ], + "indexes": [ + { + "name": "idx_user_age", + "idxtype": "index", + "idxfields": ["age"] + }, + { + "name": "idx_user_salary", + "idxtype": "unique", + "idxfields": ["id", "salary"] + } + ], + "codes": [ + { + "field": "dept_id", + "table": "department", + "valuefield": "id", + "textfield": "name", + "cond": "status=1" + } + ] + } + + # 调用函数生成 xlsx + save_table_json_to_xlsx(sample_json) + """ diff --git a/xls2ddl/xlsxData.py b/xls2ddl/xlsxData.py index 04154fb..61bc0a5 100755 --- a/xls2ddl/xlsxData.py +++ b/xls2ddl/xlsxData.py @@ -164,7 +164,7 @@ class CRUDData(XLSXData): return False if 'fields' not in names: return False - if 'validation' not in names: + if 'validation' not in names and 'indexes' not in names: return False return True @@ -175,8 +175,6 @@ class CRUDData(XLSXData): raise CRUDException(self.xlsxfile,'summary sheet missing') if not 'fields' in d.keys(): raise CRUDException(self.xlsxfile,'fields sheet missing') - if not 'validation' in d.keys(): - raise CRUDException(self.xlsxfile,'validation sheet missing') if len(d['summary']) != 1: raise CRUDException(self.xlsxfile, 'Not summary or more than one summary') self.convPrimary() @@ -251,6 +249,8 @@ class CRUDData(XLSXData): def convIndex(self): data = self.data + if data.get('indexes'): + return vs = data['validation'] nvs = [] for v in vs: