TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Lee Mac on June 01, 2009, 10:30:48 AM
-
I am not entirely confident in using this function, but I want to master it.
Currently, when extracting an item from a collection, I am using vlax-for to cycle through the collection, and using some kind of conditional within the loop to get the required object, for example:
(vlax-for lay (vla-get-layers
(vla-get-ActiveDocument
(vlax-get-acad-object)))
(if (eq "LayerName" (vla-get-Name lay))
(setq layer lay)))
But is there a way to get at this item directly? I thought perhaps vla-item, but I may be mistaken.
[ And if it isn't Vla-item, then what exactly is Vla-item for...? ]
Many thanks for your time as always,
Cheers,
Lee
-
Try this:
(setq LayerName "Duct")
(setq LayerCollection (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object))))
(setq LayObj (vl-catch-all-apply 'vla-Item (list LayerCollection LayerName)))
If the layername does not exist the catch all will save you.
-
Another way to get it. Not what you asked, I know.
(if (setq LayEnt (tblobjname "layer" Layername))
(setq LayObj (vlax-ename->vla-object LayEnt))
)
-
Excellent Alan, thanks -
I have received some great help from RonJonP over at CADTutor on this also - and with your tip of using a touch of Error Trapping - this really helps.
Many thanks for your time, it is appreciated as always,
Cheers,
Lee
-
Don't forget vlax-map-collection
(vlax-map-collection (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(function (lambda(x) (if (vlax-property-available-p x 'objectname)
(print (vla-get-objectname x)))))
)
OR
(vlax-map-collection (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-Acad-Object))) 'vlax-dump-object)
-
Hi,
Because vla-item returns an error if the item isn't found in the collection, I wrote a little function which uses vl-catch-apply so that the function returns the vla-object or nil.
(defun GetItem (col name / obj)
(vl-catch-all-apply
'(lambda () (setq obj (vla-item col name)))
)
obj
)
(GetItem (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object))) "0")
returns : #<VLA-OBJECT IAcadLayer 06ca9ad4>
(GetItem (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object))) "test")
returns nil (if there's no "test" layer in the collection)
Using the same way, I have another one to get an object from its handle if it hasn't been erased (otherwise nil).
(defun HandleToObject (handle / obj)
(vl-catch-all-apply
'(lambda ()
(setq obj (vla-HandleToObject
(vla-get-ActiveDocument (vlax-get-acad-object))
handle
)
)
)
)
obj
)
-
Don't forget vlax-map-collection
(vlax-map-collection (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(function (lambda(x) (if (vlax-property-available-p x 'objectname)
(print (vla-get-objectname x)))))
)
OR
(vlax-map-collection (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-Acad-Object))) 'vlax-dump-object)
Thanks Alan, I always seem to overlook vlax-map-collection when vlax-for always seems the easier method, but I am grateful for your informative examples :-)
Thanks
-
(defun HandleToObject (handle / obj)
(vl-catch-all-apply
'(lambda ()
(setq obj (vla-HandleToObject
(vla-get-ActiveDocument (vlax-get-acad-object))
handle
)
)
)
)
obj
)
Gile,
Thank you for your response,
I realise that your first example is similar to that posted by CAB earlier in this thread to handle errors returned from vla-item.
However, I do have a question regarding your second posted example,
Why would you use an Object's Handle in operations?
Excuse me if my question seems a little "simple", but I have never used an Object Handle in this way.
Thanks,
Lee
-
I realise that your first example is similar to that posted by CAB earlier in this thread to handle errors returned from vla-item.
Yes, but using GetItem avoid to write:
(if (not (vl-catch-all-error-p (setq LayObj (vl-catch-all-apply (vla-item ...))))) (do_something ...))
Just write:
(if (setq LayObj (GetItem ...)) (do_something ...))
Why would you use an Object's Handle in operations?
An entity's name can change from one editing session to the next, but an entity's handle remains constant. So if you need to store objects using xdatas, ldatas or xrecords in a dictionary from one session to another, you have to store their handles.
For example, I use this way to store the objects which are linked to some block reference in TotalArea.lsp (http://www.theswamp.org/index.php?topic=28604.0)
-
I have in fact used your TotalAreas.lsp - an impressive bit of kit indeed - well done.
Thank you for your superb explanation of object handles, I hadn't considered that aspect before, and originally thought that the object handle also changed with the entity name from session to session - thank you for clarifying this.
Cheers,
Lee
-
Thanks Lee Mac, you're welcome.
-
Hi,
Because vla-item returns an error if the item isn't found in the collection, I wrote a little function which uses vl-catch-apply so that the function returns the vla-object or nil.
(defun GetItem (col name / obj)
(vl-catch-all-apply
'(lambda () (setq obj (vla-item col name)))
)
obj
)
gile,
I was doing some research & ran across this old thread.
Wouldn't (vlax-erased-p Obj) work as well as your (defun GetItem ?
Just wondering if there are any pitfalls with using vlax-erased-p
-
CAB,
I assume you may be referring to Gile's post about the HandletoObject method?
I don't see why vlax-erased-p would cause a problem, but I would be far more inclined to use:
(entget (handent <handle>))
Which returns nil with no error if the object is erased.
PS> This thread seems like ages ago, its amazing how much I have learnt from you guys since then... :wink:
Lee
-
I should have been more clear with my comment.
This is what I had in mind.
(defun GetItem (col name)
(if (not (vlax-erased-p name))
(vla-item col name)
)
)
PS you've been on the "Fast Track" 8-)
-
Ooo, I've never seen it used in that way before...
At a first glance, without testing anything, I thought that vlax-erased-p just checked the erased flag of an object, so if an item never existed in a collection, then I would assume it would error out...
EDIT:
(GetItem (vla-get-layers *doc) "Lee")
; error: unable to get ObjectID: "Lee"
-
Lee Mac.
Completely off topic here: is that you in our avatar??
jb
p.s. No, that's NOT me in my avatar . . . ;)
-
Ooo, I've never seen it used in that way before...
At a first glance, without testing anything, I thought that vlax-erased-p just checked the erased flag of an object, so if an item never existed in a collection, then I would assume it would error out...
EDIT:
(GetItem (vla-get-layers *doc) "Lee")
; error: unable to get ObjectID: "Lee"
Thanks Lee, that answers my question. Looks like gile has a keeper there. :-)
-
Lee Mac.
Completely off topic here: is that you in our avatar??
jb
p.s. No, that's NOT me in my avatar . . . ;)
Hey James,
No, not me in the avatar, but I do ride a CBR600F :-)
-
Don't forget vlax-map-collection
Being as how this is LISP, one might expect vlax-map-collection to behave similar to mapcar, but noooo :(
;;vlax-map-collection returns the collection object, not a list
;;you must build the list yourself as a side effect (yuck!)
;;so here is a simple wrapper which is proper LISP, i.e. function returns a useful value
(defun map-collection (obj func / return)
(vlax-map-collection obj
'(lambda (obj / )
(setq return (cons (func obj) return))
)
)
return
)
;;equivalent
(vlax-for item collection
(setq return (cons (func item) return))
)
-
and it's slower (well, marginally) as well as uglier :)
(defun getLockedLayers1 (/ layNames)
(vlax-map-collection
(vla-get-layers (vla-get-activedocument (vlax-get-acad-object)))
'(lambda (x)
(if (= (vla-get-lock x) :vlax-true)
(setq layNames (cons (vla-get-name x) layNames))
)
)
)
(reverse layNames)
)
(defun getLockedLayers2 (/ layNames)
(vlax-for item (vla-get-layers (vla-get-activedocument (vlax-get-acad-object)))
(if (= (vla-get-lock item) :vlax-true)
(setq layNames (cons (vla-get-name item) layNames))
)
)
(reverse layNames)
)
(benchmark '((getLockedLayers1)
(getLockedLayers2)
)
)
;=> ("X_NoPlot" "x-T50" "x-T35" "x-T25")
Benchmarking [M.P. 2005 < revised kdub 2005>] ..........
Elapsed milliseconds for 128 iteration(s)/ relative Timing :
(GETLOCKEDLAYERS1).....1703 / 1.0185 <slowest>
(GETLOCKEDLAYERS2).....1672 / 1.0000 <fastest>
-
And what does this do for the time? :evil:
(defun getLockedLayers1 (/ layNames)
(vlax-map-collection (vla-get-layers (vla-get-activedocument (vlax-get-acad-object)))
(function (lambda (x)
(if (= (vla-get-lock x) :vlax-true)
(setq layNames (cons (vla-get-name x) layNames))
)
))
)
(reverse layNames)
)
-
Yep .. good point !!
Benchmarking [M.P. 2005 < revised kdub 2005>] ..........
Elapsed milliseconds for 128 iteration(s) / relative Timing :
(GETLOCKEDLAYERS1).....1172 / 1.0559 <slowest> ;<<<< using vlax-map-collection
(GETLOCKEDLAYERS2).....1125 / 1.0135 ;<<<< using vlax-for
(GETLOCKEDLAYERS3).....1110 / 1.0000 <fastest> ;<<<< using (function(lambda ... in place of '(lambda ... with vlax-map-collection
but it's still ugly :-P
... nah, it's not really :)