Hi,
I tried to create a more generic function to have more flexibility in reading the source CSV file.
The essential is to have at least the X and Y coordinates defined in the CSV, but the file can also contain other data that can be imported as an attribute value (or not!)
The file must also have an identical structure in all its content and purge it of its header line if it has one: keep only the data.
The program will first expose the 1st line and you will be asked for each element, if it is a data for an attribute value, a place value (XY and / or Z), or if you want to ignore this value, this will also determine the position of the columns and therefore those to import.
The program will generate the block with the desired number of attributes and insert it into the drawing with the respective attributes.
; str2lst
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaine à transformer en liste
;; sep : le séparateur
;;
;; Exemples
;; (str2lst "a b c" " ") -> ("a" "b" "c")
;; (str2lst "1,2,3" ",") -> ("1" "2" "3")
(defun str2lst (str sep / pos)
(if (setq pos (vl-string-search sep str))
(cons
(substr str 1 pos)
(str2lst (substr str (+ (strlen sep) pos 1)) sep)
)
(list str)
)
)
(defun c:readCSV2BLK ( / input f_open l_read key_sep str_sep l_data l_ini count count_coor key_data x_data y_data z_data l_rmv l_var inc gab_l last_y l_str l_mes blk_scl pt)
(setq
input (getfiled "Select a CSV file" "" "csv" 2)
f_open (open input "r")
l_read (read-line f_open)
)
(close f_open)
(initget "SPace Comma SEmicolon Tabulation")
(setq key_sep (getkword "\nSeparator [SPace/Comma/SEmicolon/Tabulation]? <SEmicolon>: "))
(cond
((eq key_sep "SPace") (setq str_sep " "))
((eq key_sep "Comma") (setq str_sep ","))
((eq key_sep "Tabulation") (setq str_sep "\t"))
(T (setq str_sep ";"))
)
(setq l_data (str2lst (vl-string-right-trim str_sep l_read) str_sep) count 0 count_coor 0 l_ini "Data Xlocation Ylocation Zlocation Ignore")
(foreach el l_data
(initget 1 l_ini)
(setq key_data (getkword (strcat "\nElement " el " is [" (vl-list->string (subst 47 32 (vl-string->list l_ini))) "]?: ")))
(cond
((eq key_data "Xlocation") (setq x_data count_coor l_ini (vl-string-subst "" (strcat " " key_data) l_ini) l_rmv (cons (if l_rmv (+ count (length l_rmv)) count) l_rmv) count (1- count)))
((eq key_data "Ylocation") (setq y_data count_coor l_ini (vl-string-subst "" (strcat " " key_data) l_ini) l_rmv (cons (if l_rmv (+ count (length l_rmv)) count) l_rmv) count (1- count)))
((eq key_data "Zlocation") (setq z_data count_coor l_ini (vl-string-subst "" (strcat " " key_data) l_ini) l_rmv (cons (if l_rmv (+ count (length l_rmv)) count) l_rmv) count (1- count)))
((eq key_data "Ignore") (setq l_rmv (cons (if l_rmv (+ count (length l_rmv)) count) l_rmv) count (1- count)))
(T
(set (read (strcat "DATA" (itoa count))) count)
(setq l_var (cons (read (strcat "DATA" (itoa count))) l_var))
)
)
(setq count (1+ count) count_coor (1+ count_coor))
)
(cond
((and (numberp x_data) (numberp y_data))
(setq count 0 inc (/ 5.0 3.0) gab_l (length l_var))
(mapcar
'(lambda (x y / )
(if (not (tblsearch "LAYER" x))
(entmake
(list
'(0 . "LAYER")
'(100 . "AcDbSymbolTableRecord")
'(100 . "AcDbLayerTableRecord")
(cons 2 x)
'(70 . 0)
(cons 62 y)
'(6 . "Continuous")
'(290 . 1)
'(370 . -3)
)
)
)
)
'("CSV2BLK" "CSV2BLK_x-y" "CSV2BLK_z" "CSV2BLK_ATT")
'(1 3 3 4)
)
(if (not (tblsearch "STYLE" "$CSV2BLK"))
(entmake
'(
(0 . "STYLE")
(5 . "40")
(100 . "AcDbSymbolTableRecord")
(100 . "AcDbTextStyleTableRecord")
(2 . "$CSV2BLK")
(70 . 0)
(40 . 0.0)
(41 . 1.0)
(50 . 0.0)
(71 . 0)
(42 . 2.5)
(3 . "arial.ttf")
(4 . "")
)
)
)
(if (not (tblsearch "BLOCK" "CSV2BLK"))
(progn
(entmake
'((0 . "BLOCK") (2 . "CSV2BLK") (70 . 2) (8 . "0") (62 . 0) (6 . "ByBlock") (370 . -2) (10 0.0 0.0 0.0))
)
(setq last_y 0.0 count -1 l_str nil l_mes nil)
(mapcar
'(lambda (tag mes / )
(entmake
(list
'(0 . "ATTDEF")
'(67 . 0)
'(8 . "0")
'(62 . 0)
'(6 . "ByBlock")
'(370 . -2)
(cons 10 (list 1.0 last_y 0.0))
'(40 . 1.0)
'(1 . "")
'(50 . 0.0)
'(41 . 1.0)
'(51 . 0.0)
'(7 . "$CSV2BLK")
'(210 0.0 0.0 1.0)
(cons 3 mes)
(cons 2 tag)
'(70 . 0)
)
)
(setq last_y (+ last_y (- (* inc 2))))
)
(append (list "ID-X" "ID-Y" "ID-Z") (reverse (repeat (length l_var) (setq l_str (cons (strcat "DATA" (itoa (setq count (1+ count)))) l_str)))))
(append (list "Coordinate X: " "Coordinate Y: " "Coordinate Z: ") (repeat (length l_var) (setq l_mes (cons "Data: " l_mes))))
)
(entmake
'(
(0 . "POINT")
(67 . 0)
(8 . "0")
(62 . 0)
(6 . "ByBlock")
(370 . -2)
(10 0.0 0.0 0.0)
(210 0.0 0.0 1.0)
)
)
(entmake '((0 . "ENDBLK") (8 . "0") (62 . 0) (6 . "ByBlock") (370 . -2)))
)
)
(initget 2)
(if (not (setq blk_scl (getreal "\nBlock scale? <1>: "))) (setq blk_scl 1.0))
(setq f_open (open input "r"))
(while (setq l_read (read-line f_open))
(setq
l_data (str2lst (vl-string-right-trim str_sep l_read) str_sep)
pt (list (atof (nth x_data l_data)) (atof (nth y_data l_data)) (if z_data (atof (nth z_data l_data)) 0.0))
)
(if l_rmv
(foreach el l_rmv
(setq l_data
((lambda (n lst / i rtn)
(reverse
(progn
(setq i -1)
(foreach x lst
(if (/= n (setq i (1+ i)))
(setq rtn (cons x rtn))
)
)
rtn
)
)
)
el
l_data
)
)
)
)
(setq
count 0
l_var nil
)
(repeat gab_l
(set (read (strcat "DATA" (itoa count))) count)
(setq
l_var (cons (read (strcat "DATA" (itoa count))) l_var)
count (1+ count)
)
)
(foreach n l_var
(set n (nth (eval n) l_data))
)
(entmake
(append
'(
(0 . "INSERT")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "CSV2BLK")
(100 . "AcDbBlockReference")
(66 . 1)
(2 . "CSV2BLK")
)
(list
(cons 41 (* 1.0 blk_scl))
(cons 42 (* 1.0 blk_scl))
(cons 43 (* 1.0 blk_scl))
)
'(
(50 . 0.0)
(70 . 0)
(71 . 0)
(44 . 0.0)
(45 . 0.0)
)
(list (cons 10 pt) '(210 0.0 0.0 1.0))
)
)
(setq last_y (+ (cadr pt) (* blk_scl (+ inc))) count 0 l_str nil l_mes nil)
(mapcar
'(lambda (val tag lay / )
(entmake
(append
(list
'(0 . "ATTRIB")
'(100 . "AcDbEntity")
'(67 . 0)
'(410 . "Model")
'(8 . "CSV2BLK_x-y")
'(100 . "AcDbText")
)
(list
(cons 8 lay)
(cons 10 (list (+ (car pt) (* blk_scl 1.0)) (setq last_y (+ last_y (* blk_scl (- inc)))) (caddr pt)))
(cons 1 val)
(cons 40 (* 1.0 blk_scl))
)
(list
'(50 . 0.0)
'(41 . 1.0)
'(51 . 0.0)
'(7 . "$CSV2BLK")
'(71 . 0)
'(72 . 0)
'(11 0.0 0.0 0.0)
'(210 0.0 0.0 1.0)
'(100 . "AcDbAttribute")
)
(list (cons 2 tag))
(list
'(70 . 0)
'(73 . 0)
'(74 . 0)
)
)
)
)
(append (list (rtos (car pt) 2) (rtos (cadr pt) 2) (rtos (caddr pt) 2)) (mapcar 'eval (reverse l_var)))
(append (list "ID-X" "ID-Y" "ID-Z") (reverse (repeat (length l_var) (setq l_str (cons (strcat "DATA" (itoa (setq count (1+ count)))) l_str)))))
(append (list "CSV2BLK_x-y" "CSV2BLK_x-y" "CSV2BLK_z") (repeat (length l_var) (setq l_mes (cons "CSV2BLK_ATT" l_mes))))
)
(entmake '((0 . "SEQEND") (8 . "CSV2BLK") (62 . 0) (6 . "ByBlock") (370 . -2)))
)
(close f_open)
)
(T (princ "\nNo coordinates introduced, implementation impossible!"))
)
(mapcar '(lambda (x) (eval (set x nil))) l_var)
(prin1)
)