Author Topic: How to list all the blocks in a directory form?  (Read 12340 times)

0 Members and 1 Guest are viewing this topic.

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
How to list all the blocks in a directory form?
« on: March 26, 2009, 09:25:18 PM »
In a dwg file,there are a lot of blocks.  Some blocks is nested. How to list all the blocks in a directory form?

for example ,These are blocks: "1" "2" "3" "4" "5" "6" "7"; "7" in "6","6" "5" in "4", "4"  "3" "2" in "1";
this function return value likes below:
("1" ("2" "3"  ("4"  ("5" ("6" ("7"))))))

How to get it?
Actually, I found  a way to list all the nested blocks in a Insert.But for this ,I have no idea...
I am a bilingualist,Chinese and Chinglish.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to list all the blocks in a directory form?
« Reply #1 on: March 26, 2009, 11:34:10 PM »
If you want to flatten the list this will help:
http://www.theswamp.org/index.php?topic=4064.0

Otherwise I'm lost. 8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to list all the blocks in a directory form?
« Reply #2 on: March 26, 2009, 11:50:15 PM »
I believe he wants the opposite of flattening Alan (a block def tree), but I could be wrong. :)

Simply walk thru each block definition collection (starting with the master blocks collection), recursively drilling into, and then out of each nested definition, indenting, and then de-indenting accordingly | appropriately before printing the block collection names. Should be 50 lines of code or less.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Re: How to list all the blocks in a directory form?
« Reply #3 on: March 27, 2009, 12:20:15 AM »
I believe he wants the opposite of flattening Alan (a block def tree), but I could be wrong. :)

Simply walk thru each block definition collection (starting with the master blocks collection), recursively drilling into, and then out of each nested definition, indenting, and then de-indenting accordingly | appropriately before printing the block collection names. Should be 50 lines of code or less.

Yes,extractly,I want a block def tree.
I am a bilingualist,Chinese and Chinglish.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to list all the blocks in a directory form?
« Reply #4 on: March 27, 2009, 12:42:07 AM »
REALLY QUICK, REALLY DIRTY.

But should work <starting point anyway>:

Code: [Select]
(defun c:BlockDefTree ( / foo blocks )

    (defun foo ( blocks block indent )
   
        (repeat indent (princ "    "))
        (princ (vla-get-name block))
        (princ "\n")       
   
        (vlax-for object block
            (if (eq "AcDbBlockReference" (vla-get-objectname object))
                (foo blocks (vla-item blocks (vla-get-name object)) (1+ indent))
            )
        )
    )
   
    (vlax-for block       
        (setq blocks
            (vla-get-blocks
                (vla-get-activedocument
                    (vlax-get-acad-object)
                )
            )
        )
        (foo blocks block 0)
    )   
   
    (princ)

)

Tried to stretched it out but it only spans 29 lines.  :|
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

cjw

  • Guest
Re: How to list all the blocks in a directory form?
« Reply #5 on: March 27, 2009, 01:21:07 AM »
REALLY QUICK, REALLY DIRTY.

But should work <starting point anyway>:

Code: [Select]
(defun c:BlockDefTree ( / foo blocks )

    (defun foo ( blocks block indent )
   
        (repeat indent (princ "    "))
        (princ (vla-get-name block))
        (princ "\n")       
   
        (vlax-for object block
            (if (eq "AcDbBlockReference" (vla-get-objectname object))
                (foo blocks (vla-item blocks (vla-get-name object)) (1+ indent))
            )
        )
    )
   
    (vlax-for block       
        (setq blocks
            (vla-get-blocks
                (vla-get-activedocument
                    (vlax-get-acad-object)
                )
            )
        )
        (foo blocks block 0)
    )   
   
    (princ)

)

Tried to stretched it out but it only spans 29 lines.  :|

Nice job! MP

Could you make this function return value likes below:
("1" ("2" "3"  ("4"  ("5" ("6" ("7"))))))
???
« Last Edit: March 27, 2009, 01:24:13 AM by cjw »

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to list all the blocks in a directory form?
« Reply #6 on: March 27, 2009, 01:29:26 AM »
Sure could but it's late. By the time I look at this thread tomorrow there will likely be 10 versions posted, so just wait a bit. :D
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Re: How to list all the blocks in a directory form?
« Reply #7 on: March 27, 2009, 02:25:23 AM »
Sure could but it's late. By the time I look at this thread tomorrow there will likely be 10 versions posted, so just wait a bit. :D
MP,thanks a lot.
But I want the return value is a list,(I think it is a multiway tree structure), and  if a blockdef has many same name nested blockdef in it, I just want a single ,remove those Duplicates.
Ha,What a different between our time! When we are working ,you are sleeping.Have a good dream!
« Last Edit: March 27, 2009, 02:52:28 AM by highflybird »
I am a bilingualist,Chinese and Chinglish.

cjw

  • Guest
Re: How to list all the blocks in a directory form?
« Reply #8 on: March 27, 2009, 02:38:03 AM »
Sure could but it's late. By the time I look at this thread tomorrow there will likely be 10 versions posted, so just wait a bit. :D
:-D
Time difference!!!

jxphklibin

  • Guest
Re: How to list all the blocks in a directory form?
« Reply #9 on: March 27, 2009, 04:14:49 AM »
 How my codes?

Code: [Select]
(defun AllBlkNInBlkdef (blkn / blkdef e typ bn bnl e-l)
  (setq bnl '() blkdef (tblobjname "block" blkn))
  (while (setq e (entnext blkdef))
    (setq typ (cdr (assoc 0 (entget e))))
    (if (= typ "INSERT")
      (setq bn (vla-get-name (vlax-ename->vla-object e))
    bnl (if bn
  ;;(append (list (list bn (AllBlkNInBlkdef bn))) bnl)
  (cons (list bn (AllBlkNInBlkdef bn)) bnl)
)
      )
      ;(setq el (cons e el))
    )
    (setq blkdef e)
  )
  bnl
)

(defun c:ABnInBl1 (/ i en ss blknlst ABblknlst)
  (setq ss   (ssget '((0 . "INSERT")))
ABblknlst '()
  )
  (if ss
    (repeat (setq i (sslength ss))
      (setq en       (ssname ss (setq i (1- i)))
    blkn      (vla-get-name (vlax-ename->vla-object en))
    blknlst   (AllBlkNInBlkdef blkn)
    ABblknlst (append (list (list blkn blknlst)) ABblknlst)
      )
    )
    (princ "*** 你没有选择任何图块 ***")
  )
  ;(princ)
)
« Last Edit: March 27, 2009, 04:57:49 AM by jxphklibin »

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Re: How to list all the blocks in a directory form?
« Reply #10 on: March 27, 2009, 04:46:35 AM »
OK! Now I got it!
Code: [Select]
;;;Main Function
(defun c:BT (/ AllLst bkTree)
  (setq *APP (vlax-get-acad-object))
  (setq *DOC (vla-get-ActiveDocument *APP))
  (setq *BLK (vla-get-blocks *DOC))
  (vlax-for blk *BLK
    (setq AllLst (cons (GetNestedName blk) AllLst))
  )
  (foreach n AllLst
    (setq bkTree (cons (Tree (car n)) bkTree))
  )
  (princ bkTree) ; Now BkTree is the return value, it's a blockDef tree.
  (princ)
)
;;;Get all names of Nested Blocks in A blockDef
(defun GetNestedName (blk / lst iName)
  (vlax-for n blk
    (if (or
          (= (vla-get-objectname n) "AcDbBlockReference")
          (= (vla-get-objectname n) "AcDbMInsertBlock")
        )
      (progn
        (setq iName (vla-get-name n))
        (if (not (member iName lst))
          (setq lst (cons iName lst))
        )
      )
    )
  )
  (cons (vla-get-name blk) lst)
)
;;;to Construct The BlockDef Tree
(defun Tree (name / lst)
  (foreach n (cdr (assoc name AllLst))
    (setq lst (cons (Tree n) lst))
  )
  (if lst
    (cons name (list lst))
    name
  )
)
« Last Edit: March 27, 2009, 12:11:38 PM by highflybird »
I am a bilingualist,Chinese and Chinglish.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to list all the blocks in a directory form?
« Reply #11 on: March 27, 2009, 09:10:35 AM »
But I want the return value is a list

I misunderstood what you wanted but it appears you have what you need now so all is good.

PS: I don't know if you've been formerly welcomed to the swamp, so 'Welcome to the swamp highflybird'.

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How to list all the blocks in a directory form?
« Reply #12 on: March 27, 2009, 01:41:49 PM »
I modded my original little contribution. It doesn't list redundant entries, makes it look like a tree of sorts, flags xrefs.

Code: [Select]
(defun c:BTree ( / walk main )

    (defun walk ( blocks block indent / names )
        (repeat (1- indent) (princ "    "))
        (if (< 0 indent) (princ "+-- "))
        (princ (vla-get-name block))
        (princ (if (eq :vlax-true (vla-get-isxref block)) " <XREF>\n" "\n"))
        (vlax-for object block
            (if (eq "AcDbBlockReference" (vla-get-objectname object))
                (if (null (member (setq name (vla-get-name object)) names))
                    (progn
                        (setq names (cons name names))
                        (walk
                            blocks
                            (vla-item blocks (vla-get-name object))
                            (1+ indent)
                        )
                    )
                )
            )
        )
    )

    (defun main ( / blocks index )
        (princ "\n")
        (foreach block
            (mapcar 'car
                (vl-sort       
                    (vlax-for block
                        (setq blocks
                            (vla-get-blocks
                                (vla-get-activedocument (vlax-get-acad-object))
                            )
                        )
                        (setq index
                            (cons
                                (cons block (vla-get-name block))
                                index
                            )
                        )
                    )
                   '(lambda (a b) (< (cdr a) (cdr b)))
                )   
            )   
            (walk blocks block 0)
        )
        (princ)
    )

    (main)

)

For what it's worth.

Edit: Modded so primary block collection is sorted.
« Last Edit: March 27, 2009, 03:24:43 PM by MP »
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

jxphklibin

  • Guest
Re: How to list all the blocks in a directory form?
« Reply #13 on: March 27, 2009, 08:46:16 PM »
Now , It is works.
Code: [Select]
(defun AllBlkNInBlkdef (blkn / blkdef e typ bn bnl e-l nl)
  (setq bnl    '()
blkdef (tblobjname "block" blkn)
  )
  (while (setq e (entnext blkdef))
    (setq typ (cdr (assoc 0 (entget e))))
    (if (= typ "INSERT")
      (setq bn (vla-get-name (vlax-ename->vla-object e))
    bnl (if bn
  (append (list(if (setq nl (AllBlkNInBlkdef bn))
    (list bn nl)
    (list bn)
  ))
  bnl
  )
)
      )
    )
    (setq blkdef e)
  )
  bnl
)

(defun c:ABnInBl (/ i en ss blknlst ABblknlst)
  (setq ss   (ssget '((0 . "INSERT")))
ABblknlst '()
  )
  (if ss
    (repeat (setq i (sslength ss))
      (setq en       (ssname ss (setq i (1- i)))
    blkn      (vla-get-name (vlax-ename->vla-object en))
    blknlst   (AllBlkNInBlkdef blkn)
    ABblknlst (append (list(if blknlst
(list blkn blknlst)
(list blkn)
      ))
      ABblknlst
      )
      )
    )
    (princ "*** 你没有选择任何图块 ***")
  )
  (princ ABblknlst)
(princ)
)

The new modified codes ,it works very exactly:
Code: [Select]
(defun AllBlkNInBlkdef (blkn / blkdef e typ bn bnl e-l nl)
  (setq ;bnl    '()
blkdef (tblobjname "block" blkn)
  )
  (while (setq e (entnext blkdef))
    (setq typ (cdr (assoc 0 (entget e))))
    (if (= typ "INSERT")
      (setq bn (vla-get-name (vlax-ename->vla-object e))
    bnl (if bn
  (cons (if (setq nl (AllBlkNInBlkdef bn))
    (list bn nl)
    bn
  )
  bnl
  )
)
      )
    )
    (setq blkdef e)
  )
  bnl
)

(defun c:ABnInBl (/ i en ss blknlst ABblknlst)
  (setq ss   (ssget '((0 . "INSERT")))
;ABblknlst '()
  )
  (if ss
    (repeat (setq i (sslength ss))
      (setq en       (ssname ss (setq i (1- i)))
    blkn      (vla-get-name (vlax-ename->vla-object en))
    blknlst   (AllBlkNInBlkdef blkn)
    ABblknlst (cons (if blknlst
(list blkn blknlst)
blkn
      )
      ABblknlst
      )
      )
    )
    (princ "*** 你没有选择任何图块 ***")
  )
  (princ ABblknlst)
(princ)
)
« Last Edit: March 27, 2009, 09:19:40 PM by jxphklibin »

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Re: How to list all the blocks in a directory form?
« Reply #14 on: March 27, 2009, 09:37:06 PM »
I modded my original little contribution. It doesn't list redundant entries, makes it look like a tree of sorts, flags xrefs.
......
Edit: Modded so primary block collection is sorted.
Oh, It looks awesome ! beautiful!
I am a bilingualist,Chinese and Chinglish.