鱼C论坛

 找回密码
 立即注册
查看: 115|回复: 6

[已解决]遇到了一个怪事,AI老师也不一定搞定了,大家帮看看

[复制链接]
发表于 2024-11-27 14:03:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
做了一个表格如下,写了一个程序,作用是根据excel里的管线号,找到文件夹里这个管线号的dxf文件,对里面的焊缝编号的文本,替换为标注编号。


管线号                  焊缝编号        标注编号
BD-1001-80-N1B        S1        21C
BD-1001-80-N1B        2        1B
BD-1001-80-N1B        3        2B
BD-1001-80-N1B        4        3B


之前做焊缝编号形式为S1,S2,S3类型的没出现什么问题。
这次做一个表,焊缝编号形式为1,2,3,就出现不执行替换的问题
后来反复找程序问题找不出来,就把第一个编号改为S1,去对应单线图就改这第一个编号。
后面就能依次运行顺利了,百思不得其解。
程序如下,也看不出来什么问题,没能力想到问题怎么出的,大家帮忙看看呢。
import pandas as pd
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import time
from openpyxl import load_workbook
input_file_path = ""
tem_file_path = ""
tar_folder_path = ""
df_merge = []
import ezdxf
from pyautocad import Autocad, APoint
import os

def select_input_file():
    global input_file_path
    input_file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx;*.xls")], title="请选择旧数据excel,.xlsx格式")
    if input_file_path:
        input_file.set(input_file_path)
        input_file_label.config(text=input_file_path.split('/')[-1])

def select_target_folder():
    global tar_folder_path
    tar_folder_path = filedialog.askdirectory(title="请选择输出文件夹")
    if tar_folder_path:
        target_folder.set(tar_folder_path)
        target_folder_label.config(text=tar_folder_path.split('/')[-1])


def update_cad_file(filename, old_text, new_text):

    #filename, old_text, new_text 依次是文件名,旧文本,新文本
    try:
    # 加载DXF文档
        doc = ezdxf.readfile(filename)
    except IOError:
        print(f"无法打开文件: {filename}")
        return
    except ezdxf.DXFStructureError:
        print(f"文件不是一个有效的DXF文件: {filename}")
        return

    # 获取模型空间
    msp = doc.modelspace()

    # 遍历文本实体并进行替换
    for entity in msp.query("TEXT MTEXT"):
        if entity.dxf.text == old_text:
            print(f"替换 '{old_text}' 为 '{new_text}'")
            entity.dxf.text = new_text

    # 保存更改到新文件
    # new_filename = filename.replace('.dxf', '_modified.dxf')
    # doc.saveas(new_filename)
    # print(f"保存已修改文件为: {new_filename}")
    doc.saveas(filename)
    print(f"保存已修改文件为: {filename}")

    # acad = Autocad(create_if_not_exists=True)
    # acad.doc.Open(file_path)
    #
    # for text in acad.iter_objects('Text'):
    #     if text.TextString == old_text:
    #         text.TextString = new_text
    #         text.Update()
    #
    # acad.doc.SaveAs(file_path)
    # acad.doc.Close()


def replace_text_in_dxf():
    global input_file_path
    global tem_file_path
    global tar_folder_path
    global df_merge
    status_label.config(text="正在运行中,请稍候")
    root.update()
    time.sleep(0.1)  # 模拟命令执行时间
    status_label.config(text="已完成")

    input_file = input_file_path
    template_file = tem_file_path
    target_folder = tar_folder_path

    # 读取Excel文件
    df1 = pd.read_excel(input_file)
    # 根据焊接类型增加后缀列
    df1['后缀'] = df1['焊接类型'].apply(lambda x: 'B' if x == '对焊' else ('C' if x == '承插焊' else ('D' if x == '开口焊' else None)))
    df1['新编码'] = None

    # 获取不同管线号的列表
    unique_pipelines = df1['管线号'].unique()
    for pipeline in unique_pipelines:
        # 筛选出当前管线号的数据
        pipeline_data = df1[df1['管线号'] == pipeline]
        # 初始化计数器
        count_b = 0
        count_c = 0
        count_d = 0

        # 对焊类型的新编码从1开始
        for i, row in pipeline_data[pipeline_data['焊接类型'] == '对焊'].iterrows():
            count_b += 1
            df1.loc[i, '新编码'] = count_b

        # 承插焊类型的新编码从对焊类型的总数 + 1 开始
        for i, row in pipeline_data[pipeline_data['焊接类型'] == '承插焊'].iterrows():
            count_c += 1
            df1.loc[i, '新编码'] = count_b + count_c

        # 开口焊类型的新编码从对焊和承插焊类型的总数中最大的一个值 + 1 开始
        for i, row in pipeline_data[pipeline_data['焊接类型'] == '开口焊'].iterrows():
            count_d += 1
            df1.loc[i, '新编码'] = max(count_b, count_b + count_c) + count_d

    # 新增标注编码列,值为新编码和后缀的拼接
    df1['标注编号'] = df1['新编码'].astype(str) + df1['后缀']

    new_file = "比较表格.xlsx"
    # 构建新文件的完整路径
    # new_file_path = os.path.join(output_folder_copy, new_file)
    new_file_path = f"{target_folder}/{new_file}"  # 实测这样写格式没有问题的,可以读到实际位置。

    # 保存到新的Excel文件
    df1.to_excel(new_file_path, index=False)

    for index, row in df1.iterrows():
        pipe_no = row['管线号']
        weld_no = row['焊缝编号']
        label_no = row['标注编号']

        for file in os.listdir(tar_folder_path):
            if file.endswith('.dxf') and pipe_no in file:
                update_cad_file(os.path.join(tar_folder_path, file), weld_no, label_no)

    """
    #filename, old_text, new_text 依次是文件名,旧文本,新文本
    try:
    # 加载DXF文档
        doc = ezdxf.readfile(filename)
    except IOError:
        print(f"无法打开文件: {filename}")
        return
    except ezdxf.DXFStructureError:
        print(f"文件不是一个有效的DXF文件: {filename}")
        return

# 获取模型空间
    msp = doc.modelspace()

# 遍历文本实体并进行替换
    for entity in msp.query("TEXT MTEXT"):
        if entity.dxf.text == old_text:
            print(f"替换 '{old_text}' 为 '{new_text}'")
            entity.dxf.text = new_text

# 保存更改到新文件
    new_filename = filename.replace('.dxf', '_modified.dxf')
    doc.saveas(new_filename)
    print(f"保存已修改文件为: {new_filename}")
    """

# 使用函数替换文本
# replace_text_in_dxf(r'C:\Users\Administrator\Desktop\解密放原地\0093001-VDW-F101-231301-013-i002.dxf', '2', '2B')


"""
新增图形界面
"""
#创建窗口对象
root = tk.Tk()
#设置窗口标题,注意,所有窗口标题,必须在开启窗口之前做好,不然在开启窗口后写是不生效的。
root.title("江苏瑞鼎DXF文件替换焊缝编码程序")
root.geometry("600x450+100+100")
#设置窗口锁定缩放,可以传两个bool值,指定能否缩放,True是可以拉伸的。
root.resizable(False, False)
# 设置窗口置顶,用的到,可以用
root.attributes("-topmost", True)

input_file = tk.StringVar()
template_file = tk.StringVar()
target_folder = tk.StringVar()


# 创建按钮组件 Button,注意这里都是写函数名,不加()
tk.Button(root, text="1、选择设计软件导出文件,格式为.xlsx", width=40, command=select_input_file, font=("黑体", 20)).place(x=20, y=20)
input_file_label = tk.Label(root, text="",width=40,font=("楷体", 20))
input_file_label.place(x=20, y=70)

tk.Button(root, text="2、选择要替换编码的dwf文件所在文件夹", width=40, command=select_target_folder, font=("黑体", 20)).place(x=20, y=120)
target_folder_label = tk.Label(root, text="",width=40,font=("楷体", 20))
target_folder_label.place(x=20, y=170)

# 填写一个运行的按钮
tk.Button(root, text="3、前面完成输入,按此运行", width=30, command=replace_text_in_dxf, font=("黑体", 20)).place(
        x=20, y=220)

status_label = tk.Label(root, text="等待中",width=30,font=("楷体", 20))
status_label.place(x=20, y=270)

version_label = tk.Label(root, text="软件版本:V1.0 20241031",width=30,font=("宋体", 20)).place(x=20, y=350)
author_label = tk.Label(root, text="制作:朱宁",width=10,font=("宋体", 20)).place(x=20, y=400)
tutor_label = tk.Label(root, text="指导:陈敏东",width=15,font=("宋体", 20)).place(x=250, y=400)

# 开启窗口对象
root.mainloop()
最佳答案
2024-11-27 14:20:30
颂风侯 发表于 2024-11-27 14:20
我发现焊缝编号比如1,2,3是变成了int型,怎么强制改到 ...


可以在读取Excel文件时直接将指定列转换为字符串类型,从而避免其变为`int`型。以下是如何操作的示例:

在读取Excel文件时,通过`dtype`参数指定列的数据类型,你可以将焊缝编号列设置为字符串:
# 读取Excel文件时,指定"焊缝编号"列为字符串类型
df1 = pd.read_excel(input_file, dtype={"焊缝编号": str})

这样处理后,"焊缝编号"列将被直接读取为文本类型,即使里面的内容看起来像数字。确保你的Excel文件列名和代码中的列名匹配。

如果您在别处已经读取了数据并需要转换为字符串,可以使用以下方式:
# 将焊缝编号列转换为字符串类型
df1["焊缝编号"] = df1["焊缝编号"].astype(str)

这种方法确保焊缝编号始终被当作字符串处理,无论其中存储的是数字还是字母数字组合。

如果有其他问题,请随时问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-11-27 14:03:52 | 显示全部楼层
出现这种问题可能是由于焊缝编号的处理方式不同导致的。您提到焊缝编号形式为`1, 2, 3`时,程序没有正常执行替换,而形式为`S1, S2, S3`时则没有问题。这可能与DXF文件中的文本处理有关。以下是一些可能的原因和建议:

1. **字符串匹配问题**:
   - 在DXF文件中,焊缝编号`1`、`2`、`3`等可能与其他数字(如坐标、标尺等)产生混淆。推荐在原始DXF文件确认焊缝编号是单独的文本实体。
   - 考虑在程序中将数字编号(如`1`)转换为字符串并确保匹配时是不带空格或其他多余字符的纯编号。

2. **遍历条件问题**:
   - 检查`update_cad_file`函数中的遍历和匹配逻辑,确认用于查找和替换文本的条件是否正确。
   - 尝试将焊缝编号转换为字符串进行匹配,例如将`old_text`转换为字符串再进行比较:`if str(entity.dxf.text).strip() == old_text.strip():`。

3. **编号范围或重复问题**:
   - 对于数字编号,确保在DXF文件中不存在重复或错误识别的问题。可以通过在焊缝编号前后添加特定标记(如前缀`#1#`等)来确保唯一性,从而避免混淆。

4. **调试日志**:
   - 在替换逻辑中添加调试日志,确认程序有没有正确进入替换判断,例如打印所有被判断的`entity.dxf.text`。

5. **代码冗余或错误**:
   - 仔细检查代码中有无冗余、不必要或错误的逻辑,特别是涉及到对Excel表格的读取和处理部分。

根据这些建议进行排查,看看是否可以解决问题。如果仍有问题,您可以通过进一步简化测试样例来定位具体问题。列表的支持和反馈将有助于更好地解决问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-27 14:13:29 | 显示全部楼层
这问题AI老师都能答,逆天哪,太强了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-27 14:13:41 | 显示全部楼层
颂风侯 发表于 2024-11-27 14:13
这问题AI老师都能答,逆天哪,太强了


感谢您的赞美!如果您还有其他问题或者需要进一步的帮助,请随时告诉我。祝您编程顺利!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-27 14:20:13 | 显示全部楼层
我发现焊缝编号比如1,2,3是变成了int型,怎么强制改到文本型?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-27 14:20:30 | 显示全部楼层    本楼为最佳答案   
颂风侯 发表于 2024-11-27 14:20
我发现焊缝编号比如1,2,3是变成了int型,怎么强制改到 ...


可以在读取Excel文件时直接将指定列转换为字符串类型,从而避免其变为`int`型。以下是如何操作的示例:

在读取Excel文件时,通过`dtype`参数指定列的数据类型,你可以将焊缝编号列设置为字符串:
# 读取Excel文件时,指定"焊缝编号"列为字符串类型
df1 = pd.read_excel(input_file, dtype={"焊缝编号": str})

这样处理后,"焊缝编号"列将被直接读取为文本类型,即使里面的内容看起来像数字。确保你的Excel文件列名和代码中的列名匹配。

如果您在别处已经读取了数据并需要转换为字符串,可以使用以下方式:
# 将焊缝编号列转换为字符串类型
df1["焊缝编号"] = df1["焊缝编号"].astype(str)

这种方法确保焊缝编号始终被当作字符串处理,无论其中存储的是数字还是字母数字组合。

如果有其他问题,请随时问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-27 15:24:18 | 显示全部楼层
颂风侯 发表于 2024-11-27 14:13
这问题AI老师都能答,逆天哪,太强了

厉害吧,经过了鱼油们的不断调教,AI 助理越来越强了~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 01:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表