TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Thomas 3D on December 27, 2010, 03:06:15 AM

Title: dynamic blocks
Post by: Thomas 3D on December 27, 2010, 03:06:15 AM
Hello Forum,

I have the problem, that I can't distinguish the dynamic blocks in my drawing, because all blocks have the same blockname.

I have create a dyn. block with a length1. This block I have copied several times in one drawing. I have stretched or trimed the blocks. That means I have different blocks with different lengths.

I look for a tool, which create a automatically ID number as a attribut in the dyn. block. I don't know if that is possible, when I start the copy command, that each new dyn. block gets a new attribute (ID Number).
Because I want to read the blocks in a table.

I would like to know, if anybody ever written such a tool?

I would appreciate about short message.

Best regards
Thomas
Title: Re: dynamic blocks
Post by: pBe on December 27, 2010, 07:13:47 AM
use this as reference:

Code: [Select]
(defun c:test (/ object)
   (vl-load-com)
(setq object (car (entsel "\nSelect Block:")))

(if (equal
   (vla-get-IsDynamicBlock (vlax-ename->vla-object object)) :vlax-true)
        (princ (strcat "\n<< Block " (vla-get-effectivename  (vlax-ename->vla-object object)) " is a Dynamic block >>"))
        (princ "\nNot a Dynamic block")  
          )(princ)
  )

what you can do is when you loop through the entries of the selection set (ssget ...) create a test to check for effective name/or not (that is if your block names are *U71*) and if its a dynamic
block. check for dynamic property (the length).....

hope this helps.
BTW, i cant open your file.. i'm using 2009  :-)

EDIT: I think i misunderstood the question... oh well  :-)  
Title: Re: dynamic blocks
Post by: kruuger on December 27, 2010, 08:07:10 AM
this is not reactor but... :-)
when you put all MULLION in dwg type ID (load lisp first).
you need to use my block (with new attribute ID)
kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on December 27, 2010, 02:40:25 PM
Hi pBe,

thanks for your help. I'm not sure if you have understand me. I have saved the DWG-file for you in the AutoCad 2007 format.
Sorry, but I understand nothing about programming. I have copied your code in a txt-file and then I have rename the Suffix to lsp. I hope that was right.
I don't know what it is "ssget". Would it be possible for you to give me a more detailed description?
Thanks!!!


Thomas
Title: Re: dynamic blocks
Post by: Thomas 3D on December 27, 2010, 03:05:18 PM
Hi Kruuger,

this is not reactor but... :-)
when you put all MULLION in dwg type ID (load lisp first).
you need to use my block (with new attribute ID)
kruuger

I have tried to use your 2 files, but if I type "ID"  then Autocad start the AutoCad command ID-Point. Is that right? :|

Thomas
Title: Re: dynamic blocks
Post by: kruuger on December 27, 2010, 03:34:51 PM
Hi Kruuger,

this is not reactor but... :-)
when you put all MULLION in dwg type ID (load lisp first).
you need to use my block (with new attribute ID)
kruuger

I have tried to use your 2 files, but if I type "ID"  then Autocad start the AutoCad command ID-Point. Is that right? :|

Thomas

just drag my AutoID.lsp into dwg (you need to load program before use).
then type ID again.
if you find it usefull add it to suitcase:
http://lee-mac.com/autoloading.html

kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on December 28, 2010, 09:28:25 AM
Hi Kruuger,

It does not work for me. I thing the problem is, that I work with a German AutoCad Version. The German version has a mix of German and English commands. If I type ID, then AutoCad starts the command ID-Point (x;y;z). Would it be possible for you to use another command name for your lisp command?

Thomas
Title: Re: dynamic blocks
Post by: kruuger on December 28, 2010, 09:49:14 AM
Hi Kruuger,

It does not work for me. I thing the problem is, that I work with a German AutoCad Version. The German version has a mix of German and English commands. If I type ID, then AutoCad starts the command ID-Point (x;y;z). Would it be possible for you to use another command name for your lisp command?

Thomas

Thomas
I change shortcut to AUTOID.
Please download lsp file again. When you drag file to autocad you should see this at command line: ** Loaded AUTOID.LSP. Type AUTOID to invoke. **
You need to load lisp EVERYTIME you start new dwg.
kruuger

Title: Re: dynamic blocks
Post by: Thomas 3D on December 28, 2010, 12:47:28 PM
Hi Kruuger,

I have done everything like you said it. I get the following error message:

Befehl:
** Loaded AUTOID.LSP. Type AUTOID to invoke. **
Befehl:
Befehl: AUTOID
; Fehler: no function definition: JK:ACX_ACTDOC

I have no idea what Autocad wants from me. :|

Thomas
Title: Re: dynamic blocks
Post by: kruuger on December 28, 2010, 01:48:22 PM
Hi Kruuger,

I have done everything like you said it. I get the following error message:

Befehl:
** Loaded AUTOID.LSP. Type AUTOID to invoke. **
Befehl:
Befehl: AUTOID
; Fehler: no function definition: JK:ACX_ACTDOC

I have no idea what Autocad wants from me. :|

Thomas
aaa, now everything is clear. missing sub-function.
try this attachment. now should work for 100%
kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on December 28, 2010, 03:06:48 PM
Sorry,

but now I get the following message


Befehl:
Befehl: (LOAD "E:/Neuer Ordner/AutoID.lsp")
** Loaded AUTOID.LSP. Type AUTOID to invoke. **

Befehl: AUTOID
; Fehler: no function definition: VLAX-GET-ACAD-OBJECT   :?

Title: Re: dynamic blocks
Post by: kruuger on December 28, 2010, 03:38:21 PM
Sorry,

but now I get the following message


Befehl:
Befehl: (LOAD "E:/Neuer Ordner/AutoID.lsp")
** Loaded AUTOID.LSP. Type AUTOID to invoke. **

Befehl: AUTOID
; Fehler: no function definition: VLAX-GET-ACAD-OBJECT   :?


add this (vl-load-com) at the top of AutoID.lsp
Code: [Select]
(vl-load-com)
(defun C:AUTOID (/ LS SS SS_MUL ID)
  (setq LS
....
kruuger
Title: Re: dynamic blocks
Post by: MP on December 28, 2010, 03:38:55 PM
Enter this at the command line:

(vl-load-com)

Then try your proggy again.
Title: Re: dynamic blocks
Post by: Thomas 3D on December 28, 2010, 04:34:59 PM
 :-)
It works. THANKS!!!!

What do you think? When I should start the routine? When I have finished the drawing?
When I use the routine in between,then the ID numbers have been assigned twice. Is it possible to change the routine so that the repeated use of the routine, the ID numbers will be deleted and re-assigned?
Title: Re: dynamic blocks
Post by: kruuger on December 28, 2010, 05:10:38 PM
:-)
It works. THANKS!!!!
uff  :wink:

When I use the routine in between,then the ID numbers have been assigned twice. Is it possible to change the routine so that the repeated use of the routine, the ID numbers will be deleted and re-assigned?
i'm not sure i understood you but try this one.
first block should be 1. when you add more they should be 2, 3, 4...but i'm not sure if ssget always return list object from last to first in drawing base. can someone confirm that?

thanks
kruuger

Title: Re: dynamic blocks
Post by: MP on December 28, 2010, 05:22:04 PM
i'm not sure if ssget always return list object from last to first in drawing base. can someone confirm that?

Not reliable. Sort the entities by their handle (converted to an integer) or ObjectID prior to indexing.
Title: Re: dynamic blocks
Post by: kruuger on December 28, 2010, 05:43:24 PM
i'm not sure if ssget always return list object from last to first in drawing base. can someone confirm that?

Not reliable. Sort the entities by their handle (converted to an integer) or ObjectID prior to indexing.
Thanks MP. I will keep in mind this.

kruuger
Title: Re: dynamic blocks
Post by: MP on December 28, 2010, 06:37:07 PM
Some quick code / food for thought:

PicksetToObjects:
Code: [Select]
(defun _PicksetToObjects ( ss )

    [color=green];;  Convert a pickset (selection set) to a list of objects.[/color]

    (if (eq 'pickset (type ss))
        (mapcar
            (function (lambda (x) (vlax-ename->vla-object (cadr x))))
            (vl-remove-if (function (lambda (x) (minusp (car x)))) (ssnamex ss))
        )
    )
)

SortObjects:
Code: [Select]
(defun _SortObjects ( objects foo )

    [color=green];;  Sort the objects using function foo, which takes two
    ;;  arguments, both objects. What foo does we don't care,
    ;;  our job is to invoke it if it's defined. Note: define
    ;;  foo using the (function (lambda (a b) ...)) form. If
    ;;  foo is not defined sort the objects by the ObjectIDs.[/color]
    
    (vl-sort objects
        (if [color=red]foo foo[/color]
            (function
                (lambda (a b)
                    (<
                        (vla-get-objectid a)
                        (vla-get-objectid b)
                    )
                )
            )
        )      
    )
)

Demo:
Code: [Select]
(if (setq objects ([color=red]_PicksetToObjects[/color] (ssget)))
    (progn
        (princ "\n\nObjectIDs for the unsorted list:")
        (print (mapcar 'vla-get-objectid objects))
        (princ "\n\nObjectIDs for the sorted list, default algorythm:")
        (print (mapcar 'vla-get-objectid ([color=red]_SortObjects[/color] objects nil)))
        (princ "\n\nObjectIDs for the sorted list, custom algorythm:")
        (print
            (mapcar 'vla-get-objectid
                ([color=red]_SortObjects[/color] objects
                    (function
                        (lambda (a b)
                            (<
                                (vla-get-objectname a)
                                (vla-get-objectname b)
                            )
                        )
                    )      
                )
            )
        )
        (princ)
    )
)

Output:
Code: [Select]
ObjectIDs for the unsorted list:
(51 50 49 48 46 43 52 53 54 55 56 57 58 59 60)

ObjectIDs for the sorted list, default algorithm:
(43 46 48 49 50 51 52 53 54 55 56 57 58 59 60)

ObjectIDs for the sorted list, custom algorithm:
(54 55 59 56 43 51 50 49 48 46 57 52 53 60 58)
Title: Re: dynamic blocks
Post by: pBe on December 29, 2010, 03:02:37 AM
Looks like you guys got it all covered

I would have done it the same way as kruuger's but slightly different


Code: [Select]
(defun c:test ()
  (vl-load-com)
  (setq this-dwg (vla-get-activedocument (vlax-get-acad-object)))
(while (not (setq Mullion_block (ssget '((0 . "INSERT"))))))
  (cond (
(mapcar
          '(lambda (bl_sl)
(if
(/= (vla-get-EffectiveName
                      (vlax-ename->vla-object bl_sl)) "Mullion")
  (ssdel bl_sl Mullion_block)))
         (vl-remove-if 'listp
                (mapcar 'cadr(ssnamex Mullion_block))))
         
        (setq cnt -1 row_nm (sslength mullion_block) pro_sel (ssadd))
        (while (setq mb_brp
                   (ssname  Mullion_block (setq cnt (1+ cnt))))
(setq mb_prop
          (vlax-invoke (setq mb_ss (vlax-ename->vla-object mb_brp)) 'GetDynamicBlockProperties))
                 
          (setq width_v (vlax-variant-value
                                (vla-get-value (nth 0 mb_prop)))
                     height_v (vlax-variant-value
                                (vla-get-value (nth 2 mb_prop)))
                )
          (vla-put-textstring
                  (car (vlax-invoke mb_ss 'Getattributes))
                  (strcat (rtos width_v 2 0) "x" (rtos height_v 2 0))
                )
          (setq pro_sel (ssadd mb_brp pro_sel))
          );while
          ;(pro pro_sel)<-- routine for sorting and counting the dyn blocks  would go here
          );
         )
    )

then after gathering data, create a table

Code: [Select]
(defun db_atv ()
(setq Mullion_table
  (vla-addtable  (vla-get-modelspace this-dwg) (vla-getpoint (vla-get-utility this-dwg) nil "\nPick point for Table:")
  (+ row_nm 2) 4 30 110))

  (vla-settext Mullion_table 0 0 "Mullion")
  (vla-settext Mullion_table 1 0 "Count")
  (vla-settext Mullion_table 1 1 "Block ID")
  (vla-settext Mullion_table 1 2 "Width")
  (vla-settext Mullion_table 1 3 "Height")
;;<--- code for assigning values (data  from the previous) sub would go here
  )


anyhoo.. the plan was sort and assign lowest number to the smallest duct and so on.....
i also thought of converting it to a Staticblock and assing a unique name for every block (Mullion_A, Mullion_B....)

oh well....
Title: Re: dynamic blocks
Post by: HasanCAD on December 29, 2010, 10:28:29 AM
:-)
It works. THANKS!!!!
uff  :wink:

thanks
kruuger




Error in CAD2010

Code: [Select]
Command: AUTOID
; error: no function definition: VLAX-GET-ACAD-OBJECT
Title: Re: dynamic blocks
Post by: kruuger on December 29, 2010, 10:34:51 AM
:-)
It works. THANKS!!!!
uff  :wink:

thanks
kruuger




Error in CAD2010

Code: [Select]
Command: AUTOID
; error: no function definition: VLAX-GET-ACAD-OBJECT
here was solution:
http://www.theswamp.org/index.php?topic=36412.msg414377#msg414377
kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on January 06, 2011, 02:05:25 AM
Good morning Kruuger,

I still have a question for you. I wanted to use your program for another drawing. I have implemented the ID attribut in a  new block. Then I have started your lisp routine.
Autocad said:

Befehl: autoid
; Fehler: Fehlerhafter Argumenttyp: lselsetp nil

What does that mean? Can I not use your lisp routine for other blocks?

Thomas
Title: Re: dynamic blocks
Post by: Kerry on January 06, 2011, 05:48:33 AM
That message  indicates that a symbol has nil value where a value is expected.

If you load the code into the VLIDE, set menu dropdown Debug->BreakOnError to ON (ticked) then load the code from the VLIDE into Autocad.

When the code stops with an error select Debug->LastBreakSource or Ctrl-F9 to display the line the error is on.

Adding (vl-bt) to your error trap routine may also help locating the cause of an error.
something like this
Code: [Select]
[color=green];; errortrap.lsp[/color]
  [color=green];;-------------------------------------[/color]
  (defun [color=blue]*error*[/color] (msg)
    [color=green];;----- Cancel any Active Commands[/color]
    (while (< 0 (getvar [color=Maroon]"cmdactive"[/color])) (command))
    [color=green];;----- Display error message if applicable[/color]
    (cond ((not msg))
          ((member (strcase msg t) '([color=Maroon]"console break"[/color] [color=Maroon]"function cancelled"[/color] [color=Maroon]"quit / exit abort"[/color])))
          ((princ (strcat [color=Maroon]"\nApplication Error: "[/color] (itoa (getvar [color=Maroon]"errno"[/color])) [color=Maroon]" :- "[/color] msg))
           [color=green];;----- Display backtrace[/color]
           (vl-bt)
          )
    )
    (setvar [color=Maroon]"errno"[/color] 0)
    (princ)
  )
Title: Re: dynamic blocks
Post by: kruuger on January 06, 2011, 06:33:09 PM
Hi Thomas
Do you want to use routine with new block name?
Did you change Mullion name in lisp to new name?
 Maybe you want select block first and then continue?
kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on January 07, 2011, 01:40:05 AM
Hi Kruuger,

I want to use your lisp routine for a new drawing with new different block names.

I haven't changed the Mullion name in the lisp routine. Sorry, but I do not understand Lisp programming.

Certainly it would be nice if you could first select the blocks and then I start your routine. This would not be so important, because if I create a new block, than I can say that block gets the ID-Attribute or not. Is it a big hassle for you to change your routine to the effect?

Thomas
Title: Re: dynamic blocks
Post by: kruuger on January 07, 2011, 02:51:42 AM
ok, no problem. i try to incorporate this change to lisp + MP_ SortObject function
kruuger
Title: Re: dynamic blocks
Post by: kruuger on January 07, 2011, 09:42:34 AM
try this code. let me know if it works for you.
thanks MP. Sort function works perfect :)
kruuger
Title: Re: dynamic blocks
Post by: MP on January 07, 2011, 10:48:28 AM
great to hear kruuger --- thanks for letting me know --- thanks for helping T3D
Title: Re: dynamic blocks
Post by: Thomas 3D on January 07, 2011, 04:05:04 PM
Hi Kruuger,

Thank you for your quick help. I have tested your new lisp routine. Please look at my file. When I start the routine, then the first 2 blocks are not taken into account. Have you any idea why the program such react?

Thomas
Title: Re: dynamic blocks
Post by: kruuger on January 07, 2011, 05:13:18 PM
i found a small mistake. try now
kruuger
Title: Re: dynamic blocks
Post by: Thomas 3D on January 08, 2011, 02:15:39 AM
Hi Kruuger,

It works great. Thanks!!!
I have another question for you. How you would delete the ID values, for example in all block01?

I have tried the autocad command "_-attedit". There you can select which block and which attribute you want edit.
- Attributes edit individually (Y/N)                          -> N
- Only visible on the screen to edit attributes? (Y/N) -> Y
- Enter block name specification <*>                      -> block01
- Specification for type attribute name <*>             -> ID
- Specification for type attribute value <*>             -> *
- Select attributes                                              -> I have select all blocks 01
- Enter string to be amended                                -> *
- Enter the new string                                         -> I have pressed the spacebar or Delete key

Autocad abort the function

Do you have an idea?

Thomas
Title: Re: dynamic blocks
Post by: kruuger on January 08, 2011, 12:27:39 PM
Hi Kruuger,

It works great. Thanks!!!
I have another question for you. How you would delete the ID values, for example in all block01?

I have tried the autocad command "_-attedit". There you can select which block and which attribute you want edit.
- Attributes edit individually (Y/N)                          -> N
- Only visible on the screen to edit attributes? (Y/N) -> Y
- Enter block name specification <*>                      -> block01
- Specification for type attribute name <*>             -> ID
- Specification for type attribute value <*>             -> *
- Select attributes                                              -> I have select all blocks 01
- Enter string to be amended                                -> *
- Enter the new string                                         -> I have pressed the spacebar or Delete key

Autocad abort the function

Do you have an idea?

Thomas
i'm glad it works.
Back to your question. There is a many ways to do this:
1. GATTE command from Express Menu. I'm not sure if autodesk updated the code but old one not works with dynamic blocks.
2. _QSELECT -> Block Reference -> Name -> Block01 which make selection set and then change ID value in properties pallete.
3. _FILTER -> Block name -> Add -> Apply - i think it not works with dynamic also.
4. Dynamic filter lisp which make selection set of blokcs and then change via properties pallete
Code: [Select]
(defun c:FID (/ Realss Sel Obj ss BlkName tempEnt)
  (setq Realss (ssadd))
    (if
      (and
        (setq Sel (entsel "\nSelect block to select likewise: "))
        (setq Obj (vlax-ename->vla-object (car Sel)))
        (= (vla-get-ObjectName Obj) "AcDbBlockReference")
        (setq ss (ssget "X" '((0 . "INSERT"))))
        (setq BlkName (vla-get-EffectiveName Obj))
        (progn
          (while (setq tempEnt (ssname ss 0))
            (if (= BlkName (vla-get-EffectiveName (vlax-ename->vla-object tempEnt)))
              (ssadd tempEnt Realss)
            )
            (ssdel tempEnt ss)
          )
          (> (sslength Realss) 0)
        )
      )
      (progn
        (sssetfirst nil Realss)
        (prompt (strcat "\n Block selected: " (itoa (sslength Realss))))
      )
      (prompt "\n No likeness block selected.")
    )
  (princ)
)
5. this one clear atrribute at selected block. it can be updated to clear all the same block:
Code: [Select]
(Defun C:CLS (/ OB TY OT OC)
  (setq OB (car (entsel "\nSelect block w/attribute:"))
        TY (cdr (assoc 0 (entget OB)))
        OT "ATTRIB")
  (if (= TY "INSERT")
    (progn
      (while (= OT "ATTRIB")
        (setq OB (entnext OB)
              OT (cdr (assoc 0 (entget OB)))
              OC (entget OB)
             OC (subst (Cons 1 "") (assoc 1 OC) OC))
        (EntMod OC)            
      );while
    );progn
  );if
  (princ)
);CLS
6. probably more and more and more...

kruuger