Jump to content

Recommended Posts

Posted

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

Posted

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) ;)

Posted

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

Posted

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

Posted

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.

Posted
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 ?

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

Posted

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.

Posted

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

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

Posted

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

 

 

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)

:)

Posted

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 :D

 

 

 

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)

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

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