Author Topic: Get all blocks in modelspace except XREF, how?  (Read 9893 times)

0 Members and 1 Guest are viewing this topic.

Aerdvark

  • Guest
Get all blocks in modelspace except XREF, how?
« 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.

Code: [Select]

(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.

fixo

  • Guest
Re: Get all blocks in modelspace except XREF, how?
« Reply #1 on: March 15, 2011, 04:52:01 AM »
Give this a try

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

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: Get all blocks in modelspace except XREF, how?
« Reply #2 on: March 15, 2011, 05:04:20 AM »
Using 410 flag in ssget will give you all blocks inserted in ModelSpace

Code: [Select]
(setq ss (ssget "_X" '((0 . "INSERT") (410 . "Model"))))

Then step into selection set and check if it has Path property

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

Aerdvark

  • Guest
Re: Get all blocks in modelspace except XREF, how?
« Reply #3 on: March 15, 2011, 05:33:11 AM »
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:

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


Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: Get all blocks in modelspace except XREF, how?
« Reply #4 on: March 15, 2011, 06:15:00 AM »
Here is mine

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

Aerdvark

  • Guest
Re: Get all blocks in modelspace except XREF, how?
« Reply #5 on: March 15, 2011, 07:34:37 AM »
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.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Get all blocks in modelspace except XREF, how?
« Reply #6 on: March 15, 2011, 09:08:08 AM »
That is where the visual lisp (ActiveX) comes in.

Note that the use of ActiveX isn't absolutely necessary:

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

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Get all blocks in modelspace except XREF, how?
« Reply #7 on: March 15, 2011, 09:11:04 AM »
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...

Code: [Select]
(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 <))
)
« Last Edit: March 15, 2011, 09:27:24 AM by alanjt »
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Get all blocks in modelspace except XREF, how?
« Reply #8 on: March 15, 2011, 09:32:10 AM »
That is where the visual lisp (ActiveX) comes in.

Note that the use of ActiveX isn't absolutely necessary:
[cough]dynamic blocks[/cough]

 :roll:

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

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Get all blocks in modelspace except XREF, how?
« Reply #9 on: March 15, 2011, 09:47:38 AM »
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:
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Get all blocks in modelspace except XREF, how?
« Reply #10 on: March 15, 2011, 10:13:13 AM »

Aerdvark

  • Guest
Re: Get all blocks in modelspace except XREF, how?
« Reply #11 on: March 15, 2011, 10:28:32 AM »
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.

Aerdvark

  • Guest
Re: Get all blocks in modelspace except XREF, how?
« Reply #12 on: March 16, 2011, 03:14:07 AM »
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.

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


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


gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Get all blocks in modelspace except XREF, how?
« Reply #13 on: March 16, 2011, 05:41:26 AM »
Hi,

To get block references w/out using ssget, you can use gc:GetReferences.

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 ...)))

Code: [Select]
((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
 )
)
Speaking English as a French Frog

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: Get all blocks in modelspace except XREF, how?
« Reply #14 on: March 16, 2011, 08:22:37 AM »
My code works this way:
 
Code: [Select]
  (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...