- 积分
- 1905
- 明经币
- 个
- 注册时间
- 2022-4-4
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
楼主 |
发表于 2023-12-23 15:25:49
|
显示全部楼层
本帖最后由 枫叶棋语 于 2023-12-26 14:38 编辑
- import json
- import os
- import typing
- import clr
- import System
- from pycad.runtime import *
- from pycad.system import *
- import re, csv
- clr.AddReference("System.Windows.Forms")
- clr.AddReference("System.Drawing")
- from System.Drawing import *
- from System.Windows.Forms import *
- from System.ComponentModel import BindingList
- class CurveData:
- def __init__(self, curve_id: int = 0) -> None:
- super().__init__()
- self.doc: Document = acap.Application.DocumentManager.MdiActiveDocument
- self.db = self.doc.Database
- self.句柄 = curve_id
- self.起点 = ""
- self.终点 = ""
- self.回路 = ""
- self.功率 = 0
- self.电压 = "380V"
- self.型号规格 = ""
- self.电缆拼数 = 1
- self.垂直长度 = 0
- self.余量 = 3
- self.备注 = ""
- def to_dict(self):
- return {
- "起点": self.起点,
- "终点": self.终点,
- "句柄": self.句柄,
- "回路": self.回路,
- "功率": self.功率,
- "电压": self.电压,
- "型号规格": self.型号规格,
- "电缆拼数": self.电缆拼数,
- "垂直长度": self.垂直长度,
- "余量": self.余量,
- "备注": self.备注,
- }
- @staticmethod
- def from_dict(data: dict):
- curvedata = CurveData(data.get("句柄", 0))
- curvedata.起点 = data.get("起点", "")
- curvedata.终点 = data.get("终点", "")
- curvedata.回路 = data.get("回路", "")
- curvedata.功率 = data.get("功率", 0)
- curvedata.型号规格 = data.get("型号规格", "")
- curvedata.电缆拼数 = data.get("电缆拼数", 1)
- curvedata.垂直长度 = data.get("垂直长度", 0)
- curvedata.余量 = data.get("余量", 0)
- curvedata.备注 = data.get("备注", "")
- return curvedata
- @property
- def ObjectId(self) -> ObjectId:
- if self.句柄 == 0 or self.句柄 == None or self.句柄 == "" or self.句柄 == System.DBNull.Value:
- return "None"
- else:
- return self.db.GetObjectId(False, Handle(self.句柄), 0)
- @property
- def 水平长度(self):
- if self.ObjectId == "None":
- return 0
- elif self.ObjectId.IsNull:
- self.句柄 = 0
- return 0
- elif self.ObjectId.ObjectClass.DxfName not in ["LINE", "POLYLINE", "LWPOLYLINE"]:
- return 0
- else:
- return float(f"{self.ObjectId.Length / 1000:0.2f}")
- @property
- def 总长度(self):
- return (self.水平长度 + self.垂直长度 + self.余量) * self.电缆拼数
- class DataPanel(Panel):
- def __init__(self):
- super().__init__()
- self.ColumnsTags = ["句柄", "起点", "终点", "回路", "功率", "型号规格", "水平长度", "垂直长度", "余量", "电缆拼数", "总长度", "备注"]
- self.datagrid = DataGridView()
- self.reverse = False
- self.Initial()
- def CreateColmns(self, column_name, ReadOnly: bool):
- column = DataGridViewTextBoxColumn()
- column.Name = column_name
- column.DataPropertyName = column_name # 数据属性名
- column.HeaderText = column_name # 表头文字
- column.ReadOnly = ReadOnly
- column.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
- self.datagrid.Columns.Add(column)
- return column
- def AddRowIndex(self):
- for i, row in enumerate(self.datagrid.Rows):
- row.HeaderCell.Value = str(i)
- def Initial(self):
- for tag in self.ColumnsTags:
- if tag in ["水平长度", "总长度"]:
- column = self.CreateColmns(tag, True)
- column.DefaultCellStyle.Format = "N2"
- elif tag in ["功率", "余量", "电缆拼数"]:
- column = self.CreateColmns(tag, False)
- column.DefaultCellStyle.Format = "N0"
- else:
- self.CreateColmns(tag, False)
- self.data_objects = BindingList[CurveData]()
- self.binding_source = BindingSource(self.data_objects, None)
- self.datagrid.DataSource = self.binding_source
- self.display_Column = {}
- for i in range(self.datagrid.Columns.Count):
- self.display_Column[i] = i
- self.reverse = False
- self.datagrid.DataError += self.DataError
- self.datagrid.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
- self.datagrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells
- self.datagrid.Dock = DockStyle.Fill
- self.datagrid.AllowUserToAddRows = True
- self.datagrid.AllowUserToDeleteRows = True
- self.datagrid.AllowUserToResizeRows = True
- self.datagrid.MultiSelect = True
- self.datagrid.ReadOnly = False
- self.datagrid.RowHeadersVisible = True
- self.datagrid.AutoGenerateColumns = False
- self.datagrid.RowHeadersVisible = True
- self.datagrid.AllowUserToOrderColumns = True
- self.datagrid.RowHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
- self.datagrid.RowHeadersWidth = 50
- self.datagrid.SelectionMode = DataGridViewSelectionMode.CellSelect
- self.datagrid.BorderStyle = BorderStyle.FixedSingle
- self.datagrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
- self.datagrid.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
- self.Controls.Add(self.datagrid)
- self.datagrid.ColumnHeaderMouseClick += self.On_ColumnHeaderMouseClick
- self.datagrid.CellValueChanged += self.On_CellValueChanged
- self.datagrid.KeyDown += self.On_keydown
- self.datagrid.ColumnDisplayIndexChanged += self.On_ColumnDisplayIndexChanged
- def DataError(self, s, e: DataGridViewDataErrorEventArgs):
- """处理数据类型错误"""
- e.Cancel = True
- prinf(f"{e.RowIndex}行,{e.ColumnIndex}列,输入格式错误")
- return
- def On_ColumnDisplayIndexChanged(self, sender, e):
- """处理手动调整列顺序事件,并更新显示列与数据列匹配字典"""
- for i in range(self.datagrid.Columns.Count):
- self.display_Column[self.datagrid.Columns[i].DisplayIndex] = i
- def Op_Clip(self):
- """处理剪贴板文字,变成数组"""
- if Clipboard.ContainsText():
- pasted_text = Clipboard.GetText()
- rows = csv.reader(pasted_text.splitlines(), delimiter="\t")
- data = [list(row) for row in rows]
- return data
- else:
- return None
- def On_keydown(self, s, e: KeyEventArgs):
- """按键事件"""
- selectedCells: typing.Collection[DataGridViewTextBoxCell] = self.datagrid.SelectedCells
- if selectedCells.Count > 0:
- col_display_indexes = sorted({cell.OwningColumn.DisplayIndex for cell in selectedCells})
- row_indexes = sorted({cell.RowIndex for cell in selectedCells})
- if e.KeyCode == Keys.D and e.Control:
- """处理ctrl+D快捷键"""
- for col in col_display_indexes:
- col_cells = [cell for cell in selectedCells if cell.OwningColumn.DisplayIndex == col]
- col_cells.sort(key=lambda cell: cell.RowIndex)
- value_col0 = col_cells[0].Value
- for cell in col_cells:
- cell.Value = value_col0
- if e.KeyCode == Keys.R and e.Control:
- """处理ctrl+R快捷键"""
- for row in row_indexes:
- row_cells = [cell for cell in selectedCells if cell.RowIndex == row]
- row_cells.sort(key=lambda cell: cell.OwningColumn.DisplayIndex)
- value_row0 = row_cells[0].Value
- for cell in row_cells:
- cell.Value = value_row0
- if e.KeyCode == Keys.Delete:
- """处理删除快捷键"""
- for cell in selectedCells:
- cell.Value = ""
- if e.KeyCode == Keys.V and e.Control:
- clipdata = self.Op_Clip()
- columns: DataGridViewColumnCollection = self.datagrid.Columns
- if clipdata:
- if len(selectedCells) == 1:
- selected_cell: DataGridViewTextBoxCell = selectedCells[0]
- row_index0 = selected_cell.RowIndex
- col_index0 = selected_cell.OwningColumn.DisplayIndex
- for i, row in enumerate(clipdata):
- for j, col in enumerate(row):
- if row_index0 + i < self.datagrid.Rows.Count and col_index0 + j < self.datagrid.Columns.Count:
- col_index = self.display_Column[col_index0 + j]
- self.datagrid.Rows[row_index0 + i].Cells[col_index].Value = col
- if len(selectedCells) > 1:
- row_index_min = min(row_indexes)
- col_index_min = min(col_display_indexes)
- row_index_max = max(row_indexes)
- col_index_max = max(col_display_indexes)
- if (col_index_max - col_index_min + 1) * (row_index_max - row_index_min + 1) != len(selectedCells):
- aleernt_message = "此选择无效,粘贴区域为完整连续的范围"
- MessageBox.Show(aleernt_message, "IronPycad", MessageBoxButtons.OK, MessageBoxIcon.Error)
- else:
- for i, row in enumerate(clipdata):
- for j, col in enumerate(row):
- if row_index_min + i <= row_index_max and col_index_min + j <= col_index_max:
- col_index = self.display_Column[col_index_min + j]
- self.datagrid.Rows[row_index_min + i].Cells[col_index].Value = col
- def On_CellValueChanged(self, sender, e: DataGridViewCellEventArgs):
- """处理单元格值改变事件"""
- self.binding_source.ResetItem(e.RowIndex)
- def On_ColumnHeaderMouseClick(self, sender, e: DataGridViewCellMouseEventArgs):
- """处理表头点击事件,实现排序"""
- column_name = self.datagrid.Columns[e.ColumnIndex].HeaderText
- self.data_objects = BindingList[CurveData](
- sorted(self.data_objects, key=lambda x: getattr(x, column_name), reverse=self.reverse)
- )
- self.binding_source = BindingSource(self.data_objects, None)
- self.datagrid.DataSource = self.binding_source
- self.AddRowIndex()
- self.reverse = not self.reverse
- class CunstomButton(Button):
- def __init__(self, text):
- super().__init__()
- self.Text = text
- self.Size = Size(100, 25)
- self.Font = Font("Arial", 8)
- self.Dock = DockStyle.Top
- class CustomTextBox(TextBox):
- def __init__(self):
- super().__init__()
- self.Size = Size(100, 25)
- self.Font = Font("Arial", 8)
- self.Dock = DockStyle.Top
- class OpPanel(Panel):
- def __init__(self):
- super().__init__()
- self.tag_textboex = CustomTextBox()
- self.add_btn = CunstomButton("添加曲线")
- self.load_btn = CunstomButton("加载数据")
- self.save_btn = CunstomButton("保存数据")
- self.newrow_btn = CunstomButton("添加新行")
- self.delrow_btn = CunstomButton("删除整行")
- self.SerialStart_btn = CunstomButton("起点编号")
- self.SerialEnd_btn = CunstomButton("终点编号")
- self.BindingCurve_btn = CunstomButton("绑定曲线")
- self.FindData_btn = CunstomButton("查找曲线")
- self.FindDatas_btn = CunstomButton("批量查线")
- self.Notes_btn = CunstomButton("批量备注")
- self.Controls.Add(self.Notes_btn)
- self.Controls.Add(self.FindDatas_btn)
- self.Controls.Add(self.add_btn)
- self.Controls.Add(self.FindData_btn)
- self.Controls.Add(self.BindingCurve_btn)
- self.Controls.Add(self.SerialEnd_btn)
- self.Controls.Add(self.SerialStart_btn)
- self.Controls.Add(self.tag_textboex)
- self.Controls.Add(self.newrow_btn)
- self.Controls.Add(self.delrow_btn)
- self.Controls.Add(self.load_btn)
- self.Controls.Add(self.save_btn)
- class ListPanel(Form):
- def __init__(self):
- super().__init__()
- self.doc: Document = acap.Application.DocumentManager.MdiActiveDocument
- self.jsonname = os.path.splitext(self.doc.Name)[0] + ".json"
- self.InitForm()
- def ReBindData(self, datalist):
- handles = {dataobject.句柄 for dataobject in self.datapanel.data_objects if dataobject.句柄 != 0}
- for data in datalist:
- if data.句柄 not in handles:
- self.datapanel.data_objects.Add(data)
- self.datapanel.binding_source = BindingSource(self.datapanel.data_objects, None)
- self.datapanel.datagrid.DataSource = self.datapanel.binding_source
- def InitForm(self):
- self.db = self.doc.Database
- self.Name = self.doc.Name
- self.Text = os.path.basename(self.Name)
- self.Dock = DockStyle.Fill
- self.Size = Size(1000, 600)
- self.splitContainer = SplitContainer()
- self.splitContainer.Dock = DockStyle.Fill
- self.splitContainer.Location = Point(0, 0)
- self.datapanel = DataPanel()
- self.datapanel.Dock = DockStyle.Fill
- self.datapanel.datagrid.SelectionChanged += self.On_SelectionChanged
- self.oppanel = OpPanel()
- self.oppanel.Dock = DockStyle.Fill
- self.oppanel.add_btn.Click += self.On_Add_Click
- self.oppanel.save_btn.Click += self.On_Save_Click
- self.oppanel.load_btn.Click += self.On_Load_Click
- self.oppanel.newrow_btn.Click += self.On_NewRow_Click
- self.oppanel.delrow_btn.Click += self.On_DelRow_Click
- self.oppanel.SerialStart_btn.Click += self.On_SerialStart_Click
- self.oppanel.SerialEnd_btn.Click += self.On_SerialEnd_Click
- self.oppanel.BindingCurve_btn.Click += self.On_BindingCurve_Click
- self.oppanel.FindData_btn.Click += self.On_FindData_Click
- self.oppanel.FindDatas_btn.Click += self.On_FindDatas_Click
- self.oppanel.Notes_btn.Click += self.On_Notes_Click
- self.splitContainer.Panel1.Controls.Add(self.datapanel)
- self.splitContainer.Panel2.Controls.Add(self.oppanel)
- self.Controls.Add(self.splitContainer)
- self.Load += self.ListForm_Load
- self.SizeChanged += self.ListForm_SizeChanged
- def On_Add_Click(self, sender, e):
- self.oppanel.add_btn.Enabled = False
- self.doc.Window.Focus()
- res = ssget(":A", TV(0, "LINE,*POLYLINE"))
- if not res.ok:
- self.oppanel.add_btn.Enabled = True
- return
- ids: typing.Collection[ObjectId] = tuple(res)
- datalist = [CurveData(int(objid.Handle.Value)) for objid in ids]
- self.ReBindData(datalist)
- self.datapanel.AddRowIndex()
- self.oppanel.add_btn.Enabled = True
- def ListForm_Load(self, sender, e):
- self.splitContainer.SplitterDistance = self.Width - 100
- def ListForm_SizeChanged(self, sender, e):
- if self.WindowState != FormWindowState.Minimized:
- self.splitContainer.SplitterDistance = self.Width - 100
- def GetObjectId(self, curve_id: int) -> ObjectId:
- if curve_id == System.DBNull.Value:
- prinf("句柄需要为整数")
- return
- else:
- return self.db.GetObjectId(False, Handle(curve_id), 0)
- def On_SelectionChanged(self, s, e):
- if self.datapanel.datagrid.SelectedCells.Count > 0:
- Utils.SetFocusToDwgView()
- cells = self.datapanel.datagrid.SelectedCells
- row_indexes = {cell.RowIndex for cell in cells if cell.Value != System.DBNull.Value}
- handels = [
- self.datapanel.data_objects[rowindex].句柄
- for rowindex in row_indexes
- if self.datapanel.data_objects[rowindex].句柄 != 0
- ]
- try:
- objids = [self.GetObjectId(curve_id) for curve_id in handels]
- sssetfirst(tuple(objids))
- except:
- prinf("Error: 非法句柄")
- self.datapanel.datagrid.Focus()
- def On_Save_Click(self, sender, e):
- datalist = [curvedata.to_dict() for curvedata in self.datapanel.data_objects]
- json_str = json.dumps(datalist, indent=4, ensure_ascii=False)
- with open(self.jsonname, "w", encoding="utf-8") as f:
- f.write(json_str)
- def On_Load_Click(self, sender, e):
- dialog = OpenFileDialog()
- dialog.Filter = "json文件(*.json)|*.json"
- dialog.InitialDirectory = os.path.dirname(self.jsonname)
- dialog.Multiselect = False
- if dialog.ShowDialog() == DialogResult.OK:
- filename = dialog.FileName
- with open(filename, "r", encoding="utf-8") as f:
- datalist: typing.List[dict] = json.load(f)
- self.ReBindData([CurveData.from_dict(curvedata) for curvedata in datalist])
- self.datapanel.AddRowIndex()
- def On_NewRow_Click(self, sender, e):
- self.ReBindData([CurveData()])
- self.datapanel.AddRowIndex()
- def On_DelRow_Click(self, sender, e):
- selectedCells = self.datapanel.datagrid.SelectedCells
- rows = {cell.RowIndex for cell in selectedCells}
- for row_index in sorted(rows, reverse=True):
- self.datapanel.datagrid.Rows.RemoveAt(row_index)
- def On_SerialStart_Click(self, sender, e):
- selectedCells = self.datapanel.datagrid.SelectedCells
- rows = {cell.RowIndex for cell in selectedCells}
- for row_index in rows:
- self.datapanel.data_objects[row_index].起点 = self.oppanel.tag_textboex.Text
- self.datapanel.binding_source.ResetItem(row_index)
- def On_SerialEnd_Click(self, sender, e):
- selectedCells = self.datapanel.datagrid.SelectedCells
- rows = {cell.RowIndex for cell in selectedCells}
- for row_index in rows:
- self.datapanel.data_objects[row_index].终点 = self.oppanel.tag_textboex.Text
- self.datapanel.binding_source.ResetItem(row_index)
- def On_BindingCurve_Click(self, sender, e):
- self.oppanel.BindingCurve_btn.Enabled = False
- self.doc.Window.Focus()
- rowindex = self.datapanel.datagrid.SelectedCells[0].RowIndex
- res = entsel("\n选择要绑定的曲线")
- if not res.ok:
- self.oppanel.BindingCurve_btn.Enabled = True
- return
- self.oppanel.BindingCurve_btn.Enabled = True
- objid = res.ObjectId
- if objid.ObjectClass.DxfName not in ["LINE", "POLYLINE", "LWPOLYLINE"]:
- prinf("请选择直线或多段线")
- else:
- self.datapanel.data_objects[rowindex].句柄 = int(objid.Handle.Value)
- self.datapanel.binding_source.ResetItem(rowindex)
- def On_FindData_Click(self, sender, e):
- self.datapanel.datagrid.SelectionChanged -= self.On_SelectionChanged # 禁用选择更改事件
- self.oppanel.FindData_btn.Enabled = False
- self.doc.Window.Focus()
- res = entsel("\n选择要查询的曲线")
- if not res.ok:
- self.oppanel.FindData_btn.Enabled = True
- self.datapanel.datagrid.SelectionChanged += self.On_SelectionChanged # 启用选择更改事件
- return
- self.oppanel.FindData_btn.Enabled = True
- objid = res.ObjectId
- if objid.ObjectClass.DxfName not in ["LINE", "POLYLINE", "LWPOLYLINE"]:
- prinf("请选择直线或多段线")
- else:
- curve_id = int(objid.Handle.Value)
- for row_index in range(self.datapanel.data_objects.Count):
- if self.datapanel.data_objects[row_index].句柄 == curve_id:
- self.datapanel.datagrid.ClearSelection()
- self.datapanel.datagrid.Rows[row_index].Selected = True
- for cell_index in range(self.datapanel.datagrid.ColumnCount):
- self.datapanel.datagrid.Rows[row_index].Cells[cell_index].Selected = True
- self.datapanel.datagrid.FirstDisplayedScrollingRowIndex = row_index
- self.datapanel.datagrid.SelectionChanged += self.On_SelectionChanged # 启用选择更改事件
- def On_FindDatas_Click(self, sender, e):
- self.datapanel.datagrid.SelectionChanged -= self.On_SelectionChanged # 禁用选择更改事件
- self.oppanel.FindDatas_btn.Enabled = False
- self.doc.Window.Focus()
- res = ssget(":A", TV(0, "LINE,*POLYLINE"))
- if not res.ok:
- self.oppanel.FindDatas_btn.Enabled = True
- self.datapanel.datagrid.SelectionChanged += self.On_SelectionChanged # 启用选择更改事件
- return
- ids: typing.List[ObjectId] = tuple(res)
- handles = [int(objid.Handle.Value) for objid in ids]
- self.datapanel.datagrid.ClearSelection()
- for curve_id in handles:
- for row_index in range(self.datapanel.data_objects.Count):
- if self.datapanel.data_objects[row_index].句柄 == curve_id:
- for cell_index in range(self.datapanel.datagrid.ColumnCount):
- self.datapanel.datagrid.Rows[row_index].Cells[cell_index].Selected = True
- self.oppanel.FindDatas_btn.Enabled = True
- self.datapanel.datagrid.SelectionChanged += self.On_SelectionChanged # 启用选择更改事件
- def On_Notes_Click(self, sender, e):
- selectedCells = self.datapanel.datagrid.SelectedCells
- rows = {cell.RowIndex for cell in selectedCells}
- for row_index in rows:
- self.datapanel.data_objects[row_index].备注 = self.oppanel.tag_textboex.Text
- self.datapanel.binding_source.ResetItem(row_index)
- @Command(flags=CommandFlags.UsePickSet)
- def SG(doc: Document):
- db = doc.Database
- listform = ListPanel()
- acap.Application.ShowModelessDialog(owner=doc.Window.Handle, formToShow=listform, persistSizeAndPosition=False)
复制代码 |
|