v0.0.5(2024/05/23)
1. 完善了函数注释
2. 调整了阈值和步长
3. 删除了just_open函数,以及对应的win32com库(Thank GOD!终于可以不用这个库了)
4. 重写了获取开始点位的代码,直接使用speed来判断,而不用角度,所以find_row_start_dp以及copy_data_to_excel_file函数也被一并删除
This commit is contained in:
gitea 2024-05-23 13:59:06 +08:00
parent de6d1d47c8
commit 44ef429d5a
3 changed files with 66 additions and 109 deletions

View File

@ -2,25 +2,15 @@
import os import os
import sys import sys
import openpyxl import openpyxl
from win32com.client import DispatchEx
import time import time
from threading import Thread from threading import Thread
import pythoncom
import pandas import pandas
def just_open(filename):
pythoncom.CoInitialize()
xlapp = DispatchEx("Excel.Application")
xlapp.Visible = False
xlbook = xlapp.Workbooks.Open(filename)
xlapp.DisplayAlerts = 0
xlbook.SaveAs(filename)
xlbook.Close()
xlapp.Quit()
def traversal_files(path): def traversal_files(path):
# 功能:以列表的形式分别返回指定路径下的文件和文件夹,不包含子目录
# 参数:路径
# 返回值:路径下的文件夹列表 路径下的文件列表
if not os.path.exists(path): if not os.path.exists(path):
msg = f'数据文件夹{path}不存在,请确认后重试......' msg = f'数据文件夹{path}不存在,请确认后重试......'
warn_pause_exit(msg, 1, 11) warn_pause_exit(msg, 1, 11)
@ -37,55 +27,57 @@ def traversal_files(path):
def get_threshold_step(excel_file, AXIS): def get_threshold_step(excel_file, AXIS):
# 功能负载和速度100%且是j2的时候做特殊处理
# 参数新生成的excel轴号
# 返回值:速度差阈值,处理步长
conditions = sorted(excel_file.split('\\')[-2].split('_')) conditions = sorted(excel_file.split('\\')[-2].split('_'))
# 只有负载和速度是100%时才会启用更敏感的step # 只有负载和速度是100%时才会启用更敏感的step
flg = 1 if conditions[0][-3:] == '100' and conditions[2][-3:] == '100' else 0 flg = 1 if conditions[0][-3:] == '100' and conditions[2][-3:] == '100' else 0
if flg == 1 and AXIS == 'j2': if flg == 1 and AXIS == 'j2':
threshold = 50 threshold = 30
step = 20 step = 5
else: else:
threshold = 50 threshold = 10
step = 100 step = 5
return threshold, step return threshold, step
def find_row_start(excel_file, ws_data, conditions, AV, RR, AXIS): def find_row_start(excel_file, ws_data, conditions, AV, RR, AXIS):
# 功能:查找数据文件中有效数据的行号,也即最后一个速度下降的点位
# 参数:如上
# 返回值:速度下降点位,最后的数据点位
ratio = float(conditions[1].removeprefix('speed'))/100 ratio = float(conditions[1].removeprefix('speed'))/100
speed_max = AV * ratio * RR / 6 speed_max = AV * ratio * RR / 6
row_max = row_start = ws_data.max_row
row_max = ws_data.max_row
row_start = row_max - 1000
threshold, step = get_threshold_step(excel_file, AXIS) threshold, step = get_threshold_step(excel_file, AXIS)
while row_start > 0: while row_start > step+1:
speed = ws_data[f"A{row_start}"].value speed = ws_data[f"A{row_start}"].value
if speed is None or int(speed) < 1: if speed is None or int(speed) < 1:
row_start -= step row_start -= 50
continue continue
_ = []
row_end = row_start - step for i in range(row_start, row_start-step+1, -1):
if row_end < 2: _.append(ws_data[f"A{i}"].value)
msg = f"可能是{excel_file.replace('xlsx', 'data')}, 这个文件数据采集有问题,也有可能是程序步长设定问题......" \ speed_avg = abs(sum(_))/len(_)
f"建议重新采集,或者先删除该文件夹,重新运行程序,先手动处理" if abs(speed_avg-speed_max) < threshold:
warn_pause_exit(msg, 1, 10) row_start = row_start - 10
_a = ws_data[f"A{row_start}"].value
_b = ws_data[f"A{row_end}"].value
if abs(_a-speed_max) < threshold and abs(_b-speed_max) < threshold and abs(_a-_b) < threshold:
row_start -= (step + 200)
break break
else: else:
row_start -= step row_start -= step
else: else:
os.remove(excel_file) os.remove(excel_file)
msg = f"可能是{excel_file.replace('xlsx', 'data')},这个文件数据采集有问题,比如采集的时机不对,请检查......" msg = f"可能是{excel_file.replace('xlsx', 'data')},这个文件数据采集有问题,比如采集的时机不对,也有可能是程序步长设定问题,请检查......"
warn_pause_exit(msg, 1, 9) warn_pause_exit(msg, 1, 9)
return row_max, row_start return row_max, row_start
def find_result_sheet_name(conditions, count): def find_result_sheet_name(conditions, count):
# 该函数比较简单功能是获取结果文件准确的sheet页名称 # 功能获取结果文件准确的sheet页名称
# 参数:臂展和速度的列表
# 返回值结果文件对应的sheet name
# 33%臂展_33%速度_正1 # 33%臂展_33%速度_正1
reach = conditions[0].removeprefix('reach') reach = conditions[0].removeprefix('reach')
speed = conditions[1].removeprefix('speed') speed = conditions[1].removeprefix('speed')
@ -95,12 +87,17 @@ def find_result_sheet_name(conditions, count):
def copy_data_to_result(ws_data, ws_result, row_max, row_start): def copy_data_to_result(ws_data, ws_result, row_max, row_start):
# 功能:将数据文件中有效数据拷贝至结果文件对应的 sheet
# 参数:如上
# 返回值:-
# 结果文件数据清零 # 结果文件数据清零
for row in ws_result.iter_rows(min_row=2, min_col=1, max_row=6000 - row_start + 2, max_col=2): for row in ws_result.iter_rows(min_row=2, min_col=1, max_row=2000, max_col=2):
for cell in row: for cell in row:
cell.value = None cell.value = None
# 将合适的数据复制到结果文件 # 将合适的数据复制到结果文件
row_max = row_start + 399 if row_max-row_start > 400 else row_max
data = [] data = []
for row in ws_data.iter_rows(min_row=row_start, min_col=1, max_row=row_max, max_col=2): for row in ws_data.iter_rows(min_row=row_start, min_col=1, max_row=row_max, max_col=2):
for cell in row: for cell in row:
@ -112,74 +109,16 @@ def copy_data_to_result(ws_data, ws_result, row_max, row_start):
i = i + 1 i = i + 1
def copy_data_to_excel_file(wb_data, ws_result, row_max, row_start, excel_file, RC, RR):
try:
del wb_data['dp']
wb_data.create_sheet('dp')
ws_dp = wb_data['dp']
except Exception as Err:
wb_data.create_sheet('dp')
ws_dp = wb_data['dp']
data = []
for row in ws_result.iter_rows(min_row=1, min_col=1, max_row=row_max-row_start+2, max_col=5):
for cell in row:
data.append(cell.value)
i = 0
for row in ws_dp.iter_rows(min_row=1, min_col=1, max_row=row_max-row_start+2, max_col=5):
for cell in row:
cell.value = data[i]
i = i + 1
ws_dp.cell(row=5, column=7).value = RC
ws_dp.cell(row=6, column=7).value = RR
wb_data.save(excel_file)
wb_data.close()
just_open(excel_file) # 为了能读取到公式计算的数值,必须要用 win32com 打开关闭一次
wb_data = openpyxl.load_workbook(excel_file, data_only=True)
ws_dp = wb_data['dp']
return wb_data, ws_dp
def find_row_start_dp(data_file, ws_dp, row_max, row_start, conditions, AV):
ratio = float(conditions[1].removeprefix('speed'))/100
av_max = AV * ratio
row_max_dp = row_max - row_start + 1 + 1 # title row
row_start_dp = row_max_dp - 5
while row_start_dp > 6:
# 处理异常数据当从数据文件中拷贝的有效数据超过5000时会触发下面代码块
angular = ws_dp.cell(row=row_start_dp, column=4).value
if angular is None or str(angular) == '0':
row_start_dp -= 50
continue
_a = float(ws_dp.cell(row=row_start_dp, column=4).value)
_b = float(ws_dp.cell(row=row_start_dp - 1, column=4).value)
_c = float(ws_dp.cell(row=row_start_dp - 2, column=4).value)
_d = float(ws_dp.cell(row=row_start_dp - 3, column=4).value)
_e = float(ws_dp.cell(row=row_start_dp - 4, column=4).value)
avg = (_a + _b + _c + _d + _e) / 5
if abs(avg - av_max) < 1:
row_start_dp = row_start_dp + 10 - 5 # +10 是因为结果文件 C2 的值是 10-5是做了保守处理相当于再往前移动 5 个点位
break
else:
row_start_dp -= 5 # 保守一点,每次移动 5 个点位,如果想要加快程序运行,可适当调整更大一些,建议不超过 15
else:
msg = "数据有误,未找到平衡的点,请确认!"
warn_pause_exit(msg, 1, 1)
return row_start_dp
def single_file_process(data_file, wb_result, count, AV, RR, RC, AXIS): def single_file_process(data_file, wb_result, count, AV, RR, RC, AXIS):
# 功能:完成单个数据文件的处理
# 参数:如上
# 返回值:-
excel_file = data_file.replace('.data', '.xlsx') excel_file = data_file.replace('.data', '.xlsx')
sheet_name = data_file.split('\\')[-1].removesuffix('.data') sheet_name = data_file.split('\\')[-1].removesuffix('.data')
df = pandas.read_csv(data_file, sep='\t') df = pandas.read_csv(data_file, sep='\t')
df.to_excel(excel_file, sheet_name=sheet_name, index=False) df.to_excel(excel_file, sheet_name=sheet_name, index=False)
conditions = sorted(data_file.split('\\')[-2].split('_')[1:]) conditions = sorted(data_file.split('\\')[-2].split('_')[1:])
# print(f"conditions = {conditions}")
result_sheet_name = find_result_sheet_name(conditions, count) result_sheet_name = find_result_sheet_name(conditions, count)
ws_result = wb_result[result_sheet_name] ws_result = wb_result[result_sheet_name]
@ -188,16 +127,17 @@ def single_file_process(data_file, wb_result, count, AV, RR, RC, AXIS):
row_max, row_start = find_row_start(excel_file, ws_data, conditions, AV, RR, AXIS) row_max, row_start = find_row_start(excel_file, ws_data, conditions, AV, RR, AXIS)
copy_data_to_result(ws_data, ws_result, row_max, row_start) copy_data_to_result(ws_data, ws_result, row_max, row_start)
wb_data, ws_dp = copy_data_to_excel_file(wb_data, ws_result, row_max, row_start, excel_file, RC, RR) ws_result["C2"] = int(2)
row_start_dp = find_row_start_dp(data_file, ws_dp, row_max, row_start, conditions, AV) ws_result["G2"] = int(10+4)
ws_result["G2"] = int(row_start_dp)
wb_data.save(excel_file) wb_data.save(excel_file)
wb_data.close() wb_data.close()
def now_doing_msg(docs, flag): def now_doing_msg(docs, flag):
# 功能:输出正在处理的文件或目录
# 参数文件或目录start 或 done 标识
# 返回值:-
now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
file_type = 'file' if os.path.isfile(docs) else 'dir' file_type = 'file' if os.path.isfile(docs) else 'dir'
if flag == 'start' and file_type == 'dir': if flag == 'start' and file_type == 'dir':
@ -211,6 +151,9 @@ def now_doing_msg(docs, flag):
def data_process(result_file, raw_data_dirs, AV, RR, RC, AXIS): def data_process(result_file, raw_data_dirs, AV, RR, RC, AXIS):
# 功能:完成一个结果文件的数据处理
# 参数:结果文件,数据目录,以及预读取的参数
# 返回值:-
prefix = result_file.split('\\')[-1].split('_')[0] prefix = result_file.split('\\')[-1].split('_')[0]
wb_result = openpyxl.load_workbook(result_file) # 打开和关闭结果文件夹十分耗时间 wb_result = openpyxl.load_workbook(result_file) # 打开和关闭结果文件夹十分耗时间
for raw_data_dir in raw_data_dirs: for raw_data_dir in raw_data_dirs:
@ -220,12 +163,11 @@ def data_process(result_file, raw_data_dirs, AV, RR, RC, AXIS):
# 数据文件串行处理模式--------------------------------- # 数据文件串行处理模式---------------------------------
# count = 1 # count = 1
# for data_file in data_files: # for data_file in data_files:
# now_doing_msg(data_file, 'start') # now_doing_msg(data_file, 'start')
# single_file_process(data_file, wb_result, count, AV, RR, RC, AXIS) # single_file_process(data_file, wb_result, count, AV, RR, RC, AXIS)
# count += 1 # count += 1
# now_doing_msg(data_file, 'done') # now_doing_msg(data_file, 'done')
# --------------------------------------------------- # ---------------------------------------------------
# 数据文件并行处理模式--------------------------------- # 数据文件并行处理模式---------------------------------
threads = [Thread(target=single_file_process, args=(data_files[0], wb_result, 1, AV, RR, RC, AXIS)), threads = [Thread(target=single_file_process, args=(data_files[0], wb_result, 1, AV, RR, RC, AXIS)),
Thread(target=single_file_process, args=(data_files[1], wb_result, 2, AV, RR, RC, AXIS)), Thread(target=single_file_process, args=(data_files[1], wb_result, 2, AV, RR, RC, AXIS)),
@ -242,6 +184,9 @@ def data_process(result_file, raw_data_dirs, AV, RR, RC, AXIS):
def warn_pause_exit(msg, pause_num, exit_num): def warn_pause_exit(msg, pause_num, exit_num):
# 功能:打印告警信息,并推出程序
# 参数:告警信息,暂停的次数,退出的值
# 返回值:-
print(msg + '\n') print(msg + '\n')
for i in range(pause_num): for i in range(pause_num):
_ = input("Press ENTER to continue......\n") _ = input("Press ENTER to continue......\n")
@ -249,6 +194,9 @@ def warn_pause_exit(msg, pause_num, exit_num):
def check_files(raw_data_dirs, result_files): def check_files(raw_data_dirs, result_files):
# 功能:检查数据文件以及结果文件的合规性
# 参数:数据文件夹,结果文件
# 返回值:-
if len(result_files) != 3: if len(result_files) != 3:
msg = "结果文件数目错误,结果文件有且只有三个,请确认!" msg = "结果文件数目错误,结果文件有且只有三个,请确认!"
for result_file in result_files: for result_file in result_files:
@ -299,6 +247,9 @@ def check_files(raw_data_dirs, result_files):
def delete_excel_files(raw_data_dirs): def delete_excel_files(raw_data_dirs):
# 功能:删除数据文件夹里的 .xlsx 文件
# 参数:数据文件夹
# 返回值:-
for raw_data_dir in raw_data_dirs: for raw_data_dir in raw_data_dirs:
_, raw_data_files = traversal_files(raw_data_dir) _, raw_data_files = traversal_files(raw_data_dir)
for raw_data_file in raw_data_files: for raw_data_file in raw_data_files:
@ -307,6 +258,9 @@ def delete_excel_files(raw_data_dirs):
def initialization(): def initialization():
# 功能:初始化,记录开始时间,读取预定义参数
# 参数:-
# 返回值:结果文件,数据文件夹,以及预定义参数
time_start = time.time() # 记录开始时间 time_start = time.time() # 记录开始时间
try: try:
# read init configurations from config file # read init configurations from config file
@ -331,6 +285,9 @@ def initialization():
def execution(args): def execution(args):
# 功能:执行处理所有数据文件
# 参数initialization函数的返回值
# 返回值:-
raw_data_dirs, result_files, time_start, AV, RR, RC, AXIS = args raw_data_dirs, result_files, time_start, AV, RR, RC, AXIS = args
prefix = [] prefix = []
for raw_data_dir in raw_data_dirs: for raw_data_dir in raw_data_dirs:

Binary file not shown.

View File

@ -6,8 +6,8 @@ VSVersionInfo(
ffi=FixedFileInfo( ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0. # Set not needed items to zero 0.
filevers=(0, 0, 4, 0), filevers=(0, 0, 5, 0),
prodvers=(0, 0, 4, 0), prodvers=(0, 0, 5, 0),
# Contains a bitmask that specifies the valid bits 'flags'r # Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f, mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file. # Contains a bitmask that specifies the Boolean attributes of the file.
@ -31,12 +31,12 @@ VSVersionInfo(
'040904b0', '040904b0',
[StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'), [StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'),
StringStruct('FileDescription', 'All in one automatic operating tool'), StringStruct('FileDescription', 'All in one automatic operating tool'),
StringStruct('FileVersion', '0.0.4 (2024-05-20)'), StringStruct('FileVersion', '0.0.5 (2024-05-20)'),
StringStruct('InternalName', 'AIO.exe'), StringStruct('InternalName', 'AIO.exe'),
StringStruct('LegalCopyright', '© 2024-2024 Manford Fan'), StringStruct('LegalCopyright', '© 2024-2024 Manford Fan'),
StringStruct('OriginalFilename', 'AIO.exe'), StringStruct('OriginalFilename', 'AIO.exe'),
StringStruct('ProductName', 'AIO'), StringStruct('ProductName', 'AIO'),
StringStruct('ProductVersion', '0.0.4 (2024-05-20)')]) StringStruct('ProductVersion', '0.0.5 (2024-05-20)')])
]), ]),
VarFileInfo([VarStruct('Translation', [1033, 1200])]) VarFileInfo([VarStruct('Translation', [1033, 1200])])
] ]