Dynamic Block Selection

Dynamic Block Selection

nathanwheeler27
Advocate Advocate
1,424 Views
15 Replies
Message 1 of 16

Dynamic Block Selection

nathanwheeler27
Advocate
Advocate

 

(defun sb (lyr / e name n out ss)
    (vl-load-com)
    (if (setq name "BEAM" 
              ss (ssget "_X" '((0 . "INSERT")(8 . lyr)))
              n -1
              out (ssadd)
        )
        (while (setq e (ssname ss (setq n (1+ n))))
	    (if (= :vlax-true (vla-get-IsDynamicBlock (vlax-ename->vla-object e)))
		    (if (= (strcase (vla-get-Effectivename (vlax-ename->vla-object e))) (strcase name))
			    (ssadd e out)
		    )
	    )
        )
    )

    (if (/= 0 (sslength out))(sssetfirst nil out)(princ (strcat "No Dynamic Block found by the Name - " name)))
    (command "_.draworder" "_back")
    (princ)
)

(defun c:BDRAWORDER (/ layerList data ss)
  (foreach layer '( 
        "TEXT" 
        "DIMENSIONS"
        "RAILING"
        "0"
        "* SHEARWALLS"
        "* TEXT *"
        "* TEXT - WALL LINES"
        "* DIM *"
        "* SECTION"
        "* ROOF"
        "* ROOF BEAMS"
        "* ROOF FRAMING"
        "* ROOF POSTS"
        "* CEILING BEAM"
        "* CEILING FRAMING"
        "* CEILING POSTS"
        "* FRAMING BEAMS"
        "* FRAMING"
        "* FRAMING POSTS"
        "* FND POSTS"
        "* SHEARWALLS POSTS"
        "* POST"
        "* SILL"
        "* STEM WALL"
        "* FOUNDATION"
        "* ELECTRICAL"
        "* GAS"
        "* WALLS - E"
        "* WALLS - I"
        "* DOORS"
        "* WINDOWS"
        "* STAIRS"
        "* FP"
        "* WALLS - HATCH"
        )
    (if (setq ss (ssget "_X" (list (cons 8 layer)))) ; layer has objects
      (command "_.draworder" ss "" "_back") 
      (if (= layer "* ROOF FRAMING") (sb "* ROOF BEAMS"))
        ;(cond ((= layer "* ROOF FRAMING")(sb "* ROOF BEAMS"))
                ;((= layer "* CEILING FRAMING")(sb "* CEILING BEAM"))
                ;(t nil)
        ;)
    )
  ) ; end foreach
  (princ)
)

 

 

Hi,

 

The first function "sb" was partially provided by someone on this forum and it just selects all dynamic blocks of a given name. I modified it to select block "BEAM" on whichever layer (lyr) is specified and at the end sets the draworder to back. This all seemed to work when called in the function "BDRAWORDER" until I tried changing (if (= layer "* ROOF FRAMING") (sb "* ROOF BEAMS"))  to the cond function thats now commented out.

 

 

As soon as "sb" is called, I get Command: ; error: bad SSGET list value and it stops running.

Thanks

0 Likes
Accepted solutions (1)
1,425 Views
15 Replies
Replies (15)
Message 2 of 16

hak_vz
Advisor
Advisor

Please attach a sample file for easier checking.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 3 of 16

Moshe-A
Mentor
Mentor

@nathanwheeler27 ,

 

(ssget) filter list must have constant arguments

(8 . lyr) causing the error

 

 

moshe

 

Message 4 of 16

Moshe-A
Mentor
Mentor

Or use (cons 8 lyr)

but you need to bound the filter list with (list) function

 

search this forum to find examples for (ssget) filter list

 

 

 

 

 

 

Message 5 of 16

Moshe-A
Mentor
Mentor

here an example 

 

 

Message 6 of 16

Shneuph
Collaborator
Collaborator

I have a little experience and understand what you are saying about the layer filter, @Moshe-A .. but, just out of curiosity, how could it have worked before with the (cond function and now changing to an (if function breaks it if there was no change to SB?

 

@nathanwheeler27  can you confirm it worked before with the current SB function and the (cond statement shown?

 

EDIT: nm.. you changed FROM the if statement TO the cond statement?  So, it's the cond statement that gives an error.  Let me look again.

---sig---------------------------------------
'(83 104 110 101 117 112 104 64 71 109 97 105 108 46 99 111 109)
0 Likes
Message 7 of 16

nathanwheeler27
Advocate
Advocate

 

 

(defun sb (lyr / e name n out ss)
    (vl-load-com)
    (if (setq name "BEAM" 
              ss (ssget "_X" (0 . "INSERT")(list (cons 8 lyr)))
              n -1
              out (ssadd)
        )
        (while (setq e (ssname ss (setq n (1+ n))))
	    (if (= :vlax-true (vla-get-IsDynamicBlock (vlax-ename->vla-object e)))
		    (if (= (strcase (vla-get-Effectivename (vlax-ename->vla-object e))) (strcase name))
			    (ssadd e out)
		    )
	    )
        )
    )

    (if (/= 0 (sslength out))(sssetfirst nil out)(princ (strcat "No Dynamic Block found by the Name - " name)))
    (command "_.draworder" "_back")
    (princ)
)

(defun c:BDRAWORDER (/ layer data ss)
  (foreach layer '( 
        "TEXT" 
        "DIMENSIONS"
        "RAILING"
        "0"
        "* SHEARWALLS"
        "* TEXT *"
        "* TEXT - WALL LINES"
        "* DIM *"
        "* SECTION"
        "* ROOF"
        "* ROOF BEAMS"
        "* ROOF FRAMING"
        "* ROOF POSTS"
        "* CEILING BEAM"
        "* CEILING FRAMING"
        "* CEILING POSTS"
        "* FLOOR BEAMS"
        "* FLOOR FRAMING"
        "* FLOOR POSTS"
        "* FND POSTS"
        "* SHEARWALLS POSTS"
        "* POST"
        "* SILL"
        "* STEM WALL"
        "* FOUNDATION"
        "* ELECTRICAL"
        "* GAS"
        "* WALLS - E"
        "* WALLS - I"
        "* DOORS"
        "* WINDOWS"
        "* STAIRS"
        "* FP"
        "* WALLS - HATCH"
        )
    (if (setq ss (ssget "_X" (list (cons 8 layer)))) ; layer has objects 
	(command "_.draworder" ss "" "_back")
        (cond ((= layer "* ROOF FRAMING")(sb "* ROOF BEAMS"))
                ((= layer "* CEILING FRAMING")(sb "* CEILING BEAM"))
	      	 ((= layer "* FLOOR FRAMING")(sb "* FLOOR BEAMS"))
                (t nil)
        )
    )
  ) ; end foreach
  (princ)
)

 

 

 

I'm at work, so I don't have much time to fully look into everyone's posts yet. But, I updated the code to use (list (cons 8 lyr)) and I switched back to the conditional statement since that's what I will need to accomplish what I want.

I now get "bad syntax of function call: (0 . "INSERT")" when I load the script. I have tried multiple different ways of writing this ssget function and obviously I don't fully understand the proper syntax yet. I will research that more when I am off work. If anyone can see the issue, let me know. Otherwise, I will keep researching later and provide a sample file.

0 Likes
Message 8 of 16

Shneuph
Collaborator
Collaborator

Try: 

(ssget "_X" (list '(0 . "INSERT")(cons 8 lyr)))
---sig---------------------------------------
'(83 104 110 101 117 112 104 64 71 109 97 105 108 46 99 111 109)
Message 9 of 16

Moshe-A
Mentor
Mentor

@Shneuph ,

 

give this a try 😀 did not test it cause you did not provide a sample dwg

 

Moshe

 

 

(vl-load-com) ; Load ActiveX support

(defun sb (lyr / e name n out ss AcDbEntity)
 (if (setq ss (ssget "_X" (list '(0 . "insert") (cons 8 lyr))))
  (progn 
   (setq name "BEAM" 
         n -1
         out (ssadd)
   )
   
   (while (setq e (ssname ss (setq n (1+ n))))
    (setq AcDbEntity (vlax-ename->vla-object e)) 
    (if (and
          (eq (vla-get-objectname AcDbEntity) "AcDbBlockReference")
          (eq (strcase (vla-get-effectivename AcDbEntity))  (strcase name))
          (eq (vla-get-IsDynamicBlock AcDbEntity) :vlax-true)
        )
     (ssadd e out)
    )
    (vlax-release-object AcDbEntity)
   ); while
   
   (if (> (sslength out) 0)
    (command "_.draworder" "_si" out "_back")
    (princ (strcat "\nNo Dynamic Block found by the Name - " name))
   ); if
   
  ); progn
 ); if  
); defun sb


(defun c:BDRAWORDER (/ layerList data ss)
  (foreach layer '( 
        "TEXT" 
        "DIMENSIONS"
        "RAILING"
        "0"
        "* SHEARWALLS"
        "* TEXT *"
        "* TEXT - WALL LINES"
        "* DIM *"
        "* SECTION"
        "* ROOF"
        "* ROOF BEAMS"
        "* ROOF FRAMING"
        "* ROOF POSTS"
        "* CEILING BEAM"
        "* CEILING FRAMING"
        "* CEILING POSTS"
        "* FRAMING BEAMS"
        "* FRAMING"
        "* FRAMING POSTS"
        "* FND POSTS"
        "* SHEARWALLS POSTS"
        "* POST"
        "* SILL"
        "* STEM WALL"
        "* FOUNDATION"
        "* ELECTRICAL"
        "* GAS"
        "* WALLS - E"
        "* WALLS - I"
        "* DOORS"
        "* WINDOWS"
        "* STAIRS"
        "* FP"
        "* WALLS - HATCH"
        )
    (if (setq ss (ssget "_X" (list (cons 8 layer)))) ; does layer has objects
     (command "_.draworder" ss "" "_back") 
     ; else 
     (cond
      ((= layer "* ROOF FRAMING")
       (sb "* ROOF BEAMS")
      )
      ((= layer "* CEILING FRAMING")
       (sb "* CEILING BEAM")
      )
     ); cond
    ); if
  ) ; end foreach
  (princ)
)

 

 

Message 10 of 16

ronjonp
Mentor
Mentor

 Not exactly sure what you're trying to accomplish, but give this a try 🙂

(defun c:bdraworder (/ lyrs ss)
  (setq	lyrs '("TEXT"		     "DIMENSIONS"	 "RAILING"	     "0"
		 "* SHEARWALLS"	     "* TEXT *"		 "* TEXT - WALL LINES"
		 "* DIM *"	     "* SECTION"	 "* ROOF"	     "* ROOF BEAMS"
		 "* ROOF FRAMING"    "* ROOF POSTS"	 "* CEILING BEAM"    "* CEILING FRAMING"
		 "* CEILING POSTS"   "* FLOOR BEAMS"	 "* FLOOR FRAMING"   "* FLOOR POSTS"
		 "* FND POSTS"	     "* SHEARWALLS POSTS"		     "* POST"
		 "* SILL"	     "* STEM WALL"	 "* FOUNDATION"	     "* ELECTRICAL"
		 "* GAS"	     "* WALLS - E"	 "* WALLS - I"	     "* DOORS"
		 "* WINDOWS"	     "* STAIRS"		 "* FP"		     "* WALLS - HATCH"
		)
  )
  (if
    (setq ss (ssget "_X" (list (cons 8 (apply 'strcat (mapcar '(lambda (x) (strcat x ",")) lyrs))))))
     (command "_.draworder" ss "" "_back")
  )
  (princ)
)
Message 11 of 16

Sea-Haven
Mentor
Mentor

Why not write the ssget with all the layers.

 

 

(setq ss (ssget "_X" (list (cons 8 "0,
red,
Lay3,
Lay4"
))))

 

0 Likes
Message 12 of 16

nathanwheeler27
Advocate
Advocate

Nothing seems to be working yet.

 

A sample is attached with all my layers and the "BEAM" block. Its pretty annoying checking the draw order of objects, so I use hatch to easily see the order.

What this script is supposed to do is set the draw order for all my layers. That part is pretty easy. The one issue is that the "BEAM" block that goes on the "* Beams" layers needs to go below the "* Framing" layers. So the draw order is more like this (not including the whole list of layers):

Top: "* ROOF BEAMS"
"* ROOF FRAMING"
"BEAM" blocks on "* ROOF BEAMS" layer
Bottom: "* ROOF POSTS"

 

But, since its not as simple as just writing a list, I am trying to get the if statement to trigger a function which sets the draw order for the "BEAM" block.

0 Likes
Message 13 of 16

Sea-Haven
Mentor
Mentor

I had a task using wipeouts and draworder and you would need to provide the correct order that you want objects to appear in, it can be either a list in order or multi line doing in order. 

 

The order goes in opposite the most below goes 1st the top goes last.

0 Likes
Message 14 of 16

Moshe-A
Mentor
Mentor
Accepted solution

@nathanwheeler27 ,

 

Posting a sample dwg made the difference, now it's all clear. i added the 410 dxf code to (ssget) filter cause (ssget) scans the whole database and gets objects from all spaces (including layouts) and if there are some objects there (and on your sample dwg there were) it tries to DRAWORDER them but you are in model space and the select objects of (any) modify command only accept objects from current space 😀

 

so this phase (the lisp) is running without complaining 😷

 

the question is, does this satisfied you?

 

well this depends on what objects you have and what is the order they were built? maybe to achieve what you want you also need to bring to front some objects. trail and error is the name of our game.

 

One more thing about the (sb) function, if you are looking for BEAM block, either it's dynamic, you do not have to check with (vla-get-IsDynamicBlock). validing it's name will be sufficient cause the current drawing can hold only one BEAM block (static or dynamic). 

 

cheers

moshe

 

 

 

 

 

 

 

 

 

(vl-load-com) ; Load ActiveX support

(defun sb (lyr / e name n out ss AcDbEntity)
 (if (setq ss (ssget "_X" (list '(0 . "insert") (cons 8 lyr) '(410 . "Model"))))
  (progn 
   (setq name "BEAM" 
         n -1
         out (ssadd)
   )
   
   (while (setq e (ssname ss (setq n (1+ n))))
    (setq AcDbEntity (vlax-ename->vla-object e)) 
    (if (and
          (eq (vla-get-objectname AcDbEntity) "AcDbBlockReference")
          (eq (strcase (vla-get-effectivename AcDbEntity))  (strcase name))
          (eq (vla-get-IsDynamicBlock AcDbEntity) :vlax-true)
        )
     (ssadd e out)
    )
    (vlax-release-object AcDbEntity)
   ); while
   
   (if (> (sslength out) 0)
    (command "_.draworder" "_si" out "_back")
    (princ (strcat "\nNo Dynamic Block found by the Name - " name))
   ); if
   
  ); progn
 ); if  
); defun sb


(defun c:BDRAWORDER (/ layerList data ss)
  (foreach layer '( 
        "TEXT" 
        "DIMENSIONS"
        "RAILING"
        "0"
        "* SHEARWALLS"
        "* TEXT *"
        "* TEXT - WALL LINES"
        "* DIM *"
        "* SECTION"
        "* ROOF"
        "* ROOF BEAMS"
        "* ROOF FRAMING"
        "* ROOF POSTS"
        "* CEILING BEAM"
        "* CEILING FRAMING"
        "* CEILING POSTS"
        "* FRAMING BEAMS"
        "* FRAMING"
        "* FRAMING POSTS"
        "* FND POSTS"
        "* SHEARWALLS POSTS"
        "* POST"
        "* SILL"
        "* STEM WALL"
        "* FOUNDATION"
        "* ELECTRICAL"
        "* GAS"
        "* WALLS - E"
        "* WALLS - I"
        "* DOORS"
        "* WINDOWS"
        "* STAIRS"
        "* FP"
        "* WALLS - HATCH"
        )
    (if (setq ss (ssget "_X" (list (cons 8 layer) '(410 . "Model")))) ; does layer has objects?
     (command "_.draworder" "_si" ss "_back")
     (cond
      ((= layer "* ROOF FRAMING")
       (sb "* ROOF BEAMS")
      )
      ((= layer "* CEILING FRAMING")
       (sb "* CEILING BEAM")
      )
     ); cond
    ); if
  ); foreach
  (princ)
)

 

 

 

 

 

 

 

Message 15 of 16

nathanwheeler27
Advocate
Advocate

Wow! 😥 What a pain.

 

You pretty much had it right, except for the ) for the if statement at the end. It apparently needs to come before the cond. I also spent a stupid amount of time catching a mistake for a second time (in one of my earlier code snippets posted I fixed it). The layer filter "* FRAMING" groups in two of the layers that should be above it, "* CEILING FRAMING" and "* ROOF FRAMING". I kept trying to figure why these layers were showing up out of order...😖 

 

 

(defun c:BDRAWORDER (/ layer data ss)
  (foreach layer '( 
        "TEXT" 
        "DIMENSIONS"
        "RAILING"
        "0"
        "* SHEARWALLS"
        "* TEXT *"
        "* TEXT - WALL LINES"
        "* DIM *"
        "* SECTION"
        "* ROOF"
        "* ROOF BEAMS"
        "* ROOF FRAMING"
        "* ROOF POSTS"
        "* CEILING BEAM"
        "* CEILING FRAMING"
        "* CEILING POSTS"
        ;"* FRAMING BEAMS"
        ;"* FRAMING"
        ;"* FRAMING POSTS"
        "* FND POSTS"
        "* SHEARWALLS POSTS"
        "* POST"
        "* SILL"
        "* STEM WALL"
        "* FOUNDATION"
        "* ELECTRICAL"
        "* GAS"
        "* WALLS - E"
        "* WALLS - I"
        "* DOORS"
        "* WINDOWS"
        "* STAIRS"
        "* FP"
        "* WALLS - HATCH"
        )
    (if (setq ss (ssget "_X" (list (cons 8 layer) '(410 . "Model")))) ; does layer has objects?
     (command "_.draworder" "_si" ss "_back")
     ) ; if
     (cond
      ((= layer "* ROOF FRAMING")
       (sb "* ROOF BEAMS")
      )
      ((= layer "* CEILING FRAMING")
       (sb "* CEILING BEAM")
      )
     ); cond
   
  ); foreach
  (princ)
)

 

 

Is this language super fidgety, or is it that I am just a beginner?

 

 

Thank you everyone! 

The support on this forum is impressive.

0 Likes
Message 16 of 16

Moshe-A
Mentor
Mentor

very glade i could help, please mark it as your solution.

 

 

0 Likes