Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Repeat (c:burst) command in lisp routine

29 REPLIES 29
Reply
Message 1 of 30
stoews1
2599 Views, 29 Replies

Repeat (c:burst) command in lisp routine

I am creating a lisp routine to clean up xrefs from architectural drawings for use in our draiwngs. As part of my routine, I want to burst the drawing several times to get rid of all of the blocks within blocks until the whole drawing is single entities. I've tried using the repeat command with (c:burst) and it works until there is "0 found" objects. At which point the lisp routine ends without carrying on. If I say for it to repeat for example 3 times, and it takes exactly 3 times to burst everything into single entities, the routine continues on. It only causes an error if it finds "0 found" before it has repeated the specified number of times. is there a way to make it do a "burst" as many times as needed until there is "0 found" and then continue on with the routine.

this is the part of the lisp routine in question:

(repeat 5
(sssetfirst nil (ssget "X" (list )))
(c:burst)
)
29 REPLIES 29
Message 2 of 30
Anonymous
in reply to: stoews1

You could run burst within a while loop which checks the number of objects before and
after burst.

(while (/= oldcnt newcnt)
< loop >
)

You might use the sslength function to get the count.

Joe Burke
Message 3 of 30
Kent1Cooper
in reply to: stoews1

You could also just check whether there are still any Blocks or Xrefs left in the drawing:

(while (ssget "X" '((0 . "INSERT")))
(sssetfirst nil (ssget "X" (list )))
(c:burst)
); end while

--
Kent Cooper


stoews1 wrote...
....is there a way to make it do a "burst" as many times as needed until there is "0 found" and then continue on with the routine.
Kent Cooper, AIA
Message 4 of 30
Anonymous
in reply to: stoews1

Hi Kent,

I think that would be an endless loop is there are either xrefs, or non-explodable
blocks, or blocks which ACAD cannot explode due to non-uniform scaling issues
involved.

Joe
Message 5 of 30
Kent1Cooper
in reply to: stoews1

I assume your suggestion also would not take apart Xrefs or non-explodable Blocks. I don't have a new enough version to have non-explodable blocks, so I wouldn't know about them. Is there a way to check for those?

Both Explode and Burst [unlike, for instance, Refedit] *can* handle non-uniformly-scaled Blocks [at least in ACAD2004], so that shouldn't be a problem.

As for Xref's, I hadn't ever had reason to Explode or Burst one, but sure enough, they won't do it. So yes, it would probably be necessary to precede it all with something like:

(command "_.xref" "_bind" "*")

to change them all into Blocks first.

--
Kent Cooper


Joe Burke wrote...
I think that would be an endless loop is there are either xrefs, or non-explodable blocks, or blocks which ACAD cannot explode due to non-uniform scaling issues involved.
Kent Cooper, AIA
Message 6 of 30
stoews1
in reply to: stoews1

Thanks for the replies guys.

Kent your

(while (ssget "X" '((0 . "INSERT")))
(sssetfirst nil (ssget "X" (list )))
(c:burst)
); end while

did the job perfectly. Thanks.
Message 7 of 30
Kent1Cooper
in reply to: stoews1

You're welcome. I take it that either you don't have any Xrefs to deal with, or Burst in some later version than I have can now take those apart.

--
Kent Cooper
Kent Cooper, AIA
Message 8 of 30
jj26
in reply to: stoews1

Hi guys,

Not sure if I should bump a 4 year old thread or make a new one. Anyways, I'm trying to do a similar thing as the OP, but XREF's are giving me some problems. I don't want to bind the XREF's, but want to create a routine which will clean up drawings automatically. Is there an easy way to,

 

1) Unattach all of the XREF's in a current drawing

2) Run Kent's burst loop

3) Reattach the XREF's

 

Any help is appreciated.

Message 9 of 30
jj26
in reply to: jj26

I was thinking something like,

 

(command "_.-xref" "_UNLOAD" "*")

(while (ssget "_A" '((0 . "INSERT")))
(sssetfirst nil (ssget "_A" (list)))
(c:burst)
)

(command "_.-xref" "_RELOAD" "*" )

 

But of course an unloaded XREF is still 'in' the drawing, and I don't think there's a way to select all blocks which aren't unloaded XREF's. And then if you detach the XREF you have to start keeping track of the names of the XREF's and their directories, and then that's where I don't know quite how to start.

Message 10 of 30
Kent1Cooper
in reply to: jj26


@jj26 wrote:

Hi guys,

Not sure if I should bump a 4 year old thread or make a new one. Anyways, I'm trying to do a similar thing as the OP, but XREF's are giving me some problems. I don't want to bind the XREF's, but want to create a routine which will clean up drawings automatically. Is there an easy way to,

 

1) Unattach all of the XREF's in a current drawing

2) Run Kent's burst loop

3) Reattach the XREF's

 

Any help is appreciated.


You don't want to "unattach" them [if by that you mean what AutoCAD calls Detaching them], but rather Unload them, so that you can Reload them and they'll come back as they were.  I thought you could just do an Xref Unload *, then run the burst loop, and then Xref Reload *, but (ssget "X" '((0 . "INSERT"))) finds even Unloaded Xrefs, so the loop never stops finding things, even if it can't do anything to them, so it doesn't end.

 

Another possibility I thought of was to Wblock all Xrefs out to a new drawing, burst everything, and then bring that new drawing back in.  But doing so [with one test Xref] converts it from an Xref to a regular Block.  I didn't try Xref-ing that back in, but if you have more than one Xref to deal with, I assume you wouldn't want that.

 

You may need to step through each item and check whether it's an Xref, in which case you don't need to Unload them.  I'm not where I can test this, but give it a try:

 

(defun C:YourCommandName (/ 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 blk)
          (c:burst)
        ); progn
      ); if
      (ssdel blk blks); remove that entity name from selection, go on to next
    ); repeat
  ); while
); defun

 

Might Explode do just as well as Burst under the circumstances?  If so, and given that it would do them one at a time, you wouldn't need (sssetfirst), but could replace that line and the (c:burst) line with just:

 

(command "_.explode" blk)

Kent Cooper, AIA
Message 11 of 30
jj26
in reply to: Kent1Cooper

I'm testing it on a drawing which has a few blocks and an XREF, I get,

 

'bad argument type: lselsetp <Entity name: 7ed0b988>'

 

when I try and run it. Unfortunately we have to burst the blocks, not explode.

Message 12 of 30
Kent1Cooper
in reply to: jj26


@jj26 wrote:

I'm testing it on a drawing which has a few blocks and an XREF, I get,

 

'bad argument type: lselsetp <Entity name: 7ed0b988>'

 

when I try and run it. Unfortunately we have to burst the blocks, not explode.


My mistake -- (sssetfirst) takes a selection set, not an entity name.  Try replacing this:

 

          (sssetfirst nil blk)

 

with this:

 

          (sssetfirst nil (ssadd blk))

Kent Cooper, AIA
Message 13 of 30
jj26
in reply to: jj26

Works great! Thanks.

Message 14 of 30
mwhea
in reply to: jj26

HI Kent1Cooper

 

(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

 Your burst fuction is really helpful taking out the xrefs from the burst function of the while loop, though after testing this for over a month i have noticed some drawings having problems with this function and asking the user to select objects.

 

Command: 0 found

Select Objects:

 

I thought it was to do with non exploading blocks but i have run another routine to sort through all blocks to be exploadable. When i do a ssx (entity) insert i am returned with 97 found - would you understand what is going on??

 

Cheers

Mark

 

 

Message 15 of 30
mwhea
in reply to: mwhea

If you processed the command by continuously hitting Enter it started running the routine but there was 4 objects still left i could select using ssx insert. These objects were on the Layout1 tab, is my assumption correct that ssx actually looks at all tabs model,layout and returns but because we are working in model space it cant actually run the burst routine on the blocks located in the layout tab and then causes this error in making the lisp routine fail?

 

My easy solution was to just to have the routine remove everything from layout space - though is there a way to avoid this?? 

 

 

Message 16 of 30
Kent1Cooper
in reply to: mwhea


@mwhea wrote:

If you processed the command by continuously hitting Enter it started running the routine but there was 4 objects still left i could select using ssx insert. These objects were on the Layout1 tab, is my assumption correct that ssx actually looks at all tabs model,layout and returns but because we are working in model space it cant actually run the burst routine on the blocks located in the layout tab and then causes this error in making the lisp routine fail?

 

My easy solution was to just to have the routine remove everything from layout space - though is there a way to avoid this??


I'm not positive about Burst, but I know that at least for native AutoCAD editing commands, only things in the current space are recognized in object selection, so for example, Explode would not be able to do its thing to Blocks in a paper space Layout when you're in model space.  If that's the issue with Burst too, try having the routine go into the space each object is in, so it can Burst it:

....

    (repeat (sslength blks)
      (setq blk (ssname blks 0))
      (if (not (vlax-property-available-p (vlax-ename->vla-object blk) 'Path))
        (progn
          (setq GoAgain T)

          (setvar 'ctab (cdr (assoc 410 (entget blk))))

          (sssetfirst nil (ssadd blk))
          (c:burst)
        ) ; progn
      ) ; if
      (ssdel blk blks) ; remove that entity name from selection, go on to next
    ) ; repeat

....

 

You can add a (setvar 'ctab "Model") at the end, if you like, or even save the current tab [whether model space or any paper space Layout] at the beginning, and return to it at the end.

Kent Cooper, AIA
Message 17 of 30
Kent1Cooper
in reply to: mwhea


@mwhea wrote:

.... When i do a ssx (entity) insert i am returned with 97 found - would you understand what is going on??

....


[I'm not familiar with "ssx" but I assume that by "ssx (entity) insert" you mean (ssget "_X" '((0 . "INSERT"))).]

 

The "INSERT" entity type applies not only to Blocks and Xrefs, but also to some entity types that a lot of people may not use much -- those produced by MINSERT [Multiple-insert (insert-and-array) Blocks], WMFIN [Windows Metafiles], LIGHT [light sources, which may be in my Architectural Desktop but perhaps not in vanilla AutoCAD or some other overlays], and in rather older versions of AutoCAD, HATCH [before a Hatch pattern was an entity type of its own, it was a special kind of Block].  Using (ssget) with a filter for "INSERT" entity type will find all of those.
 

Some of those can be Exploded [Hatch patterns at least], though I don't know whether Burst works on all of them.  And some can't [Minserts at least], so I assume Burst would not work on them, either.  So if you have any of those un-Burstable kinds of entities in the drawing, the routine will continue to find them.

 

If you never use those things, the problem must be something else, but if you do, you would need to build in additional checks on the sub-entity-type.  An old-style Hatch pattern has a "Block name" beginning with "*X"; a Windows Metafile has a "Block name" beginning with "WMF" [though they can be renamed, so that's not foolproof], Lights have a limited number of specific Block names, and Minserts can be identified by their entity data's second (assoc 100) entry [the following returns T]:
(= (cdr (assoc 100 (reverse EntityData))) "AcDbMInsertBlock").

 

By the way, I've since discovered a more concise way to identify an Xref as distinct from a Block:

(assoc 1 (tblsearch "block" BlockName))

returns T for an Xref, and nil for a Block.  Ordinary Blocks do not have an (assoc 1) entry in their Block table information, but Xrefs do -- it's the filepath and name, so it's just a shorter way to check whether it has a Path, as the routine currently does in a longer way by looking at whether it has the 'Path VLA property.

Kent Cooper, AIA
Message 18 of 30
mwhea
in reply to: jj26

Yeah sorry i always thoguht ssx was the alternative to ssget because it comes up with the same functions (ssx entity = 0 . INSERT) 

 

The routine is for cleaning architectural files up so each architect is different in the way they produce drawings so there is no knowing what could b in the file. Saying that however i have never come accross a WMFIN file or LIGHT and all the architects we work with have later versions so the HATCH isn't a issue. I did some further reading yesterday and added this to the lisp routine

 

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

 

Though i'll problaby use what you have pasted in blue. 

 

Is there any advantage over using the new method of finding the xrefs? or just to neaten the code up a bit as i am not very good with writing lisp routines so i wouldn't know where to insert the (assoc 1 (tblsearch "block" BlockName)) 

 

Also because MINSERT cannot be burst would it be worth to expload that once then the blocks used for the mutliple array could be bursted?

 

Cheers

Mark

Message 19 of 30
Kent1Cooper
in reply to: mwhea


@mwhea wrote:
.... I did some further reading yesterday and added this to the lisp routine

 

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

 

Though i'll problaby use what you have pasted in blue. 

 

Is there any advantage over using the new method of finding the xrefs? .... i wouldn't know where to insert the (assoc 1 (tblsearch "block" BlockName)) 

 

Also because MINSERT cannot be burst would it be worth to expload that once then the blocks used for the mutliple array could be bursted?

....


If you do filter for Insert objects only in Model space, you might want to add a line before your (setq blks... line, to make sure you're in Model space so the routine can Burst things it finds there:

(setvar 'ctab "Model")

 
The only "advantages" [if one even considers them to be, really] to the alternative way of determining whether an Insert object is an Xref are: 1) that it uses a little less code; and 2) that in this case, it eliminates the use of any (vl...) functions, so you wouldn't need to do the (vl-load-com) thing.  You would replace this line:

 

      (if (not (vlax-property-available-p (vlax-ename->vla-object blk) 'Path))

 

with this:

 

      (if (not (assoc 1 (tblsearch "block" BlockName)))

 

You can't Explode an Minsert object, unless that capability has been added in a later version than mine.  I expect a Search of this Discussion Group might turn up a way to do break one up, but I haven't searched myself.

Kent Cooper, AIA
Message 20 of 30
mwhea
in reply to: jj26

Kent, one last thing about this lisp routine. Will this fail if the selection set of blocks is greater then the maximum allowed by AutoCAD (32767) ?? Only reason i ask is that some times the routine just holds and seems to freeze autocad on larger drawings and this is the only reason i can think behind it?

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost