Help with vla and vlax

Help with vla and vlax

k_wiegertB2TX5
Explorer Explorer
272 Views
10 Replies
Message 1 of 11

Help with vla and vlax

k_wiegertB2TX5
Explorer
Explorer

Hi

I'm new here and I have a very limited understanding of lisp.

 

I have a code that  let me pick a block and gives back the blockname as "ebname" and an vla object "obj"

The goal is to skip this and put the blockname direct in the code

(while (not e)
   (and
    (setq e (car (entsel "\nSelect sample block to export: ")))
    (setq edata (entget e))
    (if (/= (cdr (assoc 0 edata)) "INSERT")(progn (princ " this is not a block! ")(setq e nil)))
   )
  )
  (setq bname (cdr (assoc 2 edata))
		ebname (vla-get-Effectivename (setq obj (vlax-ename->vla-object e)))
		atts ""
  )
  (princ (strcat bname (if (= (ascii bname) 42) (strcat " (" ebname ")") ""))) ; "*" ?

 

If I got it right I pickup something and the first element is passed to "e". (What are the other elements?)

It checks if i got a block (assoc 0) and set bname to the blockname (assoc 2) 

Now I struggle what is ebname and obj set to?

ebname is later used for a block selection:

(setq ss (ssget (list (cons 0 "INSERT")(cons 2 (strcat ebname ",`*U*"))))  i 0  cnt 0)

and obj for extracting attributes

(foreach att (vlax-invoke obj 'GetAttributes)(setq atts (strcat atts __BCdelimiter "\"" (vlax-get att 'TagString) "\"")))

and now I'm in way too advanced teritorry.  How can I put my blockname directly into the code?

 

I hope some can enlighten me

Thanks in advantage

Kai

0 Likes
273 Views
10 Replies
Replies (10)
Message 2 of 11

ВeekeeCZ
Consultant
Consultant

Why don't you post the entire original code you have, a sample file, and your goal?

0 Likes
Message 3 of 11

k_wiegertB2TX5
Explorer
Explorer

My primary Goal is to understand the code.

 

Right now I'm using ATTEXT to get the attributes and coorinates of the blocks "Blockbeschriftung", "Kabelnr_L", "Kabelnr_R" and "Steckerverbindung"

and a the lisp "L2C" to get the coorinates of the rechtangles. From there I perform some calulations in Excel.

 

I recently found the lisp "BlockCoords" witch works fine with Autocad LT. So I try to tweak it and combine the two export tasks into single one.

And the first step is to get my predefined blocks processed.

 

 

 

 

0 Likes
Message 4 of 11

ВeekeeCZ
Consultant
Consultant

You know what, that code might not be the best one to start with. It's too complex. Keep searching for something more straightforward, or we could write something. 

Besides, it's (c) and its author has his eyes everywhere.. 😉

 

BTW ebname is an Effective name. It's basically the name of Dynamic Blocks. 

0 Likes
Message 5 of 11

komondormrex
Mentor
Mentor

how do you see to place all different info on block/atts and rects in one csv file? 

0 Likes
Message 6 of 11

paullimapa
Mentor
Mentor

most of the answers to your questions can actually be seen when you copy each section of the code to the autocad command prompt and then do a search on-line for what the lisp function does:

Q1) If I got it right I pickup something and the first element is passed to "e". (What are the other elements?)

A1) Just copy & paste this section to the command prompt:

(entsel "\nSelect sample block to export: ")

After selecting an item AutoCAD returns a list with two items:

paullimapa_0-1756910357019.png

The first is the entity name which the code obtains by using the (car) function:

(car (entsel "\nSelect sample block to export: "))

The second is the coordinate of the picked point which you can obtain by using (cadr) function:

You can read up on it entsel function here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-9D4CF74D-8B8B-4D66-A952-564AFBA254E7

car function here:
https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-2DD1AF33-415C-4C1A-9631-DA958134C53A

cadr function here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-F8E9E4F0-218D-4587-9D7E-922BE57C9F9B

Q2) It checks if i got a block (assoc 0) and set bname to the blockname (assoc 2) Now I struggle what is ebname and obj set to?

The code shows the following:

(setq bname (cdr (assoc 2 edata))
		ebname (vla-get-Effectivename (setq obj (vlax-ename->vla-object e)))
		atts ""
  )

A2) To understand this you can again copy & paste the following to the command line:

(setq obj (vlax-ename->vla-object e))

AutoCAD returns vla object:

paullimapa_1-1756910877632.png

The vlax-ename->vla-object converts the selected entity e to vla object obj for vla functions. So you would now pass obj and not e to any of the vl functions.

You can read up on this here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-BD451263-76D5-4A93-B50A-3C27E89A0AD4

The vla function that is used next on the converted vla object is vla-get-Effectivename which gets the actual block name since AutoCAD introduced dynamic blocks.

You can read more about this here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-A87607A4-D7F9-40B3-94B5-B9D88011DEB5

So the ebname is set to the effective name of the block. Of course if your block that you've selected is not dynamic, this doesn't matter because it'll return the same name ebname using regular lisp function: 

(cdr (assoc 2 edata)

Then the following ssget function filters out the selecting of only blocks "INSERT" with standard block name ebname as well as all dynamic blocks which have names matching *U*:

(ssget (list (cons 0 "INSERT")(cons 2 (strcat ebname ",`*U*"))))

 you can read more on ssget function here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-0F37CC5E-1559-4011-B8CF-A3BA0973B2C3

Q3) How can I put my blockname directly into the code?

A3) Just set ebname to the name of your block. So if the name of your block is: Blockbeschriftung

(setq ebname "Blockbeschriftung")

You can read up on the setq function here:

https://help.autodesk.com/view/OARX/2026/ENU/?guid=GUID-2F4B7A7B-7B6F-4E1C-B32E-677506094EAA

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 7 of 11

k_wiegertB2TX5
Explorer
Explorer

Hi Everyone

Thanks for the replys.

First of all. I posted here not to get a working lisp but to expand my knowledge. As I wrote I have a way of doing the job.

I'm inbetween two projects and have some time to look into new things. 

 

paullimapa: thanks for your detailed reply. So I think I get now the "effective name" - it wasn't cl...

 

So do I have this right:

(entget e)  uses e not as a value but as a pointer to get the list that is "in" the block?

 

So thanks a lot so far. I hope that I find the time to get deeper into this next week (the rest of this week I have just my MacBook and can't do any lisp actions)

 

Kai

 

 

0 Likes
Message 8 of 11

paullimapa
Mentor
Mentor

Q) (entget e)  uses e not as a value but as a pointer to get the list that is "in" the block?

A) yes because e is a variable with setq function:

(setq e (car (entsel "\nSelect sample block to export: ")))

paullimapa_0-1756919138905.png

You can use the type function to check what e is:

(type e)

paullimapa_1-1756919217405.png

e would be a value like a string STR if you did this:

(setq e (getstring T "\nEnter something: "))

paullimapa_2-1756919362766.png

Since e is an entity then entget function can be used:

(setq edata (entget e))

paullimapa_3-1756919519536.png

Finally to get block name:

(setq bname (cdr (assoc 2 edata)))

paullimapa_4-1756919575110.png

But if this was a dynamic block then you'll end up with something like this as the block name: "*U4":

paullimapa_5-1756919721317.png

This is why it's necessary to convert the entity e to vla object and then use vla function to get the effective block name:

(setq bname (vla-get-Effectivename (setq obj (vlax-ename->vla-object e))))

paullimapa_6-1756919989954.png

FYI: You may want to consider installing Parallels on your Mac and then you can install AutoCAD for Windows and run that on your Mac.

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 9 of 11

ВeekeeCZ
Consultant
Consultant

Ok understood. I found this one in my archive. 

If you need to export all references of some regular blocks, you can just adjust the ssget filter. See THIS in case you need.

Also see the note. 

It probably does not work on mac but it might not be difficult to make it so.

 

(vl-load-com)

(defun c:BPropsExport ( / *error* f s l x p properties)
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if f (close f))
    (princ))
  
  
  (setq properties '(
		     "BlockTableRecord/Name"
		     "AcDbDynBlockPropertyMotor Type"
		     "Weight"
		     "X-POS"
		     "Y-POS"
		     "Position/X"
		     ))
  
  ;; paste this line to command-line to see all available props:
  ;; (dumpallproperties (car (entsel)))
  
  
  (and (setq s (ssget (list '(0 . "INSERT"))))
       (setq l (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))) ; converts a selection-set to a list
       (setq l (mapcar '(lambda (e) (mapcar '(lambda (p / x) (if (vl-catch-all-error-p (setq x (vl-catch-all-apply 'getpropertyvalue (list e p)))) "" x)) properties)) l))  ; get a property with error handeling in case it fails-property does not exists)
       (setq l (cons properties l))
       (setq f (open (setq p (strcat (getvar "dwgprefix") (getvar "dwgname") "-BPropsExport" ".csv")) "w"))
       (foreach e l
	 (write-line (write-line (substr (apply 'strcat (mapcar '(lambda (x) (strcat ",'" (vl-princ-to-string x) "'") ) e)) 2)) f))
       (write-line (strcat "Stored at '" p "'"))
       )
  
  (*error* "end")
  )

 

0 Likes
Message 10 of 11

k_wiegertB2TX5
Explorer
Explorer

Thanks for your input.

I got some work on my desk now that requiers my attention (and luckily involves signal generators and audio analyzers - wich is much more up my alley than coding 😉 )

I will definitive come back to this, but it may take a few days

0 Likes
Message 11 of 11

k_wiegertB2TX5
Explorer
Explorer

Hi

thanks to your explanations I get now that the "BlockCoords.lsp" is a great script because it can handle dynamic blocks (and probably more). Since I don't need that I looked at the L2C.lsp

and with help of this snipped I found sometimes ago (and luckily saved on my hdd )

(defun test:attwert (obj AttName / OBJLIST ATTWERT)

  (while (and(not AttWert)
            (setq obj (entnext obj))
            (setq objList(entget obj))
            (=(cdr(assoc 0 objList))"ATTRIB"))
    (if(=(strcase(cdr(assoc 2 objList)))(strcase AttName))
      (setq AttWert (cdr(assoc 1 objList))))
    )
  AttWert)


(defun c:test ( / ATTNAME ATTWERT OBJ)
  (setq AttName "DEVICE")

  (if (and (setq obj (car(entsel "\nBlock picken:")))
          (= (cdr(assoc 0 (entget obj)))"INSERT"))
    (if (setq AttWert(test:attwert obj AttName))
      (alert AttWert)
      (alert (strcat "Attribut mit dem Namen \""AttName"\" nicht gefunden.")))
    (if obj
      (alert "Das war kein Block."))
    )
  (princ))

I was able to manage to expand the L2C it to

(defun c:A2C ( / *error* ss f fName cnt e eg en typ han lyr txt tmp pnt strl att1 att2 dev ort knr bname)
;Lines 2 Csv
    ;error handle
    (defun *error* ( msg )
        (if f (close f))
        (if (not (member msg '("Function cancelled" "quit / exit abort")))
            (princ (strcat "\nError: " msg))
        );if
        (princ)
    );defun error
;ensure items selected
(if (not (setq ss (ssget '((0 . "*")))))
;(setq ss (ssget '((-4. "<OR")  (0 . "LWPOLYLINE")  (0 . "INSERT") (-4. "OR>") )))
  (progn (prompt "\n...invalid.") (exit))
);if


;be sure file does not exist
(setq fName (getvar 'DWGNAME))
(setq fName (strcat (getvar 'DWGPREFIX) (substr fName 1 (- (strlen fName) 4)) ".txt"))




(if (findfile fName)
  ;(progn (prompt "...file already exists.") (exit))
(vl-file-delete fName)
);if
;prep file/vars
;(vl-load-com)
(setq f (open fName "w"))
;(write-line "HANDLE,LENGTH,LAYER,X,Y,Z" F)



;loop through ss
(repeat (setq cnt (sslength ss))
  ;gather basic info
  (setq e (ssname ss (setq cnt (1- cnt))))
  (setq eg (entget e) typ (cdr (assoc 0 eg)))
  (setq han (cdr (assoc 5 eg)) lyr (cdr (assoc 8 eg)))
  (setq txt (strcat han "," lyr "," typ ","))
  ;get type-specific info (vertices)
 (cond
    ((eq "LWPOLYLINE" typ)
      (while (setq eg (member (assoc 10 eg) eg))
	(setq pnt (cdr (car eg)) eg (cdr eg))
	(setq tmp (strcat txt (rtos (car pnt) 2 1) ";" (rtos (cadr pnt) 2 1)))
	(write-line tmp f)
      );while
    );cond BLOCK
    ((eq "INSERT" typ)	
	(setq bname (cdr(assoc 2 eg)))	
	(cond
	   ((eq "Blockbeschriftung" bname)
		(setq pnt (cdr(assoc 10 (entget e) )))
		(setq att1 (entnext e))
		(setq dev (cdr(assoc 1 (entget att1) )))
		(setq att2 (entnext att1))
		(setq ort (cdr(assoc 1 (entget att2) )))
		(setq tmp (strcat txt (rtos (car pnt) 2 1) ";" (rtos (cadr pnt) 2 1)";" dev ";" ort ))   
      		(write-line tmp f)
	   );cond "Blockbeschriftung" 
	   ((eq "Kabelnr_R" bname)
		(setq pnt (cdr(assoc 10 (entget e) )))
		(setq att1 (entnext e))
		(setq knr (cdr(assoc 1 (entget att1) )))
		(setq tmp (strcat txt  (rtos (car pnt) 2 1) ";" (rtos (cadr pnt) 2 1) ";" knr ))   
      		(write-line tmp f)
	   );cond Kabelnummer_R
	   ((eq "Kabelnr_L" bname)
		(setq pnt (cdr(assoc 10 (entget e) )))
		(setq att1 (entnext e))
		(setq knr (cdr(assoc 1 (entget att1) )))
		(setq tmp (strcat txt   (rtos (car pnt) 2 1) ";" (rtos (cadr pnt) 2 1)";" knr ))   
      		(write-line tmp f)
	   );cond Kabelnummer_L
	 );cond

    );cond BLOCK
	

    (t (prompt "\n...invalid item selected. Ignored."))
  );cond
);repeat
;finish up / inform user
(close f)
(prompt "\nA2C Complete...")
(princ)
);defun

 

Its right now sort of a "proove of concept" but it gets away without Active-X and thanks to your explenations I fully (more or less) understand the code and can go on with it.

I may get into the Active-X stuff at a later point, but for now I'm quite happy with what I got and what I've learned.

 

So again thanks for your time and efford

Kai

 

0 Likes