TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started 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
-
use this as reference:
(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 :-)
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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 :?
-
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
(vl-load-com)
(defun C:AUTOID (/ LS SS SS_MUL ID)
(setq LS
....
kruuger
-
Enter this at the command line:
(vl-load-com)
Then try your proggy again.
-
:-)
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?
-
:-)
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
-
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.
-
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
-
Some quick code / food for thought:
PicksetToObjects:
(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:
(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:
(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:
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)
-
Looks like you guys got it all covered
I would have done it the same way as kruuger's but slightly different
(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
(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....
-
:-)
It works. THANKS!!!!
uff :wink:
thanks
kruuger
Error in CAD2010
Command: AUTOID
; error: no function definition: VLAX-GET-ACAD-OBJECT
-
:-)
It works. THANKS!!!!
uff :wink:
thanks
kruuger
Error in CAD2010
Command: AUTOID
; error: no function definition: VLAX-GET-ACAD-OBJECT
here was solution:
http://www.theswamp.org/index.php?topic=36412.msg414377#msg414377
kruuger
-
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
-
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
[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)
)
-
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
-
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
-
ok, no problem. i try to incorporate this change to lisp + MP_ SortObject function
kruuger
-
try this code. let me know if it works for you.
thanks MP. Sort function works perfect :)
kruuger
-
great to hear kruuger --- thanks for letting me know --- thanks for helping T3D
-
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
-
i found a small mistake. try now
kruuger
-
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
-
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
(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:
(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