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
Solved! Go to Solution.
Solved by Hallex. Go to Solution.
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 ?
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")
Thank you for the fast response.
That works but only deletes the TB from the current layout tab not all of them.
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) )
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 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."
@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."
@_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."
@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
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."
@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."