Author Topic: Using VLA-ITEM  (Read 8626 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Using VLA-ITEM
« 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:
Code: [Select]
(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

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #1 on: June 01, 2009, 10:41:52 AM »
Try this:
Code: [Select]
(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.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #2 on: June 01, 2009, 10:47:33 AM »
Another way to get it. Not what you asked, I know.
Code: [Select]
(if (setq LayEnt (tblobjname "layer" Layername))
  (setq LayObj (vlax-ename->vla-object LayEnt))
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #3 on: June 01, 2009, 10:48:25 AM »
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

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #4 on: June 01, 2009, 11:14:19 AM »
Don't forget vlax-map-collection

Code: [Select]
(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
Code: [Select]
(vlax-map-collection (vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-Acad-Object))) 'vlax-dump-object)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Using VLA-ITEM
« Reply #5 on: June 01, 2009, 11:48:52 AM »
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.

Code: [Select]
(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).

Code: [Select]
(defun HandleToObject (handle / obj)
  (vl-catch-all-apply
    '(lambda ()
       (setq obj (vla-HandleToObject
   (vla-get-ActiveDocument (vlax-get-acad-object))
   handle
)
       )
     )
  )
  obj
)
Speaking English as a French Frog

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #6 on: June 01, 2009, 12:05:15 PM »
Don't forget vlax-map-collection

Code: [Select]
(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
Code: [Select]
(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

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #7 on: June 01, 2009, 12:09:26 PM »
Code: [Select]
(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

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Using VLA-ITEM
« Reply #8 on: June 01, 2009, 12:43:03 PM »
Quote
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 ...))


Quote
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
Speaking English as a French Frog

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #9 on: June 01, 2009, 01:24:00 PM »
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

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Using VLA-ITEM
« Reply #10 on: June 01, 2009, 01:37:25 PM »
Thanks Lee Mac, you're welcome.
Speaking English as a French Frog

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #11 on: February 04, 2010, 11:42:05 AM »
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.

Code: [Select]
(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
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #12 on: February 04, 2010, 02:41:40 PM »
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:

Code: [Select]
(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

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #13 on: February 04, 2010, 03:27:13 PM »
I should have been more clear with my comment.
This is what I had in mind.
Code: [Select]
(defun GetItem (col name)
  (if (not (vlax-erased-p name))
    (vla-item col name)
  )
)

PS you've been on the "Fast Track"  8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #14 on: February 04, 2010, 03:30:41 PM »
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:

Code: [Select]
(GetItem (vla-get-layers *doc) "Lee")
; error: unable to get ObjectID: "Lee"
« Last Edit: February 04, 2010, 03:34:36 PM by Lee Mac »

jbuzbee

  • Swamp Rat
  • Posts: 851
Re: Using VLA-ITEM
« Reply #15 on: February 05, 2010, 07:25:07 AM »
Lee Mac.

Completely off topic here: is that you in our avatar??

jb

p.s. No, that's NOT me in my avatar . . . ;)
James Buzbee
Windows 8

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #16 on: February 05, 2010, 08:21:37 AM »
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:

Code: [Select]
(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. :-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using VLA-ITEM
« Reply #17 on: February 05, 2010, 11:47:51 AM »
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  :-)

hermanm

  • Guest
Re: Using VLA-ITEM
« Reply #18 on: February 08, 2010, 09:10:52 PM »
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 :(

Code: [Select]
;;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))
)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Using VLA-ITEM
« Reply #19 on: February 08, 2010, 10:05:40 PM »
and it's slower (well, marginally) as well as uglier :)

Code: [Select]
(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>
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using VLA-ITEM
« Reply #20 on: February 08, 2010, 11:06:33 PM »
And what does this do for the time?  :evil:
Code: [Select]
(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)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Using VLA-ITEM
« Reply #21 on: February 09, 2010, 03:12:18 AM »
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  :)
« Last Edit: February 09, 2010, 03:27:58 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.