vlax-for block collection

vlax-for block collection

DGRL
Advisor Advisor
10,541 Views
28 Replies
Message 1 of 29

vlax-for block collection

DGRL
Advisor
Advisor

Dear coders

 

Coding in Visual lisp trying to get complete list of all entities inside block using the vlax-for method

This is the code I use ( gives back all items in dwg ( model and layouts) )

Why does this code gives back all entities in the dwg instead of the entities inside the block?

I used the vla-get-blocks for active document

 

 

    (setq acadObj (vlax-get-acad-object))
    (setq doc (vla-get-ActiveDocument acadObj))
    ;; Get the Blocks collection
    (vlax-for blkColl (vla-get-Blocks doc)
		(vlax-for blkobj blkColl
		
			(setq ename (vlax-vla-object->ename blkobj))
			(print (entget ename))	
		
		)
    )

 

This is the list I get back now

 

(0 . "INSERT")
(0 . "LINE")
(0 . "LINE")  <-- BLOCK ENTITY
(0 . "CIRCLE")  <-- BLOCK ENTITY
(0 . "VIEWPORT")
(0 . "VIEWPORT")
(0 . "VIEWPORT")
(0 . "VIEWPORT")
(0 . "LWPOLYLINE")  <-- BLOCK ENTITY
(0 . "TEXT") <-- BLOCK ENTITY
(0 . "LINE")

 

 3 block entities and rest is in model space

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Accepted solutions (2)
10,542 Views
28 Replies
Replies (28)
Message 2 of 29

Kent1Cooper
Consultant
Consultant
Accepted solution

@DGRL wrote:

.... 

Coding in Visual lisp trying to get complete list of all entities inside block ....


If you're looking for all entities in a specific individual  Block definition, you can do this [here for a Block named "test"]:

 

(setq ent (tblobjname "block" "test"))
(while (setq ent (entnext ent))
  (prompt (strcat "\n" (cdr (assoc 0 (entget ent)))))
)
(princ)

 

 

Since your code does not specify a particular Block name, maybe you're after something different.  Are you looking for all entities in all Block definitions?  Or all entities in all Block references/insertions?  That is, if a Block definition contains a Circle, and that Block is inserted four times, do you want the return to include one  Circle [for the one in the definition] or all four  Circles [the one in each Block insertion listed separately]?

Kent Cooper, AIA
Message 3 of 29

DGRL
Advisor
Advisor

@Kent1Cooper

 

 

Thanks for the reply

 

What I am seeking for is this,

 

1 basic function to get all entities of an block

 

What do I want to do?

I want to get/select all the Blocks in the dwg and then process its entities

If 1 block is inserted 4 times then I want that block as 4 separate items in the list to process.

 

1. select all blocks in dwg

2. get all entities per block and do something with it

 

I wanted to learn the vlax-for function  🙂

 

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 4 of 29

DGRL
Advisor
Advisor

@Kent1Cooper

 

 

I have a question I want to ask you
Its for me to learn from

 

If you look at the code below

It makes a selection of all the blocks correct?  (i.e  vla-get-blocks)

If I run this code it prints the entget

Why do I see non block items in the list that is printed?
even though I did not made a selection based on block name I did only selected blocks or am I wrong?

 

(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(vlax-for blk (vla-get-blocks doc)
		;(if (= :vlax-false (vla-get-isxref blk))
		;(if (= blk "aTitle Block")(print "YES")(print blk))
		;(print blk)
			(vlax-for obj blk
			
			(setq ename (vlax-vla-object->ename obj))
			(print (entget ename))	
				
			); end of vlax-for obj blk
		;)
	(princ)
); end of vlax-for blk
If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 5 of 29

Kent1Cooper
Consultant
Consultant

@DGRL wrote:

.... 

1 basic function to get all entities of an block

 

What do I want to do?

I want to get/select all the Blocks in the dwg and then process its entities

If 1 block is inserted 4 times then I want that block as 4 separate items in the list to process.

.... 


I don't understand.  If you "process" the entities in the definition of a Block that is inserted 4 times, they will change in all 4 Block insertions -- you don't need to process them in each Block insertion separately.  If you want to process those in one insertion differently  from those in other insertions, then you'll have to Explode the Blocks, or you'll have to play with dynamic Blocks and visibility states or something, in which case you'll still only process the entities in the Block definition once, and then the differences between insertions will have to be done by processing the Block insertions, not the entities in them.  Am I misunderstanding?

Kent Cooper, AIA
0 Likes
Message 6 of 29

DGRL
Advisor
Advisor

@Kent1Cooper

 

 

Quote

 

" If you "process" the entities in the definition of a Block that is inserted 4 times, they will change in all 4 Block insertions "

This is not true as blocks with attributes can be inserted hundreds of times and still containing different text strings.

This is only for ATRIBS as far as i know

 

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 7 of 29

DGRL
Advisor
Advisor

Got what I need to begin with

 

	(if
		(and
			(setq sel (entsel "Select a block: "))
			(= (cdr (assoc 0 (setq nfo (entget (car sel))))) "INSERT")
		)
		(vlax-for item
			(vla-item
				(vla-get-blocks
					(vla-get-activedocument
						(vlax-get-acad-object)
					)
				)
				(cdr (assoc 2 nfo))
			)
			(setq items (cons (vlax-vla-object->ename item) items))
		)
		(prompt "\nNo block selected.")
	)
If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 8 of 29

_gile
Consultant
Consultant

Hi,

 

(vla-get-Blocks doc) returns the block table collection which contains all block definitions plus the layouts blocks (paper and model space).

 

If you want to only get entities within block definitions, you have to discard layout blocks

 

(vlax-for block	(vla-get-Blocks doc)
  (if (and (= (vla-get-IsLayout block) :vlax-false)
	   (= (vla-get-IsXref block) :vlax-false)
      )
    (vlax-for obj block
      ...
    )
  )
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 29

_gile
Consultant
Consultant

While playing with vla* functions:

 

(if (and (setq ent (car (entsel)))
	 (setq obj (vlax-ename->vla-object ent))
	 (= (vla-get-ObjectName obj) "AcDbBlockReference")
    )
  (vlax-for obj	(vla-Item (vla-get-Blocks doc) (vla-get-Name obj))
    ...
  )
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 29

DGRL
Advisor
Advisor

@_gile

 

Thanks 🙂

I have to go now but a quick test gave back an error

 

; error: ActiveX Server returned the error: unknown name: Blocks

 

Will look at it at home

BRB

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 11 of 29

Kent1Cooper
Consultant
Consultant

@_gile wrote:

.... 

(vla-get-Blocks doc) returns the block table collection which contains all block definitions plus the layouts blocks (paper and model space).

.... 


But that doesn't seem to be the case.  It seems to return more than that -- not only Blocks and the pieces in them and Layouts, but also other objects [maybe all  other objects?] that are neither Blocks nor parts of Block definitions nor Layouts.  See the two Line entities that are not identified as Block entities in Post 1, and I've confirmed the same with a little experimentation.  Since the AutoLisp Reference doesn't cover (vla-...) functions [though it does cover (vl-...) and (vlax-...) and (vlr-...) functions], I don't know how to find out what (vla-get-Blocks) actually returns, but it seems clearly not  to be as described above.

Kent Cooper, AIA
0 Likes
Message 12 of 29

rkmcswain
Mentor
Mentor
Perhaps the code here would help out?
0 Likes
Message 13 of 29

_gile
Consultant
Consultant
Accepted solution

@Kent1Cooper wrote:

@_gile wrote:

.... 

(vla-get-Blocks doc) returns the block table collection which contains all block definitions plus the layouts blocks (paper and model space).

.... 


But that doesn't seem to be the case.  It seems to return more than that -- not only Blocks and the pieces in them and Layouts, but also other objects [maybe all  other objects?] that are neither Blocks nor parts of Block definitions nor Layouts.  See the two Line entities that are not identified as Block entities in Post 1, and I've confirmed the same with a little experimentation.  Since the AutoLisp Reference doesn't cover (vla-...) functions [though it does cover (vl-...) and (vlax-...) and (vlr-...) functions], I don't know how to find out what (vla-get-Blocks) actually returns, but it seems clearly not  to be as described above.


Yes it is.

You can get the docs for the vla* function in the ActiveX Documentation.

You can also simply select vla-get-Blocks in the VLIDE and hit Ctrl+F1 which will open the ActiveX Reference Guide at the Blocks topic.

Here's the Blocks topic in the in line ActiveX Reference Guide.

 

That said, (vlax-for block (vla-ge-Blocks doc) ... )iterates through all the block table collection, just try:

 

(vlax-for block	(vla-get-Blocks
		  (vla-get-ActiveDocument
		    (vlax-get-acad-object)
		  )
		)
  (princ (strcat "\n" (vla-get-Name block)))
)

Then, while doing (vlax-for block (vla-ge-Blocks doc) (vlax-for obj block ...)) iterates through all objects in all block defintions and spaces of the drawing (i.e. all graphic entities of the drawing).

Just try:

 

(vlax-for block	(vla-get-Blocks
		  (vla-get-ActiveDocument
		    (vlax-get-acad-object)
		  )
		)
  (princ (strcat "\n" (vla-get-Name block)))
  (vlax-for obj	block
    (princ (strcat "\n\t" (vla-get-ObjectName obj)))
  )
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 29

DGRL
Advisor
Advisor

@_gile

 

May i ask you why the result of this code is giving me back all the objects in model incl. nested objects

    (setq acadObj (vlax-get-acad-object))
    (setq doc (vla-get-ActiveDocument acadObj))
    
    ;; Get the Blocks collection
    (vlax-for blkColl (vla-get-Blocks doc)

		(vlax-for blkobj blkColl
		
			(setq ename (vlax-vla-object->ename blkobj))
			(print (entget ename))	
		
		)
    )

This code gives back a list of all objects in model incl layouts and viewports
Including nested objects 

 

While this code only gives back my block collection

(vlax-for block	(vla-get-Blocks
		  (vla-get-ActiveDocument
		    (vlax-get-acad-object)
		  )
		)
  (princ (strcat "\n" (vla-get-Name block)))
)
Gives back per block  

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 15 of 29

_gile
Consultant
Consultant

I'll try an explanation.

You must try to see an AutoCAD drawing as a database.
This database contains several tables including the block table that contains all the block objects (called Block in the COM / ActiveX API used by the vla * function, or BlockTableRecord in .NET or AcDbBlockTableRecord in ObjectARX).
This includes block definitions, object and paper spaces.
Each block object is a container for graphic entities (circles, lines, block references, ...), in other words, in AutoCAD, any graphic entity belongs to a Block ob
ject.

 


@DGRL wrote:

@_gile

 

May i ask you why the result of this code is giving me back all the objects in model incl. nested objects

    (setq acadObj (vlax-get-acad-object))
    (setq doc (vla-get-ActiveDocument acadObj))
    
    ;; Get the Blocks collection
    (vlax-for blkColl (vla-get-Blocks doc)

      (vlax-for blkobj blkColl
...

 

While this code only gives back my block collection

(vlax-for block	(vla-get-Blocks
		  (vla-get-ActiveDocument
		    (vlax-get-acad-object)
		  )
		)
  ...

Because in the first one, you iterate through each entity of each Block object in the block table.

And in the second, you are only iterating through each Block object in the block table.

 

 

 

(vlax-for block (vla-get-Blocks doc) ...)

 

means: for each Block object in the drawing block table...

 

 

 

(vlax-for block (vla-get-Blocks doc)
  (vlax-for obj block
    ...
  )
)

means: for each Block object in the drawing block table do for each entity in this Block object ...

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 16 of 29

DGRL
Advisor
Advisor

@_gile

 

Thanks for the reply

this helped me a lot

 

Quote

"You must try to see an AutoCAD drawing as a database."


If you look at Acad as a database it becomes a lot easier

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 17 of 29

doaiena
Collaborator
Collaborator

Actually when you take a look at the object model and see how things are connected, it all starts to make sense. And it also helps you determine where to look for things if you are unsure.

ObjModel.png

 

Message 18 of 29

_gile
Consultant
Consultant

@doaiena, nice idea to show this,

 

But, in my opinion the top of the graph shoud have been like this:

 

ObjectModel.png

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 19 of 29

DGRL
Advisor
Advisor

@doaiena @_gile

 

 

Thanks for this info
Slowly but surely things are getting better and smoother

starting to see the big picture guys


Really really thanks for helping out. 🙂

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 20 of 29

DGRL
Advisor
Advisor

@_gile

 

 

I agree with your change for the block part.

Maybe we can ask Autodesk to change the graph

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes