Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Missing Something..

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
ThomasGlidewell
657 Views, 13 Replies

Missing Something..

I am using the attached LSP routine to delete a particular dynamic block from multiple layout tabs in a drawing. But I seem to be missing something. I keep getting this after the command finsihes:

; error: bad argument type: VLA-OBJECT nil

And can't seem to figure out why. I know it has something to do with the search during the lisp looking for dynamic blocks but don't know how to tell it to stop after it has found them all.

Any help would be great.

Thanks - 

Autocad 2012 all sp's

13 REPLIES 13
Message 2 of 14
_Tharwat
in reply to: ThomasGlidewell

Why don't you delete the Dynamic block from the first sub-function than making a new selection set and transfrom

it to another routine ?

Message 3 of 14
_Tharwat
in reply to: ThomasGlidewell

This what I mean ..

 

(defun ssdblk (effname / ssx n en)
  (if (setq ssx (ssget "_X" (list '(0 . "insert") (cons 2 (strcat effname ",`*U*")))))
    (repeat (setq n (sslength ssx))
      (setq en (ssname ssx (setq n (1- n))))
      (if (= (vla-get-effectivename (vlax-ename->vla-object en))
             effname
          )
        (vl-catch-all-apply 'entdel (list en))
      )
    )
  )
  (princ)
)

 example of usage .

 

(ssdblk "YourDynamicBlockName")

 

Message 4 of 14
ThomasGlidewell
in reply to: _Tharwat

Thank you for the fast response.
That works but only deletes the TB from the current layout tab not all of them.

Message 5 of 14
Hallex
in reply to: ThomasGlidewell

Try this Q&D code, chnage to suit

(defun C:demo(/ aclayots adoc coll)
  (vl-load-com)
(setq adoc (vla-get-activedocument (vlax-get-acad-object))
      aclayots (vla-get-Layouts adoc))
	(vlax-for olayout aclayots

	(vlax-for obj (vla-get-block olayout)
	  (if (eq (strcase (vla-get-objectname obj)) "ACDBBLOCKREFERENCE")
	    (if (eq (vla-get-effectivename obj) "LRA_TB")
	      (setq coll (cons obj coll))))))
            (mapcar '(lambda(x)(vl-catch-all-apply 'vla-delete (list x))) coll)
  (princ)
  )

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 6 of 14
ThomasGlidewell
in reply to: Hallex

That seems to do the trick and very cleanly.... THANKS so much... Smiley Happy

Message 7 of 14
_Tharwat
in reply to: ThomasGlidewell

Try this UNTESTED code .

 

(defun ssdblk (effname / ct ssx n en)
  (setq ct (getvar 'CTAB))
  (foreach l (layoutlist)
    (setvar 'CTAB l)
    (if (setq ssx (ssget "_X" (list '(0 . "insert") (cons 410 l) (cons 2 (strcat "`*U*," effname)))))
      (repeat (setq n (sslength ssx))
        (setq en (ssname ssx (setq n (1- n))))
        (if (= (vla-get-effectivename (vlax-ename->vla-object en))
               effname
            )
          (vl-catch-all-apply 'entdel (list en))
        )
      )
    )
  )
  (setvar 'CTAB ct)
  (princ)
)

 

Message 8 of 14
Hallex
in reply to: ThomasGlidewell

You're welcome
Cheers 🙂
_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 9 of 14
BlackBox_
in reply to: _Tharwat


@_Tharwat wrote:

This what I mean ..

 

(defun ssdblk (effname / ssx n en)
  (if (setq ssx (ssget "_X" (list '(0 . "insert") (cons 2 (strcat effname ",`*U*")))))
    (repeat (setq n (sslength ssx))
      (setq en (ssname ssx (setq n (1- n))))
      (if (= (vla-get-effectivename (vlax-ename->vla-object en))
             effname
          )
        (vl-catch-all-apply 'entdel (list en))
      )
    )
  )
  (princ)
)

 example of usage .

 

(ssdblk "YourDynamicBlockName")

 


Perhaps this is just my preference, but if I am going to be checking VLA Object Properties, and employing vl-Catch-All-Apply over a given selection set, then I prefer to simply iterate the ActiveSelectionSet Object instead of Repeat + VLA calls.

 

In any event, while the documentation does not clarify this, ENTDEL is in fact not deleting all instances of the applicable blocks from the selection set.

 

So as a quick adaptation that will handle dynamic, and non-dynamic blocks, consider this pseudo-code:

(vl-load-com)

(defun _DeleteBlocks (blockName /)
  (setq blockName (strcase blockName))
  (if
    (ssget "_x"
           (list '(0 . "INSERT") (cons 2 (strcat "'*U*," blockName)))
    )
     (progn
       (vlax-for x (vla-get-activeselectionset
                     (vla-get-activedocument (vlax-get-acad-object))
                   )
         (if (= blockName (strcase (vla-get-effectivename x)))

           ;; don't forget to account for locked layers

           (vla-delete x)
         )
       )
       T
     )
  )
)

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 10 of 14
BlackBox_
in reply to: Hallex


@Hallex wrote:

Try this Q&D code, chnage to suit

(defun C:demo(/ aclayots adoc coll)
  (vl-load-com)
(setq adoc (vla-get-activedocument (vlax-get-acad-object))
      aclayots (vla-get-Layouts adoc))
	(vlax-for olayout aclayots

	(vlax-for obj (vla-get-block olayout)
	  (if (eq (strcase (vla-get-objectname obj)) "ACDBBLOCKREFERENCE")
	    (if (eq (vla-get-effectivename obj) "LRA_TB")
	      (setq coll (cons obj coll))))))
            (mapcar '(lambda(x)(vl-catch-all-apply 'vla-delete (list x))) coll)
  (princ)
  )

 


Hallex, there's no need to build a list of valid Objects to feed Mapcar + Lambda here, when the Delete() Method can be called directly on the qualified Object within the IF statement.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 11 of 14
BlackBox_
in reply to: _Tharwat


@_Tharwat wrote:

Try this UNTESTED code .

 

(defun ssdblk (effname / ct ssx n en)
  (setq ct (getvar 'CTAB))
  (foreach l (layoutlist)
    (setvar 'CTAB l)
    (if (setq ssx (ssget "_X" (list '(0 . "insert") (cons 410 l) (cons 2 (strcat "`*U*," effname)))))
      (repeat (setq n (sslength ssx))
        (setq en (ssname ssx (setq n (1- n))))
        (if (= (vla-get-effectivename (vlax-ename->vla-object en))
               effname
            )
          (vl-catch-all-apply 'entdel (list en))
        )
      )
    )
  )
  (setvar 'CTAB ct)
  (princ)
)

 


Tharwat, there's no need to modify the Ctab system variable at all, and then perform multiple selection set calls, when simply changing the EntDel call to vla-Delete is sufficient for the single valid selection set.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 12 of 14
_Tharwat
in reply to: BlackBox_


@BlackBox_ wrote:

 

 

Tharwat, there's no need to modify the Ctab system variable at all, and then perform multiple selection set calls, when simply changing the EntDel call to vla-Delete is sufficient for the single valid selection set.

Cheers


I am surprized that the ENTDEL function is not working with sorts of entities , and that's why I moved to the function FOREACH with separate selection set for every tab / layout for that reason .

 

Cheers

Message 13 of 14
BlackBox_
in reply to: Hallex

As a quick speed test:

(vl-load-com)

;; tharwat
(defun ssdblk (effname / ct ssx n en)
  (setq ct (getvar 'CTAB))
  (foreach l (layoutlist)
    (setvar 'CTAB l)
    (if (setq ssx (ssget "_X"
                         (list '(0 . "insert")
                               (cons 410 l)
                               (cons 2 (strcat "`*U*," effname))
                         )
                  )
        )
      (repeat (setq n (sslength ssx))
        (setq en (ssname ssx (setq n (1- n))))
        (if (= (vla-get-effectivename (vlax-ename->vla-object en))
               effname
            )
          (vl-catch-all-apply 'entdel (list en))
        )
      )
    )
  )
  (setvar 'CTAB ct)
  (princ)
)

;; hallex
(defun C:demo (/ aclayots adoc coll)
;;;  (vl-load-com)
  (setq adoc     (vla-get-activedocument (vlax-get-acad-object))
        aclayots (vla-get-Layouts adoc)
  )
  (vlax-for olayout aclayots

    (vlax-for obj (vla-get-block olayout)
      (if (eq (strcase (vla-get-objectname obj)) "ACDBBLOCKREFERENCE")
        (if (eq (vla-get-effectivename obj) "FOO")
          (setq coll (cons obj coll))
        )
      )
    )
  )
  (mapcar '(lambda (x) (vl-catch-all-apply 'vla-delete (list x))) coll)
  (princ)
)

;; blackbox
(defun _DeleteBlocks (blockName /)
  (setq blockName (strcase blockName))
  (if
    (ssget "_x"
           (list '(0 . "INSERT") (cons 2 (strcat "'*U*," blockName)))
    )
     (progn
       (vlax-for x (vla-get-activeselectionset
                     (vla-get-activedocument (vlax-get-acad-object))
                   )
         (if (= blockName (strcase (vla-get-effectivename x)))

           ;; account for locked layers

           (vla-delete x)
         )
       )
       T
     )
  )
)

 

... Results from console:

_$ (bench '(ssdblk) '("FOO") 1)

SSDBLK
Elapsed: 86534
Average: 86534.0000

 
_$ (bench '(C:demo) '() 1)

C:DEMO
Elapsed: 62
Average: 62.0000

 
_$ (bench '(_DeleteBlocks) '("FOO") 1)

_DELETEBLOCKS
Elapsed: 31
Average: 31.0000

 
_$ 

 



"How we think determines what we do, and what we do determines what we get."

Message 14 of 14
BlackBox_
in reply to: BlackBox_


@BlackBox_ wrote:

As a quick speed test:


Forgot to mention that the test being performed, was on a single drawing with a dynamic titleblock inserted in each of 98 Layouts... Just for some context on the time noted to run a single iteration of each routine (in milliseconds).

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost