Jump to content

Import multiple unique blocks from csv


Robert89

Recommended Posts

Hi everyone,

 

First of all, thanks for the information given thus far, this forum has been both helpful and frustrating. It's like being surrounded by people who are running and jumping while I can barely crawl. :lol:

 

I'm looking for a lisp routine to insert unique blocks from a csv. Every routine/app I've encountered is limited to 1 specific blocktype. The csv would contain the following info (not necessarily in this order):

Blockname;x;y;z;layer;rotation;attribute1;attribute2;attribute3

Unique layers would be useful but not necessary, might not be worth the extra hassle.

 

Really hoping I missed an existing routine.

Thanks in advance!

Link to comment
Share on other sites

  • Replies 22
  • Created
  • Last Reply

Top Posters In This Topic

  • BIGAL

    7

  • Robert89

    7

  • pBe

    5

  • halam

    3

Top Posters In This Topic

Posted Images

Just what do you mean by "limited to 1 specific blocktype" ?

 

Sorry, not used to proper terminology.

 

I meant 1 block per list execution. Everything I've come across allows you to insert a specific block on multiple insertion points. I'd like to specify a blockname on every insertion point.

Hope that clears it up for you.

Link to comment
Share on other sites

1st step is to convert the csv file to multiple lists, Then it easy to just pull out all the answers from the new list, something like this.

 

; ; thanks to Lee-mac for this defun
(defun _csv->lst ( str / pos x lst lst2)
(if (setq pos (vl-string-position 44 str))
   (cons (substr str 1 pos) (_csv->lst (substr str (+ pos 2))))
   (list str)
   )
)

(defun c:ins->csv ( / fo x)
(setq fo (open (getfiled "Choose CSV file" "G:/AutoCAD/Lisp/" "CSV" ) "R")
(while (setq ans (read-line fo))
(setq lst (cons (_csv->lst ans) lst))
)
(setq y (length lst)) 
(setq x (- y 1))
(repeat y
(setq lst2 (nth x lst))
;(setvar 'clayer (nth 6 lst2))
(command "insert" (nth 0 lst2) (strcat (nth 1 lst2)","(nth 2 lst2)","(nth 3 lst2)) 1 (nth 5 lst2) (nth 7 lst2) (nth 8 lst2))
(setq x (- x 1))
)

) ; end defun

Edited by BIGAL
Link to comment
Share on other sites

Sorry, not used to proper terminology.

 

No need to apologize, its me who is not understanding the terminology

 

 

(setq fo (getfiled "Choose CSV file" "" "CSV"  "R")
(setq lst '())
(while (setq ans (read-line fo))
(setq lst (cons (_csv->lst ans) lst))
)

 

Missing something there BIGAL

 

  	(setq fo (getfiled "Choose CSV file" "" "CSV" 16))
[b](setq fo (open fo  "R"))[/b]
(while (setq ans (read-line fo))
  (setq lst (cons (_csv->lst ans) lst))
)

Link to comment
Share on other sites

Thanks for your input.:)

 

Encountering a few issues though...

 

This is how I set-up my test csv:

Block;x;y;z;scale;rotation;layer;att1;att2

DW_L_TL;0;0;0;1;;;;

DW_L_TL;0;5;0;1;;;;

DW_L_TL;0;10;0;1;;;;

 

I've added a ")" changed the list order a bit and canceled the layer part for now:

; ; thanks to Lee-mac for this defun
(defun _csv->lst ( str / pos )
(if (setq pos (vl-string-position 44 str))
   (cons (substr str 1 pos) (_csv->lst (substr str (+ pos 2))))
   (list str)
   )
)

 	(setq fo (getfiled "Choose CSV file" "" "CSV" 16))
(setq fo (open fo  "R"))
(while (setq ans (read-line fo))
  (setq lst (cons (_csv->lst ans) lst))
)

(repeat (setq x (- (length lst) 1))
(setq lst2 (nth x lst))
[color="lime"];(setvar 'clayer (nth 6 lst2))[/color]
(command "insert" (nth 0 lst2) (list (nth 1 lst2)(nth 2 lst2)(nth 3 lst2)) 1 (nth 5 lst2) (nth 7 lst2) (nth 8 lst2)
(setq x (- x 1))
)
[color="lime"])[/color]

 

This gives me the following error:

insert Enter block name or [?] : DW_L_TL;0;5;0;1;;;; Warning: If you are trying to insert the file: DW_L_TL;0;5;0;1;;;;

it must be inserted using the = syntax.

 

Did I mess something up? It doesn't seem to recognize the column delimiters.

Another thing I've noticed is that this routine adds every execution to the previous one, is there a way to "swipe" the current information?

 

@BIGAL

Blocks and layers both exist, for now anyway. Haven't figured out how to properly set-up my library yet, so don't want to get ahead of myself.

Link to comment
Share on other sites

Thanks Pbe just copy/pasted and typed it did not test as no user data.

 

Robert89 will test later today now I have your sample csv, if reading this use -insert stops the file dialouge.

 

Gone fishing for a little while, have to get the priorities right.

 

I will add the layer and block check.

Edited by BIGAL
Link to comment
Share on other sites

Thanks for your input.:)

 

Encountering a few issues though...

...

 

This gives me the following error:

 

insert Enter block name or [?] : DW_L_TL;0;5;0;1;;;; Warning: If you are trying to insert the file: DW_L_TL;0;5;0;1;;;;

it must be inserted using the = syntax.

 

You are supplying "DW_L_TL;0;5;0;1;;;;" as the block name instead of just "DW_L_TL"

 

3 things

 

_csv->lst sub routine is checking for ascii character 44 which represents the ","

- Try to figure out the code for ";" that were used on your csv file as a delimiter.

 

The specified number on repeat is 1 less than the list

- Leave length lst as it is then try to subtract 1 on or before you assign variable lst2 from lst OR consider using foreach

 

 

The coordinate specified on the comand line is a list with string elements

- Either use strcat to build the list OR convert 2nd , 3rd & 4th element of lst2 to real number

 

 

Other than that you're good to go

Link to comment
Share on other sites

I was using this long back. It will work on any block as you select the reference block at start

 

(DEFUN C:IMPORTBLK (/ *ERROR* INBLOCK STR->LIST A B BK C C1 D X)
 (VL-LOAD-COM)

 ;;********************************************************************************************;;
 ;;****************************************  UTILITIES ****************************************;;
 ;;********************************************************************************************;;

 (DEFUN *ERROR* (MSG)
   (IF	(NOT
  (WCMATCH (STRCASE MSG T) "*BREAK,*CANCEL*,*EXIT*")
)
     (PRINC "")
   )
   (PRINC)
 )
 (DEFUN INBLOCK (POINT BLOCKNAME XSCALE YSCALE ZSCALE ROTATION)
   (VLA-INSERTBLOCK
     (VLA-GET-MODELSPACE
(VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT))
     )
     (VLAX-3D-POINT POINT)
     BLOCKNAME
     XSCALE
     YSCALE
     ZSCALE
     ROTATION
   )
 )
 (DEFUN STR->LIST (STR / B)
   (FOREACH X (REVERSE (VL-STRING->LIST STR))
     (COND ((EQ X 44) (SETQ B (CONS (LIST X) B)))
    (T
     (IF (NOT B)
       (SETQ B (CONS (LIST X) B))
       (SETQ B (CONS (CONS X (CAR B)) (CDR B)))
     )
    )
     )
   )
   (MAPCAR '(LAMBDA (X) (VL-LIST->STRING (VL-REMOVE 44 X))) B)
 )

 ;;********************************************************************************************;;
 ;;**************************************  MAIN PRAGRAM ***************************************;;
 ;;********************************************************************************************;;

 (IF
   (AND (SETQ
   A (OPEN (GETFILED "Select Data File" "C:/" "CSV;TXT" 4) "r")
 )
 (SETQ
   BK (VLAX-ENAME->VLA-OBJECT (CAR (ENTSEL "\nSelect Block : ")))
 )
   )
    (PROGN
      (SETQ C (WHILE (SETQ B (READ-LINE A))
	 (SETQ C (CONS (STR->LIST B) C))
       )
      )
      (CLOSE A)
      (SETQ C (CDR (REVERSE C)))	; REMOVE HEADER
      (ACET-UI-PROGRESS-INIT "Plotting Blocks" (LENGTH C))
      (FOREACH	X C
 (SETQ D (INBLOCK
	   (LIST (ATOF (CAR X)) (ATOF (CADR X)) (ATOF (CADDR X)))
	   (VLA-GET-EFFECTIVENAME BK)
	   1
	   1
	   1
	   0
	 )
       X (CDDDR X)
 )
 (IF (EQ (VLA-GET-HASATTRIBUTES BK) :VLAX-TRUE)
   (MAPCAR '(LAMBDA (Y)
	      (VLA-PUT-TEXTSTRING Y (CAR X))
	      (SETQ X (CDR X))
	    )
	   (VLAX-INVOKE D 'GetAttributes)
   )
 )
 (ACET-UI-PROGRESS-SAFE
   (IF (NOT C1)
     (SETQ C1 1)
     (SETQ C1 (1+ C1))
   )
 )
      )
      (ACET-UI-PROGRESS-DONE)
    )
 )
 (VL-CMDF "ZOOM" "E")
 (PRINC)
)

Link to comment
Share on other sites

You are supplying "DW_L_TL;0;5;0;1;;;;" as the block name instead of just "DW_L_TL"

 

3 things

 

_csv->lst sub routine is checking for ascii character 44 which represents the ","

- Try to figure out the code for ";" that were used on your csv file as a delimiter.

 

The specified number on repeat is 1 less than the list

- Leave length lst as it is then try to subtract 1 on or before you assign variable lst2 from lst OR consider using foreach

 

 

The coordinate specified on the comand line is a list with string elements

- Either use strcat to build the list OR convert 2nd , 3rd & 4th element of lst2 to real number

 

 

Other than that you're good to go

 

Took a while for my post to get through "customs", so I couldn't share my progress.

 

1. Figured that out, there was no specific reason for using ; just thought the routine required that character at first, changed it to ",". Aye, ; = 59 :)

2. Can't get this to work, just trial and error cause I don't understand it yet.

3. This part works now :)

 

So it's the "repeat" part which makes a mess of it atm. It's also not wiping the repeat variable causing it to add up every time I rerun the routine. Tried stopping it by localizing the variables, but that didn't help. Running it the first time gives me the first 2 lines, then 5, 8, etc.

 

; ; thanks to Lee-mac for this defun
(defun _csv->lst ( str / pos x lst lst2)
(if (setq pos (vl-string-position 44 str))
   (cons (substr str 1 pos) (_csv->lst (substr str (+ pos 2))))
   (list str)
   )
)
(setq fo (getfiled "Choose CSV file" "G:/AutoCAD/Lisp/" "CSV" )
(setq fo (open fo  "R"))
(while (setq ans (read-line fo))
(setq lst (cons (_csv->lst ans) lst))
)

(repeat (setq x (- (length lst) 1))
(setq lst2 (nth x lst))
;(setvar 'clayer (nth 6 lst2))
(command "insert" (nth 0 lst2) (strcat (nth 1 lst2)","(nth 2 lst2)","(nth 3 lst2)) 1 (nth 5 lst2) (nth 7 lst2) (nth 8 lst2))
(setq x (- x 1))
)

Link to comment
Share on other sites

 

So it's the "repeat" part which makes a mess of it atm. It's also not wiping the repeat variable causing it to add up every time I rerun the routine. Tried stopping it by localizing the variables, but that didn't help. Running it the first time gives me the first 2 lines, then 5, 8, etc.

 

 

Make sure lst variable is localize, variable x is definitely "reset"

 

(setq lst '("Robert89" "BIGAL"  "satishrajdev" "pBe"))

(repeat (setq x (length lst))			; <-- repeat as the same number of items on the list
 	(print (nth (setq x (1- x)) lst))	; x is now 3 on the first run | fourth element of the list
 								; x is now 2 on the second run | third element of the list
 								; x is now 1 on the....
 (princ)
 		)

 

;;; no need for index/counter | also wiping out values for lst variable ;;;

 

(while (setq a (Car lst))			; a as first element of the list
 	(print a)
(setq lst (Cdr lst))			; lst is redefined as list less the first element
 (princ)
 )

 

or simply

 

;;; no need for counter ;;;

 

  	(Foreach itm lst
  (print itm)
  (princ)
  )

 

HTH

Link to comment
Share on other sites

Because the list is made up of sub lists need to repeat for number of items in the master list but the inside list starts at zero. Just forgot all about that.

 

CODE updated above in my 1st post

Edited by BIGAL
Link to comment
Share on other sites

Thanks for the input! I won't be able to try your suggestions till thursday (network licence and vpn isn't working), but lets just say the plot is thickening. :)

 

Because the list is made up of sub lists need to repeat for number of items in the master list but the inside list starts at zero. Just forgot all about that.

 

CODE updated above in my 1st post

 

Getting a bit sloppy there BIGAL :lol:

Link to comment
Share on other sites

I was just kidding BIGAL, you're all doing me a solid, would be insane to complain about that.

 

I'm restructering the way I work because another colleague is switching to AutoCAD (I was the only user).

This means there's no relevant data to be shown yet, there's just some basic functionality we really need, the rest can (mostly) be shaped around it.

 

He's a land surveyor, hence the need to directly import csv's.

Link to comment
Share on other sites

The following code seems to do the trick, thanks guys!

 

Added "curlayer" to return currentlayer to pre-routine state. And some comments so I actually know what's going on.

 

Is there anything to improve/streamline?

; ; thanks to Lee-mac for this defun
(defun _csv->lst ( str / pos )
(if (setq pos (vl-string-position 44 str))									;44 = "," delimiter
   (cons (substr str 1 pos) (_csv->lst (substr str (+ pos 2))))
   (list str)
   )
)
(defun c:csvins ( / fo lst curlayer )
(setq fo (getfiled "Choose CSV file" "G:/AutoCAD/Lisp/" "CSV" )			;File to open from
(setq fo (open fo  "R"))													;"R" = read
(while (setq ans (read-line fo))
(setq lst (cons (_csv->lst ans) lst))
)
(setq curlayer (getvar 'clayer))											;Save current layer
(Foreach itm lst
(setvar 'clayer (nth 6 itm))											;Set "insertion" layer
(command "insert" 
					(nth 0 itm)											;blockname to insert
					(strcat (nth 1 itm)","(nth 2 itm)","(nth 3 itm)) 	;x y z, strcat to combine 3 columns as string
					(nth 4 itm)											;scale
					(nth 5 itm) 										;rotation
					(nth 7 itm) 										;attribute 1
					(nth 8 itm))										;attribute 2
(setvar 'clayer curlayer)												;Return layer to old name
(princ)
)
) ; end defun

Link to comment
Share on other sites

The following code seems to do the trick, thanks guys!

 

Good for you Robert89 :thumbsup:

 

... Is there anything to improve/streamline?

 

What you need to consider are the following:

 

  • A test to check if the expressions evalautes to a none nil value to continue to evaluate the next one. (if / cond / and )
  • Closing the file opened for access (open / close )
  • A check if the block to be inserted is found ( tblsearch / findfile )
  • A check if the layer specified exists / ( Layer Make / New / Set )

 

Below is for you to figure out:

 

Set the current layer back to its pre-routine state only once

Set the osnap value to avoid messing up insertion point for the block

Look into the system variables that affect settings during insertion of blocks.

 

HTH

Link to comment
Share on other sites

Like Pbe write a little defun that checks for a layer exists on the fly, save this defun into an autoload lisp file then its available for any code that you write.

 

I have left a lot out so you can learn all the answers are in the links provided by Pbe.

(defun laycheck ( layname / )
(if (= (tblsearch........ )(vlax:true)
(princ "found")
else make layer here
)

 

; example checks if layer exists if not make it
(laycheck "fred")

Link to comment
Share on other sites

  • 11 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...