Author Topic: Block to Group in Vanilla  (Read 4806 times)

0 Members and 1 Guest are viewing this topic.

jimlapier

  • Mosquito
  • Posts: 9
Block to Group in Vanilla
« on: November 13, 2014, 04:22:41 PM »
I'm trying to help a client who is importing a ton of elements / objects from Vectorworks. Everything from VW comes in as blocks with names like Group-1, Group-124, etc. For their working purposes, they like the objects as groups but not blocks. I'd to come up with a routine that explodes all of the blocks in a drawing and converts each to a group of the same objects. This seems straight forward but I can't seem to figure it out. And the big kicker: We work only in AutoCAD for Mac, which only supports Vanilla LISP. No visual lisp, dialog boxes, etc.

I've found a great routine on the forums for exploding all blocks, but I'm not sure where to go from here.
Any help is GREATLY appreciated. Thanks!

Code: [Select]
(defun C:ExplodeAll (/ AllBlocks SolOnly )
(setvar "qaflags" 1)
(setq AllBlocks (ssget "X" (list (cons 0 "INSERT"))))
 (while (/= AllBlocks nil)
  (progn
   (command "_.explode"  AllBlocks "")
   (setq AllBlocks (ssget "X" (list (cons 0 "INSERT"))))
  );progn
 );while
(if (= AllBlocks nil)(alert "All blocks were exploded"))
(setq SolOnly (ssget "X" '((0 . "3DSOLID"))))
(command  "_.erase" "all" "R" SolOnly "")
(setvar "qaflags" 0)
(princ)
);end ACISPrep

danallen

  • Guest
Re: Block to Group in Vanilla
« Reply #1 on: November 13, 2014, 05:21:07 PM »
here is some helper material / code,

save a var for current last object in database, then explode, then group new objects using SDG_after to select

Dan

Code: [Select]
;;; Quick create anonymous group
(defun c:GP (/ ss1)
  (princ "\nSelect objects to create anonymous group:")
  (setq ss1 (ssget ":L"))
  (if ss1 (command "-group" "create" "*" "" ss1 ""))
  (princ)
)

;==============================================================================
; Returns selection set of all entities after passed in entity name
; taken from CAD Cookbook utilities
;==============================================================================
(defun SDG_AFTER (ename / ss)
  (setq ss (ssadd)) ;create selection set
  (if ename
    (while (setq ename (entnext ename))
       (ssadd ename ss) ;add entities to set
    )
;;;    (setq ss (ssget "X")) ;if no last entity, get all
  ) ;end if
  (if (> (sslength ss) 0) ss) ;return nil if no entities
)

;==============================================================================
; Returns last entity, even subentities on polylines
; used to ensure SDG_AFTER skips to the next full entity, not just a subentity
;
; by roy_043 from http://www.theswamp.org/index.php?topic=35626.msg408522#msg408522
;==============================================================================
(defun SDG_GetLast ( / ent newEnt)
  (setq ent (entlast))
  (while (and
           ent
           (setq newEnt (entnext ent))
         )
    (setq ent newEnt)
  )
  ent
)

;;; example of SDG_after in action (note this routine won't work without subroutines I didn't provide - code ref only

;;; Duplicates objects onto current layer
(defun c:CDL ()
  (SDG-ERROR-INIT (list (list
    "cmdecho" 0 ;do list of variables to be set/reset
  ) T) )
  (princ "\nCopy-DUPLICATE to current layer\n")
  (if (setq ss1   (ssget ":L")) ;if stuff selected
    (progn
      (setq elst (SDG_GetLast) ;remember last entity
            count (sslength ss1)
            ss2   (ssadd)
      )
      (while (> count 0) ;reverse selection set
        (ssadd (ssname ss1 (setq count (1- count))) ss2)
      ) ;end while
      (command ".copy" ss2 "" "@" "@") ;copy in same place
      (command ".select" (SDG_AFTER elst) "") ;reset previous to new entities since last
    ) ;end progn
  ) ;end if
  (command "chprop" "P" "" "la" (getvar "clayer") "color" "bylayer" "ltype" "bylayer" "")
  (SDG-ERROR-RESTORE)
  (princ)
)


tombu

  • Bull Frog
  • Posts: 288
  • ByLayer=>Not0
Re: Block to Group in Vanilla
« Reply #2 on: November 14, 2014, 06:42:54 AM »
If any of the blocks have attributes that you need later you may have to take that in to consideration.  Be forewarned groups are fragile, they can only exist in the drawing they were created in.  If they insert that drawing in to another drawing the grouping disappears.  Keep copies of the original files just in case. 

Tom Beauford P.S.M.
Leon County FL Public Works - Windows 7 64 bit AutoCAD Civil 3D

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: Block to Group in Vanilla
« Reply #3 on: November 14, 2014, 10:05:04 AM »
...
Code: [Select]
(defun SDG_AFTER (ename / ss)
  (setq ss (ssadd))               ;create selection set
  (if ename
    (while (setq ename (entnext ename))
       (ssadd ename ss)               ;add entities to set
    )
;;;    (setq ss (ssget "X"))            ;if no last entity, get all
  ) ;end if
  (if (> (sslength ss) 0) ss)         ;return nil if no entities
)
...
If you use Bricscad then I recommend this version see "ALE_Ss-After" (also for other conditions):
Code: [Select]
; Marc'Antonio Alessi - original by Rune Wold and Michael Puckett
; Function: ALE_LastEnt
;
; Version 1.01 - 20/12/2004
; Version 1.02 - 06/05/2010 to support Bricscad
;
; Description:
;   get the absolute last entity in the database,
;   for problems in >=r15 in blocks with attrib, and polylines
;
; Arguments: none
;
; Return Values:
;   An entity name;
;   otherwise nil, if there are no entities in the current drawing
;
; Example: (setq marker (ALE_LASTENT))
;
(defun ALE_LastEnt ( / EntNam OutVal)
  (and
    (setq OutVal (entlast))
    (while (setq EntNam (entnext OutVal))
      (setq OutVal EntNam)
    )
  )
  OutVal
)
; Marc'Antonio Alessi
; Function: ALE_Ss-After
;
; Version 1.01 - 20/12/2004
; Version 1.02 - 30/09/2005
; Version 1.03 - 06/05/2010 to support Bricscad
;
; Description:
;   get a selection set of items after EntNam in the database
;
; Arguments: An entity name
;
; Return Values:
;   A selection set;
;   otherwise nil, if there are no entities after EntNam
;
; Examples:
;   (setq marker (ALE_LASTENT)) ...create new entities...
;   to include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) marker "" ...)
;   Note: NOT valid if marker is a SEQEND of
;   blocks with attrib or old polylines (PLINETYPE = 0)
;
;   not include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) "" ...)
;
(defun ALE_Ss-After (EntNam / SelSet)
  (cond
    ( (not EntNam) (ssget "_X" '((0 . "~VIEWPORT"))) ); dwg was empty
    ( (setq EntNam (entnext EntNam)) ;"~VIEWPORT" x Bricscad
      (setq SelSet (ssadd EntNam))
      (while (setq EntNam (entnext EntNam))
        (if (entget EntNam) (ssadd EntNam SelSet))
      )
      SelSet
    )
  )
)

jimlapier

  • Mosquito
  • Posts: 9
Re: Block to Group in Vanilla
« Reply #4 on: November 14, 2014, 10:37:41 AM »
Awesome! Thanks everyone for their responses. I'll be working on this today & will post back when I have a solution. Thanks!

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Block to Group in Vanilla
« Reply #5 on: November 14, 2014, 03:16:10 PM »
I've always wondered this, and have never met someone that can give me an answer. What is the point of groups? I've never seen a point for their use, and when I have had drawings where objects are in a group, it's nothing but a nuisance.
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Block to Group in Vanilla
« Reply #6 on: November 14, 2014, 03:27:51 PM »
It allows one to collect items in container of sorts where a static container like a block won't do.

Third party apps like AutoPLANT lean on groups rather heavily to support many to one relationships between components and an invisible "intelligence" node (at_master_piping) that hosts all the data representing the members of the group (typically 3D primitives) etc. like specs, classes, port information yada. All the while allowing the visible objects to be moved about in 3D space.

A simpler example might be grouping a leader with an attributed instrument bubble block, allowing one to manipulate the leader but keep it associated with the block.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

VovKa

  • Water Moccasin
  • Posts: 1626
  • Ukraine
Re: Block to Group in Vanilla
« Reply #7 on: November 14, 2014, 03:41:11 PM »
it's nothing but a nuisance.
why 'nuisance'? it's behavior is easily controlled via PICKSTYLE variable or 'Ctrl+H' shortcut.
extremely useful feature i'd say.

ps congrats with 5000'th post :)

VovKa

  • Water Moccasin
  • Posts: 1626
  • Ukraine
Re: Block to Group in Vanilla
« Reply #8 on: November 14, 2014, 03:44:12 PM »
i have this to create groups
Code: [Select]
(defun vk_CreateGroup
      (Name EntsList SelFlag / GroupDic EntName)
  (if (and EntsList
   (setq GroupDic (cdadr
    (member (cons 3 "ACAD_GROUP") (entget (namedobjdict)))
  )
   )
   (not
     (and Name (vl-position (cons 3 Name) (entget GroupDic)))
   )
   (setq EntName (entmakex
   (append (list (cons 0 "GROUP")
(cons 100 "AcDbGroup")
(cons 300 "")
(cons 70
       (if Name
0
1
       )
)
(cons 71 SelFlag)
   )
   (mapcar (function (lambda (e) (cons 340 e))) EntsList)
   )
)
   )
   (entmod (append (entget GroupDic)
   (list (cons 3
       (if (null Name)
"*"
Name
       )
)
(cons 350 EntName)
   )
   )
   )
      )
    (if Name
      Name
      (cdadr
(member (cons 350 EntName) (reverse (entget GroupDic)))
      )
    )
  )
)

ronjonp

  • Needs a day job
  • Posts: 7526
Re: Block to Group in Vanilla
« Reply #9 on: November 14, 2014, 03:48:44 PM »
I've always wondered this, and have never met someone that can give me an answer. What is the point of groups? I've never seen a point for their use, and when I have had drawings where objects are in a group, it's nothing but a nuisance.
I use them a bit for my inhouse application. We do irrigation design and it's nice to have an adjustable "design arc" that moves with the sprinkler block. Also good for tying many small items together.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ronjonp

  • Needs a day job
  • Posts: 7526
Re: Block to Group in Vanilla
« Reply #10 on: November 14, 2014, 04:42:43 PM »
Using Vovka's group sub, this seems to work for me:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:b2r (/ _ss2list vk_creategroup ce h ss ss2 qa)
  2.   (defun vk_creategroup (name entslist selflag / groupdic entname)
  3.     (if (and entslist
  4.              (setq groupdic (cdadr (member (cons 3 "ACAD_GROUP") (entget (namedobjdict)))))
  5.              ;; RJP changed vl-position to member since OP needs vanilla lisp
  6.              (not (and name (member (cons 3 name) (entget groupdic))))
  7.              (setq entname (entmakex (append (list (cons 0 "GROUP")
  8.                                                    (cons 100 "AcDbGroup")
  9.                                                    (cons 300 "")
  10.                                                    (cons 70
  11.                                                          (if name
  12.                                                            0
  13.                                                            1
  14.                                                          )
  15.                                                    )
  16.                                                    (cons 71 selflag)
  17.                                              )
  18.                                              (mapcar (function (lambda (e) (cons 340 e))) entslist)
  19.                                      )
  20.                            )
  21.              )
  22.              (entmod (append (entget groupdic)
  23.                              (list (cons 3
  24.                                          (if (null name)
  25.                                            "*"
  26.                                            name
  27.                                          )
  28.                                    )
  29.                                    (cons 350 entname)
  30.                              )
  31.                      )
  32.              )
  33.         )
  34.       (if name
  35.         name
  36.         (cdadr (member (cons 350 entname) (reverse (entget groupdic))))
  37.       )
  38.     )
  39.   )
  40.   (defun _ss2list (ss / n out)
  41.     (if (= (type ss) 'pickset)
  42.       (repeat (setq n (sslength ss)) (setq out (cons (ssname ss (setq n (1- n))) out)))
  43.     )
  44.   )
  45.   (if (setq ss (_ss2list (ssget ":L" '((0 . "insert")))))
  46.     (progn (setq ce (getvar 'cmdecho))
  47.            (setq qa (getvar 'qaflags))
  48.            (setvar 'cmdecho 0)
  49.            (setvar 'qaflags 0)
  50.            (foreach e ss
  51.              (setq h (cdr (assoc 5 (entget e))))
  52.              (command "_.explode" e)
  53.              (if (setq ss2 (_ss2list (ssget "_P")))
  54.                (vk_creategroup h ss2 1)
  55.              )
  56.            )
  57.            (setvar 'cmdecho ce)
  58.            (setvar 'qaflags qa)
  59.     )
  60.   )
  61.   (princ)
  62. )

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

jimlapier

  • Mosquito
  • Posts: 9
Re: Block to Group in Vanilla
« Reply #11 on: November 14, 2014, 05:19:00 PM »
You guys rock! I tested this on a small file and it worked perfectly. I'm going to run it through a larger file now and see what I get.

As far as why groups, I find them useful for quickly attaching objects together for moving / copying etc. Also, for this specific case, the client imports entire files / projects from Vectorworks. During the import / export, all of the objects come in blocks, with a solid hatch background for each "part" of an assembly. These solid hatches are huge. If I explode all of the blocks, each "part" is broken down to lines, essentially an entire drawing of lines on the same layer.
By exploding the objects and grouping them, they can more easily manage them and delete the hatch objects while maintain the "parts."

After running this on a large file, it has to be re-run a few times to explode & group all of the nested blocks.
After I finish this I'll be hosting it on my blog macncad.com so anyone needing it for AutoCAD for Mac can find it. Thanks again everyone for all of your help!

trogg

  • Bull Frog
  • Posts: 255
Re: Block to Group in Vanilla
« Reply #12 on: November 15, 2014, 08:41:03 PM »
I've always wondered this, and have never met someone that can give me an answer. What is the point of groups? I've never seen a point for their use, and when I have had drawings where objects are in a group, it's nothing but a nuisance.

Alan - I thought the same thing before I started using CADWorx which also relies on groups.
There are 3 things that I have found useful about them:
1) Easily add and remove objects to/from the group
2) Manipulate the geometry of one group even though it started out just like another group - whereas if you modify a block, all of the other blocks reflect the manipulation
3) when multiple blocks are grouped, their individual parts (blocks) can be moved without moving the entire group.

just my 2 cents...
~Greg

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Block to Group in Vanilla
« Reply #13 on: November 17, 2014, 02:43:32 PM »
OK, those are sensible uses. Thanks for the explanations. Every time I've seen it, it always seemed like a separate layer or block was the right answer.
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Block to Group in Vanilla
« Reply #14 on: November 17, 2014, 05:21:45 PM »
Don't think I saw it mentioned - when asked to select objects, you can respond "Group" then type in a group name.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

77077

  • Guest
Re: Block to Group in Vanilla
« Reply #15 on: June 03, 2015, 03:48:50 AM »
Thanks ronjonp. It's useful.