TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Aerdvark on March 15, 2011, 04:25:52 AM
-
Hi Swampers,
I want to run a routine that returns:
- a list of all blocks inside a drawing
- only modelspace
- only inserts (no Xrefs or images etc)
- if possible only the used inserts (not those who are in memory but not actually placed)
This is my start, any help is much appreciated.
(defun GetBlocksInDwg (/ BlocksInDataBase NumberOfBlocksInSelSet Blockname BlockList)
(if
(setq BlocksInDataBase (ssget "_X" '((0 . "INSERT"))))
(progn
(setq NumberOfBlocksInSelSet (sslength BlocksInDataBase))
(while
(not (minusp (setq NumberOfBlocksInSelSet (1- NumberOfBlocksInSelSet))))
(setq Blockname (cdr (assoc 2 (entget (ssname BlocksInDataBase NumberOfBlocksInSelSet)))))
(if
(not (member BlockName BlockList))
(setq BlockList (append (list BlockName) BlockList))
) ;_if
) ;_while
) ;_progn
) ;_if
(princ)
) ;_defun
Please do not provide me full code and / or total different approaches for I want to learn.
Btw: I have not localized BlockList because I want to check it afterwards with !BlockList on the commandbar... maybe there is an easy way to princ out the list to the commandline...?
Also, I tend to use way too long variablenames but that will change during programming.
-
Give this a try
(if (setq ss (ssget "_X" (list (cons 0 "INSERT")(cons 410 "Model"))))
(progn
(setq i 0 lst nil)
(while (setq en (ssname ss i))
(setq elist (entget en))
(if (eq 4 (logand 4 (cdr (assoc 70 (tblsearch "block" (cdr (assoc 2 elist))))))); <-- check on xref
(ssdel en ss))
(setq i (1+ i)))))
-
Using 410 flag in ssget will give you all blocks inserted in ModelSpace
(setq ss (ssget "_X" '((0 . "INSERT") (410 . "Model"))))
Then step into selection set and check if it has Path property
(vlax-property-available-p (vlax-ename->vla-object (ssname ss i)) 'Path); for i=0 to (sslength ss), or some other iteration method
If true, it is a Xref; else is a common block
-
Thank you both for the reply!! It is of great help.
To set up a filter is not hard after all, just have to know where to look.
The "vlax-property-available-p" function is totally new to me and needs my attention big time.
My code so far, and I am ready for now:
(defun GetBlocksInDwg (/ BlocksInDataBase NumberOfBlocksInSelSet Blockname) ; BlockList)
(vl-load-com) ; make visual lisp functions available
(if
(setq BlocksInDataBase
(ssget "_X"
(list ; setting up a filter in a list
(cons 0 "INSERT") ; ... for inserts
(cons 410 "Model") ; ... that are in modelspace
)
)
)
(progn
(setq NumberOfBlocksInSelSet (sslength BlocksInDataBase))
(while
(not (minusp (setq NumberOfBlocksInSelSet (1- NumberOfBlocksInSelSet))))
(setq Blockname (cdr (assoc 2 (entget (ssname BlocksInDataBase NumberOfBlocksInSelSet)))))
(if
(and
(not (member BlockName BlockList)) ; the item must not be in the list already
(not (vlax-property-available-p
(vlax-ename->vla-object (ssname BlocksInDataBase NumberOfBlocksInSelSet))
'Path
)
)
; and also it should not be an xref
; this function however should be explored by me
; it makes no sense at all to me...
; I noticed "vlax-ename->vla-object" is not in the help section so I'll google a bit
) ;_and
(setq BlockList (append (list BlockName) BlockList))
) ;_if
) ;_while
) ;_progn
) ;_if
(princ)
) ;_defun
-
Here is mine
(defun Get_BlockNames (/ blk_name blk_list)
(if (ssget "X" '((0 . "INSERt") (410 . "MODEL")))
(vlax-for blk (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object)))
(if
(and (not (vlax-property-available-p blk 'Path))
(not (member (setq blk_name (vla-get-Name blk)) blk_list)))
(setq blk_list (cons blk_name blk_list))
)
)
)
(vl-sort blk_list '<)
)
-
OMG the code is so much less compared to mine...
That is where the visual lisp (ActiveX) comes in.
I will have to study this very hard for I never used ActiveX before.
Thanks for the code & the help.
-
That is where the visual lisp (ActiveX) comes in.
Note that the use of ActiveX isn't absolutely necessary:
(defun c:test ( / i l n s ss x ) (setq s "")
(while (setq x (tblnext "BLOCK" (null x)))
(if (= 4 (logand 4 (cdr (assoc 70 x)))) (setq s (strcat s (cdr (assoc 2 x)) ",")))
)
(if (setq ss (ssget "_X" (list (cons 0 "INSERT") (cons -4 "<NOT") (cons 2 (substr s 1 (1- (strlen s)))) (cons -4 "NOT>") (cons 410 "Model"))))
(repeat (setq i (sslength ss))
(if (not (member (setq n (cdr (assoc 2 (entget (ssname ss (setq i (1- i))))))) l))
(setq l (cons n l))
)
)
)
(if l (acad_strlsort l))
)
-
That is where the visual lisp (ActiveX) comes in.
Note that the use of ActiveX isn't absolutely necessary:
[cough]dynamic blocks[/cough]
Playing along...
(defun blockNames (/ block xrefs ss i obj name lst)
(vl-load-com)
(while (setq block (tblnext "BLOCK" (null block)))
(if (eq 4 (logand 4 (cdr (assoc 70 block))))
(setq xrefs (cons (strcat (cdr (assoc 2 block)) ",") xrefs))
)
)
(if (setq ss (ssget "_X"
(if xrefs
(list '(0 . "INSERT")
'(-4 . "<NOT")
(cons 2 (apply (function strcat) xrefs))
'(-4 . "NOT>")
'(410 . "Model")
)
'((0 . "INSERT") (410 . "Model"))
)
)
)
(repeat (setq i (sslength ss))
(if (not (vl-position
(setq name (vlax-get-property
(setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i)))))
(if (vlax-property-available-p
obj
'EffectiveName
)
'EffectiveName
'Name
)
)
)
lst
)
)
(setq lst (cons name lst))
)
)
)
(vl-sort lst (function <))
)
-
That is where the visual lisp (ActiveX) comes in.
Note that the use of ActiveX isn't absolutely necessary:
[cough]dynamic blocks[/cough]
:roll:
(defun c:test ( / i l n s ss x ) (setq s "")
(while (setq x (tblnext "BLOCK" (null x)))
(if (= 4 (logand 4 (cdr (assoc 70 x)))) (setq s (strcat s (cdr (assoc 2 x)) ",")))
)
(if
(setq ss
(ssget "_X"
(list
(cons 0 "INSERT")
(cons -4 "<NOT") (cons 2 (substr s 1 (1- (strlen s)))) (cons -4 "NOT>")
(cons 410 "Model")
)
)
)
(repeat (setq i (sslength ss))
(if (wcmatch (setq n (cdr (assoc 2 (entget (ssname ss (setq i (1- i))))))) "`*U*")
(setq n
(cdr
(assoc 2
(entget
(handent
(cdr
(assoc 1005
(cdadr
(assoc -3
(entget
(cdr
(assoc 330
(entget (tblobjname "BLOCK" n))
)
)
'("AcDbBlockRepBTag")
)
)
)
)
)
)
)
)
)
)
)
(if (not (member n l)) (setq l (cons n l)))
)
)
(if l (acad_strlsort l))
)
-
That is where the visual lisp (ActiveX) comes in.
Note that the use of ActiveX isn't absolutely necessary:
[cough]dynamic blocks[/cough]
:roll:
Now, was that so hard. :roll:
-
That is where the visual lisp (ActiveX) comes in.
Note that the use of ActiveX isn't absolutely necessary:
[cough]dynamic blocks[/cough]
:roll:
Now, was that so hard. :roll:
:-D
-
Hey you guys,
Thanks for the replies: I have forgotten all about dynamc blocks.
I dare not ask "are they different" because I know they are.
Hard times hese days :lol:
Regards.
-
I tried all the codes to see what will go wrong in case of a dynamic block.
But they all work fine, I mean, I have dynamic blocks and regular blocks combined in a dwg.
All the codes are working so what am I doing wrong in order to create an error I don't want :-)
Below are the routines with some comments / questions of mine.
Maybe you guys wanna take a look and see if my brain can be upgraded?
Thanks again, really like this way of learning.
Regards.
(defun GetBlocksInDwg (/ BlocksInDataBase NumberOfBlocksInSelSet Blockname BlockList)
; >> Localized all variables correct
(vl-load-com)
(if
(setq BlocksInDataBase
; >> In this "if" statement I tend to use "(setq VariableName..."
; >> See the other routines where this is not the occasion.
; >> Strange to me, noit using the setq here.
(ssget "_X"
(list
(cons 0 "INSERT")
(cons 410 "Model")
)
)
)
(progn
(setq NumberOfBlocksInSelSet (sslength BlocksInDataBase))
(while
(not (minusp (setq NumberOfBlocksInSelSet (1- NumberOfBlocksInSelSet))))
(setq Blockname (cdr (assoc 2 (entget (ssname BlocksInDataBase NumberOfBlocksInSelSet)))))
(if
(and
(not (member BlockName BlockList))
(not (vlax-property-available-p
(vlax-ename->vla-object (ssname BlocksInDataBase NumberOfBlocksInSelSet))
; >> vlax-ename->vla-object Transforms an entity to a VLA-object
'Path
; >> vlax-property-available-p Determines if an object has a specified property
; >> in this case it wants to know if it has a property called 'PATH
; Now here I am missing some info. WHat about 'PATH?
)
)
) ;_and
(setq BlockList (append (list BlockName) BlockList))
) ;_if
) ;_while
) ;_progn
) ;_if
;(princ) >> Leaving out this "(princ)" will cause the routine to return
; >> the list BLOCKLIST to the commandline. (What I wanted).
; >> How easy it can be...
) ;_defun
(defun Get_BlockNames (/ blk_name blk_list)
(vl-load-com) ; added this to load ActiveX functions
(if
; No setq here...
; So anything that is returned by the next line is not stored in a variable
; But where does it stay? How is it passed into the next lines?
; And in the next lines where is it?
(ssget "X" '((0 . "INSERt") (410 . "MODEL")))
; if all blocks in modelspace are selected
(vlax-for blk (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object)))
(if
(and (not (vlax-property-available-p blk 'Path))
; not being xref... again 'PATH ... cannot understand
(not (member (setq blk_name (vla-get-Name blk)) blk_list))
; not beinig in the list
)
(setq blk_list (cons blk_name blk_list))
; add it to the list
)
)
)
(vl-sort blk_list '<)
; sort in ascending order
)
The other 2 codes have too much new stuff for me.
I am not familiar with TBLNEXT and LOGAND.
To prevent me from headache I'll take it easy and stick to the 2 above.
-
Hi,
To get block references w/out using ssget, you can use gc:GetReferences (http://www.theswamp.org/index.php?topic=37186.0).
In the following example returns a list of all block references inserted in model space.
The list type is: ((blockName1 (refEname refEname ...)) (blockName2 (refEname refEname ...)))
((lambda (/ name refs blst)
(while (setq bl (tblnext "block" (not bl)))
(setq name (cdr (assoc 2 bl)))
(if (setq refs (gc:GetReferences name 2))
(setq blst (cons (list name refs) blst))
)
)
blst
)
)
-
My code works this way:
(if
(ssget "X" '((0 . "INSERt") (410 . "MODEL"))) ; creates an anonymous SelectionSet of all blocks inserted in ModeSpace
(vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object))); expanding this one, in order of evaluation
;it may be write
(setq acad_object (vlax-get-acad-object)) ; a VLA-object representing the running instance of AutoCAD, i.e. the current session
(setq current_drawing (vla-get-ActiveDocument acad_object)); a VLA-object representing current drawing (active drawing, active document - name it as you wish)
(setq ActiveSelectionSet (vla-get-ActiveSelectionSet current_drawing)); the selection created before, with (ssget... ; a VLA-object itself
;this last VLA-object, containing a colection of VLA-objects each representing a block, is passed to iteration function, vlax-for
Now, any VLA-object has a set of properties and/or methods, accessible via ActiveX;
in fact, ActiveDocument is a property of acad_object
ActiveSelectionSet is a property of current_drawing
you can see all available prop./methods of a VLA-object, using (vlax-dump-object #<VLA-OBJECT... )
Each object within ActiveSelectonSet is a vla-object which, of course, has properties and methods
PATH is a property of an external-reference and common blocks doesn't have it
So, if an object tested has PATH property, (vlax-property-available-p blk 'Path), then it is an ER; otherwise it is a block.
For getting the correct name of Dynamic Blocks, (vla-get-EffectiveName blk) should be used instead of (vla-get-Name...
-
Hi,
To get block references w/out using ssget, you can use gc:GetReferences (http://www.theswamp.org/index.php?topic=37186.0).
In the following example returns a list of all block references inserted in model space.
The list type is: ((blockName1 (refEname refEname ...)) (blockName2 (refEname refEname ...)))
((lambda (/ name refs blst)
(while (setq bl (tblnext "block" (not bl)))
(setq name (cdr (assoc 2 bl)))
(if (setq refs (gc:GetReferences name 2))
(setq blst (cons (list name refs) blst))
)
)
blst
)
)
Nice work, Gile!
-
well,...by searching one of my post...I see this post..
I know it is an old one..
but no one consider the AI_TABLE as an option.
so, just to add this idea.
(ai_table "BLOCK" 4)
-
well,...by searching one of my post...I see this post..
I know it is an old one..
but no one consider the AI_TABLE as an option.
so, just to add this idea.
(ai_table "BLOCK" 4)
Be sure the routine ai_utils.lsp is loaded.