Win32com、Python 和 AutoCAD 的变体错误
Variant Errors with Win32com, Python and AutoCAD
受到 的启发,我正在尝试使用 python 和 win32com.client 来操作打开的 AutoCAD 文件,并将给定图层中的所有对象收集到 select离子组:
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)
select 命令炸弹并显示以下错误消息:
ArgumentError: argument 2: <class 'TypeError'>: Cannot put win32com.client.VARIANT(8194, [8]) in VARIANT
我模糊地理解这个错误,因为它抱怨第二个参数的 type/format(可能还有第三个,如果它到了那么远)但我不明白为什么:它似乎在说我知道它不能在需要 VARIANT 的插槽中接受特定的 VARIANT,但我不知道为什么。
回答时请记住,我精通 python、AutoCAD 和老派的 AutoLISP 编码,但对 win32com(或任何其他 com)几乎一无所知,尤其是变体,或让 AutoCAD 与 python 一起工作。
(对于其他老派:我正在尝试模仿 SSGET 命令。)
就我个人而言,我对 selection sets 不是很有经验,所以我偶然发现了一个没有使用它们的解决方案。下面的代码是循环遍历模型 space 中的每个对象的示例,检查它是否具有特定层,并构建一个字符串,该字符串将 select 所有对象通过 SendCommand
.
我相信您实际上也可以使用 SendCommand
来操纵 select 离子组。 (类似于 autolisp 中的 (command "ssget")
)我个人发现这个解决方案更容易解决。
# 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)
在 VBA 中引用签名是:
object.Select Mode[, Point1][, Point2][, FilterType][, FilterData]
试试这个:
SSet.Select(5, None, None, FilterType, FilterData)
受到
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)
select 命令炸弹并显示以下错误消息:
ArgumentError: argument 2: <class 'TypeError'>: Cannot put win32com.client.VARIANT(8194, [8]) in VARIANT
我模糊地理解这个错误,因为它抱怨第二个参数的 type/format(可能还有第三个,如果它到了那么远)但我不明白为什么:它似乎在说我知道它不能在需要 VARIANT 的插槽中接受特定的 VARIANT,但我不知道为什么。
回答时请记住,我精通 python、AutoCAD 和老派的 AutoLISP 编码,但对 win32com(或任何其他 com)几乎一无所知,尤其是变体,或让 AutoCAD 与 python 一起工作。
(对于其他老派:我正在尝试模仿 SSGET 命令。)
就我个人而言,我对 selection sets 不是很有经验,所以我偶然发现了一个没有使用它们的解决方案。下面的代码是循环遍历模型 space 中的每个对象的示例,检查它是否具有特定层,并构建一个字符串,该字符串将 select 所有对象通过 SendCommand
.
我相信您实际上也可以使用 SendCommand
来操纵 select 离子组。 (类似于 autolisp 中的 (command "ssget")
)我个人发现这个解决方案更容易解决。
# 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)
在 VBA 中引用签名是:
object.Select Mode[, Point1][, Point2][, FilterType][, FilterData]
试试这个:
SSet.Select(5, None, None, FilterType, FilterData)