Jump to content
DesmetMartin

Un-dynamic a block - LISP

Recommended Posts

DesmetMartin

Hello all,

 

I should get the following code changed so that you can select the blocks you want to 'undynamic" first.

 

Can somebody help me?

 

(defun c:UnDynamic

   (   /
       _get_item
       _right
       _make_key
       _dynamic->static_block
       _get_locked
       _get_dynamic_inserts
       _main
   )

   (defun _get_item ( collection key / item )
       (vl-catch-all-apply
          '(lambda ( ) (setq item (vla-item collection key)))
       )
       item
   )

   (defun _right ( str n / len )
       (if (< n (setq len (strlen str)))
           (substr str (1+ (- len n)))
           str
       )
   )

   (defun _make_key ( collection prefix len / key )
       (   (lambda ( i pad )
               (while
                   (_get_item collection
                       (setq key
                           (strcat prefix
                               (_right
                                   (strcat pad (itoa (setq i (1+ i))))
                                   len
                               )
                           )
                       )
                   )
               )
               key
           )
           0
           (   (lambda ( pad )
                   (while (< (strlen pad) len)
                       (setq pad (strcat "0" pad))
                   )
                   pad
               )
               ""
           )
       )
   )

   (defun _dynamic->static_block ( blocks insert len )
       (vla-ConvertToStaticBlock
           insert
           (_make_key blocks (strcat (vla-get-EffectiveName insert) "_00") len)
       )
   )

   (defun _get_locked ( layers / locked )
       (vlax-for layer layers
           (if (eq :vlax-true (vla-get-lock layer))
               (setq locked (cons layer locked))
           )
       )
       locked
   )

   (defun _get_dynamic_inserts ( blocks / inserts )
       (vlax-for block blocks
           (vlax-for object block
               (if (eq "AcDbBlockReference" (vla-get-objectname object))
                   (if (eq :vlax-true (vla-get-isdynamicblock object))
                       (setq inserts (cons object inserts))
                   )
               )
           )
       )
       inserts
   )

   (defun _main ( document / blocks inserts locked len )
       (if
           (setq inserts
               (_get_dynamic_inserts
                   (setq blocks (vla-get-blocks document))
               )
           )
           (progn
               (foreach layer (setq locked (_get_locked (vla-get-layers document)))
                   (vla-put-lock layer :vlax-false)
               )
               (setq len (strlen (itoa (length inserts))))
               (foreach insert inserts
                   (_dynamic->static_block blocks insert len)
               )
               (foreach layer locked
                   (vla-put-lock layer :vlax-true)
               )
           )
       )
       (princ)
   )

   (_main (vla-get-activedocument (vlax-get-acad-object)))

)

 

Credits to TP from theswamp.org.

 

Thanks,

Martin.

Share this post


Link to post
Share on other sites
Grrr

Not so pretty as his, but gets the job done:

(defun C:test ( / ErrCatcher SS i o )

(defun ErrCatcher ( func varLst / rtn ) (if (not (vl-catch-all-error-p (setq rtn (vl-catch-all-apply func varLst)))) rtn))
(prompt "\nSelect blocks to convert them into static ones:" )
(if (setq SS (ssget "_:L" (list (cons 0 "INSERT"))))
	(repeat (setq i (sslength SS))
		(if (eq :vlax-true (vla-get-IsDynamicBlock (setq o (vlax-ename->vla-object (ssname SS (setq i (1- i)))))))
			(ErrCatcher 'vla-ConvertToStaticBlock (list o (vla-get-EffectiveName o)))
		)
	)
)
(princ)
);| defun |; (or (vlax-get-acad-object) (vl-load-com)) (princ)

Share this post


Link to post
Share on other sites
DesmetMartin

Thanks, it's this kind of thing I want to do.

The only problem is that the name get's changed and you can't edit you static block anymore.

Share this post


Link to post
Share on other sites
DesmetMartin

So what I'm trying to say is that the code in the 1st post should be used.

Only thing that should be added in the code is that you select the items you want to undynamic instead of all the blocks.

 

Thanks,

Martin

Share this post


Link to post
Share on other sites
Roy_043

@Grrr:

IMO this:

(or (vlax-get-acad-object) (vl-load-com))

Should be:

(or vlax-get-acad-object (vl-load-com))

Share this post


Link to post
Share on other sites
Grrr
@Grrr:

IMO this:

(or (vlax-get-acad-object) (vl-load-com))

Should be:

(or vlax-get-acad-object (vl-load-com))

 

Hi Roy,

Yes it seems that it makes more sence:

_$ vlax-get-acad-object
#<SUBR @000000a99c5a6d68 vlax-get-acad-object>
_$ (vlax-get-acad-object)
#<VLA-OBJECT IAcadApplication 00007ff604c59110>
_$ 

Thanks!

Share this post


Link to post
Share on other sites
Roy_043

It is not about 'more sense'. I expect that (vlax-get-acad-object) will fail if the VL extensions have not been loaded. I am using the word 'expect' because I am using BricsCAD where (vl-load-com) is a dummy function and VL functions are available by default.

Share this post


Link to post
Share on other sites
Grrr

Yes, I mean that I haven't noticed that instead of checking for such function, I'm instead running it with the possibility of triggering an error, such as:

_$ (defun C:test () (strcat 1))
C:TEST
_$ C:test
#<USUBR @000000a99c508570 C:TEST>
_$ (C:test)
_$ (C:test)

Error: bad argument type: stringp 1
_1$ 

You have sharp eye.

Share this post


Link to post
Share on other sites
Roy_043

Testing the (vla-ConvertToStaticBlock) function I have noticed something strange (note: as previously mentioned I use BricsCAD).

My test:

1. Insert the same dynamic block twice.

2. Make identical changes to one or more dynamic properties for each insert.

3. The inserts now look the same but reference different anonymous definitions.

4. Copy one of the inserts.

5. The copy references the same anonymous definition as its original.

6. Only convert the copy to a static block.

7. Result: The original of the copy has also become a static block (probably due to what was mentioned under #5).

 

If AutoCAD has the same behavior, converting only selected inserts to static blocks would require a more complex solution than the code posted in this thread.

Share this post


Link to post
Share on other sites
Lee Mac

1. Insert the same dynamic block twice.

2. Make identical changes to one or more dynamic properties for each insert.

3. The inserts now look the same but reference different anonymous definitions.

 

This differs in AutoCAD: inserting two references of the same dynamic block and modifying their dynamic parameters to use the same values results in the two blocks referencing the same anonymous definition.

 

4. Copy one of the inserts.

5. The copy references the same anonymous definition as its original.

 

AutoCAD has the same behaviour (as to be expected, based on the above observation).

 

6. Only convert the copy to a static block.

7. Result: The original of the copy has also become a static block (probably due to what was mentioned under #5).

 

This is not the case in AutoCAD: converting one of the dynamic block references has no effect on the others.

Share this post


Link to post
Share on other sites
Roy_043

@Lee: Thanks for your comments. I'll send a Support Request to the Bricsys team.

Share this post


Link to post
Share on other sites
Lee Mac

You're welcome Roy.

Share this post


Link to post
Share on other sites
Grrr

I've followed the steps Roy mentioned on my Acad 2015, and can comfirm this:

This is not the case in AutoCAD: converting one of the dynamic block references has no effect on the others.

Seems that it adds new block definition, under the provided name:

(vla-ConvertToStaticBlock o "ABC")

But, when I try to convert other block reference under the same / existing block definition name, I get:

_$ (vla-ConvertToStaticBlock o "ABC")

Error: Automation Error. Duplicate key
_1$ 

But/And It creates an annonymous block definition anyway:

_$ (vla-get-EffectiveName (vlax-ename->vla-object (car (entsel))))
"*U117"
_$ 

ScreenShot013.jpg

Note that the "Name" property row in the quick properties dialog, always references to the block's "effective name / definition name".

 

So thats why my previously posted code forces the creation of N annonymous block definitions:

(ErrCatcher 'vla-ConvertToStaticBlock (list o (vla-get-EffectiveName o)))

Since this always triggers an error :roll:

Share this post


Link to post
Share on other sites
Lee Mac
But, when I try to convert other block reference under the same / existing block definition name, I get:

_$ (vla-ConvertToStaticBlock o "ABC")

Error: Automation Error. Duplicate key
_1$ 

 

Of course: the block name argument for the ActiveX converttostaticblock method cannot correspond to an existing block, otherwise you will receive a duplicate key error - this is why the original code included the '_make_key' function.

Share this post


Link to post
Share on other sites
DesmetMartin

First of all, thanks for all the help so far!

I would like to think together with you guys, but since I can't program, it's though :P

 

Let me know if you find a solution please!

Thanks!

- Martin

Share this post


Link to post
Share on other sites
Grrr
First of all, thanks for all the help so far!

I would like to think together with you guys, but since I can't program, it's though :P

 

Let me know if you find a solution please!

Thanks!

- Martin

 

Try this:

(defun C:test ( / ErrCatcher BlksColl SS i o cnt flg nm )

; (ErrCatcher 'vla-item (list (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) "BlockThatDoesNotExist")) -> nil
(defun ErrCatcher ( func varLst / rtn ) (if (not (vl-catch-all-error-p (setq rtn (vl-catch-all-apply func varLst)))) rtn))

(setq BlksColl (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
(prompt "\nSelect blocks to convert them into static ones:" )
(if (setq SS (ssget "_:L" (list (cons 0 "INSERT"))))
	(repeat (setq i (sslength SS))
		(if (eq :vlax-true (vla-get-IsDynamicBlock (setq o (vlax-ename->vla-object (ssname SS (setq i (1- i)))))))
			(progn
				(setq cnt 0) (setq flg 'T)
				(while flg
					(if (not (ErrCatcher 'vla-item (list BlksColl (setq nm (strcat (vla-get-EffectiveName o) "_" (itoa (setq cnt (1+ cnt))))))))
						(progn (vla-ConvertToStaticBlock o nm) (setq flg nil))
					); if
				); while
			); progn
		); if
	); repeat
); if
(princ)
);| defun |; (or vlax-get-acad-object (vl-load-com)) (princ)

Note that the original dynamic blocks are not purged.

Share this post


Link to post
Share on other sites
DesmetMartin
Try this:

(defun C:test ( / ErrCatcher BlksColl SS i o cnt flg nm )

; (ErrCatcher 'vla-item (list (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) "BlockThatDoesNotExist")) -> nil
(defun ErrCatcher ( func varLst / rtn ) (if (not (vl-catch-all-error-p (setq rtn (vl-catch-all-apply func varLst)))) rtn))

(setq BlksColl (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
(prompt "\nSelect blocks to convert them into static ones:" )
(if (setq SS (ssget "_:L" (list (cons 0 "INSERT"))))
	(repeat (setq i (sslength SS))
		(if (eq :vlax-true (vla-get-IsDynamicBlock (setq o (vlax-ename->vla-object (ssname SS (setq i (1- i)))))))
			(progn
				(setq cnt 0) (setq flg 'T)
				(while flg
					(if (not (ErrCatcher 'vla-item (list BlksColl (setq nm (strcat (vla-get-EffectiveName o) "_" (itoa (setq cnt (1+ cnt))))))))
						(progn (vla-ConvertToStaticBlock o nm) (setq flg nil))
					); if
				); while
			); progn
		); if
	); repeat
); if
(princ)
);| defun |; (or vlax-get-acad-object (vl-load-com)) (princ)

Note that the original dynamic blocks are not purged.

 

Super! This is what I was looking for!

Thank you so much!

-Martin

Share this post


Link to post
Share on other sites

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
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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...