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 ')
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 ')