Files
ctbjrj/tools/fix_columns.py

207 lines
7.9 KiB
Python

# -*- coding: utf-8 -*-
"""
把旧工具的 Columns.Add + Columns[i].X 写法转换为 SharpDevelop 设计器认的
"列字段 + AddRange" 标准 VS 写法,让设计器里能显示列头。
"""
import io
import re
import os
import glob
BASE = r"C:\Users\099978\Documents\SharpDevelop Projects\成套报价软件\成套报价软件"
def convert_columns(designer_text, class_name):
"""把一个 Designer.cs 里的所有 DataGridView 列定义从旧格式转换为 VS 标准格式"""
lines = designer_text.split("\n")
out = []
all_column_fields = [] # 所有列字段声明
all_column_news = [] # 所有列 new 语句
all_column_blocks = [] # 所有列属性块
i = 0
while i < len(lines):
line = lines[i].strip()
# 检测: this.xxx.Columns.Add(new System.Windows.Forms.DataGridViewTextBoxColumn());
m_add = re.match(r'this\.(\w+)\.Columns\.Add\(new System\.Windows\.Forms\.(\w+Column)\(\)\);', line)
if not m_add:
out.append(lines[i])
i += 1
continue
grid_name = m_add.group(1)
col_type = m_add.group(2)
# 收集后续的 Columns[i].X = ... 行
col_idx = 0
col_props = []
j = i + 1
while j < len(lines):
st = lines[j].strip()
m_prop = re.match(r'this\.' + grid_name + r'\.Columns\[(\d+)\]\.(\w+(?:\.\w+)*)\s*=\s*(.+?);', st)
if not m_prop:
break
idx = int(m_prop.group(1))
if idx != col_idx:
break
col_props.append((m_prop.group(2), m_prop.group(3)))
j += 1
if not col_props:
out.append(lines[i])
i += 1
continue
# 生成 VS 标准写法
# 列名从 HeaderText 取
header = ""
for prop, val in col_props:
if prop == "HeaderText":
header = val.strip('"')
break
field_name = "dataGridViewColumn_%s_%d" % (grid_name, col_idx)
# 收集属性
prop_lines = []
for prop, val in col_props:
if prop == "Name" and val == '""':
continue # 跳过空 Name
prop_lines.append("\t\t\tthis.%s.%s = %s;" % (field_name, prop, val))
all_column_news.append("\t\t\tthis.%s = new System.Windows.Forms.%s();" % (field_name, col_type))
all_column_blocks.append("\t\t\t// \n\t\t\t// %s\n\t\t\t// " % field_name)
all_column_blocks.extend(prop_lines)
all_column_fields.append("\t\tprivate System.Windows.Forms.%s %s;" % (col_type, field_name))
# 记住这个列属于哪个 grid
if not hasattr(convert_columns, "_grid_cols"):
convert_columns._grid_cols = {}
convert_columns._grid_cols.setdefault(grid_name, []).append(field_name)
col_idx += 1
# 继续找下一个 Columns.Add(同一 grid 的下一列)
while j < len(lines):
st2 = lines[j].strip()
m_next = re.match(r'this\.' + grid_name + r'\.Columns\.Add\(new System\.Windows\.Forms\.(\w+Column)\(\)\);', st2)
if m_next:
col_type2 = m_next.group(1)
j += 1
col_props2 = []
while j < len(lines):
st3 = lines[j].strip()
m_prop2 = re.match(r'this\.' + grid_name + r'\.Columns\[(\d+)\]\.(\w+(?:\.\w+)*)\s*=\s*(.+?);', st3)
if not m_prop2:
break
col_props2.append((m_prop2.group(2), m_prop2.group(3)))
j += 1
field_name2 = "dataGridViewColumn_%s_%d" % (grid_name, col_idx)
for prop, val in col_props2:
if prop == "HeaderText":
header2 = val.strip('"')
break
prop_lines2 = []
for prop, val in col_props2:
if prop == "Name" and val == '""':
continue
prop_lines2.append("\t\t\tthis.%s.%s = %s;" % (field_name2, prop, val))
all_column_news.append("\t\t\tthis.%s = new System.Windows.Forms.%s();" % (field_name2, col_type2))
all_column_blocks.append("\t\t\t// \n\t\t\t// %s\n\t\t\t// " % field_name2)
all_column_blocks.extend(prop_lines2)
all_column_fields.append("\t\tprivate System.Windows.Forms.%s %s;" % (col_type2, field_name2))
convert_columns._grid_cols.setdefault(grid_name, []).append(field_name2)
col_idx += 1
else:
break
# 跳过所有已消费的行
i = j
# 在 SuspendLayout 之前插入列的 new 语句
result = []
inserted_news = False
for line in out:
if not inserted_news and "this.SuspendLayout()" in line:
result.extend(all_column_news)
inserted_news = True
result.append(line)
# 在最后一个控件属性块之后、Controls.Add 之前插入列属性块和 AddRange
final = []
inserted_blocks = False
for k, line in enumerate(result):
# 找 Controls.Add 或 AddRange(第一个容器层级的地方)
if not inserted_blocks and re.search(r'this\.\w+\.Controls\.Add', line.strip()):
# 插入列属性块
final.extend(all_column_blocks)
# 插入每个 grid 的 Columns.AddRange
for grid_name, fields in convert_columns._grid_cols.items():
inner = ",\n\t\t\t\t".join("this.%s" % f for f in fields)
final.append("\t\t\tthis.%s.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {" % grid_name)
final.append("\t\t\t\t" + inner + "});")
final.append("")
inserted_blocks = True
final.append(line)
if not inserted_blocks:
# 没找到 Controls.Add,直接在 ResumeLayout 前插
final2 = []
for line in final:
if "this.ResumeLayout" in line and not inserted_blocks:
final2.extend(all_column_blocks)
for grid_name, fields in convert_columns._grid_cols.items():
inner = ",\n\t\t\t\t".join("this.%s" % f for f in fields)
final2.append("\t\t\tthis.%s.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {" % grid_name)
final2.append("\t\t\t\t" + inner + "});")
final2.append("")
inserted_blocks = True
final2.append(line)
final = final2
# 在最后一个 private 字段声明之前插入列字段
final3 = []
inserted_fields = False
for line in final:
if not inserted_fields and re.match(r'\t\tprivate ', line) and "Column" not in line:
final3.extend(all_column_fields)
final3.append("")
inserted_fields = True
final3.append(line)
if not inserted_fields:
final3.extend(all_column_fields)
# 清理类级变量
convert_columns._grid_cols = {}
return "\n".join(final3), len(all_column_fields)
def process_file(path):
s = io.open(path, encoding="utf-8-sig").read()
# 提取类名
m = re.search(r'partial class (\w+)', s)
if not m:
return 0
class_name = m.group(1)
# 检查是否有旧格式的列定义
if "Columns.Add(new" not in s:
return 0
new_s, n_cols = convert_columns(s, class_name)
if n_cols > 0:
io.open(path, "w", encoding="utf-8-sig", newline="\r\n").write(new_s)
print("%s: 转换了 %d 个列字段" % (os.path.basename(path), n_cols))
return n_cols
if __name__ == "__main__":
total = 0
for pattern in ["xiangmu/*.Designer.cs", "shezhi/*.Designer.cs",
"ku/*.Designer.cs", "GCS母排计算/*.Designer.cs"]:
for f in glob.glob(os.path.join(BASE, pattern)):
total += process_file(f)
print("\n共转换 %d 个列" % total)