Removing nested empty blocks

Discussion in 'AutoCAD' started by dblaha, Jul 19, 2004.

  1. dblaha

    dblaha Guest

    I've worked with code ("c:DeleteEmptyBlocks" originally posted by Michael Puckett on 5/02/03) that can find and remove first-level empty blocks. And I know how to find nested blocks. But how do I remove nested empty blocks?
     
    dblaha, Jul 19, 2004
    #1
  2. dblaha

    dblaha Guest

    Never mind... I figured out how to find and remove all of them.
     
    dblaha, Jul 20, 2004
    #2
  3. dblaha

    Anne Brown Guest

    For the benefit of those who will see your original question in
    the future, would you post your solution?
     
    Anne Brown, Jul 20, 2004
    #3
  4. dblaha

    ECCAD Guest

    You got something you want to share ?

    Bob
     
    ECCAD, Jul 20, 2004
    #4
  5. dblaha

    dblaha Guest

    Well, as I mentioned in my original post, removing first-level empty blocks (inserts) has been done. But removing nested ones was really teasing my brain. After much trial and error, I eventually came up with a cross-referencing solution: I couldn't delete a nested block in the block table, but I COULD delete it if I grabbed it directly in the table--as opposed to stepping to its nested reference within another block's definition. Remove the block, and all of its nested references get removed as well.

    My routine searches the block table for nested blocks (in this case, on a specific layer). When it finds one, it does a fresh search of the block table looking up that block's definition and tests whether it is empty (DXF code -2 = "ENDBLK"). If it's empty, the block's entity name in the block table is added to the list of empty blocks to be removed. Once all the nested blocks have been checked, the blocks in the list are deleted.

    I've included the code snippet of the search process below. (It seems way too simple for the amount of aggravation it caused me.) It's not necessarily pretty but it works...


    ;; Look for empty nested blocks
    (setq Rewind T)
    (while (setq Elist1 (tblnext "BLOCK" Rewind))
    (setq Rewind nil
    Ename (cdr (assoc -2 Elist1))
    )
    (while Ename
    (setq EList (entget Ename))
    (if (= "INSERT" (cdr (assoc 0 Elist)))
    (if (= "ENDBLK" (cdr (assoc 0 (entget (cdr (assoc -2 (tblsearch "block" (cdr (assoc 2 elist)))))))))
    (setq blk_list (append blk_list (list ename)))
    )
    )
    (setq Ename (entnext Ename))
    )
    )
     
    dblaha, Jul 20, 2004
    #5
  6. dblaha

    dblaha Guest

    One correction: I don't have it searching for blocks on a specific layer in the code I posted. That was in a previous incarnation of the routine. Blame it on inadequate caffeine...
     
    dblaha, Jul 20, 2004
    #6
  7. dblaha

    dblaha Guest

    My caffeine low is worse than I thought. My description of what I did seems very confused now that I've read it again. Feel free to disregard it. At least the code works... BTW, if anyone can offer suggestions on tightening and/or speeding up this search process, by all means post it. Thanks.
     
    dblaha, Jul 20, 2004
    #7
  8. dblaha

    dblaha Guest

    OK. I've had a nice nap and some more caffeine and this all seems a bit clearer again. Of course, an empty block cannot be removed from the block table while it is also inserted into other block definitions as a nested insert. But all those nested inserts CAN be removed.

    As I tried to explain above (for those that haven't already figured all this out just by looking at it), my search routine finds inserts that are nested in blocks in the block table. It then takes the name of the insert (DXF code 2) and uses that to search for the insert's block definition in the block table. It then uses that definition to determine whether the block in question is empty. If it is, the routine adds the entity name of the nested insert it originally found into a list. Once it's looked through the whole block table for nested inserts, it deletes all the insert entities in its list.

    Below, I've pasted a complete routine using this search process. I know it's missing a few things (like being able to deal with locked layers) but it's worked on everything I've thrown at it so far. Note that this routine only deals with nested inserts. The routine mentioned in my original post deals with first-level empty inserts in the drawing quite nicely.

    Please post your comments/flames on any improvements that could be made. I'm always looking to improve...


    ;; This routine will remove all nested blocks that are empty
    ;; Make sure all layers are unlocked before running it

    (defun c:nested ( / blk_list ename elist elist1 rewind this_one this_many)
    (command "_.undo" "mark")
    (setq error_old *error* *error* ermessage)
    (setvar "cmdecho" 0)
    (setq Rewind T
    blk_list nil
    )
    (while (setq Elist1 (tblnext "BLOCK" Rewind))
    (setq Rewind nil
    Ename (cdr (assoc -2 Elist1))
    )
    (while Ename
    (setq EList (entget Ename))
    (if (= "INSERT" (cdr (assoc 0 Elist)))
    (if (= "ENDBLK" (cdr (assoc 0 (entget (cdr (assoc -2 (tblsearch "block" (cdr (assoc 2 elist)))))))))
    (setq blk_list (append blk_list (list Ename)))
    )
    )
    (setq Ename (entnext Ename))
    )
    )
    (setq this_many (rtos (length blk_list) 2 0))
    (while blk_list
    (setq this_one (car blk_list))
    (ax:DeleteObjectFromBlock this_one)
    (setq blk_list (cdr blk_list))
    )
    (command "purge" "b" "*" "n")
    (if (= this_many "1")
    (princ (strcat " " this_many " empty nested block definition removed."))
    (princ (strcat " " this_many " empty nested block definitions removed."))
    )
    (setq *error* error_old)
    (setvar "cmdecho" 1)
    (princ)
    )


    ;; This defun is a modified version of a routine posted by Frank Oquendo
    (defun ax:DeleteObjectFromBlock (ent / doc blk)
    (vl-load-com)
    (setq is_aok T
    doc (vla-get-ActiveDocument (vlax-get-acad-object))
    ent (vlax-ename->vla-object ent)
    its_name (cdr (assoc 0 (entget (vlax-vla-object->ename ent))))
    )
    (if (or (= "ENDBLK" its_name)(= "SEQEND" its_name))
    (setq is_aok nil)
    )
    (if is_aok
    (vla-Delete ent)
    )
    )

    (princ "Please type NESTED to begin.")
    (princ)
     
    dblaha, Jul 21, 2004
    #8
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.