Grrr Posted March 26, 2016 Posted March 26, 2016 Hi code fellas, Today I tried to utilize Lee Mac's "Dynamic Block Functions", and his "List Box". So my attempt is to: Select a dynamic block and it should return its: 1.Effective name 2.Visibility state parameter's name and its value (maybe a list is better?) 3.List of attribute's names and values (in a listbox) 4.List of parameter's names and values (in a listbox) Ofcourse the reason I'm making a thread is because I probably did something wrong: (defun C:test ( / sel blkname ) (vl-load-com) (setvar 'errno 0) (prompt "\nSelect block to analyze" ) (if (and (setq sel (ssget "_:S:E" '((0 . "INSERT")))) (setq blkname (LM:al-effectivename (ssname sel 0))) ;<-BLOCK NAME (princ (strcat "\nBlockName is \"" blkname "\" " )) );and (progn (if (setq vis-state-param (LM:getvisibilityparametername (ssname sel 0) )) (princ (strcat "\nVisibility state parameter: " vis-state-param " ")) );if (if (setq vis-state-val (LM:getvisibilitystate (ssname sel 0) )) (princ (strcat "\nVisibility state value: " vis-state-val " ")) );if (if (setq lst-atts (LM:getattributes (ssname sel 0) )) (LM:listbox "Select an attribute" (lst-atts) 1) );if (if (setq lst-params (LM:getdynpropallowedvalues (ssname sel 0) )) (LM:listbox "Select an parameter" (lst-params) 1) );if );progn (cond ((not blkname) (progn (princ "\nMissed.. Try again!")(C:test)) ) ((not found) (princ "\n Block not found in drawing !!!") ) (t (princ "\n couldn't find any block !!! ") ) );cond ) (princ "\n") (vla-Regen (vla-get-ActiveDocument (vlax-get-acad-object)) acActiveViewport) (princ) );defun I get: Select block to analyze Select objects: BlockName is "VLD_К.Маса-4ка" Error: bad argument type: VLA-OBJECT <Entity name: 7ff653a27260> Here are the dynamic block functions I'm referring to: http://www.lee-mac.com/dynamicblockfunctions.html Quote
Tharwat Posted March 26, 2016 Posted March 26, 2016 Hi, Read the comments of each function and compare it to the error message then you should know how to correct it. (hint : convert it) Quote
Grrr Posted March 26, 2016 Author Posted March 26, 2016 Thanks for the hint, Tharwat! (if (setq vis-state-val (LM:getvisibilitystate (vlax-ename->vla-object (ssname sel 0)) )) (princ (strcat "\nVisibility state value: " vis-state-val " ")) );if I'm almost there! Do you have any more hints up on your sleeve, about this: (if (setq lst-atts (LM:GetAttributes (ssname sel 0))) (LM:listbox "Select an attribute" lst-atts 1) );if The list box flashes(opens and closes immediately) and I get this: Select objects: BlockName is "VLD_ОСИ_V3" Visibility state parameter: Visibility1 Visibility state value: BothVisible Error: bad argument type: stringp ("X1" . "Ж") I know that the problem is because LM:GetAttributes returns an association list, but how do I split the tags and the values from it? So I end up with two lists for the listbox ;; Get Attributes - Lee Mac;; Returns: [lst] Association list of (( . ) ... ) Quote
Tharwat Posted March 26, 2016 Posted March 26, 2016 I know that the problem is because LM:GetAttributes returns an association list, but how do I split the tags and the values from it? So I end up with two lists for the listbox You can use mapcar function to get each tag name and text string in a separate list. e.g; (mapcar 'car lst-atts) ;; <- tag names (mapcar 'cdr lst-atts) ;; <- text strings Quote
Grrr Posted March 26, 2016 Author Posted March 26, 2016 Thanks alot, Tharwat! I often read about mapcar and lambda but they're hard to understand and I rarely use them. Maybe I'll neeed to learn more about list manipulation, since I'm used to work only with setting quotes in LISP. I have one last question: If I have this list (lst1) , and I filter-out all of its items, except one in a new list (lst2), and I end up with list which contains only one item - Is it possible to set a quote for that item? Because my current method for handling this problem is this: (foreach itm lst ;; For every 'itm' in the list given by 'lst' (princ (strcat "\nCurrent item is \"" itm "\" " )) ) ;; end foreach But this seems very limited, as I can't proceed with any IF/COND outside the FOREACH function. Quote
Tharwat Posted March 26, 2016 Posted March 26, 2016 Thanks alot, Tharwat! You are welcome. I often read about mapcar and lambda but they're hard to understand and I rarely use them. Maybe I'll neeed to learn more about list manipulation, since I'm used to work only with setting quotes in LISP. That is essential and Lisp word is somehow has the combination meaning of the tow words LISt Processing. I have one last question: If I have this list (lst1) , and I filter-out all of its items, except one in a new list (lst2), and I end up with list which contains only one item - Is it possible to set a quote for that item? Because my current method for handling this problem is this: (foreach itm lst ;; For every 'itm' in the list given by 'lst' (princ (strcat "\nCurrent item is \"" itm "\" " )) ) ;; end foreach But this seems very limited, as I can't proceed with any IF/COND outside the FOREACH function. I am sorry I did not get your point. Why you are after quoting an item from a list since it would be a list at the end ? Quote
Grrr Posted March 26, 2016 Author Posted March 26, 2016 That is essential and Lisp word is somehow has the combination meaning of the tow words LISt Processing. Yes, I've read why its called LISP ! And I'm ashamed with my lack of knowledge using lists ! To my question: I mean if I'm about to extract per one item from 3-4 different lists, wouldn't be more comfortable to quote these items and then proceed? Otherwise it would become some wrapping of foreach functions, for one element per list: (foreach itm1 lst1 (foreach itm2 lst2 (foreach itm3 lst3 (do my stuff with itm1 itm2 and itm3) ) ) ) Maybe "last" function would help, but I'm not sure: (setq itm1 (last lst1) ) (setq itm2 (last lst2) ) (setq itm3 (last lst3) ) (do my stuff with itm1 itm2 and itm3) My question is because that with every code I try to write: I'm used first to READ/INPUT information (from user) and then the program proceeds and in the end user gets the RETURN information from the program. I try to avoid those syntaxes from the begining to the end of the program, since its very confusing. Quote
Tharwat Posted March 26, 2016 Posted March 26, 2016 You need to give a practical example , anyway maybe append function would help to reduce the quantity of foreach function by appending lists into one list then proceed with one list. In regard to quote , I am still can't get your point but anyway there is a function call quote , try it. Quote
Grrr Posted March 26, 2016 Author Posted March 26, 2016 Thank you, Tharwat ! I'm glad that in this forum there are guys like you, skilled and helpful! I'll continue with my experiments now. Quote
Tharwat Posted March 26, 2016 Posted March 26, 2016 Thank you, Tharwat !I'm glad that in this forum there are guys like you, skilled and helpful! I am glad to be of any assistant. I'll continue with my experiments now. Best of luck. Quote
Jef! Posted March 31, 2016 Posted March 31, 2016 Hi Grrrr.. 2 little comments (cond ((not blkname) (progn (princ "\nMissed.. Try again!")[color="red"](C:test)[/color]) ) ((not found) (princ "\n Block not found in drawing !!!") ) (t... Having the cond relaunch the c:test command doesnt just relaunch the command, but relaunch it recursively! (hint 1: use a while... hint 2:Maybe you should read that thread made by a nice op called Grrrr who had the same approach before being suggested otherwise with a while example in the best reply he ever received... If I have this list (lst1) , and I filter-out all of its items, except one in a new list (lst2),and I end up with list which contains only one item - Is it possible to set a quote for that item? Ah! I just understood the question... set a quote => set quote => (set(quote => setq. Well, a for-each approach can be used for a list no matters the # of contained arguments. While (last ) retrieve the last element, you could also use (car ) to retrieve the 1rst element, or again the (nth ) to retrieve a specific element of the list (keeping in mind that the first element of a list is (nth 0 ). You could use (length ) to verify how many elements are contained in the list and act accordingly only if the length is 1. ..as for the quote function, won't be much use for you here. It just instructs cad to returns the expression without evaluating it, so (quote(princ "hello")) would literally return (PRINC "hello") ------- My question is because that with every code I try to write:I'm used first to READ/INPUT information (from user) and then the program proceeds and in the end user gets the RETURN information from the program. The next part might be usefull to understand return values only if I correctly understood what you meant. Are you reffering to the returned value of your function? If so, in your example, your users do not get the returned value. The returned value is the last expression evaluated, and the last thing you do is (princ), which exit quietly. Let's take these 2 functions. (defun foo () (princ 2) (princ) ) (defun baz () 2) By using them, here's what we get. Command: (foo)2 Command: (baz) 2 Even if it looks the same, let's bind their returned value to a symbol and see what happens Command: (setq zzz (baz))2 Command: !zzz 2 Command: (setq zzz (foo))2 Command: !zzz Command: !zzz zzz doeesn't seems to contain anything, yet is doesn't return nil. If we check what is the type... Command: (type zzz)SYM now lets check if zzz and (princ) are bound to the same object with the "nasty" (eq function (eq zzz (princ)) T ..so, any program ending by (princ) returns... (princ) Cheers (princ) Quote
Grrr Posted April 2, 2016 Author Posted April 2, 2016 Thanks, Jef!! Excuse me for the recursive relaunch, I grabbed some old routine that I mixed-up and started these experiments. I hope this would do the job: (cond ((= 52 (getvar 'errno)) (princ "\nMissed.. Try again!")(C:test) ) ((null sel) (princ "\nYou missed, try again.")(C:test) ) ((not blkname) (princ "\n Missed name of block ***") ) ((not found) (princ "\n Block not found in drawing !!!") ) (t (princ "\n couldn't find any block !!! ") ) );cond Before your post I figured out that I might just use (setq setquoteditem (car listwithoneitem)) such method didn't feel very right to me so I had to ask, but reading this from your post: You could use (length ) to verify how many elements are contained in the list and act accordingly only if the length is 1. by providing the length check for the list first would make the code look more right Anyway, everything seems to work fine.. I get all the attribute tags in the listbox I get all the attribute values in the listbox I get all the parameter tags in the listbox But I do not get the parameter values in the listbox So the reason why (it might be) is because that the "lst-param-vals" must contain a mix of numbers/strings/symbols. With my lack of list experience I came up with this (my concept doesn't work ofcourse): (setq lst-param-vals (append '(mapcar 'cdr lst-params) lst-param-vals)) ; create list with 2nd associated element from lst-params ; sort the items from the "lst-param-vals", by constructing sorted lists (foreach itm lst-param-vals (cond ((numberp itm) (setq listwithnumbers '()) (append itm listwithnumbers) ; add it to numbers list ) ((stringp itm) (setq listwithstrings '()) (append itm listwithstrings) ; add it to strings list ) ((symbolp itm) (setq listwithsymbols '()) (append itm listwithsymbols) ; add it to symbols list ) );cond );end of foreach (print listwithnumbers) (print listwithstrings) (print listwithsymbols) Construct lists to sort out the different items. However I'm not sure I'm going on the right track, I mean: ;; Get Dynamic Block Properties - Lee Mac ;; Returns an association list of Dynamic Block properties & values. ;; blk - [vla] VLA Dynamic Block Reference object ;; Returns: [lst] Association list of ((<prop> . <value>) ... ) How does one who gets such association list could benefit from it? The way I could think of it is to extract the and the of one or a few items and for example put some conditioning to select by/match by these attribute's/parameter's tags/values. (maybe for this question I should start new thread, because it could be long to discuss - working with assoc lists) Quote
Recommended Posts
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.