Jump to content

How to pass a selected object from Lisp to VBA


Recommended Posts

Posted

Hello,

 

I have been struggeling with this problem for two days now so any help would be very, very much apreciated. Unfourtunatly Im a beginner in both Lisp and Autocad but not in VBA.

 

I have written a function in VBA that let the user select a LWPOLYLINE and then the function will convert the LWPOLYLINE to a "polyline" (Changing all the arcs to several straight lines).

 

Since I want to confirm to the standard behaviour of Autocad commands, I have written some Lisp code where the user first selects the polyline, and then can choose how many lines every arc will convert to.

 

My problem is how to get the selected polyline and the settings over to vba. I have really tried, and probably is my problem a result of my bad knowledge of autocad and lisp.

 

To get the users variables over to vba I read about using the USER1-5 variable, but It didn't work (When using ThisDrawing.GetVariable("USERS1") the return was empty). So now Im writing the settings to a file, and then reads the file into vba. It looks a bit awkyard to me, but it works.

 

But how can I get the selected polyline to VBA? Please help me. And please be as clear as possible if you know the answer.

 

This is the code in VBA that I want to change to something that gets the polyline that the user selected within the lisp code:

 

 
ThisDrawing.Utility.GetEntity oEnt, vPick, vbCr & vbCr & "Select object:"

 

Sorry for writing so much... But I really really need to get this working, and Im so close. Thanks for taking your time!

 

This is my Lisp-code for letting the user select an object:

 

 
(defun C:conv  ()

;Clears vars
(setq mmtCalcMethod nil)
(setq mmtSectorAngle -1)
(setq mmtNrOfSectors -1)

(princ "\nconv: Version 1.2")

(setq again nil)
(setq p-ent nil)

(while (not p-ent)
(setq p-ent (car (entsel "\nSelect a polyline:")))
  (if (not p-ent)
     (prompt "\nNo object selected. ") ;_ end of prompt
     (progn
        ;(if (and (/= (dxf 0 p-ent) "POLYLINE") (/= (dxf 0 p-ent) "LWPOLYLINE") ) ;_ end of and
 (if (/= (dxf 0 p-ent) "LWPOLYLINE")
           (progn
              (prompt "\nNot a LWPOLYLINE, select again:" ) ;_ end of prompt
              (setq p-ent nil)
           ) ; progn
        ) ;_ end of if
     ) ;_ end of progn
  ) ;_ end of if
) ;_ end of while

 

And this is the rest of the code where the user select which calculation method to use...

 

 
;Number of vectors or degrees
;Read users last setting!
 (setq mmtCalcMethod (getcfg "AppData/MY_Stuff/mmtCalcMethod"))
 (if ( = mmtCalcMethod nil ) (setq mmtCalcMethod "A") )
;The user can use S or A
;0 = NIL is ok to return
 (initget 0 "S A")
 (setq Tmp (getkword (STRCAT "\nCalculate number of points for each arc using [Angle/Sector] <" (princ mmtCalcMethod) ">: "))) 
;The users selection was stored in Tmp and now we assign Tmp to mmtCalcMethod
 (if Tmp (setq mmtCalcMethod Tmp) )  
;Save the setting in the "Autocad" register
(setcfg "AppData/MY_Stuff/mmtCalcMethod" mmtCalcMethod) 

;Depending on the users previous selection...
(if (= mmtCalcMethod "S")
 ( progn

;Read settings from the "Autocadregistret"
  (setq mmtSectorAngle (getcfg "AppData/MY_Stuff/mmtSectorAngle"))
;
;
  (if (and ( /= mmtSectorAngle nil ) ( /= mmtSectorAngle "" )) (setq mmtSectorAngle (ATOI mmtSectorAngle)) (setq mmtSectorAngle 5))    
;
(setq Tmp (getint (STRCAT "\nEnter sector angle <" (ITOA mmtSectorAngle) ">: "))) 
;
  (if Tmp (setq mmtSectorAngle Tmp) )
;
 (setcfg "AppData/MY_Stuff/mmtSectorAngle" (ITOA mmtSectorAngle))

 )
 ( progn 
;
  (setq mmtNrOfSectors (getcfg "AppData/MY_Stuff/mmtNrOfSectors"))
;
;
  (if (and ( /= mmtNrOfSectors nil ) ( /= mmtNrOfSectors "" )) (setq mmtNrOfSectors (ATOI mmtNrOfSectors)) (setq mmtNrOfSectors 10))
;

(setq Tmp (getint (STRCAT "\nEnter number of segments for each arc <" (ITOA mmtNrOfSectors) ">: "))) 
;

  (if Tmp (setq mmtNrOfSectors Tmp) )
;
 (setcfg "AppData/MY_Stuff/mmtNrOfSectors" (ITOA mmtNrOfSectors)) 
 )
)  

 

And this is the final code where the settings are written to a file

 

 

 
*******************************************************************
; Code to get the data to VBA
*******************************************************************
; The "USER1" code below never worked. 
; The variables were always empty inside VBA
; (VBA CODE)
; Dim var1, var2 As Variant
; var1 = ThisDrawing.GetVariable("USERS1")
; var2 = ThisDrawing.GetVariable("USERS2")
; (/VBA CODE)
;(setq USERS1 mmtCalcMethod)
;(setq USERS2 (ITOA mmtSectorAngle))
;(setq USERS2 (ITOA mmtNrOfSectors))
;(setq USERS4 p-ent)

; Instead we are now saving the settings to a textfile
  (setq tempfile (open "C:\\Program Files\\AutoCAD Map 3D 2009\\temp.txt" "w"))
  (write-line (STRCAT "mmtCalcMethod: " (princ mmtCalcMethod)) tempfile)
  (write-line (STRCAT "mmtSectorAngle: " (princ (ITOA mmtSectorAngle))) tempfile)
  (write-line (STRCAT "mmtNrOfSectors: " (princ (ITOA mmtNrOfSectors))) tempfile)

  ;THIS IS MY MAJOR PROBLEM RIGHT NOW!!!!
  ;WHAT SHOULD I DO? PLEASE HELP!!!
  ;HOW CAN I GET THE SELECTED POLYLINE INTO VBA??
  ;(write-line (STRCAT "p-ent: " p-ent) tempfile)
  (close tempfile)

  (setq current_osnap_mode (getvar "osmode"))
  (setvar "osmode" 0)
  (RunVbaMacro "C:/Program Files/AutoCAD Map 3D 2009/code.dvb" "module_mmtconv.mmtconv")
  (setvar "osmode" current_osnap_mode)
  (princ) ;Exit quietly!

);defun

; *******************************************************************
; DXF
*******************************************************************
(defun dxf (code ename)
(cdr (assoc code (entget ename)))
) ;_ end of dxf

Posted

I don’t think the task necessarily requires two APIs. As a matter of fact, a good case could be made that what you already have was the trickiest part of a VBA only solution. Some creative use of ThisDrawing.Utility.InitializeUserInput, ThisDrawing.Utility.GetInteger, and maybe ThisDrawing. ActiveSelectionSet could have done the rest.

 

However, given that you already have much of the necessary code, both AutoLisp and VBA can retrieve entities by the entity’s handle. It should be possible to transfer info via “User” variables (perhaps not the most efficient method). Check the spelling, especially the type identifier USERS1, USERI1, etc.

Posted
I don’t think the task necessarily requires two APIs. As a matter of fact, a good case could be made that what you already have was the trickiest part of a VBA only solution. Some creative use of ThisDrawing.Utility.InitializeUserInput, ThisDrawing.Utility.GetInteger, and maybe ThisDrawing. ActiveSelectionSet could have done the rest.

 

However, given that you already have much of the necessary code, both AutoLisp and VBA can retrieve entities by the entity’s handle. It should be possible to transfer info via “User” variables (perhaps not the most efficient method). Check the spelling, especially the type identifier USERS1, USERI1, etc.

 

 

Thank you very much for your answer. I deleted the Lisp code and rewrote it using ThisDrawing.Utility.InitializeUserInput, ThisDrawing.Utility.GetInteger and so on. Finally it works!

 

But I still have a question. It doesn't look exactly like the Autocad-functions Im used to.... Every time I ask for the users input (using for example ThisDrawing.Utility.GetInteger) the word "Command:" is echoed to the screen after the user has enterd a value. Pretty annoying...

 

For example:

 

Select LWPolyline to convert:

Command:

Calculate number of points for each arc using [Angle/Sector] S

Command:

Enter number of segments for each arc 3

Command:

Delete original polyline [Yes/No]

Command: Regenerating model.

 

 

My code looks like this:

 

 
kwordList = "A S"
   ThisDrawing.Utility.InitializeUserInput 0, kwordList
   
   'Reads from the register
   vCalcMethod = GetSetting("MyAcad", "mmtconv", "vCalcMethod", "A")
       
   'Ask user how to convert the polyline
   returnString = ThisDrawing.Utility.GetKeyword(vbCrLf & "Calculate number of points for each arc using [Angle/Sector] <" & vCalcMethod & "> ")
   
   'ESC aborts
   If Err <> 0 Then
       Err.Clear
       Exit Sub
   End If
   
   'If not <ENTER> use users value...
   If (returnString <> "") Then
       vCalcMethod = returnString
   End If
   
   'Saves the settings in the register
   SaveSetting "MyAcad", "mmtconv", "vCalcMethod", vCalcMethod
       

 

I retried using the USERS1 variables, but still couldn't get it to work.

I use blockletters and USERS1 for String? When debuggin in Visual Lisp I can se that USERS1 contains data, but I can't get the data into VBA... Strange...

 

And just for curiosity, I would very much like to know how to write a objects handle to a file from LISP, and then read it back in using VBA. And ofcourse how to select the object when having this handle as a string!

 

If anyone know the answer, please let me know!

I was trying to write the handle to a file from LISP using the following code, but with no luck...

 

 
(setq p-ent (car (entsel "\nSelect a polyline:")))
(write-line (STRCAT "p-ent: " p-ent) tempfile)

 

Any help, tips or suggestions is as usually highly appreciated!

 

Best regards,

Marcus

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