Burst All including nested blocks

Burst All including nested blocks

Anonymous
Not applicable
5,719 Views
18 Replies
Message 1 of 19

Burst All including nested blocks

Anonymous
Not applicable

 So I'm trying to create a lisp which will burst everything in the drawing but not freeze up completely if it meets un-explodeable objects.

 

Here's my code so far:

 

	(setq burstrc 0)
	
	(while
		(and
			(/= (ssget "_X" '((0 . "Insert"))) nil)
			(<= burstrc 5)
		)
		
		(setq compare1 (ssget "_X" '((0 . "Insert"))))

		(sssetfirst nil (ssget "_X" '((0 . "Insert"))))
		(c:burst)
		
		(setq compare2 (ssget "_X" '((0 . "Insert"))))
		
		(if 	(and 
				(> (sslength compare1) 0)
				(> (sslength compare2) 0)
			)
			(if (= (sslength compare1) (sslength compare2))
				(setq burstrc (+ burstrc 1))
				(setq burstrc 0)
			)
		)
	)

 

 

The Idea is that after 5 attempted bursts without the amount of "insert" changing the loop will be broken.

 

Unfortunately at the moment im getting:

; error: bad argument type: lselsetp nil

 I can just keep executing the command and it will burst everything, but that kind of defeats the point.

 

0 Likes
Accepted solutions (1)
5,720 Views
18 Replies
Replies (18)
Message 2 of 19

Kent1Cooper
Consultant
Consultant
Accepted solution

My guess:  If it has burst everything, then the first time through, the 'compare2' variable will be nil, and on subsequent runs both 'compare1' and 'compare2' will be nil, and the routine is objecting to that when checking their lengths.

 

Also, there's no need to check whether something is not equal to nil -- you can just check whether it exists at all, and while you're at it, you may as well set that 'compare1' variable in the process, and use it in place of that second (ssget).  When it's no longer finding any, a selection-set variable will be nil, not an empty selection set, so you never need to check whether it's more than 0 items long.  Try something like [untested]:

(setq burstrc 0)
(while
  (and
    (setq compare1 (ssget "_X" '((0 . "Insert")))); still finding some [nil if none]
    (<= burstrc 5)
) (sssetfirst nil compare1) (c:burst) (if
(setq compare2 (ssget "_X" '((0 . "Insert")))); found more after burst [nil if none left]
(if (= (sslength compare1) (sslength compare2)); then check lengths (setq burstrc (+ burstrc 1)); then (setq burstrc 0); else ); inner if ); outer if ); while

 

Kent Cooper, AIA
0 Likes
Message 3 of 19

kpblc2000
Advisor
Advisor
Do not use "_X" key for ssget, because c:burst could proceed with entities only in active layout (but (ssget "_X" '((0 . "INSERT"))) will return ALL blocks in ALL layouts). Or you have to use lisp function burst-one (as i remember it name; the best practive is to check busrt comand code)

Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям! | Do you find the posts helpful? "LIKE" these posts!
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.


Алексей Кулик aka kpblc | Aleksei Kulik aka kpblc Facebook | LinkedIn
autolisp.ru
Техническая поддержка программистов Autodesk в СНГ
Библиотека пользовательских lisp-функций | Custom Lisp-function library

0 Likes
Message 4 of 19

Kent1Cooper
Consultant
Consultant

@kpblc2000 wrote:
Do not use "_X" key for ssget, because c:burst could proceed with entities only in active layout (but (ssget "_X" '((0 . "INSERT"))) will return ALL blocks in ALL layouts). Or you have to use lisp function burst-one ....
....

Good point, but you can safely do it with "_X" if you filter for only Blocks in the current layout:

 

(ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar 'ctab))))

 

[It might be worth defining that as a little subroutine, so you don't have to spell it all out multiple times.]

Kent Cooper, AIA
0 Likes
Message 5 of 19

kpblc2000
Advisor
Advisor
CTAB system variable is not enough: ctab can return Layout1, but TILEMODE will be equal to 1 (active layout is Layout1, but you activated ModelSpace by command _.MSPACE).
And there is another possible trouble: you don't check frozen or locked layers within selection. 🙂

Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям! | Do you find the posts helpful? "LIKE" these posts!
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.


Алексей Кулик aka kpblc | Aleksei Kulik aka kpblc Facebook | LinkedIn
autolisp.ru
Техническая поддержка программистов Autodesk в СНГ
Библиотека пользовательских lisp-функций | Custom Lisp-function library

0 Likes
Message 6 of 19

dbroad
Mentor
Mentor

Sounds like you're getting advice on building an improvised explosive device.  Just keep that program away from me and my drawings.

Architect, Registered NC, VA, SC, & GA.
Message 7 of 19

Kent1Cooper
Consultant
Consultant

@kpblc2000 wrote:
CTAB system variable is not enough: ctab can return Layout1, but TILEMODE will be equal to 1 (active layout is Layout1, but you activated ModelSpace by command _.MSPACE).
And there is another possible trouble: you don't check frozen or locked layers within selection. 🙂

Given the task, I wouldn't expect [for me, if I needed to do such a thing] ever to do this from a Layout, but only in Model Space, but the OP may have different circumstances.  Certainly a routine could be made to force itself into Model Space, and to thaw and unlock all Layers, etc.  And there are other possible circumstances that it might be appropriate to account for, depending on the OP's needs:  If any of the Insert objects found are Xrefs, should they be Bound into the drawing, so they and any nested Blocks [or further-nested Xrefs] in them can also be Exploded?  Should Blocks defined to not allow Exploding have their definitions altered to allow it?  Should things like Polylines and/or Mtext and/or Dimensions also be Exploded?  [Of course, if you did all of those things, there wouldn't be any getting to the point of unexplodable Insert objects, so this particular form of routine wouldn't be needed.]

Kent Cooper, AIA
0 Likes
Message 8 of 19

jdiala
Advocate
Advocate
(setq e t)
(while e
  (setq e nil) 
  (vlax-for layout (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
    (vlax-for obj (vla-get-block layout)
      (and
        (= "AcDbBlockReference" (vla-get-objectname obj))
        (vlax-property-available-p obj 'effectivename)
        (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-explode (list obj))))
        (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-delete  (list obj))))
        (setq e t)
      )
    )
  )
)
Message 9 of 19

Anonymous
Not applicable

Ok this seems to have worked. Thanks 🙂

 

I'm using this on old Piping & Instrument Diagrams that were drawn on microstation in the early 90s. I've been exploding all the blocks to get rid all the formatting that I don't need and then I can setup my own layers etc. The whole process of importing them from microstation in the first place means the drawings are a mess so exploding the blocks for a few valves (although not ideal) isn't really a big deal.

0 Likes
Message 10 of 19

john.uhden
Mentor
Mentor
Rather than stopping because of one catch-all error, why not create a list of "bads", continue, and report the list of "bads" at the conclusion? At least that informs the user of certain failures and he/she can take some kind of further action.

I like your use of the Stephan Koster method of anding.

John F. Uhden

0 Likes
Message 11 of 19

Anonymous
Not applicable
That's sounds like a good idea, but how would you do that? I'm still new to Auto Lisp.
0 Likes
Message 12 of 19

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:
.... a list of "bads", continue, and report the list of "bads" at the conclusion? At least that informs the user of certain failures and he/she can take some kind of further action.
....
@Anonymous wrote:
That's sounds like a good idea, but how would you do that? ....

If the 'compare1' and 'compare2'  variables in the code in Post 2 are not localized, then after the routine is finished, those will both be selection sets [not lists, but easy enough to turn into one] of all remaining unexplodable Insert objects.  They can then be easily put on a certain Layer, or selected/highlighted/gripped, or their names reported to the User and/or exported to a file, or whatever.

Kent Cooper, AIA
Message 13 of 19

Anonymous
Not applicable
Ah ok, I get what your saying. I'm going to go and do some more tutorials and stuff so I can get to grip with everything a bit more, but what you've given me will do fine for just now. Your help is really appreciated. Thanks 🙂
0 Likes
Message 14 of 19

john.uhden
Mentor
Mentor
(defun nukeblocks ( / error errors n)
  (setq n 0)
  (vlax-for layout (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
    (vlax-for obj (vla-get-block layout)
      (and
        (= "AcDbBlockReference" (vla-get-objectname obj))
        (vlax-property-available-p obj 'effectivename)
        (if  (vl-catch-all-error-p (setq error (vl-catch-all-apply 'vla-explode (list obj))))
          (setq errors (cons (vl-catch-all-error-message error) errors))
          (progn
            (setq n (1+ n))
            (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-delete  (list obj))))
          )
        )
      )
    )
  )
  (princ (strcat "\nExploded " (itoa n) " blocks."))
  (and
    errors
    (princ "\n\nERRORS:")
    (mapcar 'write-line errors)
  )
  (princ)
)

That's just an example of gathering and reporting errors. You can have it tell you more if you want.



John F. Uhden

0 Likes
Message 15 of 19

Anonymous
Not applicable

I'm running into trouble running this lisp.  I copied the text from the last section and saved it into a .lsp file, loaded it, then tried to initiate it with nukeblocks but that doesn't seem to be working.  Can you upload the lisp here as attachment or let me know how I am fouling this up?

 

I just need a lisp that will burst all blocks to 0, removing XREF's first is something I am doing manually.  Also, do not want this to explode any hatches.  something that has to be done discriminately on my end as we keep some and delete others.

 

Thanks

0 Likes
Message 16 of 19

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

...  I ... tried to initiate it with nukeblocks but that doesn't seem to be working.  ....


Since it begins with

 

(defun nukeblocks ...

 

it's not a command definition but a function definition.  You can either use it as a function, by putting parentheses around it when you type it in:

 

(nukeblocks)

 

or change the definition opening by putting the C: in front of the name to make it a command:

 

(defun C:nukeblocks ...

 

in which case typing just nukeblocks should run it.

Kent Cooper, AIA
Message 17 of 19

Anonymous
Not applicable

Thanks Kent,

 

Seemed to run fine.  My only question now is this the same method as the burst express tool?  I know it says explode in the command but I am hoping that it is retaining parent layer properties etc. which burst does opposed to explode.  I am guessing he grabbed most of this code from the burst express tool code?

 

I did see a previous thread that you had about burst looping until 0.  I am essentially just trying to avoid select all in model space and typing BURST over and over until there are 0 blocks left.

 

Also, is there code in here similar to the lisp that sets unexplodable flagged blocks to explodable?

 

I saw this other code and I'm wondering what differences there might be, or which you think is better?

(defun Burstzero (/ GoAgain blks blk)
  (vl-load-com)
  (setq GoAgain T)					; to begin with [make at least one pass]
  (while
    (and
      GoAgain						; will be nil once it makes a pass without finding any non-Xref blocks
      (setq blks (ssget "_X" '((0 . "INSERT")))) 	; includes Xref's
    )							; and
     (setq GoAgain nil)					; "zero out" initially for this pass
     (repeat (sslength blks)
       (setq blk (ssname blks 0))			; first [remaining] item in selection
       (if (not	(vlax-property-available-p
		  (vlax-ename->vla-object blk) 'Path))	; i.e. it's not an Xref [ordinary Blocks don't have Path property]
	 (progn
	   (setq GoAgain T)				; it found one, so run the loop again after this pass
	   (sssetfirst nil (ssadd blk))
	   (c:burst)
	 )						; progn
       )						; if
       (ssdel blk blks)					; remove that entity name from selection, go on to next
     )							; repeat
  )							; while
)							; defun

I believe I grabbed this from the other thread about bursting with loop.  If it avoids selecting XREF's then that's a plus, but not necessary.  XREF's will be detached typically.  It also can't be specific to model space as we sometimes have to burst blocks in title blocks which live in paper space.  

 

Thanks,

Warren

0 Likes
Message 18 of 19

Anonymous
Not applicable

Upon further investigation the portion of code posted earlier with the nukeblocks call didn't seem to actually be bursting.  as I saw many blocks being broken down further than intended, I saw that tag #'s were being broken down into jibberish text probably some portion of those being exploded and not burst.  I have been using the burstzero code I showed in my last post with a call c:BAB for the command.  This version seems to take an approach different that bursting from the parent layer down in a loop though.  Not sure it is the best method but it seems like it goes one block at a time?  Maybe it is going from the furthest nested block first in order to save time later down the operation?

 

My command line looks something like this:

\
1 found

\
1 found

/
<Selection set: 5df2>

the 1 found is repetitive, not sure how this code is structured to do such.

 

Modified code in question here:

(defun c:BAB (/ GoAgain blks blk)
  (vl-load-com)
  (setq GoAgain T)					; to begin with [make at least one pass]
  (while
    (and
      GoAgain						; will be nil once it makes a pass without finding any non-Xref blocks
      (setq blks (ssget "_X" '((0 . "INSERT")))) 	; includes Xref's
    )							; and
     (setq GoAgain nil)					; "zero out" initially for this pass
     (repeat (sslength blks)
       (setq blk (ssname blks 0))			; first [remaining] item in selection
       (if (not	(vlax-property-available-p
		  (vlax-ename->vla-object blk) 'Path))	; i.e. it's not an Xref [ordinary Blocks don't have Path property]
	 (progn
	   (setq GoAgain T)				; it found one, so run the loop again after this pass
	   (sssetfirst nil (ssadd blk))
	   (c:burst)
	 )						; progn
       )						; if
       (ssdel blk blks)					; remove that entity name from selection, go on to next
     )							; repeat
  )							; while
)							; defun

Also,

 

I happened to not have XREF's in the drawing I tested, but is this line calling for it to insert XREF's? Because that would not be my intent.

(setq blks (ssget "_X" '((0 . "INSERT")))) 	; includes Xref's

Thanks,

Warren

 

0 Likes
Message 19 of 19

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....,

 

I happened to not have XREF's in the drawing I tested, but is this line calling for it to insert XREF's? Because that would not be my intent.

(setq blks (ssget "_X" '((0 . "INSERT")))) 	; includes Xref's

.... 


To that one question:  No, that line is to find  all "INSERT"-class objects, and the comment at the end is just to be aware that it will  include Xref's [if there are any in the drawing] in the 'blks' selection set.

Kent Cooper, AIA