pythonwin32comautocaddxfdwg

How to change the properties of an AutoCAD object programmatically in Python


I want to automatically process a bunch of AutoCAD drawings using Python. To that end I need to change the properties of the drawing entities programmatically. I've been struggling for a while, to no avail.

This is the code I'm using to read the .dxf and open the .dwg files:

import win32com.client
import dxfgrabber
import os

folder = r'C:\path\to\my\folder'
filename = 'my_file'

dwg_path = os.path.join(folder, filename + '.dwg')
dxf_path = os.path.join(folder, filename + '.dxf')

acad = win32com.client.dynamic.Dispatch("AutoCAD.Application")
doc = acad.Documents.Open(dwg_path)
acad.Visible = True

dxf = dxfgrabber.readfile(dxf_path)

Then I iterate over the objects placed in a layer called FirstLayer and select one of them:

item = [obj for obj in dxf.entities if obj.layer == 'FirstLayer'][0]

This particular entity is a text object:

In [1122]: type(item)
Out[1122]: dxfgrabber.dxfentities.Text

In [1123]: item.insert
Out[1123]: (4022.763956904745, 3518.371877135191, 0.0)

In [1124]: item.layer
Out[1124]: 'FirstLayer'

In [1125]: item.handle
Out[1125]: '298'

My goal is to change properties such as color, layer, etc. This is one of my attempts to move the text object to a different layer called SecondLayer:

doc.SendCommand(f'CHPROP {item.insert[0]},{item.insert[1]} LA\n SecondLayer\n ')

I guess the problem is that the object cannot be selected through the coordinates of the insertion point. I also tried (unsuccessfully) to select the object by its handle using the following script:

_CHPROP (handent 298) _LA SecondLayer 

Any ideas on how to work around this?


EDIT
I came up with the following solution before @Lee Mac posted his excellent answer:

doc.SendCommand(f'CHPROP (handent "{item.handle}") \n_LA SecondLayer\n ')        

Solution

  • Upon issuing the CHPROP command, the subsequent object selection prompt will either require you to supply one or more entity names (which may be obtained by converting a handle using the AutoLISP handent function), or supplying a selection set (which may be obtained using the AutoLISP ssget function).

    You were very close with your use of handent, however entity handles in AutoCAD are represented by hexadecimal strings and so you will need to supply the handent function with a string argument surrounded by double-quotes, e.g.:

    (handent "298")
    

    If the supplied handle is valid, handent will then return an entity name pointer:

    _$ (handent "3B8")
    <Entity name: 7ffff706880>
    

    However, since CHPROP accepts a selection set argument, you needn't iterate over every entity, but instead simply supply CHPROP with a filter selection set, e.g.:

    doc.SendCommand(f'CHPROP (ssget "_x" (list (cons 8 "FirstLayer"))) LA\n SecondLayer\n ')