Python 3.x 如何使用openpyxl和Python3在Excel文件中保存数据?有没有办法花点时间呢?
程序如下:Python 3.x 如何使用openpyxl和Python3在Excel文件中保存数据?有没有办法花点时间呢?,python-3.x,excel,openpyxl,Python 3.x,Excel,Openpyxl,程序如下: 逐行读取txt文件中的数据 然后将数据发送到串行端口 将数据以数字/日期/时间的行形式保存到Excel文件中 我试过两种方法,而且都有效 但问题是: 数据越多,将新数据保存到Excel文件时花费的时间越长。例如,当将数据写入10000行时,几乎需要2秒钟(当我使用append()在Excel文件中追加新行时) 我想一直发送和保存数据,直到单击停止按钮停止Pycharm中的脚本。一旦我这样做了,以前保存的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:')
导入序列号
导入serial.tools.list_端口
导入时间
导入日期时间
导入系统
导入操作系统
导入openpyxl
从openpyxl.styles导入字体
从openpyxl.styles导入填充图案
从openpyxl.styles导入对齐方式
#保存Excel文件的路径
def creatfilepath(路径):
#path——用户输入一个路径
如果os.path.isdir(路径):
数据路径=路径
打印('\nM1:路径正常,Excel文件将以{}格式保存(数据路径))
其他:
如果os.makedirs(路径):
数据路径=路径
打印('\nM2:路径不存在,scrip将创建路径{}以保存Excel'.format(datapath))
其他:
datapath=os.getcwd()
打印('\nM3:创建路径失败,Excel将保存在脚本所在的相同路径{}。格式(数据路径))
返回数据路径
#创建Excel以保存数据
def creatdatafile(文件名、路径、数据标题):
#文件名--Excel文件名
#path——保存Excel的路径
#data_title——Excel的标题,是一个列表,默认值为['Number'、'Date'、'Time'、'Command'、'Type'、'Comment']
#创建工作簿
serial_data_1902_wb=openpyxl.Workbook()
#访问活动工作表
串行数据表=串行数据表
#书名
serial\u data\u 1902\u sheetname=datetime.datetime.now().strftime(“%Y%m%d\u%H%m%S”)
serial_data_1902_sheet.title=serial_data_1902_sheet name
#Excel的文件名
串行_数据_1902_文件名=文件名+''+\
datetime.datetime.now().strftime(“%Y%m%d_%H%m%S”)+”.xlsx'
#绝对路径
ab\U path=path+“\\”+串行数据\U 1902\U文件名
串行数据保存(ab路径)
#加载Excel
活动\u数据\u文件=openpyxl.load\u工作簿(ab\u路径)
#访问工作表
活动数据表=活动数据文件[串行数据表名称]
#设置标题
行标题=数据标题
活动数据表。附加(行标题)
#冻结第一排
活动\数据表.冻结\窗格='A2'
#访问标题的范围
title\u scope=活动的\u数据表.dimensions
#Arial/12/Bold/
title\u font\u obj=font(name='Arial',size=10,bold=True,
斜体=假,删除=假,颜色='000000')
#填充类型
title\u fill\u obj=PatternFill(fill\u type='solid',fgColor='7EC0EE')
#对齐
标题\对齐\对象=对齐(
水平class='center',垂直class='center',换行(文本=False)
#形成第一行
对于活动\u数据表[标题\u范围]中的rowOfCellObjects:
对于第行CellObjects中的cellObject:
cellObject.font=标题\u字体\u对象
cellObject.fill=标题\u fill\u对象
cellObject.alignment=标题\对齐\对象
活动数据文件。保存(ab路径)
#返回绝对路径
如果os.path.存在(ab_路径):
打印('\nM4:Excel{}已创建,路径为{}'。格式(
串行_数据_1902_文件名,路径))
返回ab_路径
其他:
打印('\nE0:创建Excel失败,请检查!')
系统出口(0)
def可用(端口):
port\u list=list(serial.tools.list\u ports.comports()
)
如果len(port_list)1和(而不是line.startswith(“#”):
命令\u hex=bytes.fromhex(
line.strip())
尝试:
打印(commamd_num,“,datetime.datetime.now(),
“”,第行)
端口写入(命令\十六进制)
#该列表包含编号/日期/时间/命令
data_list=[commamd_num,datetime.datetime.now().strftime(
“%Y/%m/%d”),datetime.datetime.now().strftime(“%H:%m:%S.%f”),line.strip()]
savecommand(commamd\u num、数据列表、abpath、工作簿、工作表)
时间。睡眠(时间间隔)
commamd_num+=1
除serial.SerialTimeoutException外:
打印(“\nE7:”)
时间。睡眠(1)
端口写入(命令\十六进制)
#该列表包含编号/日期/时间/命令
data_list=[commamd_num,datetime.datetime.now().strftime(
“%Y/%m/%d”),datetime.datetime.now().strftime(“%H:%m:%S.%f”),line.strip()]
savecommand(commamd\u num、数据列表、abpath、工作簿、工作表)
时间。睡眠(时间间隔)
commamd_num+=1
其他:
持续
除FileNotFoundError外:
打印('\nE8:')
系统出口(0)
除许可错误外:
打印('\nE9:')
系统出口(0)
端口关闭()
如果端口未打开:
打印('\nM9:')
返回commamd_num
#~~~~~~~~~~~~~~~~~~~的参数