Просмотр исходного кода

完成搜索查询树中的右键单击事件,完成GC初始数据中大部分数据的导出

wzp 3 месяцев назад
Родитель
Сommit
165003d938
4 измененных файлов: 256 добавлений и 18 удалений
  1. 120
    18
      Back/GC/GCExport.py
  2. 136
    0
      Front/main.py
  3. Двоичные данные
      SQL/1.db
  4. Двоичные данные
      SQL/测试.db

+ 120
- 18
Back/GC/GCExport.py Просмотреть файл

@@ -7,22 +7,14 @@ import os
7 7
 from PySide6.QtWidgets import QMessageBox
8 8
 from openpyxl.styles import Font, NamedStyle, Alignment
9 9
 from openpyxl.utils.dataframe import dataframe_to_rows
10
+from openpyxl import Workbook
10 11
 
11 12
 
12
-def main_function(ui, utf_en, db_path):
13
-    # 获取应用的安装目录
14
-    app_install_dir = os.path.dirname(os.path.abspath(__file__))  # 假设脚本文件位于应用的安装目录下
15
-    export_folder = os.path.join(app_install_dir, 'Export')
16
-
17
-    # 如果 Export 文件夹不存在,则创建它
18
-    if not os.path.exists(export_folder):
19
-        os.makedirs(export_folder)
20
-
21
-
22
-    # 连接数据库
23
-    conn = sqlite3.connect(db_path)
24
-
13
+def export_result_data(ui, utf_en, db_path, export_folder):
25 14
     try:
15
+        # 连接数据库
16
+        conn = sqlite3.connect(db_path)
17
+
26 18
         # 查询数据库表为DataFrame,添加 TableName 条件
27 19
         query = "SELECT * FROM GC_Output_Point WHERE TableName=?"
28 20
         df = pd.read_sql_query(query, conn, params=(utf_en,))
@@ -76,12 +68,10 @@ def main_function(ui, utf_en, db_path):
76 68
         correct_factor_df = pd.read_sql_query(query_param, conn, params=(utf_en,))
77 69
 
78 70
         correct_factor = correct_factor_df.iloc[0]['Correct_Factor']
71
+
79 72
         # 创建一个新的 Excel 工作簿
80
-        from openpyxl import Workbook
81 73
         wb = Workbook()
82 74
         ws = wb.active
83
-        # # 在最上面插入一行
84
-        # ws.insert_rows(1)
85 75
         # 在E1单元格添加内容“修正系数”
86 76
         ws.cell(row=1, column=1, value="序号")
87 77
         ws.cell(row=1, column=2, value="结果期数")
@@ -93,8 +83,7 @@ def main_function(ui, utf_en, db_path):
93 83
         ws.cell(row=1, column=8, value="期间差异")
94 84
         ws.cell(row=1, column=9, value="变形判定")
95 85
 
96
-
97
-# 将 DataFrame 写入工作表
86
+        # 将 DataFrame 写入工作表
98 87
         for r in dataframe_to_rows(df, index=False, header=True):
99 88
             ws.append(r)
100 89
 
@@ -151,3 +140,116 @@ def main_function(ui, utf_en, db_path):
151 140
     finally:
152 141
         # 关闭数据库连接
153 142
         conn.close()
143
+
144
+
145
+def export_initial_data(ui, utf_en, db_path, export_folder):
146
+    try:
147
+        # 解码 utf_en
148
+        decoded_utf_en = utf_en.decode('utf-8') if isinstance(utf_en, bytes) else utf_en
149
+
150
+        # 创建一个新的 Excel 工作簿
151
+        wb = Workbook()
152
+        ws = wb.active
153
+
154
+        # 合并指定的单元格
155
+        merge_cells = ['A1:B1', 'D1:E1', 'F1:G1', 'I1:J1']
156
+        for cell_range in merge_cells:
157
+            ws.merge_cells(cell_range)
158
+
159
+        # 设置合并单元格后的居中对齐
160
+        for cell_range in merge_cells:
161
+            cell = ws[cell_range.split(':')[0]]
162
+            cell.alignment = Alignment(horizontal='center', vertical='center')
163
+
164
+        # 填写表头信息
165
+        ws['A1'] = '观测等级'
166
+        ws['A2'] = '序号'
167
+        ws['B2'] = '起点'
168
+        ws['C2'] = '终点'
169
+        ws['D2'] = '高差(m)'
170
+        ws['E2'] = '路线长(km)'
171
+        ws['F1'] = '测站全中误差(mm)'
172
+        ws['F2'] = '序号'
173
+        ws['G2'] = '起点'
174
+        ws['H2'] = '终点'
175
+        ws['I2'] = '高差(m)'
176
+        ws['J2'] = '路线长(km)'
177
+
178
+        # 连接数据库
179
+        conn = sqlite3.connect(db_path)
180
+        cursor = conn.cursor()
181
+
182
+        # 查询数据库表为DataFrame,添加 TableName 条件
183
+        query = "SELECT * FROM GC_Input_Point WHERE TableName=?"
184
+        cursor.execute(query, (utf_en,))
185
+        rows = cursor.fetchall()
186
+
187
+        # 获取列名
188
+        column_names = [description[0] for description in cursor.description]
189
+
190
+        # 定义需要的列索引
191
+        last_id_index = column_names.index('Last_ID')
192
+        last_spname_index = column_names.index('Last_SPName')
193
+        last_epname_index = column_names.index('Last_EPName')
194
+        last_hdiff_index = column_names.index('Last_HDiff')
195
+        last_rlen_index = column_names.index('Last_RLen')
196
+        new_id_index = column_names.index('New_ID')
197
+        new_spname_index = column_names.index('New_SPName')
198
+        new_epname_index = column_names.index('New_EPName')
199
+        new_hdiff_index = column_names.index('New_HDiff')
200
+        new_rlen_index = column_names.index('New_RLen')
201
+
202
+        # 填充数据到Excel
203
+        for idx, row in enumerate(rows, start=3):
204
+            ws.cell(row=idx, column=1, value=row[last_id_index])
205
+            ws.cell(row=idx, column=2, value=row[last_spname_index])
206
+            ws.cell(row=idx, column=3, value=row[last_epname_index])
207
+            ws.cell(row=idx, column=4, value=row[last_hdiff_index])
208
+            ws.cell(row=idx, column=5, value=row[last_rlen_index])
209
+            ws.cell(row=idx, column=6, value=row[new_id_index])
210
+            ws.cell(row=idx, column=7, value=row[new_spname_index])
211
+            ws.cell(row=idx, column=8, value=row[new_epname_index])
212
+            ws.cell(row=idx, column=9, value=row[new_hdiff_index])
213
+            ws.cell(row=idx, column=10, value=row[new_rlen_index])
214
+
215
+            # 设置 D, E, I, J 列为强制保留六位小数
216
+            ws.cell(row=idx, column=4).number_format = '0.000000'
217
+            ws.cell(row=idx, column=5).number_format = '0.000000'
218
+            ws.cell(row=idx, column=9).number_format = '0.000000'
219
+            ws.cell(row=idx, column=10).number_format = '0.000000'
220
+        # 设置B,C,G,H的列宽为9.25
221
+        ws.column_dimensions['B'].width = 9.25
222
+        ws.column_dimensions['C'].width = 9.25
223
+        ws.column_dimensions['G'].width = 9.25
224
+        ws.column_dimensions['H'].width = 9.25
225
+
226
+        # 设置 D, E, I, J 列的列宽为11.5
227
+        ws.column_dimensions['D'].width = 11.5
228
+        ws.column_dimensions['E'].width = 11.5
229
+        ws.column_dimensions['I'].width = 11.5
230
+        ws.column_dimensions['J'].width = 11.5
231
+        # 设置文件名
232
+        excel_filename = f"{os.path.splitext(decoded_utf_en)[0]}-初始数据.xlsx"
233
+        excel_filepath = os.path.join(export_folder, excel_filename)
234
+
235
+        # 保存 Excel 文件
236
+        wb.save(excel_filepath)
237
+
238
+        QMessageBox.information(ui, '成功', f'初始数据文件已成功导出到 {export_folder}')
239
+    except Exception as e:
240
+        QMessageBox.critical(ui, '错误', f'导出初始数据过程中发生错误: {str(e)}')
241
+
242
+
243
+def main_function(ui, utf_en, db_path):
244
+    # 获取应用的安装目录
245
+    app_install_dir = os.path.dirname(os.path.abspath(__file__))  # 假设脚本文件位于应用的安装目录下
246
+    export_folder = os.path.join(app_install_dir, 'Export')
247
+
248
+    # 如果 Export 文件夹不存在,则创建它
249
+    if not os.path.exists(export_folder):
250
+        os.makedirs(export_folder)
251
+
252
+    # 调用导出初始数据函数
253
+    export_initial_data(ui, utf_en, db_path, export_folder)
254
+    # 调用导出结果函数
255
+    export_result_data(ui, utf_en, db_path, export_folder)

+ 136
- 0
Front/main.py Просмотреть файл

@@ -15,6 +15,7 @@
15 15
 # ///////////////////////////////////////////////////////////////
16 16
 import time
17 17
 
18
+from PySide6.QtTest import QTest
18 19
 from PySide6.QtWidgets import QFileDialog, QWidget, QVBoxLayout, QTreeWidget, QApplication, QTreeWidgetItem
19 20
 from PySide6.QtCore import Signal, Qt, Slot, QObject
20 21
 from PySide6.QtSql import QSqlTableModel, QSqlDatabase
@@ -304,6 +305,7 @@ class ElTree(QWidget):
304 305
             main_window.refresh_tree()
305 306
 
306 307
 
308
+# 查询
307 309
 # 查询
308 310
 class ElTree1(QWidget):
309 311
     """
@@ -321,6 +323,11 @@ class ElTree1(QWidget):
321 323
             lambda item: self.itemDoubleClicked.emit(item.data(0, Qt.UserRole + 1)))
322 324
         self.__render_items(True)
323 325
 
326
+        # 设置 QTreeWidget 的 contextMenuPolicy 为 Qt.CustomContextMenu
327
+        widgets.qureyTreeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
328
+        # 连接 customContextMenuRequested 信号到 contextMenuEvent 方法
329
+        widgets.qureyTreeWidget.customContextMenuRequested.connect(self.contextMenuEvent)
330
+
324 331
     def __render_items(self, is_clear: bool):
325 332
         if is_clear:
326 333
             widgets.qureyTreeWidget.clear()
@@ -342,6 +349,135 @@ class ElTree1(QWidget):
342 349
             # 挂载到树上
343 350
             widgets.qureyTreeWidget.insertTopLevelItems(0, treeWidgetItems)
344 351
 
352
+    def contextMenuEvent(self, pos):
353
+        # 创建右键菜单
354
+        context_menu = QMenu(self)
355
+
356
+        # 添加删除选项
357
+        delete_action = QAction("删除", self)
358
+        delete_action.triggered.connect(self.delete_item)
359
+        context_menu.addAction(delete_action)
360
+
361
+        # 添加导出选项
362
+        export_action = QAction("导出", self)
363
+        export_action.triggered.connect(self.export_item)
364
+        context_menu.addAction(export_action)
365
+
366
+        context_menu.exec(widgets.qureyTreeWidget.mapToGlobal(pos))
367
+
368
+    def delete_item(self):
369
+        # 获取当前选中的项目
370
+        selected_items = widgets.qureyTreeWidget.selectedItems()
371
+        if not selected_items:
372
+            QMessageBox.warning(self, '警告', '请先选择一个项目')
373
+            return
374
+
375
+        item = selected_items[0]
376
+        data = item.data(0, Qt.UserRole + 1)
377
+        if not data:
378
+            self.warning = QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
379
+            return
380
+
381
+        # 获取数据库路径和表名
382
+        dbname = data['listData'][0]
383
+        tablename = data['listData'][2]
384
+        dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
385
+
386
+        # 确保 tablename 是 UTF-8 编码的字符串
387
+        try:
388
+            tablename_utf8 = tablename.encode('utf-8')
389
+        except Exception as e:
390
+            QMessageBox.critical(self, '错误', f'表名编码转换错误: {str(e)}')
391
+            return
392
+        # 获取父节点
393
+        parent_item = item.parent()
394
+        if not parent_item:
395
+            QMessageBox.warning(self, '警告', '所选项目没有父节点')
396
+            return
397
+
398
+        parent_name = parent_item.text(0)
399
+
400
+        # 确定要删除的表
401
+        tables_to_delete = []
402
+        if parent_name == '水准测段高差稳定计算':
403
+            tables_to_delete = ['GC_Input_Param', 'GC_Input_Point', 'GC_Output_Point']
404
+        elif parent_name == '控制网复测平面基准计算':
405
+            tables_to_delete = ['GS_Input_Param', 'GS_Input_Point', 'GS_Result_Point', 'GS_Trans_Param',
406
+                                'GS_Trans_Point']
407
+        elif parent_name == '平面控制网稳定性计算':
408
+            tables_to_delete = ['WD_Input_Param', 'WD_Input_Point', 'WD_Result_Param', 'WD_Result_Point']
409
+        else:
410
+            QMessageBox.warning(self, '警告', '未知的父节点')
411
+            return
412
+
413
+        # 确认删除操作
414
+        reply = QMessageBox.question(self, '确认删除', f'确定要删除项目表 {tablename} 吗?',
415
+                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
416
+        if reply == QMessageBox.No:
417
+            return
418
+
419
+        # 清空表
420
+        try:
421
+            conn = sqlite3.connect(dbpath)
422
+            cursor = conn.cursor()
423
+            for table in tables_to_delete:
424
+                cursor.execute(f"DELETE FROM {table} WHERE TableName = ?", (tablename_utf8,))
425
+            conn.commit()
426
+            conn.close()
427
+            QMessageBox.information(self, '成功', f'表 {tablename} 中的数据已从相关表中删除')
428
+
429
+            # 刷新树状图
430
+            self.refresh_tree()
431
+            # 模拟点击 Enter 键  实现程序自动刷新的效果
432
+            QTest.keyClick(widgets.qureyTreeWidget, Qt.Key_Return)
433
+        except Exception as e:
434
+            QMessageBox.critical(self, '错误', f'删除数据时出错: {str(e)}')
435
+
436
+    def export_item(self):
437
+        # 获取当前选中的项目
438
+        selected_items = widgets.qureyTreeWidget.selectedItems()
439
+        if not selected_items:
440
+            QMessageBox.warning(self, '警告', '请先选择一个项目')
441
+            return
442
+
443
+        item = selected_items[0]
444
+        data = item.data(0, Qt.UserRole + 1)
445
+        if not data:
446
+            QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
447
+            return
448
+
449
+        # 获取数据库路径和表名
450
+        dbname = data['listData'][0]
451
+        tablename = data['listData'][2]
452
+        tablename_utf8 = tablename.encode('utf-8')
453
+        dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
454
+
455
+        # 获取父节点
456
+        parent_item = item.parent()
457
+        if not parent_item:
458
+            QMessageBox.warning(self, '警告', '所选项目没有父节点')
459
+            return
460
+
461
+        parent_name = parent_item.text(0)
462
+
463
+        # 根据父节点名称确定导出操作
464
+        if parent_name == '水准测段高差稳定计算':
465
+            GCExport.main_function(self, tablename_utf8, dbpath)
466
+        elif parent_name == '控制网复测平面基准计算':
467
+            GSExport.main_function(self, dbpath, tablename)
468
+        elif parent_name == '平面控制网稳定性计算':
469
+            WDExport.main_function(self, dbpath, tablename)
470
+        else:
471
+            QMessageBox.warning(self, '警告', '未知的父节点')
472
+            return
473
+
474
+    def refresh_tree(self):
475
+        # 调用 MainWindow 的 refresh_tree 方法
476
+        main_window = QApplication.instance().activeWindow()
477
+        if isinstance(main_window, MainWindow):
478
+            main_window.refresh_tree()
479
+
480
+
345 481
 
346 482
 # class DatabaseChangeHandler(FileSystemEventHandler):
347 483
 #     def __init__(self, main_window):

Двоичные данные
SQL/1.db Просмотреть файл


Двоичные данные
SQL/测试.db Просмотреть файл


Загрузка…
Отмена
Сохранить