Author Topic: Quick ODBX Question  (Read 10342 times)

0 Members and 2 Guests are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Quick ODBX Question
« on: January 15, 2010, 01:59:23 PM »
When iterating through a set of Documents using ObjectDBX, is it best to release the ODBX Document object before opening the next drawing?

jbuzbee

  • Swamp Rat
  • Posts: 851
Re: Quick ODBX Question
« Reply #1 on: January 15, 2010, 02:05:20 PM »
I do.

Once you've created an activex reference to an object it's best to release it.

jb
James Buzbee
Windows 8

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #2 on: January 15, 2010, 02:08:54 PM »
I do.

Once you've created an activex reference to an object it's best to release it.

jb

I've been reading an AU document, which says:

Quote
How to close a drawing (2 methods)
o (vlax-release-object odoc) ;be sure to save first.
o (vlax-open odoc “filespecification”)
o You basically have an SDI document interface with each ObjectDBX document.

I would, of course, release the ODBX doc after I have finished with all the drawings - but should I release the ODBX doc after each and every drawing is opened?

Sorry if I have repeated my question - just want to be sure  :wink:


T.Willey

  • Needs a day job
  • Posts: 5251
Re: Quick ODBX Question
« Reply #3 on: January 15, 2010, 02:11:49 PM »
I don't.  I don't see a reason to.  It is different than a regular document, as in the ODBX document is more like a application to me, than a document, so I only want one instance of the application open at a time.

Edit:  Adding example code to show what I typically do with ODBX

Code: [Select]
(defun MapDbxDocs ( func dwgList / *error* dbxApp oVer RsltList )
   
    (defun *error* (msg)
       
        (if dbxApp
            (vlax-release-object dbxApp)
        )
        (setq dbxApp nil)
        (if msg
            (prompt (strcat "\n Error--> " msg))
        )
    )
    ;--------------------------------------------
    (setq dbxApp
        (if (< (atoi (setq oVer (substr (getvar "acadver") 1 2))) 16)
            (vla-GetInterfaceObject (vlax-get-acad-object) "ObjectDBX.AxDbDocument")
            (vla-GetInterfaceObject (vlax-get-acad-object) (strcat "ObjectDBX.AxDbDocument." oVer))
        )
    )
    (foreach dwg dwgList
        (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Open (list dbxApp dwg)))
            (prompt (strcat "\n *** Error opening drawing: " dwg))
            (setq RsltList (cons (cons dwg ((eval func) dbxApp)) RsltList))
        )
    )
    (*error* nil)
    RsltList
)

Found here for a example
http://www.theswamp.org/index.php?topic=29933.0
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #4 on: January 15, 2010, 02:24:09 PM »
Thanks Tim  8-)

Here is the result of my efforts:

Code: [Select]
(defun c:CheckLayers (/ *error* ObjRelease DirDialog Get_Subs ObjectDBXDocument GetLayers Str-Make

                        DBX DOCLST DWLST FILE FOLDER LAYER_LIST PATH SHELL)
  (vl-load-com)
  ;; Lee Mac  ~  15.01.10
 

  (defun *error* (msg)
    (ObjRelease (list Shell dbx))
    (and ofile (= (type ofile) 'FILE) (close ofile))
   
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **")))
    (princ))


  (defun ObjRelease (lst)
    (mapcar
      (function
        (lambda (x)
          (if (and (eq (type x) 'VLA-OBJECT)
                   (not (vlax-object-released-p x)))
            (vl-catch-all-apply
              (function vlax-release-object) (list x))))) lst))
 

  (defun DirDialog (msg dir flag / Shell Fold Path)
    ;; Lee Mac  ~  07.06.09
   
    (setq Shell (vla-getInterfaceObject *acad "Shell.Application")
          Fold  (vlax-invoke-method Shell 'BrowseForFolder
                  (vla-get-HWND *acad) msg flag dir))
    (vlax-release-object Shell)
   
    (if Fold
      (progn
        (setq Path (vlax-get-property
                     (vlax-get-property Fold 'Self) 'Path))
        (vlax-release-object Fold)
       
        (and (= "\\" (substr Path (strlen Path)))
             (setq Path (substr Path 1 (1- (strlen Path)))))))
   
    Path)


  (defun Get_Subs (folder / file) ;; CAB
    (mapcar
      (function
        (lambda (x) (setq file (strcat folder "\\" x))
                    (cons file (apply (function append) (get_subs file)))))
        (cddr (vl-directory-files folder nil -1))))

 
  (defun ObjectDBXDocument (/ acVer)
   
    (vla-GetInterfaceObject *acad
      (if (< (setq acVer (atoi (getvar "ACADVER"))) 16) "ObjectDBX.AxDbDocument"
        (strcat "ObjectDBX.AxDbDocument." (itoa acVer)))))
 

  (defun GetLayerProperties (doc / lst)
    (vlax-for lay (vla-get-Layers doc)
      (setq lst (cons
                  (mapcar
                    (function
                      (lambda (property)
                        (vl-princ-to-string
                          (vlax-get-property lay property))))

                    '(Name Color Linetype LineWeight))

                  lst)))
   
    (vl-sort lst
      (function
        (lambda (a b) (< (car a) (car b))))))

 
  (defun Str-Make  (lst del / Pad str x i)
    (setq i 10)

    (defun Pad  (Str Del Len)
      (while (>= (strlen Str) Len) (setq Len (+ Len 5)))
      (while (< (strlen Str) Len)
        (setq Str (strcat Str Del)))
      Str)

    (apply (function strcat)
           (reverse
             (cons (last lst)
                   (mapcar
                     (function
                       (lambda ($str)
                         (Pad $str del
                              (setq i (abs (- 40 i))))))

                     (cdr (reverse lst)))))))
   

  (setq *acad (cond (*acad) ((vlax-get-acad-object)))
        *doc  (cond (*doc ) ((vla-get-ActiveDocument *acad))))

  (or *def* (setq *def* "Yes"))
 

  (if (and (setq Path (DirDialog "Select Directory" nil 0))
           (vl-file-directory-p Path)
           (setq outfile (getfiled "Output File" "" "txt" 1)))
    (progn

      (initget "Yes No")
      (setq *def* (cond ((getkword
                           (strcat "\nProcess SubDirectories? <" *def* "> : "))) (*def*)))

      (vlax-for doc (vla-get-Documents *acad)
        (setq DocLst
          (cons (cons (strcase (vla-get-FullName doc)) doc) DocLst)))
     

      (foreach dwg (setq dwLst (apply (function append)
                                       (vl-remove 'nil
                                         (mapcar
                                           (function
                                             (lambda (Path)
                                               (mapcar
                                                 (function
                                                   (lambda (File)
                                                     (strcat Path "\\" File)))
                                                 (vl-directory-files Path "*.dwg" 1))))
                                           (append (list Path)
                                                   (apply (function append)
                                                          (if (= "YES" (strcase *def*))
                                                            (Get_Subs Path))))))))

        (setq dbx (cdr (assoc (strcase dwg) DocLst)))       

        (and (not dbx) (setq dbx (ObjectDBXDocument)))
       

        (if (not (vl-catch-all-error-p
                    (vl-catch-all-apply
                      (function vla-open) (list dbx dwg))))

          (setq Layer_List (cons (cons dwg (GetLayerProperties dbx)) Layer_List))
          (setq Layer_List (cons (cons dwg '(("**Error Opening this Drawing **"))) Layer_List))))
               

      (princ (strcat "\n<< " (itoa (length dwLst)) " Drawings Processed >>")))
   
    (princ "*Cancel*"))

  (ObjRelease (list Shell dbx)) (gc) (gc)

  (if (and Layer_List
          (setq ofile (open outfile "w")))
    (progn
     
      (mapcar
        (function
          (lambda (x)
            (write-line (car x) ofile)
            (write-line (Str-Make '("Name" "Colour" "LineType" "LineWeight") (chr 32)) ofile)
            (mapcar
              (function
                (lambda (y)
                  (write-line
                    (Str-Make y (chr 32)) ofile))) (cdr x))
           
            (write-line "\n" ofile)))

        Layer_List)

      (close ofile))

    (princ "\n*Cancel*"))

  (princ))

Will list all Layers in a Folder of Drawings  :-)
« Last Edit: January 15, 2010, 08:23:09 PM by Lee Mac »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Quick ODBX Question
« Reply #5 on: January 15, 2010, 03:09:22 PM »
Hard for me to follow your code.   :-)

One thing I did see though that I would change is that you are stepping through the document collection for every file name.  Just step through it once, making an associated list of drawing path and document, and then just see if the path is within the list.  May save a little bit of time.  No sense stepping though something 50 times when you only need to once.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #6 on: January 15, 2010, 03:22:29 PM »
Hard for me to follow your code.   :-)

I try to make it clear as possible... :angel:

One thing I did see though that I would change is that you are stepping through the document collection for every file name.  Just step through it once, making an associated list of drawing path and document, and then just see if the path is within the list.  May save a little bit of time.  No sense stepping though something 50 times when you only need to once.

Ahh good point Tim - will do.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #7 on: January 15, 2010, 03:29:33 PM »
Code updated to reflect Tim's Idea  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #8 on: January 15, 2010, 03:48:31 PM »
Nice one Lee.
Does not report failed DWGs though. :evil:
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Quick ODBX Question
« Reply #9 on: January 15, 2010, 03:57:13 PM »
I think it's the indentation you use, but that is person preference, and I can understand it, it just takes me longer than I like.  The hardest part is finding the end of you sub's to me, or any long indentation portion.  If I opened it in an editor, I could check that easier, but then I would have to copy/paste it to an editor.   :wink:

One thing to watch out on is the name of drawings.  You should make the all one case, upper/lower, and then test the name the same way.

ps. This is a perfect example ( idea of code ) of how my MapDbxDocs routine could be used. :wink:
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #10 on: January 15, 2010, 04:07:19 PM »
Mod of your subroutine to try out. 8-)
Code: [Select]
(defun Str-Make (lst del / Pad str)

  (defun Pad (pStr pDel Len)
    (while (>= (strlen pStr) len)(setq len (+ len 10)))
    (while (< (strlen pStr) Len)
      (setq pStr (strcat pStr pDel))
    )
    pStr
  )

  (mapcar (function (lambda(str$ len#)
      (cond ((null str) (setq str (Pad str$ del len#)))
    ((setq str (strcat Str (Pad str$ del len#)))))))
  lst '(30 10 30 10))
  str
)
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #11 on: January 15, 2010, 04:11:57 PM »
Nice one Lee.
Does not report failed DWGs though. :evil:


Nice catch CAB - code updated.  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #12 on: January 15, 2010, 04:19:37 PM »
Mod of your subroutine to try out. 8-)

Thanks Alan,

Its good for this routine - as the del is a space   :-)

Also, the resultant string will end with the delimiter...  but I like the way that it extends the length of the padding  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #13 on: January 15, 2010, 04:24:40 PM »
Perhaps this instead?

Code: [Select]
(defun Str-Make  (lst del / Pad str x i)
  (setq i 10)

  (defun Pad  (Str Del Len)
    (while (>= (strlen Str) Len) (setq Len (+ Len 5)))
    (while (<  (strlen Str) Len)
      (setq Str (strcat Str Del)))
    Str)

  (apply (function strcat)
         (reverse (cons (last lst)
                        (mapcar
                          (function
                            (lambda ($str) (Pad $str del (setq i (abs (- 40 i))))))

                          (cdr (reverse lst)))))))

CAB, can you see any way of streamlining this a bit more?  I should imagine the "reverse" takes a bit of time...
« Last Edit: January 15, 2010, 05:05:56 PM by Lee Mac »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #14 on: January 15, 2010, 06:57:08 PM »
How about this?
Code: [Select]
(defun Str-Make (lst del / Pad str)

  (defun Pad (pStr pDel Len)
    (or (zerop len)
        (while (>= (strlen pStr) len) (setq len (+ len 10)))
        (while (< (strlen pStr) Len) (setq pStr (strcat pStr pDel)))
    )
    pStr
  )

  (mapcar (function (lambda(str$ len#)
      (cond ((null str) (setq str (Pad str$ del len#)))
    ((setq str (strcat Str (Pad str$ del len#)))))))
  lst '(30 10 30 0))
  str
)
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #15 on: January 15, 2010, 07:01:57 PM »
Nice one CAB - thats good, but of course it would only apply to lists of length 4  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #16 on: January 15, 2010, 07:19:01 PM »
Unexpectedly:

Code: [Select]
(BenchMark '((Str-Make-CAB '("1" "2" "3" "4") "+") (Str-Make-Lee '("1" "2" "3" "4") "+")))
Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (STR-MAKE-LEE (QUOTE ("1" "2" "3" "4...).....1763 / 1.01 <fastest>
    (STR-MAKE-CAB (QUOTE ("1" "2" "3" "4...).....1778 / 1.00 <slowest>
_$ (BenchMark '((Str-Make-CAB '("1" "2" "3" "4") "+") (Str-Make-Lee '("1" "2" "3" "4") "+")))
Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (STR-MAKE-LEE (QUOTE ("1" "2" "3" "4...).....1763 / 1.03 <fastest>
    (STR-MAKE-CAB (QUOTE ("1" "2" "3" "4...).....1810 / 1.00 <slowest>

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #17 on: January 15, 2010, 07:56:03 PM »
Yes, unexpected.
As for the number of string items, to make it universal i would think you would also pass the length list with it.
Code: [Select]
(Str-Make-CAB '("1" "2" "3" "4") '(30 10 30 0) "+")
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #18 on: January 15, 2010, 07:58:35 PM »
How does this version time out?
Code: [Select]
(defun Str-Make (lst del / Pad str)

  (defun Pad (pStr pDel Len)
    (or (zerop len)
        (while (>= (strlen pStr) len) (setq len (+ len 10)))
        (while (< (strlen pStr) Len) (setq pStr (strcat pStr pDel)))
    )
    pStr
  )
  (setq str "")
  (mapcar (function (lambda(str$ len#)
      (setq str (strcat Str (Pad str$ del len#)))))
  lst '(30 10 30 0))
  str
)
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #19 on: January 15, 2010, 08:02:39 PM »
Not too much in it:

Code: [Select]
(BenchMark '((Str-Make-Lee '("1" "2" "3" "4") "+") (Str-Make-CAB1 '("1" "2" "3" "4") "+") (Str-Make-CAB2 '("1" "2" "3" "4") "+")))
Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (STR-MAKE-CAB2 (QUOTE ("1" "2" "3" "...).....1810 / 1.01 <fastest>
    (STR-MAKE-LEE (QUOTE ("1" "2" "3" "4...).....1825 / 1.00
    (STR-MAKE-CAB1 (QUOTE ("1" "2" "3" "...).....1825 / 1.00 <slowest>
_$ (BenchMark '((Str-Make-Lee '("1" "2" "3" "4") "+") (Str-Make-CAB1 '("1" "2" "3" "4") "+") (Str-Make-CAB2 '("1" "2" "3" "4") "+")))
Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (STR-MAKE-LEE (QUOTE ("1" "2" "3" "4...).....1779 / 1.03 <fastest>
    (STR-MAKE-CAB1 (QUOTE ("1" "2" "3" "...).....1794 / 1.02
    (STR-MAKE-CAB2 (QUOTE ("1" "2" "3" "...).....1825 / 1.00 <slowest>
_$ (BenchMark '((Str-Make-Lee '("1" "2" "3" "4") "+") (Str-Make-CAB1 '("1" "2" "3" "4") "+") (Str-Make-CAB2 '("1" "2" "3" "4") "+")))
Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (STR-MAKE-LEE (QUOTE ("1" "2" "3" "4...).....1794 / 1.03 <fastest>
    (STR-MAKE-CAB2 (QUOTE ("1" "2" "3" "...).....1826 / 1.01
    (STR-MAKE-CAB1 (QUOTE ("1" "2" "3" "...).....1841 / 1.00 <slowest>

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #20 on: January 15, 2010, 08:19:29 PM »
How many milliseconds does it take to blink? 8-)


I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #21 on: January 15, 2010, 08:23:53 PM »
In any case, I have updated the code in my previous post  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Quick ODBX Question
« Reply #22 on: January 15, 2010, 10:55:04 PM »
BTW Lee that is clever method to get the 30 10 30.  8-)
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: Quick ODBX Question
« Reply #23 on: January 16, 2010, 04:58:28 AM »
this will speed up things a bit
Code: [Select]
(defun Pad-VovKa (String Char NewLen / PadString)
  (if (> (setq NewLen (- NewLen (strlen String))) 0)
    (strcat String
    (progn (setq PadString (if (zerop (rem NewLen 2))
     ""
     Char
   )
Char    (strcat Char Char)
   )
   (repeat (/ NewLen 2) (setq PadString (strcat PadString Char)))
   PadString
    )
    )
    String
  )
)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #24 on: January 16, 2010, 08:03:18 PM »
BTW Lee that is clever method to get the 30 10 30.  8-)

Thanks Alan  8-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #25 on: January 16, 2010, 08:12:18 PM »
this will speed up things a bit

Nice idea VovKa!  Halving the amount of operations  :-D

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Quick ODBX Question
« Reply #26 on: January 17, 2010, 02:48:35 AM »
My variant:

Code: [Select]
(defun Str-Make-ee (lst del len)
 (repeat 6 (setq del (strcat del del)))
 (apply (function strcat)
        (mapcar (function (lambda (a b / s)
                           (if (< (setq s (strlen a)) b)
                            (strcat a (substr del 1 (- b s)))
                            a
                           ) ;_  if
                          ) ;_  lambda
                ) ;_  function
                lst
                len
        ) ;_  mapcar
 ) ;_  apply
)
test:
Code: [Select]
(setq lst '("1" "2" "3" "4") del "+" len '(30 10 30 0))
(BenchMark '((Str-Make-CAB2 lst del)
             (Str-Make-CAB1 lst del)
             (Str-Make-Lee lst del)
             (Str-Make-ee lst del len)
            )
) ;_  BenchMark
Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s):

    (STR-MAKE-EE LST DEL LEN).....1953 / 2.66 <fastest>
    (STR-MAKE-CAB2 LST DEL).......5047 / 1.03
    (STR-MAKE-CAB1 LST DEL).......5047 / 1.03
    (STR-MAKE-LEE LST DEL)........5203 / 1 <slowest>


Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #27 on: January 17, 2010, 07:52:45 AM »
Nice variant Evgeniy!

I wouldn't have immediately thought to create the "Padding string" first.. of course it would only work for padding < 2^6 in length, but I'm sure that's sufficient  :-)

Lee

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: Quick ODBX Question
« Reply #28 on: January 17, 2010, 07:55:43 AM »
i think this should be sufficient :)
Code: [Select]
(repeat (1+ (fix (/ (log (apply 'max Len)) (log 2))))
    (setq del (strcat del del))
  )

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Quick ODBX Question
« Reply #29 on: January 17, 2010, 07:59:46 AM »
Nice variant Evgeniy!

I wouldn't have immediately thought to create the "Padding string" first.. of course it would only work for padding < 2^6 in length, but I'm sure that's sufficient  :-)

Lee

Hi Lee, if you know in advance a symbol for addition easier not to create and write down it in the program:
"++++++++++++++++++++++++++++++++++++++++"

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #30 on: January 17, 2010, 08:06:20 AM »
Nice variant Evgeniy!

I wouldn't have immediately thought to create the "Padding string" first.. of course it would only work for padding < 2^6 in length, but I'm sure that's sufficient  :-)

Lee

Hi Lee, if you know in advance a symbol for addition easier not to create and write down it in the program:
"++++++++++++++++++++++++++++++++++++++++"


Haha, well of course, as you know it could be any symbol  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Quick ODBX Question
« Reply #31 on: January 17, 2010, 08:08:05 AM »
i think this should be sufficient :)
Code: [Select]
(repeat (1+ (fix (/ (log (apply 'max Len)) (log 2))))
    (setq del (strcat del del))
  )

Someone knows their maths  8-)