首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >​中望CAD Python 自动化实战:参数化批量出图与标题栏自动填充方案

​中望CAD Python 自动化实战:参数化批量出图与标题栏自动填充方案

原创
作者头像
PC电脑医生
发布2026-06-26 18:43:54
发布2026-06-26 18:43:54
1480
举报

摘要: 工程制图中大量重复操作消耗的时间远超设计本身——逐张填标题栏、手工排图框、批量导出PDF,每一项都是纯体力劳动。中望CAD通过COM接口暴露了完整的对象模型,可以用Python直接驱动绘图、编辑和导出的全流程。本文以三个真实工程场景为主线,给出从环境搭建到参数化批量出图的完整代码方案,附带错误处理与调试经验。


一、启动中望CAD的COM接口

中望CAD在安装时默认注册COM组件,Python通过 win32com.clientcomtypes 库即可获取应用程序对象。两者的区别在于:win32com 基于IDispatch后期绑定,代码简洁但无智能提示;comtypes 基于类型库早期绑定,支持IDE自动补全,但需要先通过 gen_dir 生成类型桩。

以下使用 win32com(兼容性最广,中望CAD 2020-2025 均经过验证)。

环境准备

代码语言:bash
复制
pip install pywin32 pandas openpyxl

pandas 用于读取外部数据源(Excel/CSV),openpyxl 是 pandas 读取 .xlsx 的后端引擎。

建立连接

代码语言:python
复制
import win32com.client

# 启动中望CAD或连接到已运行的实例
zwcad = win32com.client.Dispatch("ZWCAD.Application")
# 获取当前活动文档
doc = zwcad.ActiveDocument
# 获取模型空间(ModelSpace),所有图形对象在此创建
ms = doc.ModelSpace

注意: Dispatch("ZWCAD.Application") 中的 ProgID 取决于中望CAD的版本。如果连接失败,尝试 "ZWCAD.Application.2025""ZWCAD.Application.2024"。可通过注册表 HKEY_CLASSES_ROOT 查看已安装版本的精确ProgID。如果中望CAD与AutoCAD共存且ProgID冲突,指定完整版本号即可隔离。


二、场景一:从Excel数据批量生成带属性图框

某电气项目包含42张原理图,每张需要插入A3图框并填写图号、图名、设计人和日期。Excel中已维护完整图纸清单:

图号

图名

设计

日期

EL-001

主接线图

张工

2025-06-20

EL-002

控制回路

张工

2025-06-20

...

...

...

...

核心代码

代码语言:python
复制
import pandas as pd

# 读取Excel图纸清单
df = pd.read_excel("D:/Project/图纸清单.xlsx", sheet_name="Sheet1")

# 图框块名称(需在模板文件中预先定义为带属性的块参照)
BLOCK_NAME = "A3_TITLE_BLOCK"

for idx, row in df.iterrows():
    # 图框插入点(每张图Y方向偏移420mm = A3图框高度+间距)
    insert_point = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,
                                           [0.0, -idx * 420.0, 0.0])
    # 插入图框块参照
    block_ref = ms.InsertBlock(insert_point, BLOCK_NAME, 1, 1, 1, 0)

    # 遍历块的属性并填充
    attrs = block_ref.GetAttributes()
    for attr in attrs:
        tag = attr.TagString.upper()
        if tag == "DWG_NO":
            attr.TextString = str(row["图号"])
        elif tag == "DWG_NAME":
            attr.TextString = str(row["图名"])
        elif tag == "DESIGNER":
            attr.TextString = str(row["设计"])
        elif tag == "DATE":
            attr.TextString = str(row["日期"])

print(f"完成:{len(df)} 张图框已生成")

# 缩放到全部图形范围
zwcad.ZoomExtents()

关键点: 图框块必须在模板文件(.dwt 或 .dwg)中预先定义为带属性的块参照。属性标签(TagString)在块定义阶段设定,上述代码中的 DWG_NODWG_NAME 等标签需要与块定义中的属性标签完全一致(代码中做了大写转换容错)。如果不确定属性标签名称,可以先在CAD中打开块编辑器逐个查看,或用以下代码打印所有属性标签:

代码语言:python
复制
for attr in block_ref.GetAttributes():
    print(f"Tag: {attr.TagString}, Value: {attr.TextString}")

三、场景二:基于配置文件自动绘制轴网

建筑和结构图纸的第一步通常是绘制轴网——由水平和垂直轴线组成的网格,轴线间距和编号由设计参数决定。手工绘制一组 8×6 的轴网需要反复执行偏移、标注、编号操作,而用Python可以在三秒内生成。

配置层:用JSON定义轴网参数

代码语言:json
复制
{
    "grid_name": "轴网-01",
    "x_spacing": [4200, 3600, 3600, 4200],
    "y_spacing": [6000, 2400, 6000],
    "x_labels": ["1", "2", "3", "4", "5"],
    "y_labels": ["A", "B", "C", "D"],
    "extension": 2500,
    "circle_radius": 400
}

绘制代码

代码语言:python
复制
import json

with open("D:/Project/grid_config.json", "r", encoding="utf-8") as f:
    cfg = json.load(f)

def add_line(start, end):
    """在中望CAD模型空间中添加直线"""
    return ms.AddLine(
        win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list(start)),
        win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list(end))
    )

def add_circle(center, radius):
    """添加圆(用于轴线编号)"""
    return ms.AddCircle(
        win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list(center)),
        radius
    )

# 计算累积坐标
x_coords = [0]
for sp in cfg["x_spacing"]:
    x_coords.append(x_coords[-1] + sp)

y_coords = [0]
for sp in cfg["y_spacing"]:
    y_coords.append(y_coords[-1] + sp)

ext = cfg["extension"]
cir_r = cfg["circle_radius"]

# 绘制垂直轴线(沿X方向偏移)
for i, x in enumerate(x_coords):
    y_min = y_coords[0] - ext
    y_max = y_coords[-1] + ext
    add_line((x, y_min, 0), (x, y_max, 0))
    # 底部编号圆
    add_circle((x, y_min - cir_r * 2, 0), cir_r)

# 绘制水平轴线(沿Y方向偏移)
for i, y in enumerate(y_coords):
    x_min = x_coords[0] - ext
    x_max = x_coords[-1] + ext
    add_line((x_min, y, 0), (x_max, y, 0))
    # 左侧编号圆
    add_circle((x_min - cir_r * 2, y, 0), cir_r)

print("轴网绘制完成")

设计思路: 轴网间距参数用JSON管理而非硬编码,原因有二:一是不同项目的轴网尺寸不同,修改配置文件比修改代码安全;二是JSON可以纳入版本管理(Git),设计变更时追溯轴网参数的历史记录。


四、场景三:批量导出PDF——图幅自动识别

图纸完成后最常见的体力劳动是将DWG逐张导出为PDF。中望CAD的导出方法需要指定打印范围,手动操作需要逐张框选。Python方案是遍历模型空间中的图框块,读取每个图框的边界坐标作为打印窗口,一键批量导出。

代码语言:python
复制
import os

output_dir = "D:/Project/PDF_Output"
os.makedirs(output_dir, exist_ok=True)

# 遍历模型空间中所有块参照
for entity in ms:
    if entity.EntityName == "AcDbBlockReference":
        name = entity.Name.upper()
        if "TITLE_BLOCK" not in name and "A3" not in name and "A4" not in name:
            continue  # 跳过非图框块

        # 获取图框包围盒
        bbox = entity.GetBoundingBox()
        min_pt = bbox[0]  # 左下角
        max_pt = bbox[1]  # 右上角

        # 获取图纸编号(从图框属性中提取)
        dwg_no = "unknown"
        for attr in entity.GetAttributes():
            if attr.TagString.upper() == "DWG_NO":
                dwg_no = attr.TextString
                break

        # 设置打印窗口并导出PDF
        layout = doc.ActiveLayout
        plot_cfg = doc.PlotConfigurations.Add(f"TEMP_{dwg_no}")

        # 图幅尺寸判断(A3=420×297, A4=297×210)
        width = max_pt[0] - min_pt[0]
        height = max_pt[1] - min_pt[1]
        paper_name = "A3" if width > 350 else "A4"
        plot_cfg.CanonicalMediaName = paper_name

        # 窗口打印范围
        plot_cfg.PlotWindowArea(
            win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,
                                    [min_pt[0], min_pt[1]]),
            win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,
                                    [max_pt[0], max_pt[1]])
        )

        pdf_path = os.path.join(output_dir, f"{dwg_no}.pdf")
        doc.PlotToFile(pdf_path, plot_cfg.ConfigName)
        print(f"[{dwg_no}] → {pdf_path}")

print(f"PDF导出完成,文件数:{len(os.listdir(output_dir))}")

实际使用中的两个坑:

一是中望CAD的打印配置在批量操作时不稳定,连续打印过多文件后偶尔出现内存泄漏导致COM连接中断。解决方法是在每10张图后插入 doc.Regen(0) 刷新图形数据库并手动调用垃圾回收。

二是DWG文件名与图框中的图号不一致时,PDF文件名会出错。建议在实际脚本开头加入一致性校验:遍历所有图框提取图号集合,与Excel清单做差集比对,发现不匹配时输出警告后暂停。


五、COM接口的常见坑与调试方案

COM自动化开发中最难排查的不是语法错误,而是COM对象引用失效——Python端的变量指向了CAD中已被释放的对象,调用时报 COMError: (-2147417848, '被调用的对象已与其客户端断开连接')

排查路径:

  1. 不要缓存COM对象引用。每次循环迭代时重新获取 ActiveDocumentModelSpace,避免因图形数据库更新导致引用失效。
  2. 所有坐标参数必须显式转换为 win32com.client.VARIANT 类型,直接传Python的tuple在部分COM方法中会导致类型不匹配的静默错误——对象被创建但位置落在原点。
  3. 开发调试时建议先打开中望CAD手动新建一个空白文档,再用 GetObject(None, "ZWCAD.Application") 连接到已运行实例(而不是每次Dispatch启动新实例),可以直观看到脚本每一步在CAD中的效果。

本文基于中望CAD 2025 + Python 3.11 + pywin32 306 实测。代码中的VARIANT数组构造依赖 pythoncom 模块,该模块随 pywin32 一并安装,无需额外依赖。中望CAD可通过官网下载安装,支持 Windows 10/11 系统。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、启动中望CAD的COM接口
    • 环境准备
    • 建立连接
  • 二、场景一:从Excel数据批量生成带属性图框
    • 核心代码
  • 三、场景二:基于配置文件自动绘制轴网
    • 配置层:用JSON定义轴网参数
    • 绘制代码
  • 四、场景三:批量导出PDF——图幅自动识别
  • 五、COM接口的常见坑与调试方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档