Read CSV and use values to insert and populate a block

186 views Asked by At

I'm attempting to write a code that will read a csv file, and for each line, spit out a block with the attributes defined using that csv. I seem to get errors no matter what I try, and AutoLISP is so very confusing to me despite plenty of prior programming knowledge. At first I tried using "vl-string-split" but AutoCAD told me that function doesn't exist (despite having VisualLISP). Next I tried using Lee Mac's read-csv code, and now I get an error of "too few arguments". I know I'm probably missing something very basic here, but I've hit my limit of searching forums for an answer that fits. If someone could kindly point this newb in the right direction it would be greatly appreciated!

Not sure if its relevant, but I'm using AutoCAD Map 3D 2020

(defun c:poleTest ()

;; 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
)
;; End of Lee Mac code
    (setq filePath (getfiled "Select CSV file" "" "csv" 0))
    (progn
(setq file (open filePath "r"))
        (while (setq line (LM:csv->lst file))
            (setq filePath "Z:\\Project Tools\\Customized Tools\\CAD\\prog\\BELL\\polebase1.dwg")
            (setq xyz "0,0,0")
            (setq scale "1,1,1")
            (setq height (car (last line)))
            (setq circ (car (nth 14 line)))
            (setq year (car (nth 13 line)))
            (setq txno (car (nth 12 line)))
            (setq ground (car (nth 17 line)))
            (setq slground (car (nth 18 line)))
            (setq pics (car (nth 6 line)))
            (setq poleno (car (nth 4 line)))
            (setq poleID (car (nth 5 line)))
            (setq owner (car (car line)))
            (princ filePath)
            (princ xyz)
            (princ scale)
            (princ height)
            (princ circ)
            (princ year)
            (princ txno)
            (princ ground)
            (princ slground)
            (princ pics)
            (princ poleno)
            (princ poleID)
            (princ owner)
            (command "insert" filePath xyz scale height circ year txno ground slground pics poleno poleID owner)

        )
    )
)
1

There are 1 answers

3
Lee Mac On

My LM:readcsv function will read the contents of a CSV file into a list of lists, which you can then iterate over (using a foreach loop, for example) in order to insert your blocks.

The issue with your current code is that you are calling my LM:csv->lst function, which requires three arguments: a string to be parsed, a delimiter character, and an initial character position (always 0). Instead, you should call my LM:readcsv function.

Consider the following code:

(defun c:poleTest ( / atr circ fnm ground height lst owner pics poleID poleno rot scl slground txno xyz year )
    (cond
        (   (not (setq fnm (getfiled "Select CSV file" "" "csv" 16)))
            (princ "\n*Cancel*")
        )
        (   (not (setq lst (LM:readcsv fnm)))
            (princ "\nError reading CSV file.")
        )
        (   t
            (setq blk "Z:\\Project Tools\\Customized Tools\\CAD\\prog\\BELL\\polebase1.dwg"
                  xyz '(0 0 0)
                  scl 1.0
                  rot 0.0
            )
            (setq atr (getvar 'attreq))
            (setvar 'attreq 1)
            (foreach row lst
                (setq height   (last   row)
                      circ     (nth 14 row)
                      year     (nth 13 row)
                      txno     (nth 12 row)
                      ground   (nth 17 row)
                      slground (nth 18 row)
                      pics     (nth  6 row)
                      poleno   (nth  4 row)
                      poleID   (nth  5 row)
                      owner    (nth  0 row)
                )
                (command 
                    "_.-insert" blk "_S" scl "_R" rot "_non" xyz
                    height circ year txno ground slground pics poleno poleID owner
                )
            )
            (setvar 'attreq atr)
        )
    )
    (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
)

(princ)