Novak
Novak

Reputation: 4779

Variant Errors with Win32com, Python and AutoCAD

Inspired by this answer, I am trying to use python and win32com.client to manipulate an open AutoCAD file, and gather all objects from a given layer into a selection set:

from comtypes.client import *
from comtypes.automation import *
import win32com.client

acad = GetActiveObject("AutoCAD.Application")
doc = acad.ActiveDocument
SSet = doc.SelectionSets[0]

FilterType = win32com.client.VARIANT(VT_ARRAY|VT_I2, [8]) 
FilterData = win32com.client.VARIANT(VT_ARRAY|VT_VARIANT, ["Layer1"])
SSet.Select(5, FilterType, FilterData)

The select command bombs with the following error message:

ArgumentError: argument 2: <class 'TypeError'>: Cannot put win32com.client.VARIANT(8194, [8]) in VARIANT

I vaguely understand the error inasmuch as it is complaining about the type/format of the second argument (and probably the third, if it got that far) but I do not understand why: It seems to be telling me that it cannot accept a particular VARIANT in a slot that wants a VARIANT, but I don't know why.

Bear in mind when answering that I am proficient in python, in AutoCAD, and in old-school AutoLISP coding, but know almost nothing about win32com (or any other com), about variants in particular, or about getting AutoCAD to work with python.

(For the other old-schoolers: I'm trying to mimic an SSGET command.)

Upvotes: 1

Views: 1518

Answers (2)

Vitaly Tregubov
Vitaly Tregubov

Reputation: 41

In VBA reference the signature is:

object.Select Mode[, Point1][, Point2][, FilterType][, FilterData]

Try this:

SSet.Select(5, None,  None,  FilterType, FilterData)

Upvotes: 0

DoubleDouble
DoubleDouble

Reputation: 358

Personally I'm not very experienced with selection sets and so I stumbled across a solution without using them. The code below is an example of looping through each of the objects in the model space, checking if it has a specific layer, and builds a string that will select all the objects via SendCommand.

I believe you could actually use SendCommand to manipulate selection sets as well. (similar to (command "ssget") in autolisp) I just personally found this solution much easier to work out.

# I personally had better luck with comtypes than with win32com
import comtypes.client
try:
    # Get an active instance of AutoCAD
    app = comtypes.client.GetActiveObject('AutoCAD.Application', dynamic=True)
except WindowsError: # No active instance found, create a new instance.
    app = comtypes.client.CreateObject('AutoCAD.Application', dynamic=True)
    # if you receive dispatch errors on the line after this one, a sleep call can
    # help so it's not trying to dispatch commands while AutoCAD is still starting up.
    # you could put it in a while statement for a fuller solution

app.Visible = True
doc = app.ActiveDocument
# if you get the best interface on an object, you can investigate its properties with 'dir()'
m = comtypes.client.GetBestInterface(doc.ModelSpace)
handle_string = 'select'
for entity in m:
    if entity.Layer == 'Layer1':
        handle_string += ' (handent "'+entity.Handle+'")'

handle_string += '\n\n'
doc.SendCommand(handle_string)

Upvotes: 1

Related Questions