AutoCAD Performance Issue When Inserting Large Number of Blocks via LISP

AutoCAD Performance Issue When Inserting Large Number of Blocks via LISP

frjuniornogueira1
Participant Participant
1,272 Views
12 Replies
Message 1 of 13

AutoCAD Performance Issue When Inserting Large Number of Blocks via LISP

frjuniornogueira1
Participant
Participant

I’m experiencing a performance issue when inserting a large number of blocks into AutoCAD using the script below.

The script works perfectly — it correctly inserts the blocks, sets the insertion point, and adjusts the visibility state as expected. However, when I try to insert a large number of blocks (for example, using the attached CSV file), the process becomes extremely slow and can take several hours to complete.

I have a few questions:

  1. Is there a way to improve performance and make the insertion process faster?

  2. I noticed that this method creates many anonymous blocks (*U22, *U23, *U123, etc.). Could this be the reason why performance degrades over time? It starts fast but becomes progressively slower.

  3. If the block definition is not already present in the drawing and exists only in an external file (e.g., C://example//PNT_IMPORT.dwg), what would be the best approach to handle this efficiently?

I’ve attached a sample DWG and CSV file for reference.

Thank you in advance for your help.

(defun c:DEMO ( )
  (setvar 'REGENMODE 0)
  (if
    (and
      (setq file (getfiled "Select CSV File" (getvar 'DWGPREFIX) "csv" 16))
      (setq data (LM:readcsv file))
    )
    (foreach line data
      (setq item line)
      (setq pnt (list (atof (nth 9 item)) (atof(nth 8 item)) 0.0 ))
      (import:BlkInsert-Short 
        (car item) 
        pnt  ;;ponto
        (nth 1 item) ;visibilidade
        (nth 2 item) ;info1
        (nth 3 item) ;info2
        (nth 4 item) ;info3
        (nth 5 item) ;info4
        (nth 6 item) ;info5
        (nth 7 item) ;info6
      )
    )
  )
  (setvar 'REGENMODE 1)
  (princ)
)

(defun import:BlkInsert-Short (nomebloco ponto visibility INFO1 INFO2 INFO3 INFO4 INFO5 INFO6 / block atts)
  (if (and nomebloco ponto)
    (progn
      (setq block 
        (vla-InsertBlock
          (if (= 1 (getvar 'cvport))
            (vla-get-paperspace (vla-get-activedocument (vlax-get-acad-object)))
            (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object)))
          )
          (vlax-3d-point (trans ponto 1 0))
          nomebloco 1 1 1 0
        )
      )      
      (LM:SetVisibilityState block visibility)      
      ;; Se você sabe a ordem exata dos atributos no bloco
      (if (vla-get-HasAttributes block)
        (progn
          (setq atts (vlax-safearray->list (vlax-variant-value (vla-getAttributes block))))          
          ;; Atribui na ordem: ajuste os índices conforme seu bloco
          (if (>= (length atts) 4)
            (progn
              (vla-put-TextString (nth 0 atts) INFO1) 
              (vla-put-TextString (nth 1 atts) INFO2) 
              (vla-put-TextString (nth 2 atts) INFO3)
              (vla-put-TextString (nth 3 atts) INFO4)
              (vla-put-TextString (nth 4 atts) INFO5)
              (vla-put-TextString (nth 5 atts) INFO6)
            )
          )
        )
      )
    )
  )
  (princ)
)


;; Read CSV  -  Lee Mac
;; Parses a CSV file into a matrix list of cell values.
;; csv - [str] filename of CSV file to read
 
(defun LM:readcsv ( csv / des lst sep str )
    (if (setq des (open csv "r"))
        (progn
            (setq sep (cond ((vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList")) (",")))
            (while (setq str (read-line des))
                (setq lst (cons (LM:csv->lst str sep 0) lst))
            )
            (close des)
        )
    )
    (reverse lst)
)

;; CSV -> List  -  Lee Mac
;; Parses a line from a CSV file into a list of cell values.
;; str - [str] string read from CSV file
;; sep - [str] CSV separator token
;; pos - [int] initial position index (always zero)
 
(defun LM:csv->lst ( str sep pos / s )
    (cond
        (   (not (setq pos (vl-string-search sep str pos)))
            (if (wcmatch str "\"*\"")
                (list (LM:csv-replacequotes (substr str 2 (- (strlen str) 2))))
                (list str)
            )
        )
        (   (or (wcmatch (setq s (substr str 1 pos)) "\"*[~\"]")
                (and (wcmatch s "~*[~\"]*") (= 1 (logand 1 pos)))
            )
            (LM:csv->lst str sep (+ pos 2))
        )
        (   (wcmatch s "\"*\"")
            (cons
                (LM:csv-replacequotes (substr str 2 (- pos 2)))
                (LM:csv->lst (substr str (+ pos 2)) sep 0)
            )
        )
        (   (cons s (LM:csv->lst (substr str (+ pos 2)) sep 0)))
    )
)

(defun LM:csv-replacequotes ( str / pos )
    (setq pos 0)
    (while (setq pos (vl-string-search  "\"\"" str pos))
        (setq str (vl-string-subst "\"" "\"\"" str pos)
              pos (1+ pos)
        )
    )
    str
)



;; Set Dynamic Block Visibility State  -  Lee Mac
;; Sets the Visibility Parameter of a Dynamic Block (if present) to a specific value (if allowed)
;; blk - [vla] VLA Dynamic Block Reference object
;; val - [str] Visibility State Parameter value
;; Returns: [str] New value of Visibility Parameter, else nil

(defun LM:SetVisibilityState ( blk val / vis )
  (if
    (and
      (setq vis (LM:getvisibilityparametername blk))
      (member (strcase val) (mapcar 'strcase (LM:getdynpropallowedvalues blk vis)))
    )
    (LM:setdynpropvalue blk vis val)
  )
)

;-------------------------------------------------------------------------------;
;; Get Visibility Parameter Name  -  Lee Mac
;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Name of Visibility Parameter, else nil

(defun LM:getvisibilityparametername ( blk / vis )  
    (if
        (and
            (vlax-property-available-p blk 'effectivename)
            (setq blk
                (vla-item
                    (vla-get-blocks (vla-get-document blk))
                    (vla-get-effectivename blk)
                )
            )
            (= :vlax-true (vla-get-isdynamicblock blk))
            (= :vlax-true (vla-get-hasextensiondictionary blk))
            (setq vis
                (vl-some
                   '(lambda ( pair )
                        (if
                            (and
                                (= 360 (car pair))
                                (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))))
                            )
                            (cdr pair)
                        )
                    )
                    (dictsearch
                        (vlax-vla-object->ename (vla-getextensiondictionary blk))
                        "ACAD_ENHANCEDBLOCK"
                    )
                )
            )
        )
        (cdr (assoc 301 (entget vis)))
    )
)

;-------------------------------------------------------------------------------;
;; Get Dynamic Block Property Allowed Values  -  Lee Mac
;; Returns the allowed values for a specific Dynamic Block property.
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; Returns: [lst] List of allowed values for property, else nil if no restrictions

(defun LM:getdynpropallowedvalues ( blk prp )
    (setq prp (strcase prp))
    (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'allowedvalues)))
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)

;-------------------------------------------------------------------------------;
;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
    (setq prp (strcase prp))
    (vl-some
       '(lambda ( x )
            (if (= prp (strcase (vla-get-propertyname x))) 
                (progn
                    (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                    (cond (val) (t))
                )
            )
        )
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)

(defun LM:getvisibilitystate ( blk / vis )
    (if (setq vis (LM:getvisibilityparametername blk))
        (LM:getdynpropvalue blk vis)
    )
)


;; Get Dynamic Block Property Value  -  Lee Mac
;; Returns the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)

(defun LM:getdynpropvalue ( blk prp )
    (setq prp (strcase prp))
    (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'value)))
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)



0 Likes
Accepted solutions (2)
1,273 Views
12 Replies
Replies (12)
Message 2 of 13

paullimapa
Mentor
Mentor

Answering your last two questions

 

Q2. I noticed that this method creates many anonymous blocks (*U22, *U23, *U123, etc.). Could this be the reason why performance degrades over time? It starts fast but becomes progressively slower.

A2: When dynamic blocks are used, AutoCAD stores the different visibility states using different block names (*U22, *U23, *U123, etc.). But since they all do reference the same block definition, this should not be the reason for the slowness as more of them are inserted from the CSV.

 

Q3.If the block definition is not already present in the drawing and exists only in an external file (e.g., C://example//PNT_IMPORT.dwg), what would be the best approach to handle this efficiently?

A3: You can use AutoCAD 2021+'s built-in -INSERTCONTENT command to bring a block in that's located inside another dwg such as PNT_IMPORT.dwg

AutoCAD documentation:

https://help.autodesk.com/view/ACDLT/2022/ENU/?guid=GUID-B5D64510-561E-4FA9-8AD6-625445CCD81F

Thread demonstrating usage:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/quot-insertcontent-quot-not-function...


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 3 of 13

Sea-Haven
Mentor
Mentor

Also posted at AutoCAD Performance Issue When Inserting Large Number of Blocks via Script.

 

Made some suggestions to try, as @paullimapa suggested no check for does block exist. If not maybe do a message or at end display all block names not found.

 

 

 

Message 4 of 13

frjuniornogueira1
Participant
Participant

@paullimapa,

I'm already using something similar. Currently, I'm using the "_.insert" command and running the loop as shown in the attachment.

Even so, I'll test your suggestion to see if I can get any performance improvement.

Thank you for your contribution!

@Sea-Haven ,

I saw and tested your answer on the other forum, but unfortunately I didn't get any performance gain.

From what I observed, the main problem is really the insertion speed. When the volume is large, the process starts quickly, but as the number of blocks increases, it becomes progressively slower.

I'm considering splitting the CSV into parts (1/3, 2/3, 3/3...) and running it in stages as an alternative solution.

However, before doing that, I'd like to know if anyone has another suggestion or a more efficient approach.

0 Likes
Message 5 of 13

Sea-Haven
Mentor
Mentor

Read Theswamp post for more suggestions.

0 Likes
Message 6 of 13

CADaSchtroumpf
Advisor
Advisor
Accepted solution

@frjuniornogueira1  a écrit :

I’m experiencing a performance issue when inserting a large number of blocks into AutoCAD using the script below.

The script works perfectly — it correctly inserts the blocks, sets the insertion point, and adjusts the visibility state as expected. However, when I try to insert a large number of blocks (for example, using the attached CSV file), the process becomes extremely slow and can take several hours to complete.

I have a few questions:

  1. Is there a way to improve performance and make the insertion process faster?

  2. I noticed that this method creates many anonymous blocks (*U22, *U23, *U123, etc.). Could this be the reason why performance degrades over time? It starts fast but becomes progressively slower.

  3. If the block definition is not already present in the drawing and exists only in an external file (e.g., C://example//PNT_IMPORT.dwg), what would be the best approach to handle this efficiently?

I’ve attached a sample DWG and CSV file for reference.

Thank you in advance for your help.


Is there a way to improve performance and make the insertion process fasterHi,
I suggest another way.
I consider that the use of visibility on a block, in your case, is not really useful...
My way is to use standard blocks (4 blocks), but that's just my point of view.
Nevertheless, the use of blocks with a visibility option will greatly increase the weight of the file (and the implementation) and I don't think you will try to change the visibility on about 88000 blocks...
If you try my code in a new drawing, it will only take about 4 minutes to set up the blocks (in my case)
You just need to select your CSV file after running the IMPORT command.

 

Message 7 of 13

frjuniornogueira1
Participant
Participant

@CADaSchtroumpf This approach — and especially the speed — is simply outstanding!

For me, the insertion time was under 4 minutes, which is an excellent result.

However, I need to insert dynamic blocks (the attached block is just an example).

I’ve already tried a few different approaches, but the performance result remains practically the same.

Here’s what I’ve tested so far:

  • Used a loop to insert the attributes (method below);

  • Tried using vla-purgeall;

Unfortunately, the performance difference was almost imperceptible.

My question is: is there any way to improve performance — even slightly — when working with dynamic blocks?
As it stands, the process ends up taking almost an entire day to complete the insertions.

I honestly believe there must be a more optimized way to handle this — perhaps a different approach that I’m not considering.

(defun imp:insertblock-fast (target-space nomebloco ponto atributos / blk atts i)
  ;; 1. Inserção direta no espaço já fornecido (evita checar CVPORT toda vez)
  (setq blk (vla-insertblock target-space (vlax-3d-point ponto) nomebloco 1.0 1.0 1.0 0.0))
  
  ;; 2. Visibility State - Só chama se houver mudança necessária
  ;; Nota: Se muitos blocos tiverem o mesmo estado, o AutoCAD tenta reaproveitar o bloco anônimo.
  (if (and LM:setvisibilitystate (car atributos)) 
    (LM:setvisibilitystate blk (car atributos))
  )

  ;; 3. Atributos - Otimização de loop (evita o uso exaustivo de 'nth')
  (if (and (= (vla-get-hasattributes blk) :vlax-true) (cdr atributos))
    (progn
      (setq atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk))))
      (setq i 0)
      ;; Usamos um foreach nos valores para evitar percorrer a lista 'atts' com 'nth' 17 vezes por bloco
      (foreach val (cdr atributos)
        (if (and (< i (length atts)) val)
          (vla-put-textstring (nth i atts) (vl-princ-to-string val))
        )
        (setq i (1+ i))
      )
    )
  )
  blk
)
0 Likes
Message 8 of 13

CodeDing
Mentor
Mentor
Accepted solution

@frjuniornogueira1 ,

 

I got my version to complete in under 2 minutes. Hopefully it works well for you also. See attached lsp file.

 

But, honestly it could be MUCH faster if we could avoid one block with multiple visibilities like @CADaSchtroumpf suggested.

 

Best,

~DD

Message 9 of 13

frjuniornogueira1
Participant
Participant

It turned out very well, @CodeDing . In the end, I managed to solve it another way.

What I did was create a “Master Block” (template) for each visibility state and then use the vla-copy command. Since the object is already fully configured, copying it is practically instantaneous because AutoCAD doesn’t need to recalculate or reapply the visibility parameters.

With this approach, the total processing time dropped to around three minutes.

Message 10 of 13

norman.yuan
Mentor
Mentor

While there are 2 replies have been accepted as solution, I think things are quite clear: it is not the code that inserting the block (regardless of that the block definition already exists in the drawing, or the block definition has to be inserted into the drawing from a block dwg file), be the code as LISP/VBA/.NET API..., that causes the performance issue/the slowness. It is DEFINITELY BECAUSE OF the block being dynamic block with properties that could have different property values, especially in your case that the block has visibility parameter with many visibility states. If the drawing contains large number of this type of dynamic block,  inserting the block or setting its dynamic property or properties is bound to be really slow. My guess the slowness while setting the dynamic property value (visibility state, in your case) is that AutoCAD does things like this:

 

When a dynamic property (visibility state, in your case) is set to a newly inserted block, instead of creating an anonymous block definition, AutoCAD would first search all the anonymous block definition created based on the block definition to found a match. If no match found, then AutoCAD create a new anonymous block definition, than assign the newly inserted block reference to the matched (existing, or newly created) anonymous block definition. The reason for AutoCAD doing this, again, it is my guess, is to try to create anonymous block definition as less as possible, in order to prevent bloated drawing file size, in comparison to always create anonymous block definition every time a dynamic property value is set, even a suitable anonymous block definition already exist.

 

So, the rule of thumb is that that while dynamic block offers great flexibility of block design, one should avoid using large number of block references of the same dynamic block with many property values options for performance reason.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 11 of 13

CADaSchtroumpf
Advisor
Advisor

By taking up the excellent idea of @CodeDing  (copy the block), I can offer this version adapted only to your CSV file.
To do this, the block must be defined in the insertion drawing for a good execution.
The processing time is equivalent to my first proposal.

(defun make_blk_u (vis_blk / block val atts)
  (setq block
    (vla-insertblock
      Space
      (vlax-3D-point (trans'(0 0 0) 1 0))
      "PNT_IMPORT"
      1.0 1.0 1.0 0.0
    )
  )
  (vl-some
    '(lambda (x)
      (and
        (= (vla-get-propertyname x) "Visibility1")
        (setq val (vlax-get x 'Value))
        (or
          (vlax-put x 'Value vis_blk)
          t
        )
      )
     )
    (vlax-invoke block 'getdynamicBlockproperties)
  )
  (setq atts (vlax-safearray->list (vlax-variant-value (vla-getAttributes block))))
  (mapcar
    '(lambda (a v)
      (vla-put-TextString a v)
    )
    atts
    (list "" "" "" "" "" "")
  )
  block
)
(defun import:BlkInsert-Short (nam_blk pt_ins vis_blk info1 info2 info3 info4 info5 info6 / blk_cp val atts)
  (mapcar '(lambda (x y) (if (= vis_blk x) (setq blk_cp (vla-copy (eval (read y)))))) '("PNT" "PNTTR" "PNTCH" "OCULTO") '("blk1" "blk2" "blk3" "blk4"))
  (vla-Move blk_cp (vlax-3D-point (trans'(0 0 0) 1 0)) (vlax-3D-point (trans pt_ins 1 0)))
  (setq atts (vlax-safearray->list (vlax-variant-value (vla-getAttributes blk_cp))))
  (mapcar
    '(lambda (a v)
      (vla-put-TextString a v)
    )
    atts
    (list info1 info2 info3 info4 info5 info6)
  )
)
(defun get_dyn_property_by_name (dyn_property_name insert_object / dyn_property_found)
  (if (vl-some '(lambda (dyn_property) (= dyn_property_name (vla-get-propertyname (setq dyn_property_found dyn_property))))
          (vlax-invoke insert_object 'getdynamicblockproperties)
    )
    dyn_property_found
    nil
  )
)
(defun set_dyn_property (dyn_property_name value obj / stamp_property)
  (if (setq stamp_property (get_dyn_property_by_name dyn_property_name obj)) 
    (vla-put-value stamp_property value)
  )
)
(defun c:my_demo ( / AcObj AcDoc Space input f_open block first l_read nam_blk visib info1 info2 info3 info4 info5 info6 x_data y_data new_pt blk1 blk2 blk3 blk4)
    (setq
    AcObj (vlax-get-acad-object)
    AcDoc (vla-get-ActiveDocument AcObj)
    Space
    (if (= 1 (getvar "CVPORT"))
      (vla-get-PaperSpace AcDoc)
      (vla-get-ModelSpace AcDoc)
    )
  )
  (setq
    input (getfiled "Select CSV file" "" "csv" 2)
    f_open (open input "r")
  )
  (read-line f_open)
;(command "_.zoom" "_c" '(7651892.1534 209550.3199 0.0000) 31157.4340)
  (mapcar '(lambda (x y) (set (read (strcat "blk" x)) (make_blk_u y))) '("1" "2" "3" "4") '("PNT" "PNTTR" "PNTCH" "OCULTO"))
  (while (setq l_read (read-line f_open))
    (setq
      nam_blk (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      visib (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info1 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info2 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info3 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info4 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info5 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info6 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      x_data (atof (substr l_read 1 (vl-string-position 59 l_read)))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      y_data (atof (substr l_read 1 (vl-string-position 59 l_read)))
      new_pt (list x_data y_data 0.0)
    )
    (import:BlkInsert-Short 
      "PNT"
      new_pt
      visib
      info1
      info2
      info3
      info4
      info5
      info6
    )
  )
  (close f_open)
  (mapcar 'vla-delete (mapcar 'eval '(blk1 blk2 blk3 blk4)))
  (prin1)
)
Message 12 of 13

Sea-Haven
Mentor
Mentor

Just a comment you can read Excel direct no need to write a CSV, given large row number not sure if it will slow down process. 

 

Just read a row here (read-line f_open) (readcell myxl "AX") where X is row number. You can auto get the max row of an Excel via lisp.

 

Will give it a try when have time.

0 Likes
Message 13 of 13

Sea-Haven
Mentor
Mentor

 @CADaSchtroumpf Not sure if this will improve speed but may be worth trying. Not tested. Using a defun can sometimes speed up things and it is not recalculating l_read.

 

(while (setq l_read (read-line f_open))
    (setq
      nam_blk (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      visib (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info1 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info2 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info3 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info4 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info5 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      info6 (substr l_read 1 (vl-string-position 59 l_read))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      x_data (atof (substr l_read 1 (vl-string-position 59 l_read)))
      l_read (substr l_read (+ 2 (vl-string-position 59 l_read)))
      y_data (atof (substr l_read 1 (vl-string-position 59 l_read)))
      new_pt (list x_data y_data 0.0)
    )
    (import:BlkInsert-Short 
      "PNT"
      new_pt
      visib
      info1
      info2
      info3
      info4
      info5
      info6
    )
  )
  (close f_open)

replace with
(while (setq l_read (read-line f_open))
    (setq lst (csv->lst l_read 59))
    (import:BlkInsert-Short  (nth 0 lst)(list (nth 8 lst)(nth 9 lst))(nth 1 lst)(nth 2 lst)(nth 3 lst)(nth 4 lst)(nth 5 lst)(nth 6 lst)(nth 7 lst))
    )
)
(close f_open)

Put this at start
; thanks to Lee-mac for this defun
(defun csv->lst (str ans / pos )
(if (setq pos (vl-string-position ans str))
    (cons (substr str 1 pos) (csv->lst (substr str (+ pos 2)) ans))
    (list str)
    )
)

@c 

0 Likes