Author Topic: Help finding tag blocks more than one level deep  (Read 1437 times)

0 Members and 1 Guest are viewing this topic.

Rabbit

  • Guest
Help finding tag blocks more than one level deep
« on: November 21, 2012, 09:39:17 AM »
I have a routine which will give me certain attribute contents of nested tag blocks.  Works great for when the tag blocks are nested one level deep.  Problem is, when the tag block is nested 2 or more levels deep.  This is the third time I have re-written this and still having the same result.  Any ideas?

Attached are three (3) routines.  The first if a utility subroutine to get attributes.  The second is the main body.  And the third is used to call the main routine.  I've also added a 2012 .DWG which have three of the types of blocks I need to search through.

All help is appreciated,
Rabbit

Code - Auto/Visual Lisp: [Select]
  1. ;;;UTILITY SUBROUTINE
  2. ;;;------------------------------------------------------------------------------------------------
  3. ;;;Thanks to J. Roper for this section:
  4. ;;---------------------------------------------------------
  5. ;ATT:GETS - Utility routine to get all attributes for
  6. ;an insert object (EN).
  7. ;;
  8. ;;You pass this function an entity name, like something that would be returned from this example:
  9. ;;(setq EN (car (entsel "\nSelect block")))
  10. ;;an entity name looks like this when returned on a command line  --><Entity name: 4119ab90>
  11. ;;You use this function like this:  (setq ATTLIST (ATT:GETS EN))
  12. ;;it returns a list like this ---> (("TAG1 . "VALUE1")("TAG2" . "VALUE2")....)
  13. (defun ATT:GETS (EN / EL RES)
  14.   ;entnext goes on to the next entity.  If what you passed is an attributed block, the next entity will be an attribute.
  15.   (setq EN (entnext EN)
  16.         EL (entget EN));entget "breaks open" the entity name to reveal the entity list
  17.   (while (= "ATTRIB" (cdr (assoc 0 EL)));we check the entity list to see if it is an attribute
  18.     (setq RES (cons
  19.                 (cons (cdr (assoc 2 EL));if it is, we create a list of its tag and value, dxf code 2 and 1, using CONS
  20.                       (cdr (assoc 1 EL))) RES)
  21.           EN (entnext EN);go to the next entity
  22.           EL (entget EN)));get the next entities list
  23.   (reverse RES);reverse the list to put it in proper order.
  24.   )
  25.  
  26. ;;;MAIN SUBROUTINE
  27. ;;;Returns a list of all tags, from all blocks, with the name within variable "NestedLookForName"
  28. (defun FINDNESTEDTAGS (NestedLookForName)
  29.   ;;;sub routine to get tag info.  Returns formatted tag info.
  30.   (defun ProcessTags (ent / 1stAtt TagAtts TagList)
  31.     ;checks to see if tag is an equipment tag.
  32.     (if (= "ITEM#" (caar (ATT:GETS ent)))
  33.       ;if so, then process to get tag attributes
  34.       (setq TagAtts (cdar (ATT:GETS ent)))
  35.       ;if not, then process the other type of tag for it's attributes
  36.       (progn
  37.         ;get tag number
  38.         (setq 1stAtt (cdar (ATT:GETS ent)))
  39.         ;get tag type and string it together with the tag number
  40.         (setq TagAtts (strcat
  41.                         (cond; this section just puts the number attributes to 3 digits dot two digits, i.e. change 0.00 & 00.00 to 000.00
  42.                           ((< (strlen 1stAtt) 5) (setq 1stAtt (strcat "00" 1stAtt)))
  43.                           ((< (strlen 1stAtt) 6) (setq 1stAtt (strcat "0" 1stAtt)))
  44.                           (T 1stAtt)
  45.                         );cond
  46.                         (cdadr (ATT:GETS ent))
  47.                       );strcat
  48.         );setq
  49.       );progn
  50.     );if
  51.     TagAtts
  52.   );defun
  53.  
  54.   ;;get a selection set of all blocks
  55.   (setq sset (ssget "_X" '((0 . "INSERT")))
  56.         SelectedEntity nil
  57.         SelectedEntityCodes nil
  58.         BlockDefinition nil
  59.         NestedEntity nil
  60.         NestedEntityCodes nil
  61.         TagList nil)
  62.   ;;start to loop through selection set (entities will get deleted from seletion set each round)
  63.   (while (setq SelectedEntity (ssname sset 0))
  64.     ;check to see if entity is a tag block
  65.     (if (and (= "INSERT" (cdr (assoc 0 (setq SelectedEntityCodes (entget SelectedEntity)))))
  66.              (= NestedLookForName (cdr (assoc 2 SelectedEntityCodes)))
  67.         );and
  68.       ;if so, process tag block in selection set
  69.       (setq TagAtts (ProcessTags SelectedEntity)
  70.             TagList (cons TagAtts TagList))
  71.       ;if not, process for nested blocks
  72.       (progn
  73.         ;find blocks within the first block in the selection set
  74.         (setq BlockDefinition (tblsearch "BLOCK" (cdr (assoc 2 (entget SelectedEntity)))))
  75.         ;get dxf code -2 for nested blocks
  76.         (setq NestedEntity (cdr (assoc -2 BlockDefinition)))
  77.         ;loop through internal entities of block
  78.         (while NestedEntity
  79.           ;get codes of internal entity
  80.           (setq NestedEntityCodes (entget NestedEntity))
  81.           ;check to make sure internal entity is a block, has correct name, has attributtes and is visible
  82.           (if (and (= (cdr (assoc 0 NestedEntityCodes)) "INSERT")
  83.                    (= NestedLookForName (cdr (assoc 2 NestedEntityCodes)))
  84.                    (= (cdr (assoc 66 NestedEntityCodes)) 1)
  85.                    (/= 1 (cdr (assoc 60 NestedEntityCodes)))
  86.               );and
  87.             ;if ok, then process internal entity
  88.             (setq TagAtts (ProcessTags NestedEntity)
  89.                   TagList (cons TagAtts TagList)
  90.                   NestedEntity (entnext NestedEntity))
  91.             (setq NestedEntity (entnext NestedEntity))
  92.             );if
  93.         );while
  94.       );progn processing nested entities
  95.     );if checking for tag in selection set
  96.     ;remove entity from selection set
  97.     (ssdel SelectedEntity sset)
  98.   );while processing selectionset
  99. TagList
  100. );defun
  101.  
  102. ;;;test function to get tags
  103. (defun c:test6 () (setq Allblocks (FINDNESTEDTAGS "ERINTAG")))
  104.  

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Help finding tag blocks more than one level deep
« Reply #1 on: November 22, 2012, 12:26:05 AM »
In one word: Recursion.
 
Redesign the portion inside the loop as a defun in itself taking the ename of an insert as argument. This defun would:
  • Step through each entity inside the definition of that insert.
  • Check if this nested entity is an INSERT
  • If so call itself with the nested ISNERT's ename as argument (this is the "Recursion").
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Rabbit

  • Guest
Re: Help finding tag blocks more than one level deep
« Reply #2 on: November 23, 2012, 12:43:47 PM »
I've done some searching and looks like I've got to do some researching to find out how this works.

Here seems to be a good document on explaining it.
http://autocad.xarch.at/lisp/recursive.html

Unfortunately, I'll have to wait until the week after next before I can go through it.  Next week I'm at AU in Las Vegas getting my brain overloaded.

Thanks for the idea.  I'll definitely be considering this method.

Sincerely,
Rabbit