Author Topic: ToList - convert various arguments to lists  (Read 1772 times)

0 Members and 1 Guest are viewing this topic.

mkweaver

  • Bull Frog
  • Posts: 352
ToList - convert various arguments to lists
« on: January 29, 2011, 01:12:39 PM »
Here is a routine I have been using for a while.  This morning I was working with dictionaries and decided to make ToList handle dictionaries.  Here is the result.  I'm looking for suggestions and comments.
Code: [Select]
;|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  Routine: ToList
  Purpose: A general purpose routine to convert a variety of arguments to lists.

  Signature #1
Arguments: col - a list
Returns: col, unchanged
Example: (tolist '(1 2 3)) returns (1 2 3)

  Signature #2
Arguments: col - a string
Returns: a list of ascii character codes - same as
  vl-string->list
Example: (tolist "Testing") returns (84 101 115 116 105 110 103)

  Signature #3
Arguments: col - a selection set
Returns: a list of the enames in the selection set
Example: (tolist (ssget))
may return (<Entity name: 735e80b0>
  <Entity name: 735e80f0> <Entity name: 735e8060>)

  Signature #4
Arguments: col - a variant array
Returns: A list of the array contents
Example: (tolist (vla-get-insertionpoint obj))
  may return (24.435 13.817 0.0)

  Signature #5
Arguments: col - a vla-object that is a collection such, as the
  layers collection, or the blocks collection.
Returns: a list of the objects in the collection.
Example: (tolist (vla-get-layers doc))
  may return (#<VLA-OBJECT IAcadLayer 10991f94>
  #<VLA-OBJECT IAcadLayer 109953c4>)

  Signature #6
  Arguments: col - a vla-object that is a dictionary, such as the
    mleaderstyles dictionary.
  Returns: a list of the objects in the collection.
  Example: (tolist (vla-item (vla-get-dictionaries doc) "ACAD_MLEADERSTYLE"))
    may return:
    (("Standard" . #<VLA-OBJECT IAcadMLeaderStyle 0000000026a1a678>)
                           ("Annotative" . #<VLA-OBJECT IAcadMLeaderStyle 0000000026a46458>)
                          )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|;

(defun ToList (col / rtlist)
  (cond ;;We have a list
((listp col) col)
;;We have a string
((= 'STR (type col)) (vl-string->list col))
;;We have a selection set
((= 'PICKSET (type col))
(vl-remove-if
   'null
   (vl-remove-if-not
     (function (lambda (e) (= 'ENAME (type e))))
     (apply 'append (ssnamex col))
   )
)
)
;;We have a variant array
((and (= 'variant (type col)) (<= 8192 (vlax-variant-type col)))
(vlax-safearray->list (vlax-variant-value col))
)
;;We have a table
((and (= 'VLA-OBJECT (type col)) (wcmatch (vla-get-objectname col) "*Table"))
(vlax-for item col (setq rtlist (cons item rtlist)))
(reverse rtlist)
)
;;We have a dictionary
((and (= 'VLA-OBJECT (type col)) (= "AcDbDictionary" (vla-get-objectname col)))
(setq
   indx -1
   count (vla-get-count col)
   )
(while (> count (setq indx (1+ indx)))
   (setq
     entry (vla-item col indx)
     rtlist (if (vlax-property-available-p entry 'name)
      (cons (cons (vla-get-name entry) entry) rtlist)
      ;;I considered using the objectname instead of "UnNamed"
      (cons (cons "UnNamed" entry) rtlist)
      )
     )
   )
rtlist
)
;;We have a generic collection object
((and (= 'VLA-OBJECT (type col))(vlax-property-available-p col 'count))
(vlax-for item col (setq rtlist (cons item rtlist)))
(reverse rtlist)
)
(T
(if (= 'VLA-OBJECT (type col))
   (strcat "Error|Unhandled collection type:" (vla-get-objectname col))
   (strcat "Error|Unhandled col argument:" (vl-prin1-to-string (type col)) ":" (vl-prin1-to-string col))
   )
)
  )
)

Thanks,
Mike

Lee Mac

  • Seagull
  • Posts: 12929
  • London, England
Re: ToList - convert various arguments to lists
« Reply #1 on: January 29, 2011, 01:19:49 PM »
Nice idea Mike  :-)

You asked for suggestions, so here are two of mine:

** You can iterate through VLA Dictionaries using vlax-for, so the conditions for Tables/Dictionaries and Collections could be merged into one vlax-for loop, with a check for the existence of the name property.

** For Variants, I would be inclined to handle them in the following way:

In the condition, make a call to this sub (originally by Nesterovsky I think, not sure though):

Code: [Select]
(defun VariantValue ( value )
  (cond
    ( (eq 'variant (type value))

      (VariantValue (vlax-variant-value value))
    )
    ( (eq 'safearray (type value))

      (mapcar 'VariantValue (vlax-safearray->list value))
    )
    ( value )
  )
)

And recursively supply the return to the main function:

Code: [Select]
(ToList (VariantValue <variant>))
Example:

Code: [Select]
;; ToList by mkweaver
;;
;; Modified by Lee Mac

(defun ToList ( col / VariantValue rtlist )

  (defun VariantValue ( value )
    (cond
      ( (eq 'variant (type value))

        (VariantValue (vlax-variant-value value))
      )
      ( (eq 'safearray (type value))

        (mapcar 'VariantValue (vlax-safearray->list value))
      )
      ( value )
    )
  )
 
  (cond
    (
      (listp col) col
    )
    (
      (eq 'STR (type col)) (vl-string->list col)
    )
    (
      (eq 'PICKSET (type col))

      (vl-remove-if 'null
        (vl-remove-if-not
          (function (lambda ( e ) (= 'ENAME (type e)))) (apply 'append (ssnamex col))
        )
      )
    )
    (
      (eq 'VARIANT (type col))

      (ToList (VariantValue col))
    )
    (
      (and (= 'VLA-OBJECT (type col)) (vlax-property-available-p col 'count))

      (vlax-for item col
        (setq rtlist (cons item rtlist))
      )
      (reverse rtlist)
    )
    (T
      (if (= 'VLA-OBJECT (type col))
        (strcat "Error | Unhandled collection type:" (vla-get-objectname col))
        (strcat "Error | Unhandled col argument:" (vl-prin1-to-string (type col)) ":" (vl-prin1-to-string col))
      )
    )
  )
)

[ Sincere apologies for messing with your code - I'll remove the above if you want ]

Lee
« Last Edit: January 29, 2011, 01:28:35 PM by Lee Mac »

mkweaver

  • Bull Frog
  • Posts: 352
Re: ToList - convert various arguments to lists
« Reply #2 on: January 29, 2011, 01:56:26 PM »
Lee,
I certainly don't have a problem with you tweaking my code.   I appreciate the feedback.

A question though, why "eq" instead of "=" ?

Also, thanks for the Variantvalue routine.  That is slick.

Incorporating your suggestions:
Code: [Select]
(defun ToList (col / rtlist)
 (defun VariantValue (value) ;from a post on TheSwamp.org http://www.theswamp.org/index.php?topic=36908.msg418922#msg418922
   (cond
     ((eq 'variant (type value))
      (VariantValue (vlax-variant-value value))
     )
     ((eq 'safearray (type value))
      (mapcar 'VariantValue (vlax-safearray->list value))
     )
     (value)
   )
 )
  (cond ;;We have a list
((listp col) col)
;;We have a string
((eq 'STR (type col)) (vl-string->list col))
;;We have a selection set
((eq 'PICKSET (type col))
(vl-remove-if
   'null
   (vl-remove-if-not
     (function (lambda (e) (= 'ENAME (type e))))
     (apply 'append (ssnamex col))
   )
)
)
;;We have a variant array
((eq 'variant (type col))
(tolist (variantvalue col))
)
;;We have a table
((and (eq 'VLA-OBJECT (type col)) (wcmatch (vla-get-objectname col) "*Table"))
(vlax-for item col (setq rtlist (cons item rtlist)))
(reverse rtlist)
)
;;We have a dictionary
((and (eq 'VLA-OBJECT (type col)) (= "AcDbDictionary" (vla-get-objectname col)))
(vlax-for entry col
     (if (vlax-property-available-p entry 'name)
      (cons (vla-get-name entry) entry)
      ;;I considered using the objectname instead of "UnNamed"
      (cons "UnNamed" entry)
      )
     )
   )
;;We have a generic collection object
((and (eq 'VLA-OBJECT (type col))(vlax-property-available-p col 'count))
(vlax-for item col (setq rtlist (cons item rtlist)))
(reverse rtlist)
)
(T
(if (eq 'VLA-OBJECT (type col))
   (strcat "Error|Unhandled collection type:" (vla-get-objectname col))
   (strcat "Error|Unhandled col argument:" (vl-prin1-to-string (type col)) ":" (vl-prin1-to-string col))
   )
)
  )
)

Lee Mac

  • Seagull
  • Posts: 12929
  • London, England
Re: ToList - convert various arguments to lists
« Reply #3 on: January 29, 2011, 02:19:13 PM »
A question though, why "eq" instead of "=" ?

Just a habit I have acquired at some point really I suppose: I tend to use '=' for numerical comparison, 'eq' for symbols/strings and 'equal' for lists/enames, or where fuzz is needed.