首页 > 其他分享 >Excel 转换为 DBC 文件

Excel 转换为 DBC 文件

时间:2024-08-07 15:25:47浏览次数:12  
标签:转换 DBC Excel header tk file save data row

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


文章摘要

文章探讨如何使用 Python 将 Excel 文件转换为 DBC 格式。这个过程包括从 Excel 表读取数据,并将其转换为适合 DBC 文件的结构化文本格式。


以下是本篇文章正文内容

一、基本介绍

1.CAN通信

CAN通信和DBC文件编辑是汽车电子领域的重要部分。CAN(Controller Area Network)是一种串行通信协议,广泛用于汽车和工业应用。它允许ECU(电子控制单元)之间进行实时数据交换。

2.DBC文件

1. 简介

  • DBC文件是CAN数据库文件,定义了CAN网络的信号和消息。
  • 包含标识符、信号名称、单位、范围等信息。

2. 编辑工具

  • CANdb++ Editor:Vector提供的工具,用于创建和编辑DBC文件。
  • 功能:定义消息和信号、设置信号值、添加注释等。

3. 基本操作

  • 创建消息:设置标识符和数据长度。
  • 添加信号:定义信号名称、起始位、长度、缩放因子和偏移量。
  • 设置属性:例如信号的发送类型和周期时间。

参考链接:https://blog.csdn.net/qq_40552138/article/details/133464278

二、转换思路框架

1.基于DBC文件(.dbc)可以用文本格式(.txt)格式打开的思路,对照标准DBC文件的文本格式来进行转换

在这里插入图片描述
参考链接:https://bbs.huaweicloud.com/blogs/319492

2.Excel 文件处理:提取Excel信息,填入到文本相对应位置(具体位置,参考完整代码)

在这里插入图片描述

3.创建文件选择和处理的简单 GUI

# 保存路径窗口
def open_save_dialog():
    save_path = filedialog.askdirectory()
    if save_path:
        save_entry.delete(0, tk.END)
        save_entry.insert(0, save_path)
# 选取文件窗口
def open_file_dialog():
    file_paths = filedialog.askopenfilenames(filetypes=[("Excel files", "*.xls;*.xlsx;*.xlsm")])
    if file_paths:
        file_entry.delete(0, tk.END)
        file_entry.insert(0, ";".join(file_paths))
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Excel2DBC")

    # 选择文档
    file_frame = tk.Frame(root)
    file_frame.pack(padx=10, pady=10)

    file_label = tk.Label(file_frame, text="选择需要转换的Excel文档:")
    file_label.pack(side=tk.LEFT)

    file_entry = tk.Entry(file_frame, width=50)
    file_entry.pack(side=tk.LEFT, padx=5)

    browse_button = tk.Button(file_frame, text="Browse", command=open_file_dialog)
    browse_button.pack(side=tk.LEFT)

    # 选择保存路径
    save_frame = tk.Frame(root)
    save_frame.pack(padx=10, pady=10)

    save_label = tk.Label(save_frame, text="选择保存路径:")
    save_label.pack(side=tk.LEFT)

    save_entry = tk.Entry(save_frame, width=50)
    save_entry.pack(side=tk.LEFT, padx=5)

    save_button = tk.Button(save_frame, text="Browse", command=open_save_dialog)
    save_button.pack(side=tk.LEFT)

    # 程序处理按钮写入
    process_button = tk.Button(root, text="Process", command=process_file)
    process_button.pack(pady=10)

    root.mainloop()

在这里插入图片描述

三、代码实现

1.导入库

import xlrd
import re
import os
import tkinter as tk
from tkinter import filedialog, messagebox

2.GUI窗口实现

# 保存路径窗口
def open_save_dialog():
    save_path = filedialog.askdirectory()
    if save_path:
        save_entry.delete(0, tk.END)
        save_entry.insert(0, save_path)
# 选取文件窗口
def open_file_dialog():
    file_paths = filedialog.askopenfilenames(filetypes=[("Excel files", "*.xls;*.xlsx;*.xlsm")])
    if file_paths:
        file_entry.delete(0, tk.END)
        file_entry.insert(0, ";".join(file_paths))
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Excel2DBC")

    # 选择文档
    file_frame = tk.Frame(root)
    file_frame.pack(padx=10, pady=10)

    file_label = tk.Label(file_frame, text="选择需要转换的Excel文档:")
    file_label.pack(side=tk.LEFT)

    file_entry = tk.Entry(file_frame, width=50)
    file_entry.pack(side=tk.LEFT, padx=5)

    browse_button = tk.Button(file_frame, text="Browse", command=open_file_dialog)
    browse_button.pack(side=tk.LEFT)

    # 选择保存路径
    save_frame = tk.Frame(root)
    save_frame.pack(padx=10, pady=10)

    save_label = tk.Label(save_frame, text="选择保存路径:")
    save_label.pack(side=tk.LEFT)

    save_entry = tk.Entry(save_frame, width=50)
    save_entry.pack(side=tk.LEFT, padx=5)

    save_button = tk.Button(save_frame, text="Browse", command=open_save_dialog)
    save_button.pack(side=tk.LEFT)

    # 程序处理按钮写入
    process_button = tk.Button(root, text="Process", command=process_file)
    process_button.pack(pady=10)

    root.mainloop()

3.Excel文件处理实现

# 文件处理函数
def process_file():
    file_paths = file_entry.get().split(";")
    save_path = save_entry.get()
    if not file_paths or file_paths == ['']:
        messagebox.showerror("Error", "Please select one or more files.")
        return
    if not save_path:
        messagebox.showerror("Error", "Please select a save directory.")
        return

    try:
        for file_path in file_paths:
            file_name = os.path.basename(file_path)
            save_file_path = os.path.join(save_path, file_name.rsplit('.', 1)[0] + '.dbc')

            process_excel_file(file_path, save_file_path)
        messagebox.showinfo("Success", f"Processed data saved to {save_path}")
    except Exception as e:
        messagebox.showerror("Error", str(e))
# 读取xls文件指定工作表的数据
def read_xls(file_path, sheet_index):
    workbook = xlrd.open_workbook(file_path, encoding_override='gbk')  # 使用GBK编码读取文件
    sheet = workbook.sheet_by_index(sheet_index)
    data = []

    for row_idx in range(sheet.nrows):
        row = sheet.row_values(row_idx)
        data.append(row)

    return data

以下代码需要根据自己的Excel表格信息进行修改,来读取需要填入文本中的关键信息。
代码注释中###的内容是需要在文本中填充的内容,也是需要在Exccel中进行提取的

需要注意:

单纯Copy无效:相关信息已进行删改处理,
仅提供思路,供以参考,欢迎指正!!!

# 处理工作表的数据
def process_excel_file(file_path, output_path):

    data_1 = read_xls(file_path, 0)  # 第一个工作表,索引为0
    data_2 = read_xls(file_path, 1)  # 第二个工作表,索引为1
    data_3 = read_xls(file_path, 2)  # 第三个工作表,索引为2
    data_4 = read_xls(file_path, 3)  # 第四个工作表,索引为3

    # 根据表头来选取需要填入文本中的信息
    header_1 = data_1[0]
    header_2 = data_2[0]
    header_3 = data_3[0]
    header_4 = data_4[1]

    # 创建combined_data
    combined_data = "\n".join(header) + "\n"

    ### 报文帧网络节点(表2)
    Node = data_2[1][header_2.index('Node')]
    if len(data_2[1]) >= len(header_2):
        combined_data += f'BU_: {Node} Vector__XXX\n' \
                         f'\n'

    ### 报文帧部分
    for row_data_4 in data_4[2:]:

        # 报文帧部分转换(表4)
        Name = row_data_4[header_4.index('Name')]
        ZCU_PR = row_data_4[26]

        if len(row_data_4) >= len(header_4):
            if Name:
                MsgID = hex_to_decimal(row_data_4[header_4.index('MsgID')])
                if ZCU_PR == 'R':
                    ZCU_PR = data_4[1][27]
                else:
                    ZCU_PR = data_4[1][26]
                # 报文信息:报文ID、报文名称、报文长度(单位:字节/Byte)
                combined_data += f'\n' \
                                 f'BO_ {MsgID} {Name}: {convert_int(MsgLength)} {ZCU_PR}\n'
            else:
                StartBit_convert = lsb_to_msb(StartBit, BitLength)
                if ZCU_PR == 'R':
                    ZCU_PR = data_4[1][26]
                else:
                    ZCU_PR = data_4[1][27]
                # 报文下的信号信息:信号短名、起始位、信号长度(单位:位/Bit)、信号字节顺序(0:Motorola|1:Inter)、
                # 信号数值类型、信号精度、信号偏移量、信号物理最小值、信号物理最大值、信号单位、信号的接收节点
                combined_data += f' SG_ {SignalName_Short} : {StartBit_convert}|{BitLength}@{get_byte_order(ByteOrder)}{get_data_type(DataType)} ' \
                                 f'({Resolution},{Offset}) [{SignalMinValuePhy}|{SignalMaxValuePhy}] "{Unit}"  ' \
                                 f'{ZCU_PR}\n'
        else:
            continue

    # 添加空行
    combined_data += f'\n\n\n\n\n'

    ### 注解部分
    for row_data_4 in data_4[2:]:

        # 注解部分转换(表4)
        Name = row_data_4[header_4.index('Name')]
        MsgID = row_data_4[header_4.index('MsgID')]


        if len(row_data_4) >= len(header_4):
            if Name:
                combined_data += f'\n'
                MsgID4 = hex_to_decimal(MsgID)
            else:
                if SignalDescription == '':
                    combined_data += ''
                else:
                    # 注解:CM_为关键字,表示注解;SG_为注解的对象类型,表示消息类型;报文ID;信号短名;信号描述
                    combined_data += f'\nCM_ SG_ {MsgID4} {SignalName_Short} "{SignalDescription}";'
        else:
            continue

    ### 属性部分1:属性定义BA_DEF_ 和 属性初始值BA_DEF_DEF_ 信息
    combined_data += "\n"
    combined_data += "\n".join(BA_DEF_info) + "\n"

    ### 属性部分2:通用属性的定义
    for row_data_1 in data_1[1:]:

        # 属性部分转换(表1)
        ILTxTimeout = row_data_1[header_1.index('ILTxTimeout')]
        if len(row_data_1) >= len(header_1):
            combined_data += f'\nBA_ "ILTxTimeout" {ILTxTimeout};' \
                             f'\nBA_ "DBName" "{DBName}";'
        else:
            continue

    # 添加空行
    combined_data += f'\n'

    ### 属性部分3:AUTOSAR网络管理属性
    for row_data_2 in data_2[1:]:

        # 属性部分转换(表2)
        Node_id = row_data_2[header_2.index('Node')]
        NmNode = yes_no_to_binary(row_data_2[header_2.index('NmNode')])


        if len(row_data_2) >= len(header_2):
            combined_data += f'\nBA_ "NmNode" BU_ {Node_id} {NmNode};' \
                             f'\nBA_ "NmAsrCanMsgCycleOffset" BU_ {Node_id} {CycleOffset};' \
                             f'\nBA_ "NmStationAddress" BU_ {Node_id} {NmStationAddress};' \
                             f'\nBA_ "NmAsrNodeIdentifier" BU_ {Node_id} {NmAsrNodeIdentifier};' \
                             f'\nBA_ "NodeLayerModules" BU_ {Node_id} "{NodeLayerModules}";' \
                             f'\nBA_ "ILUsed" BU_ {Node_id} {ILUsed};' \
                             f'\nBA_ "NmAsrCanMsgReducedTime" BU_ {Node_id} {NmAsrCanMsgReducedTime};' \
                             f'\nBA_ "NmAsrNode" BU_ {Node_id} {NmAsrNode};' \
                             f'\n'
        else:
            continue

    # 添加空行
    combined_data += f'\n'

    ### 属性部分4:Com属性1
    i = 1
    for row_data_4 in data_4[2:]:
        # 属性部分转换(表4)
        Name = row_data_4[header_4.index('Name')]
        GenSigSendType = getMsgSendtype(row_data_4[header_4.index('SignalSendType')])


        if Name:
            for row_data_3 in data_3[i:]:
                # 属性部分转换(表3)
                GenMsgSendType = getMsgSendtype(row_data_3[header_3.index('GenMsgSendType')])
                GenMsgStartDelayTime = row_data_3[header_3.index('GenMsgStartDelayTime(ms)')]
                
                MsgID_4 = hex_to_decimal(MsgID)
                combined_data += f'BA_ "GenMsgSendType" BO_ {MsgID_4} {GenMsgSendType};\n' \
                                 f'\n'
                i += 1
                break
        else:
            GenSigTimeoutValue = hex_to_decimal(row_data_4[header_4.index('GenSigTImeoutValue (Hex)')])
            GenSigInactiveValue = hex_to_decimal(row_data_4[header_4.index('InactiveValue(Hex)')])
            GenSigStartValue = hex_to_decimal(row_data_4[header_4.index('InitialValue(Hex)')])
            combined_data += f'BA_ "GenSigSendType" SG_ {MsgID_4} {SignalName_Short} {GenSigSendType};\n' \
                             f'\n'

    ### 属性部分5:Com属性2
    for row_data_4 in data_4[2:]:
        GenSigTimeoutTime = convert_int(row_data_4[header_4.index('GenSigTimeoutTime (ms)')])
        ZCU_PR = row_data_4[26]

        if len(row_data_4) >= len(header_4):  # 确保行中至少有需要的列数
            if Name != '':
                MsgID_4 = hex_to_decimal(row_data_4[header_4.index('MsgID')])
            else:
                if ZCU_PR == 'R':
                    ZCU_PR = data_4[1][26]
                    combined_data += f'BA_REL_ "GenSigTimeoutTime" BU_SG_REL_ {ZCU_PR} SG_ {MsgID_4} {SignalName} {GenSigTimeoutTime};\n'
        else:
            continue

    ### 数值表部分(值列表)
    for row_data_4 in data_4[2:]:

        # 数值表部分转换(表4)
        SignalName = row_data_4[header_4.index('SignalName(Short Name)')]

        # 去除 SignalValueDescription 中的换行符
        SignalValueDescription = re.sub(r'0x([0-9A-Fa-f]+):\s*(.*?)(?=\s*0x[0-9A-Fa-f]+:|\s*$)', format_signal_description,
                                        SignalValueDescription)
        # 确保每个描述之间有一个空格
        SignalValueDescription = ' '.join(re.split(r'\s+', SignalValueDescription.strip()))

        if len(row_data_4) >= len(header_4): 
            if Name != '':
                MsgID_4 = hex_to_decimal(row_data_4[header_4.index('MsgID')])
            else:
                if SignalValueDescription != '':
                    combined_data += f'VAL_ {MsgID_4} {SignalName} {SignalValueDescription} ;\n'
        else:
            continue

    combined_data += f'\n'

    write_txt(output_path, combined_data)

上述代码还有很多函数未陈列:比如16进制转10进制、lsb格式转msb格式、判断报文发送类型、byte_order的判断等,这里提供一个lsb转换公式。其余部分函数可关注私信交流!

# 定义LSB到MSB转换函数(Excel文件中的是LSB格式,CANdb++里边打开是MSB格式)
# 转换公式:temp = (start_bit + 7 - 2 * (start_bit % 8) - bit_length + 1)
#          msb_start_bit = temp + 7 - 2 * (temp % 8)

总结

以上就是Excel 转换为 DBC 文件的实现,相关内容已做删改。作为入行新手,如有不足之处,还请指正!完整代码可通过关注私信获取,希望对大家有所帮助,感谢支持!

标签:转换,DBC,Excel,header,tk,file,save,data,row
From: https://blog.csdn.net/bbu1227368213989/article/details/140985967

相关文章

  • 有了Power BI还需要深入学习Excel图表制作吗?
    PowerBI和Excel都是微软公司的产品,但它们在数据分析和可视化方面有着不同的定位和功能。PowerBI是一个强大的商业分析工具,它提供了数据集成、数据建模、报告和仪表板的创建等功能。PowerBI特别适合处理大量数据,并且可以连接到多种数据源。它还支持高级的数据分析技术,如机器......
  • 使用IText7和miniExcel处理pdf并输出内容
    使用框架:.net8.0、winform操作系统:windows11编译器:vs2022内容:使用iText7、miniExcel,介绍如何简单读取pdf文件文字内容,并做处理后输出至excel文件中秉承着一贯的风格,还是只讲操作,囫囵吞枣就是要讲究一个稳准狠......
  • 基本数据类型转换
    五、基本数据类型转换自动类型转换:容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。......
  • 8 Python字符串与二进制文本相互转换
     欢迎来到@一夜看尽长安花博客,您的点赞和收藏是我持续发文的动力对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:[email protected]。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。   专栏:java全栈C&C++PythonAIP......
  • 如何将数据帧转换为 Great_expectations 数据集?
    我有一个pandas或pyspark数据框df我想在其中运行期望。我的数据框已经在内存中了。如何将我的数据框转换为Great_expectations数据集?以便我可以执行以下操作:df.expect_column_to_exist("my_column")GreatExpectations不直接在Pandas或PySpark数......
  • uniapp vue3 转换华为鸿蒙(以及问题一些解决方案)
         主要是从Windows系统配置、配置离线SDK和DevEco-Studio、HBuilderX、三方面进行配置。     因为我也是之前写小程序的用uniappvue3写的看官网(uni-app开发鸿蒙应用|uni-app官网)的时候看到vue3uniapp写法可以转换华为鸿蒙开发,我就自己来尝试一......
  • JDBC
    一、JDBC开发步骤1.加载驱动2.获取连接对象3.写sql语句4.创建statement5.执行sql语句6.关闭连接 二、JDBC接口核心的API1.DriverManager类:驱动管理类,用于管理所有注册的驱动程序   registerDriver(driver):注册驱动类对象   ConnectiongetConnection(u......
  • Excel 根据单元格值设置行颜色
     开始》条件格式》管理规则》新建格式规则》使用公式确定要设置格式的单元格只为满足以下条件的单元格设置格式:=SEARCH("进行中",$E5)>0;(注释:此处筛选的是包含进行中的数据)格式:选择满足条件的单元格设置什么格式 应用于:选择此行需要改颜色格式的单元格  对某个单元格......
  • Java使用POI导出excel记录
    eg:@OverridepublicvoidexportExcel(HttpServletResponseresponse)throwsException{//创建Excel文档XSSFWorkbookworkbook=newXSSFWorkbook();XSSFSheetsheet=workbook.createSheet("设备厂商");//创建表头XSSFRow......
  • 我正在 python 中使用 aspose.pdf 将 pdf 转换为 excel 。但问题是它只能将 pdf 的前
    `从tkinter导入*将aspose.pdf导入为ap从tkinter导入文件对话框importpandasaspdinput_pdf=filedialog.askopenfilename(filetypes=(("PDF文件",".pdf"),("所有文件",".")))output_file=filedialog.asksaveasfil......