Import Block from exel help

Import Block from exel help

her5157
Explorer Explorer
1,439 Views
13 Replies
Message 1 of 14

Import Block from exel help

her5157
Explorer
Explorer

I have a really decent lisp for importing blocks from a csv file, however i want to modify it to be able to populate a single attribute value upon import. I have a csv file formatted as follows: (BLOCKNAME,x,y,z,ATTRIBUTEVALUE). I was able to modify the lisp to parse the list correctly, however i have been struggling with a solution to populate the attribute value.

The constraints that i must maintain are :

  • An existing CAD file where the block reference already exists in the drawing.
  • A Hardcoded CSV file location
  • The blocks can be different (example files contains only one block reference)
  • The attribute value can change for each block

The lisp is as follows:

(defun c:BLKCSV1	(/ SplitStr doc spc csv csv data bn)
  
  (defun SplitStr (s d / p)
    (if	(setq p (vl-string-search d s))
      (cons (substr s 1 p)
	    (SplitStr (substr s (+ p 1 (strlen d))) d)
      )
      (list s)
    )
  )
  
  (if (and (setq doc (vla-get-activedocument (vlax-get-acad-object))
		 spc (vla-get-block (vla-get-activelayout doc))
		 	   )
	   (setq csv (open "C:/Users/%username%/Documents/Drawing1.csv" "r"))
	   (read-line csv)
      );and

    (while (and	(setq data (read-line csv))
		(setq data (splitstr data ",")
		      bn   (car data)
                      ;;modified variable to get xyx
		      pnt  (cdr (reverse (cdr (reverse data))))
                      ;;added variable for attribute
		      att  (last data)
		)
	   )
	   
      (if (tblsearch "block" bn)
	(vla-InsertBlock
	  spc
	  (vlax-3d-point (mapcar 'atof pnt))
	  bn
	  1
	  1
	  1
	  0
	);insertblock
;;NOT WORKING
;(setq attributes (vlax-safearray->list (vlax-variant-value (vla-getAttributes bn))))
;; get the first attribute of the list to set its "value" (TextString property)
;(vla-put-TextString (car attributes) att) 
	
	);if

    );while
  
  );if
 
  (if csv
    (close csv)
  )
  (princ)
)

 

This lisp originated in a CAD forum, i think it was CAD tutor or something like that. I modified it to read the attribute value from the CSV but as i said, i cant figure out how to get the value to populate based on the csv.

The section marked ";;NOT WORKING" is a solution i found in the Autodesk forums, however it isn't working for me. Can anyone point me in the right direction here? Any help would be greatly appreciated.

 

0 Likes
Accepted solutions (2)
1,440 Views
13 Replies
Replies (13)
Message 2 of 14

hak_vz
Advisor
Advisor
Accepted solution

Try this. Since this is insert of single attribute block some checking are not needed, but

I've done it just for test. In attachment is modified csv.

 

(defun c:BLKCSV1	(/ LM:vl-setattributevalue SplitStr doc spc csv data ins bn att_name att_value)
	(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)
	)
	)
  (defun SplitStr (s d / p)
    (if	(setq p (vl-string-search d s))
      (cons (substr s 1 p)
	    (SplitStr (substr s (+ p 1 (strlen d))) d)
      )
      (list s)
    )
  )
  
  (if (and 
		(setq
			doc (vla-get-activedocument (vlax-get-acad-object))
			spc (vla-get-block (vla-get-activelayout doc))
			csv (open "C:/Users/%username%/Documents/Drawing1.csv" "r")
		)
      );and

    (while (and (setq data (read-line csv)))
		(mapcar 'set '(bn x y z att_name att_value) (SplitStr data ","))
		(cond
			((tblsearch "block" bn)
				(setq block
					(vla-InsertBlock
					  spc
					  (vlax-3d-point (mapcar 'atof (list x y z)))
					  bn
					  1
					  1
					  1
					  0
					)
				)
				(if(member att_name (mapcar '(lambda (x)(vlax-get x 'Tagstring)) (vlax-safearray->list (vlax-variant-value (vla-getAttributes block)))))
					(LM:vl-setattributevalue block att_name att_value)
				)
			)
		) 
    );while
  );if
  (if csv
    (close csv)
  )
  (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.
0 Likes
Message 3 of 14

pbejse
Mentor
Mentor
Accepted solution

@her5157 wrote:

The constraints that i must maintain are :

  • An existing CAD file where the block reference already exists in the drawing.
  • A Hardcoded CSV file location
  • The blocks can be different (example files contains only one block reference)
  • The attribute value can change for each block

 

(defun c:BLKCSV1 (/ SplitStr doc spc csv csv data bn SourceFile InsertedBlock)
  
  (defun SplitStr (s d / p)
    (if	(setq p (vl-string-search d s))
      (cons (substr s 1 p)
	    (SplitStr (substr s (+ p 1 (strlen d))) d)
      )
      (list s)
    )
  )
  (if (and (setq doc (vla-get-activedocument (vlax-get-acad-object))
		 spc (vla-get-block (vla-get-activelayout doc)))
	   (setq SourceFile (findfile "C:/Users/%username%/Documents/Drawing1.csv")) ; Always include 'Findfile	 
	   (setq csv (open SourceFile "r"))
	   (read-line csv)
      );and
  (progn
    (while (and	(setq data (read-line csv))
		(setq data (splitstr data ",")
		      bn   (car data)
		      pnt  (cdr (reverse (cdr (reverse data))))
			  att  (last data)
		)
	   )
	   
      (if (and
	    (tblsearch "block" bn)
	    (setq InsertedBlock (vla-InsertBlock  spc
		  (vlax-3d-point (mapcar 'atof pnt)) bn 1 1 1 0)
		)
	    (minusp (vlax-get InsertedBlock 'HasAttributes))
	    )
	  	(vla-put-textstring
		  (car (vlax-invoke InsertedBlock 'GetAttributes)) att)
		)
	      )
  (close csv)
    )
    )
  (princ)
)

 

 

0 Likes
Message 4 of 14

her5157
Explorer
Explorer

That worked fantastically. Thank you. Really great work.

0 Likes
Message 5 of 14

her5157
Explorer
Explorer

Thank you for this great solution.

0 Likes
Message 6 of 14

Sea-Haven
Mentor
Mentor

Like pbe answer you can insert a block and have it populate more than 1 attribute automatically, including reading block names that may have different number of attributes. A more global routine. Uses the getattributes and compares how many to apply to.

 

Blk1,x,y,att1,att2

Blk2,x,y,att1

 

0 Likes
Message 7 of 14

pbejse
Mentor
Mentor

@Sea-Haven wrote:

A more global routine. Uses the getattributes and compares how many to apply to.

 

Blk1,x,y,att1,att2

Blk2,x,y,att1


You are right, a change in the code is in order

(defun c:BLKCSV1 (/ SplitStr doc spc csv csv data bn SourceFile InsertedBlock) 
  (defun SplitStr (s d / p)
    (if	(setq p (vl-string-search d s))
      (cons (substr s 1 p)
	    (SplitStr (substr s (+ p 1 (strlen d))) d)
      )
      (list s)
    )
  )
  (if (and (setq doc (vla-get-activedocument (vlax-get-acad-object))
		 spc (vla-get-block (vla-get-activelayout doc)))
	   (setq SourceFile (findfile "C:/Users/%username%/Documents/Drawing1.csv")) 
	   (setq csv (open SourceFile "r"))
	   (read-line csv)
      );and
  (progn
    (while (and	(setq data (read-line csv))
		(setq data (splitstr data ",")
		      bn   (car data)
		      pnt  (list (cadr data)(caddr data)(cadddr data))
			  att  (cddddr data)
		)
	   )
	   
      (if (and
	    (tblsearch "block" bn)
	    (setq InsertedBlock (vla-InsertBlock  spc
		  (vlax-3d-point (mapcar 'atof pnt)) bn 1 1 1 0)
		)
	    (minusp (vlax-get InsertedBlock 'HasAttributes))
	    )
	(mapcar 'vla-put-textstring
		  (vlax-invoke InsertedBlock 'GetAttributes)
		att)
		)
	      )
  (close csv)
    )
    )
  (princ)
)

Using the rest of the list as the att value instead of a single string enables the use of mapcar function that takes any number of arguments.

 

if you have this as the value on the csv file.

AnotherBlock,2580600.133,13840993.83,0,Value32,
data would be ("AnotherBlock"" "2580600.133" "13840993.83" "0" "Value32")
att = ("Value32")

and some are 

BLOCK_1,2580724.633,13840993.83,0,Value35,Value of another, One more
data would be ("AnotherBlock" "2580724.633" "13840993.83" "0" "Value35" "Value of another" "One more")
att = ("Value35" "Value of another" "One more")

You can use the values of att variable as one of the arguments and the other the list of attributes of the inserted block.

Both att values will still work regardless if AnotherBlock block has three attributes and vice versa

 

If the supplied lists are unequal in length, mapcar will cease evaluation when the shortest list has been processed

 

HTH

 

0 Likes
Message 8 of 14

Anonymous
Not applicable

Good afternoon!

How do you run the program?

Thanks

0 Likes
Message 9 of 14

hak_vz
Advisor
Advisor

@Anonymous  Copy code and paste it to some text editor. Create some directory where you'll have your list codes and save file there with extension .lsp. Copy Drawing1.csv to your documents folder and edit according to your need (this was created according to @her5157 request). When done load the lisp file tools-> Auto lisp ->load application-> and select your file. Add your lisp directory to trusted location.

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.
0 Likes
Message 10 of 14

Sea-Haven
Mentor
Mentor

Like hak_vz, a quicky way is to use explorer you can drag and drop a lsp file onto Autocad and it will run, yes you may get a trusted paths message just click ok. If your going to use lots of lisp's then a menu may be worthwhile looking into, with all your lisps raedy to pick,  if you can use notepad you can make a menu.

0 Likes
Message 11 of 14

Anonymous
Not applicable

@hak_vz Hi, when I load this particular .lsp, it says it loaded successfully but does not do anything after that, I did not see a command to type in to run it. This lisp appears to be exactly what I need, to take csv data and fill in to blocks, I have three different types of blocks for different instances, the data is all different, not sure why it does not seem to do anything when I run it

0 Likes
Message 12 of 14

hak_vz
Advisor
Advisor
BLKCSV1	

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.
0 Likes
Message 13 of 14

Anonymous
Not applicable

@hak_vz Hello, I load the program with Appload and it say successfully loaded, then I type in the cmd BLKCSV1 and enter and it does nothing.

0 Likes
Message 14 of 14

Sea-Haven
Mentor
Mentor

Make this simple change allows a select csv. Change D & Acadtemp to your drive and directory.

 

 

(setq SourceFile (findfile "C:/Users/%username%/Documents/Drawing1.csv"))
to
(setq sourcefile (getfiled "Select a CSV File" "D:\\Acadtemp\\" "CSV" 8))

 

PS add this as very last line then will run on loading. (c:blkcsv1)

0 Likes