Процедура:
Чтение данных из текстового файла построчно;
Затем отправьте данные в последовательный порт;
Сохраните данные в файл Excel в строке с номером / датой / временем
Я пробовал два метода, и оба из них работают.
Но вот какая проблема:
Чем больше данных , тем больше времени берется при сохранении новых данных в файл Excel. Например, при записи данных в строку 10000 почти требуется 2 секунды (когда я использую append () для добавления новой строки в файл Excel);
Я хочу отправлять и сохранять данные все время, пока я не остановлю скрипт в Pycharm, нажав кнопку STOP . Как только я это сделал, Excel, сохраненный ранее, имеет сломанный и НЕ МОЖЕТ открыть его снова.
Я хочу решить эту проблему. Может у кого-нибудь есть предложения? Большое спасибо!
Вот код:
import serial
import serial.tools.list_ports
import time
import datetime
import sys
import os
import openpyxl
from openpyxl.styles import Font
from openpyxl.styles import PatternFill
from openpyxl.styles import Alignment
# The path to palce the Excel file
def creatfilepath(path):
# path -- The user input a path
if os.path.isdir(path):
datapath = path
print('\nM1:The path is OK, and the Excel file will be saved in {}'.format(datapath))
else:
if os.makedirs(path):
datapath = path
print('\nM2:The path does not exist, and scrip will creat the path {} to save the Excel'.format(datapath))
else:
datapath = os.getcwd()
print('\nM3:Creating the path is failed, and the Excel will be saved in same path {} where the script is.'.format(datapath))
return datapath
# Creating the Excel to save the data
def creatdatafile(filename, path, data_title):
# filename -- Excel filename
# path -- The path to save the Excel
# data_title -- Excel's title, which is a list and the default value is ['Number', 'Date', 'Time', 'Command', 'Type', 'Comment']
# Creating a Workbook
serial_data_1902_wb = openpyxl.Workbook()
# Accessing the active sheet
serial_data_1902_sheet = serial_data_1902_wb.active
# sheet'title
serial_data_1902_sheetname = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
serial_data_1902_sheet.title = serial_data_1902_sheetname
# Excel's filename
serial_data_1902_filename = filename + '_' + \
datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + '.xlsx'
# The absolute path
ab_path = path + "\\" + serial_data_1902_filename
serial_data_1902_wb.save(ab_path)
# Loading the Excel
active_data_file = openpyxl.load_workbook(ab_path)
# Accessing the sheet
active_datasheet = active_data_file[serial_data_1902_sheetname]
# Setting the title
row_title = data_title
active_datasheet.append(row_title)
# Freezing the 1st row
active_datasheet.freeze_panes = 'A2'
# Accessing the title's scope
title_scope = active_datasheet.dimensions
# Arial/12/Bold/
title_font_obj = Font(name='Arial', size=10, bold=True,
italic=False, strike=False, color='000000')
# Fill type
title_fill_obj = PatternFill(fill_type='solid', fgColor='7EC0EE')
# Alignment
title_align_obj = Alignment(
horizontal='center', vertical='center', wrap_text=False)
# Formating the 1st row
for rowOfCellObjects in active_datasheet[title_scope]:
for cellObject in rowOfCellObjects:
cellObject.font = title_font_obj
cellObject.fill = title_fill_obj
cellObject.alignment = title_align_obj
active_data_file.save(ab_path)
# Return the absolute path
if os.path.exists(ab_path):
print('\nM4:The Excel {} have created, and the path is {}'.format(
serial_data_1902_filename, path))
return ab_path
else:
print('\nE0:Creating Excel is failed, please check!')
sys.exit(0)
def isavailable(port):
port_list = list(serial.tools.list_ports.comports()
)
if len(port_list) <= 0:
print('\nE1:There is not serial port on the host!')
sys.exit(0)
else:
port_name_list = []
for port_objet in port_list:
port_name = port_objet[0]
port_name_list.append(port_name.lower())
print('\nM5:The serial ports is:{}'.format(port_name_list))
if port.lower() in port_name_list:
print('\nM6:')
else:
print('\nE2:')
sys.exit(0)
# Creating a vitural serial port and open it
def createport(port, baudrate=115200):
isavailable(port)
try:
serialport = serial.Serial(port, baudrate, timeout=1, write_timeout=1)
except ValueError:
sys.exit('\nE3:')
except (OSError, serial.SerialException):
sys.exit('\nE4:')
if serialport.is_open and port == serialport.portstr:
print('\nM7:')
serialport.flushInput()
else:
sys.exit('\nE5:')
return serialport
def savecommand(num, command_list, excelabpath, excelworkbook, excelsheet):
# num -- The number of command
# command_list -- A list which contain the data
# excelabpath -- The absolute path of Excel
# excelworkbook -- The Excel which save data
# excelsheet -- the sheet which save the data
try:
i = 0
for row in excelsheet.iter_rows(min_row=num+1, max_col=5, max_row=num+1):
for cell in row:
cell.value = command_list[i]
i += 1
if i < len(command_list):
continue
else:
break
excelworkbook.save(excelabpath)
except TypeError:
print('\nE10:')
def sendcommand(abpath, workbook, sheet, commandfile, port, intertime=0.5, commamd_num=1):
#
if not port.is_open:
try:
port.open()
except:
print('\nE6:')
else:
pass
try:
with open(commandfile, 'r', encoding='utf-8') as file_object:
for line in file_object:
if len(line) > 1 and (not line.startswith('#')):
command_hex = bytes.fromhex(
line.strip())
try:
print(commamd_num, " ", datetime.datetime.now(),
" ", line)
port.write(command_hex)
# The list contain the number/date/time/command
data_list = [commamd_num, datetime.datetime.now().strftime(
'%Y/%m/%d'), datetime.datetime.now().strftime('%H:%M:%S.%f'), line.strip()]
savecommand(commamd_num, data_list, abpath, workbook, sheet)
time.sleep(intertime)
commamd_num += 1
except serial.SerialTimeoutException:
print("\nE7:")
time.sleep(1)
port.write(command_hex)
# The list contain the number/date/time/command
data_list = [commamd_num, datetime.datetime.now().strftime(
'%Y/%m/%d'), datetime.datetime.now().strftime('%H:%M:%S.%f'), line.strip()]
savecommand (commamd_num, data_list, abpath, workbook, sheet)
time.sleep(intertime)
commamd_num += 1
else:
continue
except FileNotFoundError:
print('\nE8:')
sys.exit(0)
except PermissionError:
print('\nE9:')
sys.exit(0)
port.close()
if not port.is_open:
print('\nM9:')
return commamd_num
# ~~~~~~~~~~~~~~ The parameters of serial port ~~~~~~~~~~~~~~~~~~
# port number
comNumber = 2
# port name
comPort = 'com{}'.format(comNumber)
# baudRate
baudRate = 115200
# ~~~~~~~~~~~~~~ Other parameters ~~~~~~~~~~~~~~~~~~
# The path of command file
commandPath = r'.\1902.txt'
# The Excel path
savePath = r'D:\1902Code'
# The name of Excel
excelName = 'SerialData1902'
# The title
excelTitle = ['Number', 'Date', 'Time', 'Command', 'Type', 'Comment']
# The time between two command was sent
interTime = 0.01
#
isForever = 1
# ~~~~~~~~~~~~~~~~~~~~~ Begin ~~~~~~~~~~~~~~~~~~~
# Creating the path which save the Excel
excel_path = creatfilepath(savePath)
# Creating the Excel
excel_ab_path = creatdatafile(excelName, excel_path, excelTitle)
# Loading the Excel
excel_workbook = openpyxl.load_workbook(excel_ab_path)
# Accessing the sheet
excel_sheet = excel_workbook.active
# Creating the serial port
serial_port = createport(comPort, baudRate)
# The number of sending command and start with 1
command_num = 1
if isForever:
print('\nM10:')
while isForever:
command_num = sendcommand(excel_ab_path, excel_workbook, excel_sheet,
commandPath, serial_port, interTime, command_num)
elif isForever == 0:
print('\nM11:')
command_num = sendcommand(excel_ab_path, excel_workbook, excel_sheet,
commandPath, serial_port, interTime, command_num)
else:
print('\nE11:')