这次增加了测试结果导出到EXCEL、项目阶段需要安装定义的表格中的name PN来处理
This commit is contained in:
@@ -97,6 +97,7 @@ class DUTModel(QObject):
|
||||
"SN": row.get("SN", ""),
|
||||
"name": row.get("name", ""),
|
||||
"project": row.get("project", ""),
|
||||
"projectPhase": row.get("projectPhase", ""),
|
||||
"projectType": row.get("projectType", ""),
|
||||
"phase": row.get("phase", ""),
|
||||
"weeks": row.get("weeks", 0) if row.get("weeks") is not None else 0,
|
||||
@@ -141,7 +142,7 @@ class DUTModel(QObject):
|
||||
|
||||
# 查询 dutList 表中的所有 DUT
|
||||
cursor.execute("""
|
||||
SELECT SN, name, project, projectType, phase, weeks, stationAssigned,
|
||||
SELECT SN, name, project,projectPhase, projectType, phase, weeks, stationAssigned,
|
||||
itemOnGoing, itemsFinished, status, testReq, inspector, id,
|
||||
description, deadLine, createdate, workOrder, direction_codes
|
||||
FROM dutList
|
||||
@@ -174,6 +175,7 @@ class DUTModel(QObject):
|
||||
"SN": row[0] if row[0] else "",
|
||||
"name": row[1] if row[1] else "",
|
||||
"project": row[2] if row[2] else "",
|
||||
"projectPhase": row[3] if row[3] else "",
|
||||
"projectType": row[3] if row[3] else "",
|
||||
"phase": row[4] if row[4] else "",
|
||||
"weeks": row[5] if row[5] is not None else 0,
|
||||
|
||||
@@ -13,6 +13,14 @@ from PyQt5.QtWidgets import (
|
||||
QTextEdit, QPushButton, QLabel, QWidget
|
||||
)
|
||||
from PyQt5.QtCore import Qt
|
||||
import requests
|
||||
|
||||
# 尝试导入配置
|
||||
try:
|
||||
from config import USE_HTTP_API, HTTP_API_BASE_URL
|
||||
except ImportError:
|
||||
USE_HTTP_API = False
|
||||
HTTP_API_BASE_URL = "http://127.0.0.1:5050"
|
||||
|
||||
|
||||
class DUTFormDialog(QDialog):
|
||||
@@ -26,12 +34,20 @@ class DUTFormDialog(QDialog):
|
||||
self.setModal(True)
|
||||
self.resize(800, 480)
|
||||
|
||||
# HTTP API 配置
|
||||
self.use_http_api = USE_HTTP_API
|
||||
self.api_base_url = HTTP_API_BASE_URL
|
||||
|
||||
# 机台数据缓存
|
||||
self.machines = []
|
||||
self.current_machine = None
|
||||
|
||||
# 项目阶段数据缓存
|
||||
self.project_phases = [] # 存储从后端获取的项目阶段列表
|
||||
|
||||
self._build_ui()
|
||||
self._load_machines() # 加载机台数据
|
||||
self._load_project_phases() # 加载项目阶段数据
|
||||
self._fill_form(self.dut_form)
|
||||
self._apply_lock()
|
||||
|
||||
@@ -62,7 +78,7 @@ class DUTFormDialog(QDialog):
|
||||
self.input_testReq = QLineEdit()
|
||||
self.input_phase = QComboBox()
|
||||
self.input_phase.setEditable(True)
|
||||
self.input_phase.addItems(["A Sample", "B Sample", "C Sample", "Work Sample", "阶段1", "阶段2"]) # 示例项
|
||||
# 项目阶段选项将在 _load_project_phases() 中从后端加载
|
||||
|
||||
# 右列控件 - 设备分配(二级选择)
|
||||
self.input_dtMachine = QComboBox() # 机台选择
|
||||
@@ -143,6 +159,58 @@ class DUTFormDialog(QDialog):
|
||||
except Exception as e:
|
||||
print(f"加载机台数据失败: {e}")
|
||||
|
||||
def _load_project_phases(self):
|
||||
"""从后端加载项目阶段数据"""
|
||||
try:
|
||||
# 尝试使用 HTTP API
|
||||
if self.use_http_api:
|
||||
try:
|
||||
url = f"{self.api_base_url}/dbTableAccess"
|
||||
response = requests.get(
|
||||
url,
|
||||
params={"table": "projectPhase"},
|
||||
timeout=5
|
||||
)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
data = result.get("data", [])
|
||||
|
||||
if data:
|
||||
self.project_phases = data
|
||||
print(f"从 HTTP API 加载了 {len(data)} 个项目阶段")
|
||||
else:
|
||||
print("后端返回的项目阶段数据为空")
|
||||
self.project_phases = []
|
||||
|
||||
except Exception as e:
|
||||
print(f"HTTP API 加载项目阶段失败: {e},回退到 SystemModel")
|
||||
# 回退到使用 SystemModel
|
||||
if self.system_model:
|
||||
self.project_phases = self.system_model.load_project_phases()
|
||||
else:
|
||||
self.project_phases = []
|
||||
else:
|
||||
# 直接使用 SystemModel
|
||||
if self.system_model:
|
||||
self.project_phases = self.system_model.load_project_phases()
|
||||
else:
|
||||
self.project_phases = []
|
||||
|
||||
# 填充下拉框:显示 name,存储 PN 作为 itemData
|
||||
self.input_phase.clear()
|
||||
for phase in self.project_phases:
|
||||
name = phase.get("name", "")
|
||||
pn = phase.get("PN", "")
|
||||
if name: # 只添加有名称的项
|
||||
self.input_phase.addItem(name, pn) # 显示 name,数据存储 PN
|
||||
|
||||
print(f"项目阶段下拉框已填充 {self.input_phase.count()} 个选项")
|
||||
|
||||
except Exception as e:
|
||||
print(f"加载项目阶段数据失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def _on_machine_changed(self, index):
|
||||
"""机台选择变化时更新通道列表"""
|
||||
self.input_station.clear()
|
||||
@@ -181,13 +249,22 @@ class DUTFormDialog(QDialog):
|
||||
self.input_SN.setText(str(f.get("SN", "")))
|
||||
self.input_project.setText(str(f.get("project", "")))
|
||||
self.input_testReq.setText(str(f.get("testReq", "")))
|
||||
phase_val = str(f.get("phase", ""))
|
||||
if phase_val:
|
||||
idx = self.input_phase.findText(phase_val)
|
||||
if idx >= 0:
|
||||
self.input_phase.setCurrentIndex(idx)
|
||||
else:
|
||||
self.input_phase.setEditText(phase_val)
|
||||
|
||||
# 项目阶段:f.get("phase") 存储的是 PN 值,需要匹配 itemData
|
||||
phase_pn = str(f.get("phase", ""))
|
||||
if phase_pn:
|
||||
# 查找匹配的 PN
|
||||
found = False
|
||||
for i in range(self.input_phase.count()):
|
||||
item_pn = self.input_phase.itemData(i)
|
||||
if item_pn == phase_pn:
|
||||
self.input_phase.setCurrentIndex(i)
|
||||
found = True
|
||||
break
|
||||
|
||||
# 如果没有找到匹配项,使用可编辑功能填充
|
||||
if not found:
|
||||
self.input_phase.setEditText(phase_pn)
|
||||
|
||||
# 设备分配:使用 Model 解析后的 dtMachine 和 station 字段
|
||||
dtm = f.get("dtMachine", "").strip()
|
||||
@@ -224,11 +301,16 @@ class DUTFormDialog(QDialog):
|
||||
|
||||
def get_form_dict(self):
|
||||
# 以 dut_form 的结构返回数据
|
||||
# 项目阶段:优先获取 itemData(PN值),如果没有则使用用户输入的文本
|
||||
phase_pn = self.input_phase.currentData() # 获取当前选中项的 PN
|
||||
if phase_pn is None: # 如果是用户手动输入的文本
|
||||
phase_pn = self.input_phase.currentText().strip()
|
||||
|
||||
dut_form = {
|
||||
"SN": self.input_SN.text().strip(),
|
||||
"project": self.input_project.text().strip(),
|
||||
"testReq": self.input_testReq.text().strip(),
|
||||
"phase": self.input_phase.currentText().strip(),
|
||||
"phase": phase_pn, # 存储 PN 值
|
||||
"weeks": int(self.input_weeks.text() or 0),
|
||||
"workOrder": self.input_workOrder.text().strip(),
|
||||
"inspector": self.input_inspector.text().strip(),
|
||||
|
||||
@@ -75,7 +75,7 @@ class LoginDialog(QDialog):
|
||||
title_label = QLabel("跌落试验管理系统")
|
||||
title_label.setAlignment(Qt.AlignCenter)
|
||||
title_font = QFont()
|
||||
title_font.setPointSize(18)
|
||||
title_font.setPointSize(16)
|
||||
title_font.setBold(True)
|
||||
title_label.setFont(title_font)
|
||||
title_label.setStyleSheet("color: #333; margin-bottom: 20px;")
|
||||
@@ -92,7 +92,7 @@ class LoginDialog(QDialog):
|
||||
self.username_combo = QComboBox()
|
||||
self.username_combo.setEditable(True)
|
||||
self.username_combo.addItems(['test', 'admin', 'topAdmin123'])
|
||||
self.username_combo.setCurrentText('') # 默认为空
|
||||
self.username_combo.setCurrentText('test') # 默认test
|
||||
|
||||
# 保存箭头图标以便在样式表中引用
|
||||
arrow_path = "e:/WORK/DTM-PY-ALL/UI/temp_arrow.png"
|
||||
|
||||
@@ -302,7 +302,7 @@ class TestPlanView(QWidget):
|
||||
self.table.setItem(idx, 0, QTableWidgetItem(str(plan.get('index', idx+1))))
|
||||
self.table.setItem(idx, 1, QTableWidgetItem(plan.get('SN', '')))
|
||||
self.table.setItem(idx, 2, QTableWidgetItem(plan.get('project', '')))
|
||||
self.table.setItem(idx, 3, QTableWidgetItem(plan.get('phase', '')))
|
||||
self.table.setItem(idx, 3, QTableWidgetItem(plan.get('projectPhase', '')))
|
||||
self.table.setItem(idx, 4, QTableWidgetItem(plan.get('testReq', '')))
|
||||
self.table.setItem(idx, 5, QTableWidgetItem(str(plan.get('weeks', ''))))
|
||||
# 测试设备(带颜色)
|
||||
|
||||
@@ -7,10 +7,15 @@
|
||||
|
||||
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QPushButton, QTableWidget, QTableWidgetItem,
|
||||
QHeaderView, QLineEdit, QComboBox, QDateTimeEdit, QMessageBox, QGridLayout)
|
||||
QHeaderView, QLineEdit, QComboBox, QDateTimeEdit, QMessageBox, QGridLayout,
|
||||
QFileDialog, QProgressDialog, QApplication)
|
||||
from PyQt5.QtCore import Qt, QDateTime, QSize
|
||||
import requests
|
||||
from config import HTTP_API_BASE_URL
|
||||
import datetime
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
|
||||
class TestResultView(QWidget):
|
||||
@@ -235,10 +240,61 @@ class TestResultView(QWidget):
|
||||
self.page_size_combo.currentTextChanged.connect(self.on_page_size_changed)
|
||||
pager_layout.addWidget(self.page_size_combo)
|
||||
|
||||
# 上一页按钮
|
||||
self.prev_btn = QPushButton("上一页")
|
||||
self.prev_btn.clicked.connect(self.go_prev_page)
|
||||
pager_layout.addWidget(self.prev_btn)
|
||||
|
||||
# 页码跳转
|
||||
goto_label = QLabel("跳转至")
|
||||
pager_layout.addWidget(goto_label)
|
||||
|
||||
self.page_input = QLineEdit()
|
||||
self.page_input.setFixedWidth(60)
|
||||
self.page_input.setPlaceholderText("页码")
|
||||
self.page_input.setAlignment(Qt.AlignCenter)
|
||||
self.page_input.setStyleSheet("""
|
||||
QLineEdit {
|
||||
padding: 4px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
QLineEdit:focus {
|
||||
border: 1px solid #3A84FF;
|
||||
}
|
||||
""")
|
||||
# 按回车键跳转
|
||||
self.page_input.returnPressed.connect(self.go_to_page)
|
||||
pager_layout.addWidget(self.page_input)
|
||||
|
||||
goto_page_label = QLabel("页")
|
||||
pager_layout.addWidget(goto_page_label)
|
||||
|
||||
# 跳转按钮
|
||||
self.goto_btn = QPushButton("跳转")
|
||||
self.goto_btn.setFixedWidth(60)
|
||||
self.goto_btn.clicked.connect(self.go_to_page)
|
||||
self.goto_btn.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #3A84FF;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #2B6FE6;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #1F5BD1;
|
||||
}
|
||||
QPushButton:disabled {
|
||||
background-color: #cccccc;
|
||||
}
|
||||
""")
|
||||
pager_layout.addWidget(self.goto_btn)
|
||||
|
||||
# 下一页按钮
|
||||
self.next_btn = QPushButton("下一页")
|
||||
self.next_btn.clicked.connect(self.go_next_page)
|
||||
pager_layout.addWidget(self.next_btn)
|
||||
@@ -444,7 +500,261 @@ class TestResultView(QWidget):
|
||||
if self.current_page < total_pages:
|
||||
self.current_page += 1
|
||||
self.load_data()
|
||||
|
||||
def go_to_page(self):
|
||||
"""跳转到指定页码"""
|
||||
try:
|
||||
# 获取输入的页码
|
||||
page_text = self.page_input.text().strip()
|
||||
|
||||
if not page_text:
|
||||
QMessageBox.warning(self, "提示", "请输入页码")
|
||||
return
|
||||
|
||||
# 尝试转换为整数
|
||||
try:
|
||||
target_page = int(page_text)
|
||||
except ValueError:
|
||||
QMessageBox.warning(self, "错误", "页码必须是整数")
|
||||
self.page_input.clear()
|
||||
return
|
||||
|
||||
# 计算总页数
|
||||
total_pages = max(1, (self.total_count + self.page_size - 1) // self.page_size)
|
||||
|
||||
# 检查页码有效性
|
||||
if target_page < 1:
|
||||
QMessageBox.warning(self, "错误", f"页码不能小于 1")
|
||||
self.page_input.clear()
|
||||
return
|
||||
|
||||
if target_page > total_pages:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"错误",
|
||||
f"页码不能大于总页数 {total_pages}"
|
||||
)
|
||||
self.page_input.clear()
|
||||
return
|
||||
|
||||
# 如果已经在当前页,不需要重复加载
|
||||
if target_page == self.current_page:
|
||||
QMessageBox.information(self, "提示", f"当前已在第 {target_page} 页")
|
||||
self.page_input.clear()
|
||||
return
|
||||
|
||||
# 跳转到目标页
|
||||
self.current_page = target_page
|
||||
self.page_input.clear()
|
||||
self.load_data()
|
||||
|
||||
except Exception as e:
|
||||
print(f"页码跳转失败: {e}")
|
||||
QMessageBox.critical(self, "错误", f"跳转失败:{str(e)}")
|
||||
self.page_input.clear()
|
||||
|
||||
def on_export(self):
|
||||
"""导出结果"""
|
||||
QMessageBox.information(self, "导出", "导出功能开发中...")
|
||||
"""导出结果到Excel"""
|
||||
try:
|
||||
# 获取满足筛选条件的总数
|
||||
total_count = self.total_count
|
||||
if total_count == 0:
|
||||
QMessageBox.information(self, "提示", "没有数据可以导出")
|
||||
return
|
||||
|
||||
# 生成默认文件名:testResult+日期
|
||||
default_filename = f"testResult_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
|
||||
# 显示另存为对话框
|
||||
file_path, _ = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"导出测试结果",
|
||||
default_filename,
|
||||
"Excel Files (*.xlsx);;All Files (*)"
|
||||
)
|
||||
|
||||
if not file_path:
|
||||
return # 用户取消
|
||||
|
||||
# 确保文件后缀名
|
||||
if not file_path.endswith('.xlsx'):
|
||||
file_path += '.xlsx'
|
||||
|
||||
# 显示进度对话框
|
||||
progress = QProgressDialog("正在导出数据...", "取消", 0, 100, self)
|
||||
progress.setWindowModality(Qt.WindowModal)
|
||||
progress.setWindowTitle("导出进度")
|
||||
progress.setMinimumDuration(0)
|
||||
progress.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 分批获取策略:每次最多获取500条数据
|
||||
batch_size = 500
|
||||
total_batches = (total_count + batch_size - 1) // batch_size
|
||||
|
||||
# 创建Excel工作簿
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "测试结果"
|
||||
|
||||
# 设置表头
|
||||
headers = [
|
||||
"序号", "样品编号", "项目代码", "项目阶段", "项目方案", "测试周次",
|
||||
"工单名称", "产品序列号", "测试设备", "测试通道", "跌落方向",
|
||||
"跌落高度(mm)", "跌落速度(次/Min)", "样品跌落次数", "方向当前次数",
|
||||
"木板累计跌落次数", "试验开始时间", "试验结束时间"
|
||||
]
|
||||
ws.append(headers)
|
||||
|
||||
# 设置表头样式
|
||||
header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
|
||||
header_font = Font(bold=True, color="FFFFFF", size=11)
|
||||
header_alignment = Alignment(horizontal="center", vertical="center")
|
||||
|
||||
for col_num, header in enumerate(headers, 1):
|
||||
cell = ws.cell(row=1, column=col_num)
|
||||
cell.fill = header_fill
|
||||
cell.font = header_font
|
||||
cell.alignment = header_alignment
|
||||
|
||||
# 分批获取并写入数据
|
||||
all_data = []
|
||||
for batch_num in range(total_batches):
|
||||
if progress.wasCanceled():
|
||||
QMessageBox.information(self, "提示", "导出已取消")
|
||||
return
|
||||
|
||||
# 更新进度
|
||||
progress_value = int((batch_num / total_batches) * 80) # 0-80%用于数据获取
|
||||
progress.setValue(progress_value)
|
||||
progress.setLabelText(f"正在获取数据... ({batch_num + 1}/{total_batches})")
|
||||
QApplication.processEvents()
|
||||
|
||||
# 获取当前批次数据
|
||||
batch_data = self._fetch_batch_data(batch_num + 1, batch_size)
|
||||
if batch_data:
|
||||
all_data.extend(batch_data)
|
||||
|
||||
# 应用前端筛选(测试人员)
|
||||
progress.setValue(85)
|
||||
progress.setLabelText("正在筛选数据...")
|
||||
QApplication.processEvents()
|
||||
|
||||
filtered_data = self._filter_data_by_inspector(all_data)
|
||||
|
||||
# 写入数据到Excel
|
||||
progress.setValue(90)
|
||||
progress.setLabelText(f"正在写入Excel... 共{len(filtered_data)}条数据")
|
||||
QApplication.processEvents()
|
||||
|
||||
for idx, item in enumerate(filtered_data):
|
||||
row_data = [
|
||||
self._format_cell_value(item.get('mysequence', idx + 1)),
|
||||
self._format_cell_value(item.get('SN')),
|
||||
self._format_cell_value(item.get('dutProject')),
|
||||
self._format_cell_value(item.get('dutPhase')),
|
||||
self._format_cell_value(item.get('dutProjectType')),
|
||||
self._format_cell_value(item.get('dutWeeks')),
|
||||
self._format_cell_value(item.get('dutWorkOrder')),
|
||||
self._format_cell_value(item.get('SN')),
|
||||
self._format_cell_value(item.get('machine_sn')),
|
||||
self._format_cell_value(item.get('station_no')),
|
||||
self._format_cell_value(item.get('dropDirection')),
|
||||
self._format_cell_value(item.get('dropHeight_int')),
|
||||
self._format_cell_value(item.get('dropSpeed')),
|
||||
self._format_cell_value(item.get('dropCycles')),
|
||||
self._format_cell_value(item.get('itemCurrentCycles')),
|
||||
self._format_cell_value(item.get('stationDropCycles')),
|
||||
self._format_cell_value(item.get('startTime')),
|
||||
self._format_cell_value(item.get('endTime'))
|
||||
]
|
||||
ws.append(row_data)
|
||||
|
||||
# 每100行更新一次进度
|
||||
if (idx + 1) % 100 == 0:
|
||||
progress_value = 90 + int((idx + 1) / len(filtered_data) * 8) # 90-98%
|
||||
progress.setValue(progress_value)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 设置列宽
|
||||
for col_num in range(1, len(headers) + 1):
|
||||
column_letter = get_column_letter(col_num)
|
||||
ws.column_dimensions[column_letter].width = 15
|
||||
|
||||
# 保存文件
|
||||
progress.setValue(99)
|
||||
progress.setLabelText("正在保存文件...")
|
||||
QApplication.processEvents()
|
||||
|
||||
wb.save(file_path)
|
||||
|
||||
progress.setValue(100)
|
||||
progress.close()
|
||||
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"成功",
|
||||
f"导出成功!\n共导出 {len(filtered_data)} 条数据\n文件保存在:{file_path}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(f"导出失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
QMessageBox.critical(self, "错误", f"导出失败:{str(e)}")
|
||||
|
||||
def _fetch_batch_data(self, page, page_size):
|
||||
"""获取指定页的数据"""
|
||||
try:
|
||||
url = f"{self.api_base_url}/dbTableAccess"
|
||||
|
||||
# 构建请求参数(与当前筛选条件一致)
|
||||
params = {
|
||||
'table': 'testReqResult',
|
||||
'pageSize': page_size,
|
||||
'currentPage': page,
|
||||
}
|
||||
|
||||
# 添加时间筛选
|
||||
start_dt = self.start_datetime_edit.dateTime().toString("yyyy/MM/dd HH:mm:ss")
|
||||
end_dt = self.end_datetime_edit.dateTime().toString("yyyy/MM/dd HH:mm:ss")
|
||||
params['date1'] = start_dt
|
||||
params['date2'] = end_dt
|
||||
|
||||
# 添加样品编号筛选
|
||||
sn_filter = self.sn_input.text().strip()
|
||||
if sn_filter:
|
||||
params['SN'] = sn_filter
|
||||
|
||||
# 添加工单筛选
|
||||
workorder_filter = self.workorder_input.text().strip()
|
||||
if workorder_filter:
|
||||
params['dutWorkOrder'] = workorder_filter
|
||||
|
||||
# 调用后端API
|
||||
response = requests.get(url, params=params, timeout=30)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
if 'data' in result:
|
||||
return result['data']
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取第{page}页数据失败: {e}")
|
||||
return []
|
||||
|
||||
def _filter_data_by_inspector(self, data):
|
||||
"""根据测试人员筛选数据(前端筛选)"""
|
||||
inspector_filter = self.inspector_input.text().strip().lower()
|
||||
|
||||
if not inspector_filter:
|
||||
return data
|
||||
|
||||
filtered = []
|
||||
for item in data:
|
||||
inspector = str(item.get('tester', '')).lower()
|
||||
if inspector_filter in inspector:
|
||||
filtered.append(item)
|
||||
|
||||
return filtered
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -127,6 +127,17 @@ a = Analysis(
|
||||
'tkinter.constants',
|
||||
'tkinter.filedialog',
|
||||
|
||||
# openpyxl 相关(Excel导出功能)
|
||||
'openpyxl',
|
||||
'openpyxl.styles',
|
||||
'openpyxl.utils',
|
||||
'openpyxl.cell',
|
||||
'openpyxl.worksheet',
|
||||
'openpyxl.workbook',
|
||||
'openpyxl.reader',
|
||||
'openpyxl.writer',
|
||||
'et_xmlfile',
|
||||
|
||||
# 其他依赖
|
||||
'websockets',
|
||||
'serial',
|
||||
|
||||
@@ -127,6 +127,17 @@ a = Analysis(
|
||||
'tkinter.constants',
|
||||
'tkinter.filedialog',
|
||||
|
||||
# openpyxl 相关(Excel导出功能)
|
||||
'openpyxl',
|
||||
'openpyxl.styles',
|
||||
'openpyxl.utils',
|
||||
'openpyxl.cell',
|
||||
'openpyxl.worksheet',
|
||||
'openpyxl.workbook',
|
||||
'openpyxl.reader',
|
||||
'openpyxl.writer',
|
||||
'et_xmlfile',
|
||||
|
||||
# 其他依赖
|
||||
'websockets',
|
||||
'serial',
|
||||
|
||||
@@ -10,4 +10,5 @@ gevent~=23.9.1
|
||||
websockets~=12.0
|
||||
pyinstaller==6.3.0
|
||||
setuptools==65.5.1
|
||||
pywebview==5.3.2
|
||||
pywebview==5.3.2
|
||||
openpyxl~=3.1.0
|
||||
Reference in New Issue
Block a user