A Replacement for VB Evaluate(string)

To graph a function we need to evaluate a string into its math equivalent. Excel VBA has the Application.Evaluate method which takes a variant for an argument and will evaluate a wide range of math symbols, with or without quotations – whatever is between the parentheses. In Visual Studio that doesn’t exist. We want to type a function (the right side of Y = some expression of X) into a textbox on a form, save it to a string variable, then calculate the value to a double for a range of X values. For instance,

strfunc = “X^3 – 3*X^2 + 2*x + 2”

A loop calculates X and Y values starting at X minimum, incrementing by a small X increment, ending at X maximum, and saving all the values to an array to be an argument for AddLightWeightPolyline.

the number of points to be stitched into a graph is calculated –
numpts = CInt((Xmax – Xmin) / Xinc) ‘number of line segments

there is always one more point than line segments
numpts = numpts + 1

the array of doubles is sized –
ReDim Pt(0 To numpts * 2 – 1) ‘store x and y for one pt

after the number of points has been calculated, and the array is ready, the loop is

For i = 1 To numpts
x = Xmin + ((i - 1) * Xinc)
y = eval_func(strfunc, x)
pt(i * 2 - 2) = x
pt(i * 2 - 1) = y
Next i

X is recalulated each time through the loop. Rather than adding the increment to a running sum, its more accurate to use the loop counter to multiply the increment, because of the imprecision of doubles. With odd numbers you might eventually run one cycle short or long. The loop counter should always be an integer. Calculation of Y is handed off to a function with the function string and the current value of X. The function substitutes the numerical value of X whereever X the symbol appears.

Debug.Print strfunc
strfunc = Replace(strfunc, “x”, x, , , vbTextCompare)
Debug.Print strfunc

the first time thru where X is at the starting value of, say, -6, the string and the modified string look like –

X^3 – 3*X^2 + 2*x + 2
-6^3 – 3*-6^2 + 2*-6 + 2

then the final scalar value is calculated and the value returned as Y.

dbl_result = Evaluate(strfunc)

This code was being run from Excel. Evaluate was a method of the top level Application.

For Visual Studio VB.Net we need a replacement for Evaluate.

A lot of people have asked this question. There are quite a few homebuilt parser class solutions. Another method is to link to another language and use its Eval method. A quick easy solution was found, credit to user kleinma


As kleinma says, “Set a reference in your app to “Microsoft Script Control 1.0″ It is under the COM tab in references, not in the .NET tab”

A lot of testing will show if its a decent fix or just the first try.

    Public Xmin As Double
    Public Xmax As Double
    Public Xinc As Double
    Public Ylim As Double
    Public g_stop As Boolean
    Public g_err_counter As Integer

    Function calc_xy(strfunc As String) As Double()
        'returns an array of x and y doubles
        'Xmax, Xmin, Xinc, Ylim are all assumed to have values
        Dim x, y As Double
        Dim i, numpts As Integer
        Dim Pt() As Double

        g_err_counter = 0
        g_stop = False

        numpts = CInt((Xmax - Xmin) / Xinc) 'number of line segments 
        numpts = numpts + 1   'one more pt than line segment
        ReDim Pt(0 To numpts * 2 - 1) 'store x and y for one pt

        For i = 1 To numpts
            x = Xmin + ((i - 1) * Xinc)
            y = eval_func(strfunc, x)

            If g_stop Then  'if eval_func set g_stop then
                MsgBox("errorcounter at 3 - exiting")
                Exit For
            End If
            Pt(i * 2 - 2) = x
            Pt(i * 2 - 1) = y
        Next i

        Return Pt
    End Function

    Function eval_func(ByVal strfunc As String, x As Double) As Double
        'returns a double
        'on error returns Ylim but sets a flag to stop after 3 errors
        'which would indicate a bad formula
        'one or two error is ok because havent solved the mid-graph asymptote yet
        Dim result As Double
        strfunc = Replace(strfunc, "x", x.ToString, , , vbTextCompare)

        Dim SC As New MSScriptControl.ScriptControl
        SC.Language = "VBSCRIPT"
            result = Convert.ToDouble(SC.Eval(strfunc))
        Catch ex As Exception         
            MessageBox.Show(ex.GetType.ToString & " " & ex.Message)
            g_err_counter = g_err_counter + 1
            If g_err_counter > 2 Then
                g_stop = True
            End If
            result = Ylim
        End Try

        Return result
    End Function

3 Equations in 3 Unknowns

“The central problem of linear algebra is the solution of simultaneous linear equations. The most important case is when the number of unknowns equals the number of equations… we begin in three dimensions.” Gilbert Strang – Linear Algebra and its Applications

Ax + By + Cz = D is a linear equation which can be represented by a plane. The intersection of 3 planes at a single point is the solution of the 3 equations used to plot the planes.

its hard to show the intersection of 3 planes with a static image. the Region object is trimmable with the command SurfTrim.
this is the very first example set of equations from Strang’s (old version) book.

A plane is defined by 3 points. But the equation for the plane is more directly derived from a single point and a vector that is orthogonal (perpendicular) to the plane. The dot product of two vectors is

\mathbf{a} \cdot \mathbf{b} = |\mathbf{a}| |\mathbf{b}| \cos \theta

so if the angle between the vectors is 90 degrees, the scalar dot product is zero. The dot product also has the alternative computation that if vector a = (a1, a2, a3) and b = (b1, b2, b3) then

\mathbf{a} \cdot \mathbf{b} = (a1 \ast b1) + (a2 \ast b2) + (a3 \ast b3)

if N is the vector perpendicular to the plane,

\mathbf{N} =   \begin {pmatrix}  A \\  B \\  C \\  \end{pmatrix}

if P1 is the specific point in the plane, and P is a generic point in the plane,

\mathbf{P1} =   \begin {pmatrix}  x1 \\  y1 \\  z1 \\  \end{pmatrix}

\mathbf{P} =   \begin {pmatrix}  x \\  y \\  z \\  \end{pmatrix}

then a vector from P1 to P is (P – P1) and the dot product of N and this line is zero.

\mathbf{N} \cdot (\mathbf{P} - \mathbf{P1}) = 0

according to the rules, that can be written as

\mathbf{N} \cdot \mathbf{P} = \mathbf{N} \cdot \mathbf{P1}

which becomes

Ax + By + Cz = A(x1) + B(y1) + C(z1)

the numbers on the right have specific values, because we are using a specific point and a specific vector, so we can just call those D

Ax + By + Cz = D

which is the standard equation for a plane. The constants A B and C are from the normal vector.

In linear algebra, we are usually given 3 of these equations, and asked to solve it, which means find the intersection of the planes, if it exists. To plot from this equation, Ax + By + Cz = D, where A,B,C and D have actual values, to autocad or any other graphic method, we need three points. About the only way to do that i know is to substitute values. In the most general case where neither A, B or C is zero, the plane intersects all 3 axes, and the 3 intersection points can be found by solving the equation with two variables of x, y and z set to zero. Where one variable of A, B, and C is set to zero, the plane is parallel to the missing axis variable. Where two variables are zero the plane is parallel to both. Its a little tedious, but you just set up tables and solve the equation in the abstract with the missing variables visualizing the plane. Then a select case statement will be the gateway to the actual drawing of the plane.

The other method needed – besides plotting given only the standard equation – is deriving the equation from 3 given points. For that the cross product is essential. 3 non-linear points form a triangle, from which you can see 2 vectors in the plane. The cross product of 2 vectors is a third vector that is orthogonal (perpendicular) to both of them. the cross product gives you the normal vector, with ABC direction numbers. Then you use one of the 3 points, the normal vector, and derive the equation.

all this is covered in the latter third of a full calculus book, the chapter on vectors in space, or 3D vectors, or geometry of space. its also in analytic geometry books and implied or explained in linear algebra books. I am making a linear algebra homework tool.

In the most general case where neither A, B, or C is zero, the axis intercepts are calculated, a triangle can be drawn, and it can be filled with a Region object. If D is zero the plane goes thru the origin, and that is also a special case, the 3 intercepts are the same.

If you are given the std equation, you have the normal vector, but if you are given the 3 points in the plane, you need the normal vector. That is a pretty simple operation with the cross product. the cross product is a pretty fussy formula, but once it is captured to a sub its easy to use.

    Function find_norm(ptA() As Double, ptB() As Double, ptC() As Double) As Double()
        'given 3 points, not co-linear, find norm
        Dim AB() As Double
        Dim AC() As Double
        Dim norm() As Double

        AB = Minusv(ptB, ptA)
        AC = Minusv(ptC, ptA)
        norm = Cross_Product(AB, AC)

        Return norm
    End Function

    Function Cross_Product(t() As Double, v() As Double) As Double()
        Dim x, y, z As Double
        x = t(1) * v(2) - t(2) * v(1)
        y = t(2) * v(0) - t(0) * v(2)
        z = t(0) * v(1) - t(1) * v(0)
        Cross_Product = Pt(x, y, z)

        Return Cross_Product
    End Function

now having 3 points and a normal vector, its optional, but i find the centroid of the triangle as a convenient reference point. if the vertexes are F, G, H, the centroid is very simply (F + G + H) / 3. Now using a vector from the centroid to a vertex, and having the normal, you can once again use the cross product to find a vector orthogonal to both of them. For the purpose of creating a UCS (User Coordinate System) in the plane. Once you have created the UCS, its a simple matter to enlarge your plane, using a Circle center at the centroid, or a square or rectangle.

its a work in progress, here is current state of form. its not really easy to pick off the intersections graphically. the regions can be trimmed but i am going to look at other objects and methods.

Converting Autocad VBA ActiveX to Visual Studio

The Autocad ActiveX and VBA Developer’s Guide, Work in Three Dimensional Space (chap 8 in the old print version), is available with 10 sample code programs here

also in your autocad installation as a CHM file, (very easy to work with)
ProgramFiles\Common Files\Autodesk Shared\acadauto.chm

these sample programs paste in to Visual Studio with a few but not too many problems. Below is a screenshot of the first one. On the left is the virgin code. On the right is the corrected version which runs as intended.

Visual Studio throws up 8 errors on paste. (see ThisDrawing discussion below)
Let and Set assignment is no longer supported. You simply delete them.
acRed and acBlue is not declared. Hovering over the word acRed, Visual Studio suggests the fix, add the namespace ACAD_COLOR
Variant is no longer a supported type: Use the Object type instead.

Changing Variant to Object does eliminate the error on that line, but creates errors where it is accessed. Arrays are an area where dot.net has fixed logical inconsistencies in VBA. Autocad declared a return value of variant because static arrays could not accept an assigment. Dynamic arrays could accept assignment, but that was not in the very first version of VBA, and apparently never made it into the Autocad ActiveX implementation. There is no longer a distinction in dot.net between dynamic and static arrays.

We know the point data for polylines is a Double, and we know the autocad Coordinates method will return a variable number of points, so lets declare the variable as we would a double type dynamic array.

Dim get2Dpts() as Double

now we get an error on assigment –
get2Dpts = pline2DObj.Coordinates
Option Strict On disallows implicit conversions from ‘Object’ to ‘Double’.

anytime you get that and you know your variables are convertible the solution is Ctype(var, type)
get2Dpts = CType(pline2DObj.Coordinates, Double())

Autocad VBA sample code references a variable called ThisDrawing which is always available in the VBA environment. From Visual Studio, I run a sub called Connect_Acad that makes the connection and uses a global AcadDocument variable which can be named ThisDrawing and that is what i have done here. It is added to the top of the sample code.

Make those changes and it runs as is.

There is a simplification on the array assignments available in Visual Studio. In VBA I made subroutines to try to make the awkward point data assigments flow easier. VB.Net has a good new array feature called an initialization list.

you can change all this –

Dim points2D(0 To 5) As Double
Dim points3D(0 To 8) As Double

‘ Define three 2D polyline points
points2D(0) = 1 : points2D(1) = 1
points2D(2) = 1 : points2D(3) = 2
points2D(4) = 2 : points2D(5) = 2

‘ Define three 3D polyline points
points3D(0) = 1 : points3D(1) = 1 : points3D(2) = 0
points3D(3) = 2 : points3D(4) = 1 : points3D(5) = 0
points3D(6) = 2 : points3D(7) = 2 : points3D(8) = 0

to this –

‘ Define three 2D polyline points
Dim points2D() As Double = {1, 1, 1, 2, 2, 2}

‘ Define three 3D polyline points
Dim points3D() As Double = {1, 1, 0, 2, 1, 0, 2, 2, 0}

side by side screenshots –

9 errors on paste
Method arguments must be enclosed in parentheses.
acWorld and acUCS is not declared.

fix those and down to 4 all due to Variant.

Dim WCSPnt As Variant
Dim UCSPnt As Variant

Lets try that again where we change the variant array to its target double array.
Dim WCSPnt() As Double
Dim UCSPnt() As Double

Again we get an error where Autocad Utility Getpoint is returning an Object, originally it was a Variant. We know its a double array so we can use the Ctype function.

The other and last error though is on the boolean argument in Utility.TranslateCoordinates.
UCSPnt = ThisDrawing.Utility.TranslateCoordinates(WCSPnt, AcCoordinateSystem.acWorld, AcCoordinateSystem.acUCS, False)
Strict On disallows implicit conversions from ‘Boolean’ to ‘Integer’.

That makes me want to look at the ActiveX Reference Guide under Objects Utility TranslateCoordinates. Its a flag possible values are True or False but its a Long type not Boolean. it affects whether the first argument is treated as an absolute point value or a vector. i dont quite know why its implemented like that but i can go with the value zero to get the intent.

That allows another error which has been in the queue on the same line. which is fixed by the familiar Ctype function.
And now it runs.

Arrays in VB.Net are all normally zero-based (with some exceptions). So VBA declarations such as Dim pt (0 to 2) as double can be changed to Dim pt(2) as Double. But we can also use the initialization list to clean up.

change this –
Dim origin(0 To 2) As Double
Dim xAxisPnt(0 To 2) As Double
Dim yAxisPnt(0 To 2) As Double

origin(0) = 4 : origin(1) = 5 : origin(2) = 3
xAxisPnt(0) = 5 : xAxisPnt(1) = 5 : xAxisPnt(2) = 3
yAxisPnt(0) = 4 : yAxisPnt(1) = 6 : yAxisPnt(2) = 3

to this –
Dim origin() As Double = {4, 5, 3}
Dim xAxisPnt() As Double = {5, 5, 3}
Dim yAxisPnt() As Double = {4, 6, 3}

    Sub Ch8_NewUCS()
        Call Connect_acad()
        Dim ucsObj As AcadUCS

        Dim origin() As Double = {4, 5, 3}
        Dim xAxisPnt() As Double = {5, 5, 3}
        Dim yAxisPnt() As Double = {4, 6, 3}

        ' Add the UCS to the UserCoordinatesSystems collection
        ucsObj = ThisDrawing.UserCoordinateSystems.Add(origin, xAxisPnt, yAxisPnt, "New_UCS")
        ' Display the UCS icon
        ThisDrawing.ActiveViewport.UCSIconAtOrigin = True
        ThisDrawing.ActiveViewport.UCSIconOn = True

        ' Make the new UCS the active UCS
        ThisDrawing.ActiveUCS = ucsObj
        MsgBox("The current UCS is : " & ThisDrawing.ActiveUCS.Name & vbCrLf & " Pick a point in the drawing.")

        ' Find the WCS and UCS coordinate of a point
        Dim WCSPnt() As Double
        Dim UCSPnt() As Double

        WCSPnt = CType(ThisDrawing.Utility.GetPoint(, "Enter a point: "), Double())
        UCSPnt = CType(ThisDrawing.Utility.TranslateCoordinates(WCSPnt, AcCoordinateSystem.acWorld, AcCoordinateSystem.acUCS, 0), Double())

        MsgBox("The WCS coordinates are: " & WCSPnt(0) & ", " & WCSPnt(1) & ", " & WCSPnt(2) & vbCrLf &
     "The UCS coordinates are: " & UCSPnt(0) & ", " & UCSPnt(1) & ", " & UCSPnt(2))
    End Sub

8 errors on paste
Set, Arguments not enclosed in parentheses, unfound enumerations that need namespaces, and use of Variant arrays.

Dim firstVertex As Variant
firstVertex = plineObj.Coordinate(0)

looking up Polyline Object in the ActiveX Rerference Guide then clicking on Coordinate says the property value is a two or three element array of doubles.

change to –
Dim firstVertex() As Double
firstVertex = CType(plineObj.Coordinate(0), Double())

Dim coordinateWCS As Variant
coordinateWCS = ThisDrawing.Utility.TranslateCoordinates(firstVertex, AcCoordinateSystem.acOCS, AcCoordinateSystem.acWorld, False, plineNormal)

change to –
Dim coordinateWCS() As Double
coordinateWCS = CType(ThisDrawing.Utility.TranslateCoordinates(firstVertex, AcCoordinateSystem.acOCS, AcCoordinateSystem.acWorld, 0, plineNormal), Double())

    Sub Ch8_TranslateCoordinates()
        Call Connect_acad()
        Dim plineObj As AcadPolyline
        Dim points() As Double = {1, 1, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0, 4, 4, 0}

        ' Create a light weight Polyline object in model space
        plineObj = ThisDrawing.ModelSpace.AddPolyline(points)

        ' Find the X and Y coordinates of the first vertex of the polyline
        Dim firstVertex() As Double
        firstVertex = CType(plineObj.Coordinate(0), Double())

        ' Find the Z coordinate for the polyline using the elevation property
        firstVertex(2) = plineObj.Elevation

        ' Change the normal for the pline so that the difference between the coordinate systems is obvious.
        Dim plineNormal() As Double = {0#, 1.0#, 2.0#}
        plineObj.Normal = plineNormal

        Dim coordinateWCS() As Double
        coordinateWCS = CType(ThisDrawing.Utility.TranslateCoordinates(firstVertex, AcCoordinateSystem.acOCS, AcCoordinateSystem.acWorld, 0, plineNormal), Double())

        ' Display the coordinates of the point
        MsgBox("The first vertex has the following coordinates:" & vbCrLf & "OCS: " & firstVertex(0) & ", " &
     firstVertex(1) & ", " & firstVertex(2) & vbCrLf & "WCS: " & coordinateWCS(0) & ", " & coordinateWCS(1) & ", " & coordinateWCS(2))
    End Sub

here is one we can clean up quite a bit. it pastes in with only two errors, both trivial. It runs just by deleting the word Set, adding AcadApp. in front of ZoomAll and adding Connect_acad as the first line .
Here is the original VBA from Autocad.

Sub Ch8_Create3DMesh()
    Dim meshObj As AcadPolygonMesh
    Dim mSize, nSize, Count As Integer
    Dim points(0 To 47) As Double

    ' create the matrix of points
    points(0) = 0: points(1) = 0: points(2) = 0
    points(3) = 2: points(4) = 0: points(5) = 1
    points(6) = 4: points(7) = 0: points(8) = 0
    points(9) = 6: points(10) = 0: points(11) = 1
    points(12) = 0: points(13) = 2: points(14) = 0
    points(15) = 2: points(16) = 2: points(17) = 1
    points(18) = 4: points(19) = 2: points(20) = 0
    points(21) = 6: points(22) = 2: points(23) = 1
    points(24) = 0: points(25) = 4: points(26) = 0
    points(27) = 2: points(28) = 4: points(29) = 1
    points(30) = 4: points(31) = 4: points(32) = 0
    points(33) = 6: points(34) = 4: points(35) = 0
    points(36) = 0: points(37) = 6: points(38) = 0
    points(39) = 2: points(40) = 6: points(41) = 1
    points(42) = 4: points(43) = 6: points(44) = 0
    points(45) = 6: points(46) = 6: points(47) = 0

    mSize = 4: nSize = 4

    ' creates a 3Dmesh in model space
    Set meshObj = ThisDrawing.ModelSpace. _
 Add3DMesh(mSize, nSize, points)

    ' Change the viewing direction of the viewport
    ' to better see the cylinder
    Dim NewDirection(0 To 2) As Double
    NewDirection(0) = -1
    NewDirection(1) = -1
    NewDirection(2) = 1
    ThisDrawing.ActiveViewport.Direction = NewDirection
    ThisDrawing.ActiveViewport = ThisDrawing.ActiveViewport
End Sub

code that runs in visual studio

   Sub Ch8_Create3DMesh()
        Call Connect_acad()
        Dim meshObj As AcadPolygonMesh
        Dim mSize, nSize, Count As Integer

        Dim points() As Double =
            {0, 0, 0,
             2, 0, 1,
             4, 0, 0,
             6, 0, 1,
             0, 2, 0,
             2, 2, 1,
             4, 2, 0,
             6, 2, 1,
             0, 4, 0,
             2, 4, 1,
             4, 4, 0,
             6, 4, 0,
             0, 6, 0,
             2, 6, 1,
             4, 6, 0,
             6, 6, 0}

        mSize = 4 : nSize = 4
        ' creates a 3Dmesh in model space
        meshObj = ThisDrawing.ModelSpace.Add3DMesh(mSize, nSize, points)

        ' Change the viewing direction of the viewport 
        Dim NewDirection() As Double = {-1, -1, 1}
        ThisDrawing.ActiveViewport.Direction = NewDirection
        ThisDrawing.ActiveViewport = ThisDrawing.ActiveViewport
    End Sub

sample code from object UCS method GetUCSMatrix in ActiveX Reference Guide

Here is the corrected code. I have added a loop to read and print the matrix values.
The orig program creates a new UCS, makes it active, then draws a circle. That illustrates that coordinate input from ActiveX is always interpreted as World coordinates (VBA ignores the current UCS). The program then runs

newMatrix = UCSobj.GetUCSMatrix

which moves the circle from its world coordinates to the equivalent UCS coordinates.

We never have to examine the Matrix or know what its dimensions are. I added a loop to read it. The matrix is a square 4×4. It contains point values as columns. The bottom row seems to be unused.

col1 is the same data as the variable UCSXDIR, its the X vector from the UCS origin.
col2 is the same data as the variable UCSYDIR, its the Y vector from the UCS origin
col3 is the Z vector, which is obtainable from the XY vectors by the right hand rule.
col4 is the origin.

if we were writing our own matrix we would do

dim Matrix(3 , 3) as Double


dim Matrix( , ) as Double =
{ {1,0,0,2},
{ 0,1,0,2},
{ 0,0,1,0},
{ 0,0,0,1} }

these are direction vectors.
UCSXDIR = 1,0,0
UCSYDIR = 0,1,0
Z DIR = 0,0,1

absolute point
UCSORG = 2,2,0

this is not the whole story, Transformation Matrices are a fascinating topic in linear algebra. TransformBy has some useful examples, including scaling, which occurs on the main diagonal. ARX Developers Guide (search on transformation matrix) has better help page than ActiveX. First 3 columns are both rotation and scaling. last column is translation. Transformation matrixes can be combined so translation, scaling and rotation are all accomplished in a single operation.

TransformBy is a method of the elementary AcadEntity, meaning it is enabled for every object in the drawing.

Sub Example_GetUCSMatrix()
        ' This example creates a new UCS and finds the UCS matrix for it.
        ' It then creates a circle using WCS coordinates and
        ' transforms the circle for the UCS.
        Call Connect_acad()

        ' Define a new UCS and turn on the UCS icon at the origin.
        Dim ucsObj As AcadUCS
        Dim origin() As Double = {2, 2, 0}
        Dim xAxisPoint() As Double = {3, 2, 0}
        Dim yAxisPoint() As Double = {2, 3, 0}

        'Dim xAxisPoint() As Double = {4, 4, 0}
        'Dim yAxisPoint() As Double = {0, 4, 0}

        ucsObj = ThisDrawing.UserCoordinateSystems.Add(origin, xAxisPoint, yAxisPoint, "UCS1")
        ThisDrawing.ActiveUCS = ucsObj

        Dim vportObj As AcadViewport
        vportObj = ThisDrawing.ActiveViewport
        vportObj.UCSIconOn = True
        vportObj.UCSIconAtOrigin = True
        ThisDrawing.ActiveViewport = vportObj

        ' Create a circle using WCS coordinates
        Dim circleObj As AcadCircle
        Dim center() As Double = {1, 1, 0}
        Dim radius As Double = 0.5
        circleObj = ThisDrawing.ModelSpace.AddCircle(center, radius)

        ' Get the UCS transformation matrix
        Dim TransMatrix(,) As Double
        TransMatrix = CType(ucsObj.GetUCSMatrix(), Double(,))

        Dim str As String
        Dim r, c As Integer
        For r = 0 To UBound(TransMatrix, 1)
            For c = 0 To UBound(TransMatrix, 2)
                str = "r = " & CStr(r) & " c = " & CStr(c) & "   " & CStr(TransMatrix(r, c))

        ' Transform the circle to the UCS coordinates
        MsgBox("Transform the circle.", , "GetUCSMatrix Example")
        MsgBox("The circle is transformed.", , "GetUCSMatrix Example")
    End Sub

How Do I Access Autocad Com Objects From Visual Studio?

I have stopped ignoring visual studio. I am having no issues accessing Com ActiveX objects from VB.Net with nearly the same code that works in VBA. I am not sure what all the naysaying is about. Every thread i have ever seen on running Com objects from Visual Studio says, Don’t do it, It’s a Bad Idea.

It seems to work fine.

as time goes by I may update this, but at this point –

Right click References in Solution Explorer, Add Reference, add the autocad type library.
To get the Autocad namespace to work across all modules, double click My Project in Solution Explorer and add Autocad to Imported Namespaces.

Get a book or study online the differences in syntax. They are pretty minor. The code editor is much improved. Arrays are a little simplified. Indexing is a little different, no static type. There is no variant type, but there is an object type that microsoft uses to read and write arrays to excel spreadsheets. (microsoft has a good one page link to connect to excel com objects HERE) Autodesk has no such single page that i can find, but here are some useful links.





All methods to be capitalized. All arguments in parentheses. No set statements.
Sometimes you have to figure out how to get the namespace shortcuts to work. The error reporting in vs really helps.
The Try, Catch, End Try error system works more cleanly.
Many more tools to use with collections and array types.
There is a stricter approach to datatypes, a setting to relax it, but i have Option Strict On. this is where a book will help. 2012 books are cheap.

So far i have pasted in VBA code, made changes per notes above, and the same objects work with the same logic – lines, polylines, dimensions, blocks, ucs, text, selection sets.

Code below is for version 2018 (“Autocad.Application.22”)

Module Module_Connect_Acad

    Public acadApp As AcadApplication
    Public acaddoc As AcadDocument
    Public acadms As AcadModelSpace

    Public Sub Connect_acad()
        acadApp = Nothing
        Dim strProgId As String = "AutoCAD.Application.22"

        Try         '' Get a running instance of AutoCAD
            'acadApp = GetObject(, strProgId)
            acadApp = CType(GetObject(, strProgId), AcadApplication)

            Try     '' Create a new instance of AutoCAD
                acadApp = CType(CreateObject(strProgId), AcadApplication)

            Catch ex As Exception
                Exit Sub
            End Try
        End Try

        acadApp.Visible = True  '' Display the application
        ' MsgBox("Now running " & acadApp.Name & " version " & acadApp.Version)

        'load whatever globals needed based on acadapp
        acaddoc = acadApp.ActiveDocument
        acadms = acadApp.ActiveDocument.ModelSpace
    End Sub

End Module