Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Importing survey data via csv to write multi attribute blocks into the correct layer for the rest of my LISPS to call on

33 REPLIES 33
SOLVED
Reply
Message 1 of 34
orourkestuart
3524 Views, 33 Replies

Importing survey data via csv to write multi attribute blocks into the correct layer for the rest of my LISPS to call on

Hi all, quick recap of where I'm at:

I've got a full suite of LISP routines for several different automated annotation and calculation tools which worked beautifully until I moved employer. Previously I have been dealing with Trimble survey data exchanged as dxf's and the data in that format gave me "DIAG_CROSS" blocks with the point attributes written into the block. Having moved companies I now find myself dealing with Leica and LisCAD and the only reliable way I have of extracting point data with an extensive attribute from the survey kit set is via csv.

What I need is a LISP to read in a csv and create a "DIAG_CROSS" block at each of the coordinates and generate 8 block attributes that match the points attribute tables, the last column in the csv contains the target layer designation for the block.

Attached are a sample dxf in the format I used to deal with, and a csv (saved as a txt since I can't attach a csv) of invented points in the format I'll be using, the headers in the csv are what I need the block attributes to be called in the block, which I can then call on with the rest of my LISP suite. Across the whole set of survey points the number of attributes will always be the same and be called the same.

The format of the csv is:

 

PtNo.,x,y,z,CODE,DEPTH,SIZE,MATERIAL,COMMONNOTES,END,NUMBEROF,METHOD,NOTES,LAYER,

 

and the attributes I need to be named and attached to the blocks are:

 

PtNo.,CODE,DEPTH,SIZE,MATERIAL,COMMONNOTES,END,NUMBEROF,METHOD,NOTES. I don't need the elevation as displayed in the dwg.

 

I've set the last value as a fixed value in the survey controller for each code, so the LISP can call on it to set the layer for the block insertion.

Thanks in advance

33 REPLIES 33
Message 2 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

..What I need is a LISP to read in a csv and create a "DIAG_CROSS" block at each of the coordinates and generate 8 block attributes that match the points attribute tables, the last column in the csv contains the target layer designation for the block.
..


Questions:

  • Do you want to maintain the DIAG_CROSS block definition at it is now? Its a non-attributed block.
  • What about colors? it doesnt show anywhere on the csv file, drawing sample shows colors as ByBlock.
  • AttDisp is OFF. so attributes are not invisble. is that by design?
  • DIAG_CROSS is inserted at scale 0.0010 for X, Y and Z. 

 

Message 3 of 34
orourkestuart
in reply to: pbejse

what I'm going to do is reauthor a block called "diag_cross" at an appropriate scale. When the Trimble controller wrote out the survey data I had to rescale them because the size of the block when it arrived in CAD varied depending on the screen scale on the controller when the dxf file was written. So if I'm going to do that I should probably write a "DIAG_CROSS" with the attributes already in it?

 

I'm not interested in the colour of the block after it's inserted, they act as the 'anchor' when I use my Mleader LISPS and provide the autopopulate with the text strings I need to write the text body in the leader, and as long as I've given the block "By Block" colour assignation it will just adopt the LAYER colour in my drawing template, even if it doesn't the blocks are removed into a single layer called "Survey points" at the end of the drafting process by a FJ extended command I use. As long as the blocks end up in the correct layer the Mleader LISP will drop the leader into the correct layer based on "LAYER"_TXT and my template is already set up to assign colours etc to the text.

 

Thx

Message 4 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

So if I'm going to do that I should probably write a "DIAG_CROSS" with the attributes already in it?


Preferably yes, BUT we can still work on its current state if redefining the block will cause to much trouble.

What ever makes the transfer of data from Trimble to cad easier for you. Its your call.

 


@orourkestuart wrote:

I'm not interested in the colour of the block after it's inserted, they act as the 'anchor' when I use my Mleader LISPS ..


 

One less thing to worry about then. Tell me once you decide what to do with the "DIAG_CROSS" block.

 

Message 5 of 34
orourkestuart
in reply to: pbejse

yeah, so I'll reauthor the block and give it attributes:

 

Pt

DEPTH

SIZE

MATERIAL

COMMONNOTES

END

NUMBEROF

METHOD

NOTES

 

Man you're totally saving my bacon here 🙂

 

Message 6 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

yeah, so I'll reauthor the block and give it attributes:


Settled then, post the block when your'e done "reauthoring" . Its an easy code and simple program

 

Message 7 of 34
hak_vz
in reply to: orourkestuart

Here is my starting code. Test it when you create block with attributes you described.

I didn't have time to create required block, so there may be some error that I can fix later.

 

(defun c:diag-cross-csv 
;hak_vz 11.20.2020
	( /
		*error* LM:str->lst  LM:vl-setattributevalue f file1 defs 
		restdefs x y z layer record
	)
	(defun *error* ()
		(setvar 'cmdecho 1)
		(close file1)
	)
	(defun LM:str->lst ( str del / pos )
		(if (setq pos (vl-string-search del str))
			(cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del))
			(list str)
		)
	)
	(defun LM:vl-setattributevalue ( blk tag val)
		(setq tag (strcase tag))
		(vl-some
		   '(lambda ( att )
				(if (= tag (strcase (vla-get-tagstring att)))
					(progn (vla-put-textstring att val) val)
				)
			)
			(vlax-invoke blk 'getattributes)
		)
	)
	
	(setvar 'cmdecho 0)
	(setq f (getfiled "Open csv file" (getvar "dwgprefix") "txt" 2) file1 (open f "r"))
	(setq defs (LM:str->lst (read-line file1) ","))
	(setq restdefs '("Pt" "CODE" "DEPTH" "SIZE" "MATERIAL" "COMMONNOTES" "END""NUMBEROF" "METHOD" "NOTES"))
	(while (setq record (read-line file1))
		(setq record (mapcar 'cons defs (LM:str->lst  record ",")))
		(setq x (atof(cdr (assoc "X" record))))
		(setq y (atof(cdr (assoc "Y" record))))
		(setq z (atof(cdr (assoc "Z" record))))
		(setq layer (cdr (assoc "LAYER" record)))
		(command "._layer" "_M" layer "")
		(setvar 'clayer layer)
		(command "-insert" "diag_cross" (list x y z) 1 1 0 "")
		(foreach value restdefs
			(LM:vl-setattributevalue (entlast) value (cdr (assoc value record)))
		)
	)
	(setvar 'cmdecho 1)
	(close file1)
	(princ "\nDone")
)
(princ "\nType DIAG-CROSS-CSV to run command")
(princ)

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 8 of 34
hak_vz
in reply to: orourkestuart

In attachment are three files i.e. updated code, test file, and dwg with diag_cross attribute defined.

 

Default x and y scale for block are set to 0.1.

In text file first line is all caps.

 

 

 

PT,X,Y,Z,CODE,DEPTH,SIZE,MATERIAL,COMMONNOTES,END,NUMBEROF,METHOD,NOTES,LAYER

 

 

 

 

 

 

(defun c:diag-cross-csv 
;hak_vz 11.21.2020
	( /
		*error* LM:str->lst  LM:vl-setattributevalue f file1 defs pt
		restdefs x y z layer record xscale yscale rotation attlist e0
	)
	(defun *error* ()
		(setvar 'cmdecho 1)
		(close file1)
	)
	(defun LM:str->lst ( str del / pos )
		(if (setq pos (vl-string-search del str))
			(cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del))
			(list str)
		)
	)
	(setq xscale (getreal "Block X scale <0.1> >"))
	(setq yscale (getreal "Block Y scale <0.1> >"))
	(setq rotation (getreal "Block rotation angle <0> >"))
	
	(initget "YES NO")
	(if (null (setq use_z(getkword "\nUse Z [Yes/No] <No> >")))
		(setq use_z "NO")
	)
	
	(if (not xscale) (setq xscale 0.1))
	(if (not yscale) (setq yscale 0.1))
	(if (not rotation) (setq rotation 0))
	(setvar 'cmdecho 0)
	(setvar 'ATTDIA 0)
	(setq f (getfiled "Open csv file" (getvar "dwgprefix") "txt" 2) file1 (open f "r"))
	(setq defs (LM:str->lst (read-line file1) ","))
	(setq restdefs '("PT" "CODE" "DEPTH" "SIZE" "MATERIAL" "COMMONNOTES" "END""NUMBEROF" "METHOD" "NOTES"))
	(while (setq record (read-line file1))
		(setq record (mapcar 'cons defs (LM:str->lst  record ",")))
		(setq x (atof(cdr (assoc "X" record))))
		(setq y (atof(cdr (assoc "Y" record))))
		(setq z (atof(cdr (assoc "Z" record))))
		(if (= use_z "NO") (setq pt (list x y))  (setq pt (list x y z)))
		(setq layer (cdr (assoc "LAYER" record)))
		(command "_.layer" "_M" layer "")
		(setvar 'clayer layer)
		(command "-insert" "diag_cross" pt xscale yscale rotation)
		(while (> (getvar 'cmdactive) 0) (command ""))
		(foreach value restdefs (setq attlist (cons (cons value (cdr (assoc value record))) attlist)))
		(foreach att (vlax-invoke (vlax-ename->vla-object (entlast)) 'getattributes)(if (setq itm (assoc (vla-get-tagstring att) attlist))(vla-put-textstring att (cdr itm))))
		(setq attlist nil)
	)
	(setvar 'cmdecho 1)
	(close file1)
	(setvar 'ATTDIA 1)
	(princ "\nDone")
)
(princ "\nType DIAG-CROSS-CSV to run command")
(princ)

 

 

 

 

 

Untitled.png

 

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 9 of 34
hak_vz
in reply to: hak_vz

After checking your sample dwg I think you should change values for xscale and yscale to 0.001.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 10 of 34
orourkestuart
in reply to: hak_vz

Gentlemen I couldn't thank you more for your contributions.

 

The LISP works perfectly 🙂

 

Apologies for you guys having to author the block on my behalf, by the time I realised you where trying to chase me up on it I was home with no CAD software, I only got the PM as I was faling into bed at midnight NZ time.

 

This has removed one of my biggest obstacles to my workflow for the immediate future TYVM

Message 11 of 34
hak_vz
in reply to: orourkestuart

@orourkestuart 

Check the code to see it works well with larger dataset. If there is something to add just ask. 

This was not such a big problem to code and  it can also be used in my practice.

 

If this is what you asked for accept my reply with autolisp code under #8 as a solution to this post.

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 12 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

Apologies for you guys having to author the block on my behalf,


I would have rather you create the block, so you get what you ask for kinda thing. My idea was maintain the color of the object to "bylock" so the program can still assign a color to differentiate the items visually even without a defined layer on the drawing, similar to your sample drawing. 

 

Anyway, i wanted to write something else entirely different, leave the blocks as it is [ non-attributed block ], and add attributes on the fly, it can be any of the blocks on your drawing and it can also add any attribute tags names from the csv.

(setq validBlocks
       '("BOX"		   "CIRCLE"	     "CROSS"
	 "DIAG_CROSS"	   "DOUBLE_CIRCLE"   "DOUBLE_TRIANGLE"
	 "STAKED_FLAG"	   "TRIANGLE"
	)
)

 

I had many plans to streamline your work.

For now we will apply the KISS principle.

(defun c:DiagCross ( / _DelTolst spc bname allData csv listOfTags Layer
		    	TagAndValue InsertedBlock layername)  
(defun _DelTolst ( str m / pos x lst lst2)
	(if (setq pos (vl-string-position m str))
	   (cons (substr str 1 pos) (_DelTolst (substr str (+ pos 2)) m ))
	   (list str)
	   )
)
(setq spc  (vlax-get (vla-get-ActiveLayout (vla-get-activedocument
                           (vlax-get-acad-object))) 'Block)
      bname "DIAG_CROSS")
  
(defun Layer (Nme)
  (entmake (list (cons 0 "LAYER")
                 (cons 100 "AcDbSymbolTableRecord")
                 (cons 100 "AcDbLayerTableRecord")
                 (cons 2 Nme)
                 (cons 70 0))))
  
(if (and
      (tblsearch "BLOCK" bname)
      (setq allData nil
	       csv (getfiled "Select data source" (getvar 'dwgprefix) "csv" 16))
      )
      (progn
  	(setq opf (open csv "r"))
	(setq NameAndTag (_DelTolst (read-line opf) 44))
	(setq listOfTags (cons (Car NameAndTag) (cddddr NameAndTag)))
	
	(while (setq data (read-line opf))
	(setq allData (cons (_DelTolst data 44) allData))
	)
	(close opf)
	(setq sc (if (zerop (getvar 'Luprec)) 1.0 0.001))	
	(foreach itm allData
	  (setq	pt
		 (mapcar 'atof (list (cadr itm) (caddr itm) (cadddr itm)))
	  )
	  (setq itm (cons (Car itm) (cddddr itm)))
	  (setq TagAndValue (mapcar 'cons listOfTags itm))
	  (setq	InsertedBlock
		 (vlax-invoke
		   spc 'InsertBlock pt bname sc sc sc 0)
	  )
	  (foreach att (Vlax-invoke InsertedBlock 'GetAttributes)
	    (if	(setq f (Assoc (strcase (vla-get-tagstring att)) TagAndValue)
		)
	      (Vla-put-textstring att (Cdr f))
	    )
	  )
	  (if (not (tblsearch "Layer" (setq lname (last itm))))
	    	(Layer lname))
	  (Vla-put-layer InsertedBlock lname)	  
	)
	)
  )
  (princ)
  )

The LUPREC system variable will dictate the size of the block. MM (0) M (any number except 0)).

The program is prompting for CSV extension instead of txt.

 

HTH

 

 

 

Message 13 of 34
orourkestuart
in reply to: pbejse

@ HAK_VZ, hey man I might have sent you wrong with my previous reply, when I run the LISP I think I missed the "too many arguments" prompt the first time and didn't realise. When I enter the attached file it inserts the first block but then stops and doesn't populate the block attributes, I get "too many arguments" in the command bar.

 

@pbejse, morning 🙂 Your script runs except I'm not getting the PT attribute populated. I've attached a .dwg that HAK_VZ was kind enough tom supply containing a diag_cross block in it that I will adopt as our own. 

Message 14 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

@pbejse, morning 🙂 Your script runs except I'm not getting the PT attribute populated. I've attached a .dwg that HAK_VZ was kind enough tom supply containing a diag_cross block in it that I will adopt as our own. 


Here you go.

 

(defun c:DiagCross ( / _DelTolst spc bname allData csv listOfTags Layer
		    	TagAndValue InsertedBlock layername)  
(defun _DelTolst ( str m / pos x lst lst2)
	(if (setq pos (vl-string-position m str))
	   (cons (substr str 1 pos) (_DelTolst (substr str (+ pos 2)) m ))
	   (list str)
	   )
)
(setq spc  (vlax-get (vla-get-ActiveLayout (vla-get-activedocument
                           (vlax-get-acad-object))) 'Block)
      bname "DIAG_CROSS")
  
(defun Layer (Nme)
  (entmake (list (cons 0 "LAYER")
                 (cons 100 "AcDbSymbolTableRecord")
                 (cons 100 "AcDbLayerTableRecord")
                 (cons 2 Nme)
                 (cons 70 0))))
  
(if (and
      (tblsearch "BLOCK" bname)
      (setq allData nil
	       csv (getfiled "Select data source" (getvar 'dwgprefix) "csv;txt" 16))
      )
      (progn
  	(setq opf (open csv "r"))
	(setq NameAndTag (_DelTolst (read-line opf) 44))
	(setq listOfTags (mapcar 'strcase (cons (Car NameAndTag) (cddddr NameAndTag))))
	
	(while (setq data (read-line opf))
	(setq allData (cons (_DelTolst data 44) allData))
	)
	(close opf)
	(setq sc (if (zerop (getvar 'Luprec)) 1.0 0.001))	
	(foreach itm allData
	  (setq	pt
		 (mapcar 'atof (list (cadr itm) (caddr itm) (cadddr itm)))
	  )
	  (setq itm (cons (Car itm) (cddddr itm)))
	  (setq TagAndValue (mapcar 'cons listOfTags itm))
	  (setq	InsertedBlock
		 (vlax-invoke
		   spc 'InsertBlock pt bname sc sc sc 0)
	  )
	  (foreach att (Vlax-invoke InsertedBlock 'GetAttributes)
	    (if	(setq f (Assoc (strcase (vla-get-tagstring att)) TagAndValue)
		)
	      (Vla-put-textstring att (Cdr f))
	    )
	  )
	  (if (not (tblsearch "Layer" (setq lname (last itm))))
	    	(Layer lname))
	  (Vla-put-layer InsertedBlock lname)	  
	)
	)
  )
  (princ)
  )

Now you can select either csv or txt

 

HTH

 

Think about if you want to pursue the other option of using the none attribute blocks?  Its a good alternative.

 

 

 

Message 15 of 34
orourkestuart
in reply to: pbejse

TY 🙂 VM

Message 16 of 34
pbejse
in reply to: orourkestuart


@orourkestuart wrote:

TY 🙂 VM


YAW 🙂 MP

Message 17 of 34
hak_vz
in reply to: orourkestuart

@pbejseYou've done nice work.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 18 of 34
pbejse
in reply to: hak_vz


@hak_vz wrote:

@pbejseYou've done nice work.


 

Thank you for saying that @hak_vz , you are not so bad yourself buddy. Keep up the good work. 

 

And if you liked that code, you would've flipped with what i had originally planned for the OP as mentioned on post # 12.

Too bad the OP did not sign off on it. 😊  

 

 

Message 19 of 34
hak_vz
in reply to: pbejse


@pbejse wrote:


.....you would've flipped with what i had originally planned for the OP as mentioned on post # 12.


Actually I was thinking about that option too. This is the way to go since blocks are than tailored for particular job.

As you say in other topic, generic solutions are better option.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 20 of 34
pbejse
in reply to: hak_vz


@hak_vz wrote

Actually I was thinking about that option too. This is the way to go since blocks are than tailored for particular job.


 

Have a go at it then, like you said on your other post "practice" and try to create your own sub functions as much as possible.

Happy coding Hak_vz.

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


AutoCAD Beta