Lisp to turn a VBA Macro into a type command

Lisp to turn a VBA Macro into a type command

hmsnake
Participant Participant
1,427 Views
11 Replies
Message 1 of 12

Lisp to turn a VBA Macro into a type command

hmsnake
Participant
Participant

Hi, I am new to using VBA and Lisps to customize Civil3D. I am kinda confused about how the two work together. I have been watching some videos and looking at forums, but it never really works when I try to do it. My VBA Macro works perfectly but I can't get a working lisp to execute it with a typed command. Anyone have any ideas? This is what I have tried out. I saw it on some forums and youtube videos.

I was also wondering if it would be better/possible to just recreate the VBAmacros as a lisp instead.

Here is the macro I made: AddAreaAsMText. It asks for a closed polyline, gets the area, converts it to SY, then creates an mtext box for it that is inserted wherever the user clicks.

Here is the lisp I made to try to make this into a command on the command line.

Sorry this probably sucks I am really just frankenstiening everything together.

Video I used: https://youtu.be/iQLRy9lFwfI?si=5b3rS8z7t6HLmMXj
Help pages I used: https://help.autodesk.com/view/CIV3D/2023/ENU/?guid=GUID-D991386C-FBAA-4094-9FCB-AADD98ACD3EF 

I run Autodesk Civil 3D 2023.

0 Likes
Accepted solutions (3)
1,428 Views
11 Replies
Replies (11)
Message 2 of 12

paullimapa
Mentor
Mentor

I had to first load VBA for my version of AutoCAD from this download link:

https://www.autodesk.com/support/technical/article/caas/tsarticles/ts/3kxk0RyvfWTfSfAIrcmsLQ.html

paullimapa_0-1723247537656.png

I also changed your lisp code because you had spaces where there should not be and missing quotes:

(defun c:AddAreaT ()
;(defun c: AddAreaT ()
;  (command "-vbaload "PATH TO DVB")
  (command "_-vbaload" "AddAreaText.dvb")
           (setvar "cmdecho" 0)
  (command "vbarun" "AddAreaText.dvb!Module1.AddAreaAsMText")
)

But attempting to run your macro I received this error:

Macro not found."AddAreaText.dvb!Module1.AddAreaAsMText"

Then I manually started the VBARUN command selected VBA Manager button and attempted to Load your dvb file

paullimapa_2-1723247801468.png

But then I got this error message:

paullimapa_1-1723247659924.png

 

 


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

ec-cad
Collaborator
Collaborator
Accepted solution

Took a few small snipits from this Forum to create a 'converted' VBA to AutoLisp.

Included the VBA code fragments as comments every step of the way.

No error checking, that could be added.

Here's the code.

 

ECCAD

 

 

 

;; Filename: VBCode.lsp
;; Convert VB Code to AutoLisp Code
;; 8-10-2024 Control Systems & Services, LLC (Arizona LLC)
;; Note: no Error Checking, or system variable set/changes
;;
; Function to check if a Polyline is Closed
; [ename] - light weight/heavy weight polyline
;return: T if closed, nil otherwise

(defun isPolyClosed (ename)
  (= 1 (logand 1 (cdr (assoc 70 (entget ename)))))
); function


 (defun C:GO () ; Function to Run this Program

; VB Code
;    ' Prompt user to select a closed polyline
;    On Error Resume Next
;    promptMessage = "Select a closed polyline: "
;    acadDoc.Utility.GetEntity selectedObject, crossHairLocation, promptMessage

 (princ "\nSelect a closed polyline: ")
  (setq ss (ssget "_+.:E:S" '((0 . "LWPOLYLINE"))))

  (if ss
   (progn
    (setq polyename (ssname ss 0)); Entityname

; VB Code
;    ' Check if the polyline is closed
;    If selectedObject.Closed = False Then
;        acadDoc.Utility.Prompt "The selected polyline is not closed."
;        Exit Sub
;    End If

    (setq check_closed (isPolyClosed polyename))
     (if check_closed
      (progn

; VB Code
;    ' Get the area of the polyline in square feet
;    areaInSqFt = selectedObject.Area
;    
;    ' Convert the area to square yards (1 square yard = 9 square feet)
;    areaInSy = areaInSqFt / 9

       (setq polylineObj (vlax-ename->vla-object polyename)); as Object
       (setq poly_area (vlax-get-property polylineObj 'Area))
       (if poly_area
         (setq poly_sqft (/ poly_area 9.0))
       ); if
; VB Code
;    ' Prompt user to specify the insertion point for MText
;    acadDoc.Utility.Prompt "Specify insertion point for area text: "
;    tempPoint = acadDoc.Utility.GetPoint(, "Specify insertion point for area text: ")
;    
;    ' Assign the captured point to the insertionPoint array
;    insertionPoint(0) = tempPoint(0)
;    insertionPoint(1) = tempPoint(1)
;    insertionPoint(2) = tempPoint(2)

      (setq MTpt (getpoint "\nSpecify insertion point for area text: "))

;VB Code
;    ' Add MText with area information
;    Dim areaText As String
;    areaText = "Area: " & Format(areaInSy, "0.00") & " SY"
;    
;    Dim mText As AcadMText
;    Set mText = acadDoc.ModelSpace.AddMText(insertionPoint, 0, areaText)
;    mText.Height = 0.9 ' Set the text height as needed

     (setvar 'TextSize 0.9)
     (command "_MTEXT" MTpt MTpt (strcat "Area: " (rtos poly_sqft 2 2) " SY") "")
     ); progn
    ); if - check_closed
   ); progn
  ); if - ss
 ); function C:GO
 (princ "\nType GO to run this Lisp:")
 (princ)

 

 

 

0 Likes
Message 4 of 12

Sea-Haven
Mentor
Mentor

Worked for me opened vbaman and saved the code as a DVB. 

 

(command "vbarun" "AddAreaText.dvb!Module1.AddAreaAsMText")
should be
(command "vbarun" "AddAreaAsMText")

 

0 Likes
Message 5 of 12

hmsnake
Participant
Participant

Thanks ECCAD! This worked for me! I will continue to try to get my other one to work as well, but moving forward, do you think it's more beneficial to try to do everything with AutoLisp?

0 Likes
Message 6 of 12

pkenewell6347
Advocate
Advocate
Accepted solution

Here are 2 functions I have been using for years to load and run DVB files:

;|==============================================================================
  Function Name: (pjk-DVBload <DVB file name><Macro>)
  Arguments:
    <DVB file name> = Name of a VBA macro file to load
    <Macro> = Name of the macro to run
  Description: This function loads and optional runs a DVB file.
==============================================================================|;
(defun pjk-DVBload (dvbfil macro)
	(if (setq dvbfil (findfile dvbfil))
	    (progn
          (vl-vbaload dvbfil)
          (if macro (vl-vbarun macro))
       )
	    (princ (strcat "\nERROR: VBA File \"" dvbfil "\" Not Found."))
	)
) ;; End Function (pjk-DVBload)

;|==============================================================================
  Function Name: (pjk-AutoVBALoad)
  Arguments:
     cmd = String; command to assign to the VBA macro.
     dvbfile = String; DVB macro file to load (Note: no path checking).
     macro = String; Name of the macro to run within the DVB file.
  Usage:
  Returns:  N/A
  Description: This function defines a command to load and run a DVB file,
  similar to the (autoload) function for LISP files.
================================================================================|;
(defun pjk-AutoVBALoad (cmd dvbFile macro)
   (eval
      (list 'defun (read (strcat "C:" cmd))
         '()
         (list 'vl-vbarun
            (strcat dvbFile "!" (if macro macro cmd))
         )
         (princ)
      )
   )
) ;; End Function (pjk-AutoVBALoad)

 

0 Likes
Message 7 of 12

scot-65
Advisor
Advisor
Accepted solution

@hmsnake 

 

I typically do not like to give out my utilities but would rather have you

learn by example so that you can learn the language.

 

The original utility was written in December 1998 - before VL- came out.

 

Key items:

1. Filter polylines that are closed and on the current layer, polylines with linetype generation is on, and circles greater than 12":

 (if (setq s (ssget (list
      (cons -4 "<or")
       (cons -4 "<and")
        (cons 0 "LWPOLYLINE")(cons 8 (getvar "CLAYER"))(cons 70 1)
       (cons -4 "and>")
       (cons -4 "<and")
        (cons 0 "LWPOLYLINE")(cons 8 (getvar "CLAYER"))(cons 70 129)
       (cons -4 "and>")
       (cons -4 "<and")
        (cons 0 "CIRCLE")(cons 8 (getvar "CLAYER"))(cons -4 ">")(cons 40 12.0)
       (cons -4 "and>")
      (cons -4 "or>")
     )))

 

2. Find and convert the areas (while in a WHILE loop):

    (command ".AREA" "e" (ssname s n))
    (setq a (/ (getvar "area") 144.0))

The above converts square-inch to square-feet.

 

3. Create the MTEXT:

     (if (setq p1 (getpoint "\n Specify text location: "))
      (entmake (list (cons 0 "MTEXT")         
       (cons 100 "AcDbEntity")
       (cons 100 "AcDbMText")
       (cons 10 p1)
       (cons 1 a)
       (cons 7 (getvar "TEXTSTYLE"))
       (cons 40 (/ (getvar "DIMSCALE") 2.0))
       (cons 62 7)
      ))
     );if

 

DFX 40 is text height. DFX 62 is color.

The utility as written can be used for files having different scale drawings for the text height.

 

Hope this helps.

 


Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.

0 Likes
Message 8 of 12

ec-cad
Collaborator
Collaborator

VBA - OR - AutoLisp ?

Well, that depends. MicroSoft is no longer supporting Visual Basic, went on to .Net

But, AutoDesk still supports the VBA interface for Object Oriented Programming.

So, IF you are more comfortable using VBA for quick results, keep on doing that.

But, at the same time, to cover the possibility that AutoDesk (could) drop the VBA,

I would try to keep up with current software (support) by learning AutoLisp.

MicroSoft Windows is yet another issue. 🙂

So it's up to you.

 

ECCAD

 

0 Likes
Message 9 of 12

Sea-Haven
Mentor
Mentor

@ec-cad "But, AutoDesk still supports the VBA interface for Object Oriented Programming." 

 

About 5 years ago Autodesk announced that it would no longer support VBA, its answer at the time was you must download the VBA module separate, still happening. Here we are though 2024 I have not seen any comments recently about a definite cease date. My Bricscad V24 has VBA. 

 

As you mention it's all about Microsoft direction. 

 

I dont think anyone here uses the Macro record its way to limited, look at Excel macro record writes VBA code. Excel is owned by Microsoft is that a conflict of future direction ? Then we have Dynamo where is the plain Autocad version ? Is it another Macro record idea that was seen as the way to go in future ?

 

Years ago played with some CAD software it's macro record wrote VBA code.

 

Last comment its a good idea to learn lisp as an alternative as often use code by others, people like Lee-mac.com has some great functions doing very complex tasks.

 

0 Likes
Message 10 of 12

hmsnake
Participant
Participant

Thank you! This actually helped a lot with learning the syntax. I think I will use this along with Lee-mac to learn AutoLisp (suggested). Do you have any other resources that you think are especially helpful?

0 Likes
Message 11 of 12

ec-cad
Collaborator
Collaborator

You said: "I will continue to try to get my other one to work as well"..

How are you doing with the 'other' one ?

 

ECCAD

0 Likes
Message 12 of 12

scot-65
Advisor
Advisor
Most of my learning LISP has been on this board.
I would on occasion take code snippets and save to my local directory for future reference.
For some snippets I will include the author's name as part of the opening header comments in the specific LSP file. Lee-Mac supplied the ENTMAKE(x).

Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.

0 Likes