AfraLISP - Learn AutoLISP for AutoCAD productivity

Object Collections - Part 2

by Kenny Ramage

On the first page we looked at changing all the Layers Color property using the repeat command. Here's a much easier and quicker way :

(defun laycol1 ()
 
(vl-load-com)
  
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(vlax-for item theLayers
 
       	(vla-put-color item 3)
  
)
 
(princ)
 
);defun

vlax-for allows you to loop through each item in the collection, without having to count the number of objects and doing away with the need for loop control. This is the same method I used in the tempList function that we used earlier on in this tutorial.

Here's another example. Would you like to ensure that all your Layers are On before performing a certain function? Have a look at this :

(defun layeron ()
 
(vl-load-com)
  
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(vlax-for item theLayers
 
     (vlax-put-property item "LayerOn" ':vlax-true)
  
);vlax-for
 
(princ)
 
);defun

One word of warning. Do not add or remove objects whilst iterating through a collection. This can and will cause errors.

One of the most powerful commands in our collections arsenal is the vlax-map-collection function. If you are not familiar with the mapcar and lambda functions, I suggest you read my tutorial on these functions which you can find here.

Load and run this in the Visual Lisp Editor :

(defun layer-dump ()
 
(vl-load-com)
 
(setq theList '())
  
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(vlax-map-collection theLayers 'vlax-dump-object)
 
(princ)
 
);defun

This will dump all properties of all the Layer objects in your drawing to the console screen.

You are not limited to Visual Lisp functions within a vlax-map-collection call. You can also use your own user defined function. Let's say for some reason we wanted to make a list of all Layers in your drawing, switch all Layers On and change every Layer in the drawing to Color "5". This is how you could do it :

(defun layerMap ()
 
(vl-load-com)
 
(setq theList '())
  
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(vlax-map-collection theLayers 'layer-mod)
 
(princ)
 
);defun
 
(defun layer-mod (theLayer)
 
  (setq dwgName (vlax-get-property theLayer 'Name))
 
  (setq theList (append (list dwgName) theList))
 
  (setq theList (reverse theList))
 
  (vlax-put-property theLayer "LayerOn" ':vlax-true)
 
  (vla-put-color thelayer 5)
 
);defun

As you can see, each Layer object is passed to the function layer-mod as the argument. You could also write this as an inline function using lambda :

(defun layerMap1 ()
 
(vl-load-com)
 
(setq theList '())
  
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(vlax-map-collection theLayers
 
  '(lambda (theLayer)
 
    (setq dwgName (vlax-get-property theLayer 'Name))
 
    (setq theList (append (list dwgName) theList))
 
    (setq theList (reverse theList))
 
    (vlax-put-property theLayer "LayerOn" ':vlax-true)
 
    (vla-put-color thelayer 5)
 
  );lambda
 
);vlax-map-collection
 
(princ)
 
);defun

Want to add to a collection? Let's add a new Layer to our drawing :

(defun layerAdd ()
 
(vl-load-com)
 
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
 
(setq theLayers (vla-get-layers acadDocument))
 
(setq newLayer (vla-add theLayers "Steel"))
 
(vla-put-color newLayer 5)
 
(vla-put-linetype newLayer "Dashed2")
 
(princ)
 
);defun

This routine creates a new Layer named "Steel" with Color "5" and a Linetype of "Dashed2". If the Layer already exists, this routine simply does nothing.

To delete a Layer from the collection, simply use the delete method :

_$ (vla-delete newLayer)

Be careful though, if any objects within your drawing are referencing this Layer, you will get an error :

_$ (vla-delete newLayer)
; error: Automation Error. Object is referenced by other object(s)

Right, I've had enough of talking about collections. Now I'm going to check out my beer collection. It's not very big as I only collect the full ones. The empty ones I throw away. Ta, ta for now…