Lisp - extracting subentities from a block

Hello there,

I'm currently working on a AutoLisp program to extract the DXF-Information (Group code) from sub entities (lines, circls, polylines and so on) contained in an Insert/Block and write it to a file. I did quite well extracting Entities from a drawing but for this issue I only have a rough idea.

variables used:

cntr (Counter)
oSubEnt (old subentity)
nSubEnt (new subentity)
subEntList (list of all subentities)

(setq subEntList(list))

(setq oSubEnt "")

(while (< cntr(sslength [set of all sub-entities]))

(setq nSubEnt (entget(entnext(cdr(car oSubEnt)))))

[add nSubEnt to subEntList]

(setq oSubEnt nSubEnt)

(setq cntr (+ cntr 1))

)

Practically I need help with everything within the square braces. I developed the basic idea from reading Jeffery P. Sanders tutorial. If it actually told how I could solve this problem I ether overred it or simply didn't understand.

I'd be very thankfull for every kind of help.

Please note my actual mothertongue is german so i ask you to excouse my possible typos and grammar misstakes.

Comments

  • Hi Stefen,
    use the following routine to display the DXF codes in the Text Window (F2)
    or to write them to a file....you can select any entity
    For subentities of Blocks you will have to read the block definition of the INSERT
    the command is   listDXF

    Here is the code
    I hope this helps !

    [code]
    (defun print_elist (elist flag / filenam fp )
     (if flag
       (progn
          (setq filenam (getfiled "TXT Datei erstellen" "" "txt" 1))
          (setq fp (open filenam "a"))
          (foreach idx elist
            (print idx fp)
           )
          (close fp)
         )
       (progn
         (foreach idx elist
            (print idx)
             )
         (princ)
         )
     )
    )

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    (defun atr_pop (en / lst AtrList )
       (setq AtrList (list "ATR" ))
       (while (not (equal (cdr (assoc 0 lst)) "SEQEND"))
          (setq en  (entnext en)
                lst (entget  en)
                AtrList (append AtrList lst)
                )
       )
     (cdr AtrList)
    )

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    (defun c:listDXF ( / en elist flagFile)
     (prompt "Select an Entity :\n")
     (setq en    (car(entsel))
           elist (entget en)
      )
     
     (if (AND (= (cdr (assoc 0 elist)) "INSERT") ; if Block Insert
              (= (cdr (assoc 66 elist)) 1)       ; if attributes exist
              )
      (setq elist (append elist (atr_pop en)))
      )

     (setq flagFile (getstring "\nWrite to a file : "))
     (if (OR  (equal (strcase flagFile)  "Y")
              (equal (strcase flagFile)  "YE")
              (equal (strcase flagFile)  "YES")
              )
       (print_elist elist T)
       (print_elist elist nil)
       )
     (princ)
     )
      [/code]
     



  • @ Steven:
    [code]; Return value: List of enames.
    (defun Block_EnameListNested (blockName / ename ret)
      (if (setq ename (tblobjname "block" blockName))
        (reverse
          (while (setq ename (entnext ename))
            (setq ret (cons ename ret))
          )
        )
      )
    )[/code]

    To manipulate the list look into the Lisp functions foreach, append and cons.

    You should be aware that certain group codes in the entget-list (e.g. the ones with enames) make no sense when written to a text file. So you need a way to filter out those group codes.
  • First of all thank you to the two of you!

     @Konstantin:
    Your code didn't exactly do what I was looking for (yet it wasallready executable). But it helps me a lot understanding Lisp.... At least I think so!

    @Roy:
    Your code PROPABLY does the Job. All I need to do now is to figure out a way to crochet it into my existing code properly.

    A little confession: This is my second day of learning Lisp and working with it and I feel like a total noob asking These questions.

  • Stefen,
    i have integrated the code from Roy with minor changes into my code...
    So now you get everything from a block...
    All the DXF data from the Block Table  (Block definition, Nested Entities+ ATTDEF )
    and from the Entities Section  (Block Insert, Attributes if exist)
    You can choose to dump everything to the text screen or write it to a file  !
    ...command   listDXF

    Here is the code

    [code]
    (defun print_elist (elist flag / filenam fp )
     
     (if flag
       (progn
          (setq filenam (getfiled "TXT Datei erstellen" "" "txt" 1))
          (setq fp (open filenam "a"))
          (foreach idx elist
            (print idx fp)
           )
          (close fp)
         )
       (progn
         (foreach idx elist
            (print idx)
             )
         (princ)
         )
     )
    )

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    (defun atr_pop (en / lst AtrList )
       (setq AtrList (list "ATR" ))
       (while (not (equal (cdr (assoc 0 lst)) "SEQEND"))
          (setq en  (entnext en)
                lst (entget  en)
                AtrList (append AtrList lst)
                )
       )
     (cdr AtrList)
    )

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    (defun c:listDXF ( / en elist flagFile)
     (prompt "Select an Entity :\n")
     (setq en    (car(entsel))
           elist (entget en)
      )

     (if (= (cdr (assoc 0 elist)) "INSERT") ; if Block Insert
      (setq elist (append (Block_EnameListNested (cdr (assoc 2 elist))) elist ) )
      )
     
     (if (AND (= (cdr (assoc 0  (entget en))) "INSERT") ; if Block Insert
              (= (cdr (assoc 66 (entget en))) 1)        ; if attributes exist
              )
     
       (setq elist (append elist (atr_pop en)))
     
      )

     (setq flagFile (getstring "\nWrite to a file : "))
     (if (OR  (equal (strcase flagFile)  "Y")
              (equal (strcase flagFile)  "YE")
              (equal (strcase flagFile)  "YES")
              )
       (print_elist elist T)
       (print_elist elist nil)
       )
     (princ)
     )
     
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    ; Return value: List of enames of block nested entities from Block Definition
    (defun Block_EnameListNested (blockName / ename ret)
     (setq ename (tblobjname "block" blockName)
           ret   (entget ename)
           )
      (if ename
       
          (while (setq ename (entnext ename))
            (setq ret (append ret (entget ename) ))
          )
       
      )
    )
     
    [/code]
  • A thousand thanks!
    Thats exactly what I needed. I'll emedietly beginn to fit your solution into my code.
    Thanks Roy and thanks Konstantin!
This discussion has been closed.