gen_table_excel.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/usr/bin/env python3
  2. """从 aidopdev 数据库导出全部表结构到 Excel,按业务分类分 Sheet。"""
  3. import pymysql
  4. from openpyxl import Workbook
  5. from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
  6. from collections import OrderedDict
  7. DB_CFG = dict(
  8. host="123.60.180.165", port=3306,
  9. user="aidopremote", password="1234567890aiDOP#",
  10. database="information_schema", charset="utf8mb4",
  11. )
  12. CATEGORY_ORDER = OrderedDict([
  13. ("系统基础(Sys)", lambda t: t.startswith("Sys")),
  14. ("审批流程(Approval)", lambda t: t.startswith("Approval")),
  15. ("钉钉集成(DingTalk)", lambda t: t.startswith("DingTalk") or t.startswith("ding_talk")),
  16. ("GoView可视化", lambda t: t.startswith("GoView")),
  17. ("S0 基础主数据", lambda t: t.startswith("ado_s0_")),
  18. ("S1 产销协同", lambda t: t.startswith("ado_s1_")),
  19. ("S2 生产计划", lambda t: t.startswith("ado_s2_")),
  20. ("S3 物料计划", lambda t: t.startswith("ado_s3_")),
  21. ("S4 采购", lambda t: t.startswith("ado_s4_")),
  22. ("S5 仓储来料", lambda t: t.startswith("ado_s5_")),
  23. ("S6 生产执行", lambda t: t.startswith("ado_s6_")),
  24. ("S7 成品管理", lambda t: t.startswith("ado_s7_")),
  25. ("S8 预警异常", lambda t: t.startswith("ado_s8_")),
  26. ("S9 管理看板KPI", lambda t: t.startswith("ado_s9_")),
  27. ("智慧运营(SmartOps)", lambda t: t.startswith("ado_smart_ops_")),
  28. ("主数据(MD)", lambda t: t.startswith("ado_md_")),
  29. ("集成(Intg)", lambda t: t.startswith("ado_intg_")),
  30. ("移动端(Mobile)", lambda t: t.startswith("ado_mobile_")),
  31. ("Demo表", lambda t: t in ("ado_orders", "ado_plans", "ado_work_orders")),
  32. ("其他", lambda t: True),
  33. ])
  34. HEADER_FILL = PatternFill("solid", fgColor="4472C4")
  35. HEADER_FONT = Font(name="微软雅黑", bold=True, color="FFFFFF", size=10)
  36. BODY_FONT = Font(name="微软雅黑", size=9)
  37. TBL_FILL = PatternFill("solid", fgColor="D9E2F3")
  38. TBL_FONT = Font(name="微软雅黑", bold=True, size=10)
  39. THIN_BORDER = Border(
  40. left=Side(style="thin"), right=Side(style="thin"),
  41. top=Side(style="thin"), bottom=Side(style="thin"),
  42. )
  43. WRAP = Alignment(wrap_text=True, vertical="center")
  44. def fetch_data():
  45. conn = pymysql.connect(**DB_CFG)
  46. cur = conn.cursor()
  47. cur.execute(
  48. "SELECT TABLE_NAME, TABLE_COMMENT, TABLE_ROWS "
  49. "FROM TABLES WHERE TABLE_SCHEMA='aidopdev' ORDER BY TABLE_NAME"
  50. )
  51. tables = {r[0]: {"comment": r[1] or "", "rows": r[2]} for r in cur.fetchall()}
  52. cur.execute(
  53. "SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, "
  54. "COLUMN_DEFAULT, COLUMN_COMMENT "
  55. "FROM COLUMNS WHERE TABLE_SCHEMA='aidopdev' "
  56. "ORDER BY TABLE_NAME, ORDINAL_POSITION"
  57. )
  58. columns = {}
  59. for row in cur.fetchall():
  60. columns.setdefault(row[0], []).append(row[1:])
  61. cur.close()
  62. conn.close()
  63. return tables, columns
  64. def classify(tables):
  65. result = OrderedDict((k, []) for k in CATEGORY_ORDER)
  66. assigned = set()
  67. for cat, pred in CATEGORY_ORDER.items():
  68. for tname in tables:
  69. if tname not in assigned and pred(tname):
  70. result[cat].append(tname)
  71. assigned.add(tname)
  72. return result
  73. def write_overview(ws, tables, classified):
  74. headers = ["序号", "分类", "表名", "表说明", "记录数"]
  75. widths = [6, 22, 42, 36, 10]
  76. for ci, (h, w) in enumerate(zip(headers, widths), 1):
  77. c = ws.cell(row=1, column=ci, value=h)
  78. c.font = HEADER_FONT
  79. c.fill = HEADER_FILL
  80. c.alignment = WRAP
  81. c.border = THIN_BORDER
  82. ws.column_dimensions[c.column_letter].width = w
  83. idx = 0
  84. for cat, tnames in classified.items():
  85. for tname in tnames:
  86. idx += 1
  87. info = tables[tname]
  88. vals = [idx, cat, tname, info["comment"], info["rows"]]
  89. for ci, v in enumerate(vals, 1):
  90. c = ws.cell(row=idx + 1, column=ci, value=v)
  91. c.font = BODY_FONT
  92. c.alignment = WRAP
  93. c.border = THIN_BORDER
  94. ws.auto_filter.ref = f"A1:E{idx + 1}"
  95. def write_detail_sheet(ws, cat, tnames, tables, columns):
  96. headers = ["字段名", "类型", "可空", "默认值", "说明"]
  97. widths = [28, 22, 6, 14, 36]
  98. for ci, w in enumerate(widths, 1):
  99. ws.column_dimensions[ws.cell(row=1, column=ci).column_letter].width = w
  100. row = 1
  101. for tname in tnames:
  102. info = tables[tname]
  103. c = ws.cell(row=row, column=1,
  104. value=f"{tname} — {info['comment']} (约{info['rows'] or 0}行)")
  105. c.font = TBL_FONT
  106. c.fill = TBL_FILL
  107. c.border = THIN_BORDER
  108. for ci in range(2, 6):
  109. cc = ws.cell(row=row, column=ci)
  110. cc.fill = TBL_FILL
  111. cc.border = THIN_BORDER
  112. ws.merge_cells(start_row=row, start_column=1, end_row=row, end_column=5)
  113. row += 1
  114. for ci, (h, w) in enumerate(zip(headers, widths), 1):
  115. c = ws.cell(row=row, column=ci, value=h)
  116. c.font = HEADER_FONT
  117. c.fill = HEADER_FILL
  118. c.alignment = WRAP
  119. c.border = THIN_BORDER
  120. row += 1
  121. for col_info in columns.get(tname, []):
  122. col_name, col_type, nullable, default, comment = col_info
  123. vals = [col_name, col_type, nullable, str(default) if default is not None else "", comment or ""]
  124. for ci, v in enumerate(vals, 1):
  125. c = ws.cell(row=row, column=ci, value=v)
  126. c.font = BODY_FONT
  127. c.alignment = WRAP
  128. c.border = THIN_BORDER
  129. row += 1
  130. row += 1
  131. def main():
  132. tables, columns = fetch_data()
  133. classified = classify(tables)
  134. wb = Workbook()
  135. ws_overview = wb.active
  136. ws_overview.title = "总览"
  137. write_overview(ws_overview, tables, classified)
  138. for cat, tnames in classified.items():
  139. if not tnames:
  140. continue
  141. safe_title = cat[:31]
  142. ws = wb.create_sheet(title=safe_title)
  143. write_detail_sheet(ws, cat, tnames, tables, columns)
  144. out = "/root/aidopdemo/docs/db/aidopdev_表结构汇总.xlsx"
  145. wb.save(out)
  146. print(f"Done → {out}")
  147. if __name__ == "__main__":
  148. main()