Jump to content

Filtering Selection to Only Allow Selecting Single Dynamic Block


Recommended Posts

Posted

Hello All,

I have a lisp for making a series of modifications one dynamic block at time. I have the lisp working but it errors out when a non-dynamic block is selected.

 

My goal is to create a while loop that keeps looping until the user selects a dynamic block (or preferably matching a certain name.) I am not sure how to write the check... Here is an excerpt from the code.

 

(vl-load-com)
(setq acadDocument (vla-get-activedocument(vlax-get-acad-object)))
(setq RX (entsel))
(setq oBkRef (vlax-Ename->Vla-Object (car RX))) 

Posted

You should consider using SSGET in lieu of ENTSEL, as it will allow you to enter the appropriate selection set filter to catch both anonymous and actual named dynamic blocks.

 

Additionally, you'll need to iterate the Block Collection to compile a list of dynamic BlockDefinition Names based upon an IF statement filtering for vla-Get-IsDynamicBlock == :vlax-true.

 

That will allow you to check the EffectiveName of the BlockReference selected against the list of Dynamic BlockDefinition Names.

 

Cheers

Posted

To prove what BB 's just said with codes , here is my try . :D

 

To the OP , Replace the variable Blockname with your dynamic block name .

 

 (while (or  (not (setq s (ssget "_+.:S" '((0 . "INSERT")))))
             (not (eq (vla-get-effectivename
                        (vlax-ename->vla-object (ssname s 0))
                      )
                     [color=blue] Blockname[/color]
                  )
             )
        )
   (princ "Nil or Wrong Selection !!")
 )

Posted

... A lil'somethin for testing purposes:

(vl-load-com)

(defun c:BlockIs (/ ss oBlocks blockName)
 (while (setq ss (ssget ":S:E" '((0 . "INSERT"))))
   (prompt
     (if (= :vlax-true
            (vla-get-isdynamicblock
              (vla-item
                (cond (oBlocks)
                      ((setq oBlocks (vla-get-blocks
                                       (vla-get-activedocument
                                         (vlax-get-acad-object)
                                       )
                                     )
                       )
                      )
                )
                (setq blockName (vla-get-effectivename
                                  (vlax-ename->vla-object
                                    (ssname ss 0)
                                  )
                                )
                )
              )
            )
         )
       (strcat "\n\"" blockName "\" is dynamic block ")
       (strcat "\n\"" blockName "\" is not dynamic block ")
     )
   )
 )
 (princ)
)

Posted

Blackbox & Tharwat,

Thank you both for your help. I am pretty sure I can get this to work though I haven't been able to get it to work for checking against multiple names. For example if I have BLOCK1, BLOCK2, BLOCK3, BLOCK4, & BLOCK5, I only want it to work if BLOCK1 or BLOCK3 is selected.

 

I tried a few solutions but alas they did not work... :ouch:

 

 

 

(defun C:block_check ()
(while (or  (not (setq s (ssget "_+.:S" '((0 . "INSERT")))))
             (not (eq (vla-get-effectivename
                        (vlax-ename->vla-object (ssname s 0))
                      )
                      "BLOCK1"
                  )
             )
		                (not (eq (vla-get-effectivename
                        (vlax-ename->vla-object (ssname s 0))
                      )
                      "BLOCK3"
                  )
             )
        )
   (princ "Nil or Wrong Selection !!")
 )
 (princ "Good choice")
)

Posted

Try this instead . :)

 

(defun c:block_check (/ s vla)
 (while
   (or
     (not (setq s (ssget "_+.:S" '((0 . "INSERT")))))
     (not
       (or
         (eq (strcase (vla-get-effectivename
                        (setq vla (vlax-ename->vla-object (ssname s 0)))
                      )
             )
             "BLOCK1"
         )
         (eq (strcase (vla-get-effectivename
                        vla
                      )
             )
             "BLOCK3"
         )
       )
     )
   )
    (princ "Nil or Wrong Selection !!")
 )
 (princ "\nGood choice")
 (princ)
)

Posted
Blackbox & Tharwat,

Thank you both for your help. I am pretty sure I can get this to work though I haven't been able to get it to work for checking against multiple names. For example if I have BLOCK1, BLOCK2, BLOCK3, BLOCK4, & BLOCK5, I only want it to work if BLOCK1 or BLOCK3 is selected.

 

 

Something odd about your request. if you already know the name of the block I can assume you know its a Dynamic block. Then all you really need is

 

(ssget ":S:E" '((0 . "INSERT")(2 . Block1,Block2,`*U*"))) and a test for effectivename to check if its a match for the names you specify.

Posted (edited)

Tharwat, this didn't seem to work... I kept getting the error for for "Nil or Wrong Selection !!". :(

 

Try this instead . :)

 

(defun c:block_check (/ s vla)
 (while
   (or
     (not (setq s (ssget "_+.:S" '((0 . "INSERT")))))
     (not
       (or
         (eq (strcase (vla-get-effectivename
                        (setq vla (vlax-ename->vla-object (ssname s 0)))
                      )
             )
             "BLOCK1"
         )
         (eq (strcase (vla-get-effectivename
                        vla
                      )
             )
             "BLOCK3"
         )
       )
     )
   )
    (princ "Nil or Wrong Selection !!")
 )
 (princ "\nGood choice")
 (princ)
)

 

 

Pbe,

I ran this as a test:

(setq x (ssget ":S:E" '((0 . "INSERT")(2 . "BLOCK1","BLOCK3",`*U*"))))

 

I received this in response: ; "error: extra cdrs in dotted pair on input"

 

All,

Does anyone have any information about the filtering of ssget or a tutorial. I found these on CADPANACEA.com (Exploring the autolisp SSGET function - part 1 & part 2) but they didn't relate to dynamic blocks. The Autocad wasn't much help either. An Autolisp wiki would be nice...

Edited by TheyCallMeJohn
Misspelled name.
Posted
this didn't seem to work... I kept getting the error for for "Nil or Wrong Selection !!". :(

 

Firstly , you did write me name wrongly .

Secondly , are you selecting the right name block with Block1 or Block3 ?

 

Does anyone have any information about the filtering of ssget or a tutorial. I found these on CADPANACEA.com (Exploring the autolisp SSGET function - part 1 & part 2) but they didn't relate to dynamic blocks. The Autocad wasn't much help either. An Autolisp wiki would be nice...

 

Maybe the following filter to select Dynamic Block only .

 

(setq ss (ssget (list '(0 . "INSERT") (cons 2 (strcat "`*U*," "Block1,Block3")))))

Posted (edited)

(defun _selectOnlyListedBlocks (listOfBlockNames / lst ent block)
 (setq lst (mapcar 'strcase (setq listOfBlockNames (vl-sort listOfBlockNames '<))))
 (while
   (progn
     (setvar 'ERRNO 0)
     (setq ent
            (entsel (if (eq (length listOfBlockNames) 1)
                      (strcat "\nSelect " (car listOfBlockNames) " block: ")
                      (strcat "\nAcceptable blocks: "
                              (vl-prin1-to-string listOfBlockNames)
                              "\nSelect matching block: "
                      )
                    )
            )
     )
     (cond
       ((eq (getvar 'ERRNO) 7) (princ "\nMissed, try again."))
       ((eq (type (car ent)) 'ENAME)
        (if
          (and
            (eq (cdr (assoc 0 (entget (car ent)))) "INSERT")
            (member (strcase (vla-get-effectivename (setq ent (vlax-ename->vla-object (car ent)))))
                    lst
            )
          )
           (not (setq block ent))
           (princ "\nInvalid object!")
        )
       )
     )
   )
 )
 block
)

 

eg.

(_selectOnlyListedBlocks '("Block1" "Block 3"))

Edited by alanjt
Posted
FWIW - This post may be of use.

 

As I tried to suggest previously by sharing the link above, this sub-function requires two arguments, the first being the Document Object to search (which makes this available for use with ObjectDBX), and the second a WCMATCH string of block name(s) to match... A list of any matching dynamic BlockReference Object(s) is returned if found:

 

(vl-load-com)

(defun _GetDynamicBlocks (doc match / oBlocks blockName blocks)
 ;; Example:
 ;; (_GetDynamicBlocks acDoc "*MyBlockName*")
 (if (and (setq oBlocks (vla-get-blocks doc))
          (setq match (strcase match))
     )
   (foreach space
            (list (vla-get-modelspace doc) (vla-get-paperspace doc))
     (vlax-for x space
       (if
         (and
           (= "AcDbBlockReference" (vla-get-objectname x))
           (wcmatch
             (strcase (setq blockName (vla-get-effectivename x)))
             match
           )
           (= :vlax-true
              (vla-get-isdynamicblock
                (vla-item oBlocks blockName)
              )
           )
         )
          (setq blocks (cons x blocks))
       )
     )
   )
 )
 blocks
)

 

 

... And for those that would rather not be relegated to dynamic block returns (given the Block name argument(s)):

 

(vl-load-com)

(defun _GetBlocks (doc match / oBlocks blockName blocks)
 ;; Example:
 ;; (_GetBlocks acDoc "*MyBlockName*")
 (if (and (setq oBlocks (vla-get-blocks doc))
          (setq match (strcase match))
     )
   (foreach space
            (list (vla-get-modelspace doc) (vla-get-paperspace doc))
     (vlax-for x space
       (if
         (and
           (= "AcDbBlockReference" (vla-get-objectname x))
           (wcmatch
             (strcase (setq blockName (vla-get-effectivename x)))
             match
           )
         )
          (setq blocks (cons x blocks))
       )
     )
   )
 )
 blocks
)

Posted

Blackbox,

I apologize, I had not made time to fully review the post you suggested before my last post. Since then I reviewed the information you posted and that appears to be for selecting all the dynamic blocks in a given drawing. Much of the code was far above my current skill level. But if am correct, this is not exactly what I am looking for as I only want to select on of the blocks with that name.

 

As I tried to suggest previously by sharing the link above, this sub-function requires two arguments, the first being the Document Object to search (which makes this available for use with ObjectDBX), and the second a WCMATCH string of block name(s) to match... A list of any matching dynamic BlockReference Object(s) is returned if found:

 

---------------

 

Tharwat,

Sorry for the misspelling. I found the issue but am not sure how to modify it. Your programming works for the parameters I listed (i.e. dynamic blocks named BLOCK1, BLOCK2, BLOCK3, etc) however I was only using those names as examples. I does not work with my actual block names which are similar to "Brace-Rigid-Xdata-OLD". I didn't realize it would make a difference. Is there way to make it work with those type of names?

 

This works:

(setq ss (ssget (list '(0 . "INSERT") (cons 2 (strcat "`*U*," "Block1,Block3")))))

...But is there away to tweak it so you don't have to hit enter after selecting the objects?

 

-----------------

 

Alanjt,

I really like your sub-function but alas I am having the same problem as I did with Tharwat suggestion. It works great with simple names like "BLOCK1" but doesn't work with longer names like "Brace-Rigid-Xdata-OLD".

 

-----------------

 

All,

Thank you for you help. I am trying to learn as quickly as I am able. I appreciate your patience. :oops:

Posted

 

Alanjt,

I really like your sub-function but alas I am having the same problem as I did with Tharwat suggestion. It works great with simple names like "BLOCK1" but doesn't work with longer names like "Brace-Rigid-Xdata-OLD".

 

That's because I'm a moron who doesn't capitalize the effective name before comparing it to a list of names that I capitalized. I have revised the code. Try it now.

Posted
Blackbox,

I apologize, I had not made time to fully review the post you suggested before my last post. Since then I reviewed the information you posted and that appears to be for selecting all the dynamic blocks in a given drawing. Much of the code was far above my current skill level. But if am correct, this is not exactly what I am looking for as I only want to select on of the blocks with that name.

 

Ahhh... Now worries; I didn't think my post would have been necessarily perfect for your situation, just that you could cull from it what you like. We all start somewhere, and I see Alan's on the case, so I'll gladly go back to what I was doing... I'm sure I'll see you around. :beer:

Posted
That's because I'm a moron who doesn't capitalize the effective name before comparing it to a list of names that I capitalized. I have revised the code. Try it now.

 

Thanks Alanjt. That worked like a charm. :thumbsup:

Posted
Thanks Alanjt. That worked like a charm. :thumbsup:

 

:) You're welcome.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...