Jump to content

Recommended Posts

Posted

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!

  • 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

Posted
Hi everyone,

I'm looking for a lisp routine to insert unique blocks from a csv.

 

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

Posted
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.

Posted (edited)

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
Posted
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))
)

Posted

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.

Posted (edited)

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
Posted
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

Posted

Some more hints

atof converts a string to real
(chr x) v;s (ascci "A")
then maybe a (OR function so you can look for ; or ,

Posted

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)
)

Posted

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))
)

Posted

 

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

Posted (edited)

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
Posted

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:

Posted

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.

Posted

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

Posted
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

Posted

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")

  • 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...