重复造轮子,只是为了熟悉一下DBC格式。
与同类工具的不同点:
-
能批量转换在同一文件夹下的所有DBC,省时省力。
-
很多同类工具转换后的excel列宽较小,不能直接显示全部信息。本代码使用了自适应的列宽,看起来更方便。**
coding=UTF-8
import os
import argparse
import xlsxwriter as xw
import pandas as pd
import re
import openpyxlDBC信息解码,返回字典
def decode(str1):
ans = {}
# 报文帧
if str1.startswith('BO_'):
list1 = re.split(" |: |\n",str1)
ans['message_id'],ans['message_name'],ans['message_size'],ans['transmitter'] = list1[1],list1[2],list1[3],list1[4]
return ans
# 信号帧
elif str1.startswith(' SG_'):
str1 = str1[5:] # 去掉" SG_ ",共5个字符
ans['empty1'],ans['empty2'],ans['empty3'],ans['empty4'] = None,None,None,Nonesub = ':' spt = [sub.start() for sub in re.finditer(sub , str1)] ans['signal_name'],ans['multiplexer_indicator'] = re.split(" ",str1[0:spt[0]])[0], re.split(" ",str1[0:spt[0]])[1] str1 = str1[spt[0]+2:] sub = '@' spt = [sub.start() for sub in re.finditer(sub , str1)] ans['start_bit'],ans['signal_size'],ans['byte_order'],ans['value_type'] = str1[0: str1.find('|',0,spt[0])], str1[str1.find('|',0,spt[0])+1:spt[0]], str1[spt[0]+1], str1[spt[0]+2] if ans['byte_order'] == '0': ans['byte_order'] = 'intel' elif ans['byte_order'] == '1': ans['byte_order'] = 'motorola' if ans['value_type'] == '+': ans['value_type'] = '无符号数' elif ans['value_type'] == '-': ans['value_type'] = '有符号数' str1 = str1[spt[0]+4:] spt = str1.find(' ') ans['factor'],ans['offset'] = re.split(",",str1[1:spt-1])[0], re.split(",",str1[1:spt-1])[1] str1 = str1[spt+1:] sub = ']' spt = [sub.start() for sub in re.finditer(sub , str1)] ans['minimum'],ans['maximum'] = str1[1: str1.find('|',0,spt[0])], str1[str1.find('|',0,spt[0])+1:str1.find(']')] str1 = str1[spt[0]+2:] ans['unit'],ans['receiver'] = str1[0:str1.find(' ')], str1[str1.find(' ')+1:-2] return ans
if name == 'main':
parser = argparse.ArgumentParser(description='将文件夹中的所有DBC文件转换为excel') parser.add_argument('dbc_dir', type=str,help='DBC文件所在的文件夹地址') parser.add_argument('excel_dir', type=str,help='excel的保存地址') parser.add_argument('excel_name', type=str,help='excel文件名') args = parser.parse_args() dbc_dir = args.dbc_dir excel_dir = args.excel_dir excel_name = args.excel_name title = ['message_id', 'message_name', 'message_size','transmitter', 'signal_name', 'multiplexer_indicator', 'start_bit', 'signal_size', 'byte_order', 'value_type','factor', 'offset', 'minimum', 'maximum', 'unit', 'receiver'] # 遍历指定文件夹下的DBC文件绝对路径,保存为list。 dbcfiles = [] for filename in os.listdir(dbc_dir): if filename.endswith('.dbc'): dbcfiles.append(filename) df = pd.DataFrame() df.to_excel(excel_name) for dbc in dbcfiles: # 将数据按表头顺序存入list with open(dbc_dir + '/' + dbc, 'r', encoding='gbk') as f: string = f.readlines() for i in string: data = decode(i) # data = translate(data) if data != None: val = list(data.values()) df1 = pd.DataFrame([val]) df = pd.concat([df,df1],axis=0) with pd.ExcelWriter(excel_name, mode='a', engine="openpyxl") as writer: df.to_excel(writer, sheet_name=dbc, header=title, index=False) workbook = openpyxl.load_workbook(excel_name) worksheet = workbook['Sheet1'] workbook.remove(worksheet) for sheet_name in workbook.sheetnames: sheet = workbook[sheet_name] for column in sheet.columns: max_length = 0 column = [cell for cell in column] for cell in column: try: if len(str(cell.value)) > max_length: max_length = len(cell.value) except: pass adjusted_width = (max_length + 2) sheet.column_dimensions[column[0].column_letter].width = adjusted_width workbook.save(excel_dir+"\\"+excel_name)