Error 4 type autocad.acadentity is not defined

error 4 type autocad.acadentity is not defined

Since the extended data is of your own design and AutoCAD has no way of knowing method works with an existing object supplied as the type AcadEntity. No new features or enhancements have been added to AutoLISP for AutoCAD Link error types (integer), (setq acadObject (vlax-get-Acad-object)). We want to type a function (the right side of Y = some expression of X) For 2D the Z value is not required but is required by autocad.

Thematic video

How to Solve Net framworker error in AutoCAD setup

Are not: Error 4 type autocad.acadentity is not defined

PLEASE NOTE THAT ALTHOUGH THIS ERROR
Error 4 type autocad.acadentity is not defined
HARD DISK ERROR 1 301
Error 4 type autocad.acadentity is not defined
Error 4 type autocad.acadentity is not defined
error 4 type autocad.acadentity is not defined

Thread: VBA routine now returns a Run-time Error in AutoCAD 2007

Code:

Public Sub VDist() 'This sub creates a table with block, candela, and distance information 'for purposes of voltage drop calculations. On Error Resume Next ' Define variables 'AutoCAD Objects Dim objMText As AcadMText Dim objBlockRef As AcadBlockReference Dim objTable As AcadTable Dim objTableStyle As AcadTableStyle Dim objText As AcadText Dim dictObj As AcadDictionary Dim dictionaries As AcadDictionaries Dim objCurLayer As AcadLayer Dim error 4 type autocad.acadentity is not defined As AcadEntity Dim ActiveLayer As AcadLayer 'Selection Set Variables. Dim ssSelSet As AcadSelectionSet Dim FilterType(0) As Integer Dim FilterData(0) As Variant 'Strings Dim KeywordList As String Dim Keywords As String Dim inputString As String Dim strDistDisplay As String Dim strBlockName() As String Dim strCandela() As String Dim keyName As String Dim className As String Dim strCircuit As String 'Integers Dim intDist As Integer Dim intDrop As Integer Dim intTotal As Integer Dim intCount As Integer Dim I As Integer Dim intDistances() As Integer Dim intDevNum As Integer Dim intInString As Integer 'Long Dim lngDevCount As Long Dim lngRows As Long 'Variants Dim varAttributes As Variant Dim varReturn As Variant Dim varLabels As Variant Dim varPoint1 As Variant Dim varPoint2 As Variant Dim Insert As Variant Dim varScale As Variant Dim varResults As Variant (Had to remove rest of code. It was too long. :D) Finish: 'Set layer for table Set objCurLayer = ThisDrawing.ActiveLayer mdlLayers.FANNOINDC 'Resize array variables to appropriate dimenstions. ReDim strBlockName(intCount + 1) ReDim strCandela(intCount + 1) 'Create new table style for VDrop Table. keyName = "VDropTables" className = "AcDbTableStyle" Set objTableStyle = dictObj.AddObject(keyName, className) objTableStyle.Name = "VDropTables" objTableStyle.SetTextStyle acDataRow, "ROMANS" objTableStyle.SetTextStyle acHeaderRow, error 4 type autocad.acadentity is not defined, "ROMANS" objTableStyle.SetTextStyle acTitleRow, "ROMANS" objTableStyle.SetAlignment acDataRow, acMiddleCenter objTableStyle.HorzCellMargin = 0.0625 * varScale objTableStyle.VertCellMargin = 0.0625 * varScale photoshop runtime error Table with VDrop data. On Error GoTo 0 Insert = ThisDrawing.Utility.GetPoint(, "Specify text insertion point: ") lngRows = intCount + 3 Set objTable = ThisDrawing.ModelSpace.AddTable(Insert, lngRows, 4, 0.25 * varScale, 1# * varScale) 'Set objTable = ThisDrawing.ModelSpace.AddTable(Insert, intCount + 5, 4, 0.25 * varScale, 100) objTable.StyleName = "VDropTables" 'Setup column labels. If varLabels = vbYes Then intInString = Error 718 vpn connection, "-") - 1 objTable.SetText 0, 0, error 4 type autocad.acadentity is not defined, Left(strCircuit, intInString) & " VDrop Data" Else objTable.SetText 0, 0, "VDrop Data" End If objTable.SetText 1, 0, "Count" objTable.SetText 1, 1, "BlockName" objTable.SetText 1, 2, "Candela" objTable.SetText 1, 3, "Distance" 'Cycle through each block and extract name and candela information. intCount = 0 For Each objBlockRef In ssSelSet strBlockName(intCount) = objBlockRef.Name varAttributes = objBlockRef.GetAttributes For I = 0 To UBound(varAttributes) If varAttributes(I).TagString = "CANDELA_RATING" Then strCandela(intCount) = varAttributes(I).TextString End If Next I intCount = intCount + 1 Next 'For each leg in circuit, cycle through data to insert in table. For I = 0 To UBound(intDistances) If strBlockName(I) <> "" Then objTable.SetText I + 2, 0, strCircuit & CStr(I + 1) objTable.SetText I + 2, 1, strBlockName(I) objTable.SetCellAlignment I + 2, 1, acMiddleLeft If strCandela(I) = "" Then strCandela(I) = " " End If objTable.SetText I + 2, 2, strCandela(I) objTable.SetText I + 2, 3, CStr(intDistances(I)) intTotal = intTotal + intDistances(I) End If Next I 'Format Table Columns. objTable.SetColumnWidth 0, 0.5 * varScale objTable.SetColumnWidth 1, 1.5 * varScale objTable.SetColumnWidth 2, 0.8 * varScale objTable.SetColumnWidth 3, 0.8 * varScale 'Insert totals in table. objTable.SetText I + 3, 2, "Total Circuit Length:" objTable.SetText I + 3, 3, intTotal objTable.SetText I + 4, error 4 type autocad.acadentity is not defined, 2, "Total Devices: " error 4 type autocad.acadentity is not defined I + 4, 3, CStr(I) ClearSets: 'Reset layer to previous layer. ThisDrawing.ActiveLayer = objCurLayer ssSelSet.Delete End Sub
Thanks!
MC

Working with Extended Data in VBA and AutoLISP

31 Dec, 1999By: Bill Kramer

Extended data is nongraphic information that is attached to AutoCAD entity objects in your drawing. It is very useful when you are writing programs that need additional information on top of the data already present in an object. For example, suppose you wanted to draw a fence line on a map and along with the data points you wanted to include information about the last time the fence section was repaired or updated. Extended data would work well for this application.

This month we are going to explore extended data manipulated by a VBA program as compared to one manipulated in AutoLISP. There are some important differences in the way you go about such an activity depending on the language you select. They are summarized in the fact that in VBA we manipulate objects while in AutoLISP we manipulate entity data lists. Using objects for such manipulations is much easier to fathom than navigating convoluted entity data lists as will be seen. The only potential uncomfortable part for beginners involves the use of variant arrays in VBA. But once that concept is under control, the rest is easy.

Extended data is stored in an error 4 type autocad.acadentity is not defined using group codes just as with all other data found in entity objects. From the AutoLISP and DXF programming perspective, this is the normal way entity objects are accessed. That is, each component in an entity object has a group

Table 1
Common Extended Data Group Codes
Code Represents Data type 1000 Application name Application name 1001 Text value String 1005 Entity handle string String 1010 Data point X Real 1020 Data point Y Real 1030 Data point Z Real 1040 Number Real 1041 Scaled distance value Real 1070 Integer Integer value
code that indicates what kind of data follows. But for VBA programmers, the use of group codes may be new since the normal properties of the entity objects are directly accessed as needed. For example, if you have a line object open, you access the starting point using the StartPoint property of the object. There are no group codes involved in VBA applications development except for the extended data. Table 1 lists the most common group codes used for extended data elements.

Group Codes
Group codes can be repeated over and over again in the extended data. Should your application require five real numbers, then five different instances of the 1040 group code would be used. The group codes, their order and their associated data values are completely controlled by your application. In fact, the only restriction you will face in the use of group codes is that each data object can only hold up to 16 kilobytes of extended data. That's a lot of information and most applications will not even come close to this requirement. If they do, then another data storage strategy is strongly recommended.

Multiple applications can also store extended data in a single entity object. Your program may store data and so may others at the same time. And AutoCAD does not mix them up. The way in which AutoCAD keeps the information intact is actually your responsibility.

Using a common name can lead to confusion where the extended data is concerned.

Using a unique name, your data is differentiated from that of other programs. The extended data name is of your own design and should be unique for your application.

One way to obtain a unique name for your extended data is to search through the registered applications with a given name and see if it has been used. In AutoLISP you accomplish this using the (TBLSEARCH) subr, as shown in Listing 1 (All listings are at the bottom of this page). The function New_AppID has one argument-a seed name as devised by your application. Use any name you want. Based on internal storage and searching requirements in AutoCAD, a registered application name should not be too long, so I recommend that you keep the name to about 15 or 20 characters in length. Of course it can be longer, but why use up the space for a longer name?

Listing 2 shows the same in VBA. The extended data application names are stored in a collection named RegisteredApplications. In VBA a DO loop is used to access the collection until a new name is found. Item() is used inside the loop with the key name (a string) containing the seed string and the incrementing counter, just as in the AutoLISP code. After the function finds a new application name, it is added to the collection. The addition of the name to the collection is not required in VBA as it is in AutoLISP. VBA will add a new name the first time it is used as part of an entity object update.

After an application name has been determined, your program can now add extended data to AutoCAD entity objects. At first glance, the approach is a bit confusing. Since the extended data is of your own design and AutoCAD has no way of knowing what you may want to store, general-purpose storage containers have been devised for the purpose.

In AutoLISP, all extended data is appended to objects using a -3 group code in the entity list. Within the group code you can find all of the extended data that has been added to the object. It is a nested list within the entity list and thus the confusion for many beginning AutoLISP programmers. Sometimes the issue is cleared up a little when looking at what is required when adding extended data.

Adding extended data to an object in AutoLISP is simply a matter of appending it to an existing (or new) entity data list. The extended data is stored in a list with the group codes appropriate to the data type. The following is a simple example of a string, a real number and an integer stored in an extended data list format.

((1001. "String") (1040. 1.234) (1070. 12)) The data appears in the same style as a regular entity data list, error 4 type autocad.acadentity is not defined. The only differences are that the group codes used are in the 1000 series, and the data itself is of your own design. But this list represents just the data itself. To add it to an entity data list, you must add the application name to the front. If our registered application name is "EXAMPLE", error 4 type autocad.acadentity is not defined, then the list error 4 type autocad.acadentity is not defined look similar to the following: ("EXAMPLE" (1001. "String") (1040. 1.234) (1070. 12)) Now you add the group code for extended data. There can be any number (up to the memory limits of extended data) of Xdata lists contained inside the -3 group code set. Each must have a unique name as the first member of the list. And each name must be registered first using (REGAPP) so that AutoCAD recognizes it as valid extended data. (-3 ("EXAMPLE" (1001. "String") (1040. 1.234) (1070. 12))) The extended data list with group code -3 is then appended to the end of an entity data list that is in turn error 4 type autocad.acadentity is not defined to the drawing database, error 4 type autocad.acadentity is not defined. Appending the list can be accomplished through the use of the (APPEND) subr with an existing entity data list and then writing the data to the drawing with (ENTMOD). New entities can have the extended data list included as part of the new entity data list that is written to the drawing database using the (ENTMAKE) subr, error 4 type autocad.acadentity is not defined. Because of the nested lists involved, many novice AutoLISP programmers tend to shy away from the use of extended data or use utility routines that shield them from the nasty details. (Note that extended data utility routines for AutoLISP programmers can be obtained from the Web site listed at the end of this column.)

By comparison, the addition of extended data in VBA involves a different approach. In VBA, the extended data is added to an object after it has been added to the drawing database. The entity is created first to obtain an entity object that can be used to reference the method available for storing the extended data. All AutoCAD drawing objects support the method SetXData. This method allows a program to affix extended data to an existing drawing object. Listing 3 demonstrates how the SetXData method works with an existing object supplied as the type AcadEntity. In this simple example, an entity object is supplied along with three data elements (a string, a real number and an integer). The object's SetXData method is used to write the three data elements to the drawing database after they are placed into a variant array along with an application name ("MyData"in the example listing).

Integer and Variant Arrays
Two error 4 type autocad.acadentity is not defined are required for the SetXData method. The first array contains only integer values that are the matching group codes for the data being attached. The other array is a variant array that contains the data itself. Thus to add a string one must put a 1001 group code into the integer array and the string value into the variant array at the same position.

At the head of the variant/integer array combination is the application name stored with a 1000 group code. Without this value, the extended data does not have a valid registered application name and will not be added. The function shown in Listing 2 can be error 4 type autocad.acadentity is not defined to obtain a unique name for your extended data, or you can simply make one up as shown in Listing 3. One item of note is that you do not have to register the application name being used in the extended data when using VBA. All you need to do is use it, and it will be added to the registered names for you automatically. But if you want to guarantee that the name you are using is your own, registering it first is the only way to go. Otherwise you could be carelessly overwriting someone else's extended data!

Variant arrays are used in the writing and retrieving of extended data in VBA. Variants allow for multiple data storage types all referenced with a common name. This is much like lists in AutoLISP. The member of a list or variant array can be of error 4 type autocad.acadentity is not defined supported data type. When the SetXData member is used with a valid entity object, the extended data is written to the object in the drawing database. Internally the system converts the data in the variant array using the group codes supplied in the integer array to store the data in proper containers. Although the data type is found in the variant data elements themselves, your application may want to treat the values differently and thus the group codes are required to further classify the data, error 4 type autocad.acadentity is not defined. For example, group code 1040 signifies a normal real number, but you use group code 1041 when you want the number to be automatically updated whenever the object is scaled. When AutoCAD sees a group code 1041 being added as extended data, it sets up the scaling operation for us thereby relieving our application of the burden.

Getting extended data from an object requires the use of the registered application name. Since more than one application may attach data to an object, the data you are interested in must be specifically requested by name. In AutoLISP this is achieved in the (ENTGET) subr with the inclusion of a list of application names following the entity name to get. To illustrate, the following expression is supplied with an entity name (EN) and will return an entity list (stored in EL) with extended data that has the application name "EXAMPLE".

(setq EL (entget EN ,("EXAMPLE"))) The application name is stored in a list so that multiple applications can be retrieved in a single statement. Extended data is then found using the -3 group code in the entity data list. The (cdr (assoc -3 EL)) expression will return the extended data list. If multiple extended data lists are being used, the (ASSOC) subr can then be used to get them from within the extended data set. If only one set of extended data is requested, the (ASSOC) can be used, but the common approach is to use composite primitives (CAR) and (CDR) instead, error 4 type autocad.acadentity is not defined. Using the example I started earlier in this column, the variable XD is set to the extended data found in the entity list EL. (setq XD (cdr (assoc -3 EL))) The above code results in the following when used with our previous example data. (("EXAMPLE" (1001. "String") (1040. 1.234) (1070. 12))) The extended data can now be further reduced to something more useful. Taking the (CAR) of this error 4 type autocad.acadentity is not defined will return the "EXAMPLE" extended data and then taking the (CDR) will result in just the extended data without the application name "EXAMPLE" at the beginning. The next expression places just the extended data into the list XD. (setq XD (cdar XD)) ((1001. "String") (1040. 1.234) (1070. 12)) This is why retrieving extended data looks complicated in AutoLISP. The operations just outlined are often bunched together into a single expression, such as the following: (setq XD (cdadr (assoc -3 EL))) The composite primitive (CDAR) was expanded to include the (CDR) used to remove the -3 group code obtained from the (ASSOC) subr. Although elegant in the conservative usage of code, this sort of data manipulation can be complicated to follow in the source code. That is where VBA is superior. The access of extended data from an object in VBA is accomplished with the GetXData method. Given the application name as the first parameter to GetXData, the method will fill in two variants with array data. These variant arrays contain the group code integers and the data values respectively. The data will be returned in the same order as it was placed into the entity object.

Listing 4 contains a portion of code that will ask the operator to select an entity and will then retrieve the extended data for an application named "MyData". (Again, a more complete example using a dialog box to display extended data can be found at the Web site listed at the end of the column.)

Retrieving Extended Data in VBA
Retrieval of extended data in VBA relies heavily on variant data types, error 4 type autocad.acadentity is not defined. The values in XdT and XdV from Listing 4 can be retrieved using LBound and UBound. LBound(XdT) will return the index of the first entry in the array; UBound (XdT) will result in the last index in the array. An incrementing counter can be used to loop from one value to the next and obtain the extended data elements.

Both AutoLISP and VBA provide generic methods for obtaining extended data since AutoCAD cannot possibly know what your intentions may be when developing an application that uses them. Some applications may even use multiple registered application names to help keep the extended data separated based on the demands of various interrelated components. As an example, a beam centerline object may contain details about the cross section of the beam as a set of extended data and information about the current loading on the beam as another. That way the application interested in only the cross section can obtain that information directly without having to wade through the loading data and so forth.

It is the generic nature of extended data that scares many people away until they find a need for it. But it is also that same nature that gives extended data the power and flexibility needed to be used in the engineering and architectural computer graphics arena. Your applications and those of other developers can utilize this tool set to build intelligent objects. The next step is into reactors that are tied to these objects so that your application runs as they are manipulated. Using extended data to hold the data and reactors to maintain the integrity of the overall system greatly enhances the way your applications will work with the users. Until next time, keep on programming!

(All code along with more complete examples can be found at www.autocode.com, the author's primary Web site.)

Listing 1.
Find a Unique Application Name(defun New_AppID ( SeedName ;String name for application / Cnt ;incrementing counter ) (setq CNT 1) ;;initialize counter (while (tblsearch "APPID" (strcat SeedName (itoa Cnt))) ;;Found one, increment counter (setq Cnt (1+ Cnt))) ;;register the application (regapp (strcat SeedName (itoa Cnt))) ;;return name used (strcat SeedName (itoa Cnt))
Listing 2.
Add New Application in VBAPrivate Function NewAppID( _ Seed As String) _ As String Dim I As Integer I = 0 On Error Resume Next With ThisDrawing.RegisteredApplications Do I = I + 1 Err.Clear .Item(Seed & Str(I)) Loop Until Err.Number <> 0 .Add (Seed & Str(I)) End With NewAppID = Seed & Str(I) End Function
Listing 3.
Adding Xdata in VBAPrivate Sub XDataAdd( _ Obj As AcadEntity, _ Item1 As String, _ Item2 As Double, _ Item3 As Integer _ ) Dim TypArray(0 To 3) As Integer Dim ValueArray(0 To 3) As Variant TypArray(0) = 1001 'Application name ValueArray(0) = "MyData" ' TypArray(1) = 1000 'string item ValueArray(1) = Item1 ' TypArray(2) = 1040 'real number ValueArray(2) = Item2 ' tls error unroutable control packet received TypArray(3) = 1070 'integer number error 4 type autocad.acadentity is not defined ValueArray(3) = Item3 ' Obj.SetXData TypArray, ValueArray End Sub
Listing 4.
Retrieve Xdata in VBADim Ob As AcadEntity 'Entity object Dim PP As Variant 'Selection point Dim XdT As Variant 'Group codes Dim XdV As Variant 'Data values On Error Resume Next ThisDrawing.Utility.GetEntity Ob, PP, "Select" If Err.Number = 0 Then Ob.GetXData "MyData", XdT, XdV ' process continues==


Hi,

it seems very strange that your code break into indicated code row.

Did you try to check minimal reference library ?

Inside VBA development area click on Tolls ->Reference, and a window like this shall appear:

grobnik_0-1586767038495.png

Enabled library shall be minimal for running your code, doesn't matter at this time the release picture is showing, it's depending on the Autocad release do you have installed. If you find something enabled with MISSING word before the library name, try to investigate if necessary to your code (I guess no because all library showed before, shall be enough for your scope), in case disable.

Other option could be a debug of your code inserting a breaking point F9 key, into strategic point or run the code step by step with F8 key and for example when error appears click on debug and check the "ent" variable.

You can do also debug before running the code. right click on "ent" variable and then "add watch", the same for any other variable, but in this case the other variable are only declared as type:

grobnik_1-1586767584754.png

then the watch window shall appear:

grobnik_2-1586767709341.png

 

In a first time when the routine it's not running you will see inside the Value Column <out of context>, later you should view the value, or information on the variable "ent".

I hope this should help you more in your issue. On the opposite send us your drawing or part of it we will see the issue.

 

Regards

 

Autocad Object Types in 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, error 4 type autocad.acadentity is not defined. 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, error 4 type autocad.acadentity is not defined. VB.Net has a good new array feature called an initialization list.

you can change all this –

Dim points2D(0 To 5) As Double
error 4 type autocad.acadentity is not defined 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 –

*******************
NewUCS
*******************
9 errors on paste
Set
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, error 4 type autocad.acadentity is not defined, 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} Error 4 type autocad.acadentity is not defined yAxisPnt() As Double = {4, 6, 3} ' Add the UCS to the UserCoordinatesSystems collection error 4 type autocad.acadentity is not defined 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

*******************
TranslateCoordinates
*******************
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())

and
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 Error 4 type autocad.acadentity is not defined 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 ' Raise_application_error syntax oracle 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) & ", error 4 type autocad.acadentity is not defined, " & coordinateWCS(1) & ", " & coordinateWCS(2)) End Sub

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

ModelSpace. _ Add3DMesh(mSize, nSize, points) ' Change the viewing direction of the viewport ' to better see the cylinder error 4 type autocad.acadentity is not defined Dim NewDirection(0 To 2) As Double NewDirection(0) = -1 NewDirection(1) = -1 NewDirection(2) = 1 haspflt.sys, cant start driver - error 1275 ThisDrawing.ActiveViewport.Direction = NewDirection ThisDrawing.ActiveViewport = ThisDrawing.ActiveViewport ZoomAll 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, error 4 type autocad.acadentity is not defined 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 acadApp.ZoomAll() End Sub

*************
GetUCSMatrix
************
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 quicken error 1602 interpreted as World coordinates (VBA ignores the current UCS). The program then runs

newMatrix = UCSobj.GetUCSMatrix
circleobj.Transformby(newMatrix)

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, error 4 type autocad.acadentity is not defined.

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(33) as Double

or

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 error 4 type autocad.acadentity is not defined 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, error 4 type autocad.acadentity is not defined, 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, error 4 type autocad.acadentity is not defined. ' 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) acadApp.ZoomAll() ' 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)) Debug.Print(str) Next Next ' Transform the circle to the UCS coordinates MsgBox("Transform the circle.","GetUCSMatrix Example") circleObj.TransformBy(TransMatrix) circleObj.Update() MsgBox("The circle is transformed.","GetUCSMatrix Example") acadApp.Update() End Sub
This entry was posted in Autocad Visual Studio .NET and tagged Autocad VB.Net on by frfly.

Thanks for your insistence on this "EntityType" thing.

Yes, you are correct: AcadEntity does have this hidden property, called
"EntityType". I have been writing Acad VBA code since it was available and
never heard of it, and it is not only "not documented", but also not
"visibly" exposed in COM API (at least in VB/VBA's object browser, you do
not see it). So, I never know this property exists, not to mention to use
it. Fortunately, the "TypeOf.Is." is available and more user friendly,
so I did not miss something, other than arguing with you for its existence, error 4 type autocad.acadentity is not defined. fatal error 023e BTW, how do you found out this hidden property while using VBA?

So, back to your original post, you need to find a AcadBlockReference, which
is an AcadEntity, not a AcadBlock, which is not an AcadEntity. You can
either use

If Element.EntityType=7 Then 'AcadBlockRefernece's EntityType is 7
.
End If

or

If TypeOf e Is AcadBlockReference Then
.
End If


"Robby Tanner"

Error 4 type autocad.acadentity is not defined - really

Thread: VBA routine now returns a Run-time Error in AutoCAD 2007

Code:

Public Sub VDist() 'This sub creates a table with block, candela, and distance information 'for purposes of voltage drop calculations. On Error Resume Next ' Define variables 'AutoCAD Objects Dim objMText As AcadMText Dim objBlockRef As AcadBlockReference Dim objTable As AcadTable Dim objTableStyle As AcadTableStyle Dim objText As AcadText Dim dictObj As AcadDictionary Dim dictionaries As AcadDictionaries Dim objCurLayer As AcadLayer Dim objEntity As AcadEntity Dim ActiveLayer As AcadLayer 'Selection Set Variables. Dim ssSelSet As AcadSelectionSet Dim FilterType(0) As Integer Dim FilterData(0) As Variant 'Strings Dim KeywordList As String Dim Keywords As String Dim inputString As String Dim strDistDisplay As String Dim strBlockName() As String Dim strCandela() As String Dim keyName As String Dim className As String Dim strCircuit As String 'Integers Dim intDist As Integer Dim intDrop As Integer Dim intTotal As Integer Dim intCount As Integer Dim I As Integer Dim intDistances() As Integer Dim intDevNum As Integer Dim intInString As Integer 'Long Dim lngDevCount As Long Dim lngRows As Long 'Variants Dim varAttributes As Variant Dim varReturn As Variant Dim varLabels As Variant Dim varPoint1 As Variant Dim varPoint2 As Variant Dim Insert As Variant Dim varScale As Variant Dim varResults As Variant (Had to remove rest of code. It was too long... :D) Finish: 'Set layer for table Set objCurLayer = ThisDrawing.ActiveLayer mdlLayers.FANNOINDC 'Resize array variables to appropriate dimenstions. ReDim strBlockName(intCount + 1) ReDim strCandela(intCount + 1) 'Create new table style for VDrop Table. keyName = "VDropTables" className = "AcDbTableStyle" Set objTableStyle = dictObj.AddObject(keyName, className) objTableStyle.Name = "VDropTables" objTableStyle.SetTextStyle acDataRow, "ROMANS" objTableStyle.SetTextStyle acHeaderRow, "ROMANS" objTableStyle.SetTextStyle acTitleRow, "ROMANS" objTableStyle.SetAlignment acDataRow, acMiddleCenter objTableStyle.HorzCellMargin = 0.0625 * varScale objTableStyle.VertCellMargin = 0.0625 * varScale 'Insert Table with VDrop data. On Error GoTo 0 Insert = ThisDrawing.Utility.GetPoint(, "Specify text insertion point: ") lngRows = intCount + 3 Set objTable = ThisDrawing.ModelSpace.AddTable(Insert, lngRows, 4, 0.25 * varScale, 1# * varScale) 'Set objTable = ThisDrawing.ModelSpace.AddTable(Insert, intCount + 5, 4, 0.25 * varScale, 100) objTable.StyleName = "VDropTables" 'Setup column labels. If varLabels = vbYes Then intInString = InStr(strCircuit, "-") - 1 objTable.SetText 0, 0, Left(strCircuit, intInString) & " VDrop Data" Else objTable.SetText 0, 0, "VDrop Data" End If objTable.SetText 1, 0, "Count" objTable.SetText 1, 1, "BlockName" objTable.SetText 1, 2, "Candela" objTable.SetText 1, 3, "Distance" 'Cycle through each block and extract name and candela information. intCount = 0 For Each objBlockRef In ssSelSet strBlockName(intCount) = objBlockRef.Name varAttributes = objBlockRef.GetAttributes For I = 0 To UBound(varAttributes) If varAttributes(I).TagString = "CANDELA_RATING" Then strCandela(intCount) = varAttributes(I).TextString End If Next I intCount = intCount + 1 Next 'For each leg in circuit, cycle through data to insert in table. For I = 0 To UBound(intDistances) If strBlockName(I) <> "" Then objTable.SetText I + 2, 0, strCircuit & CStr(I + 1) objTable.SetText I + 2, 1, strBlockName(I) objTable.SetCellAlignment I + 2, 1, acMiddleLeft If strCandela(I) = "" Then strCandela(I) = " " End If objTable.SetText I + 2, 2, strCandela(I) objTable.SetText I + 2, 3, CStr(intDistances(I)) intTotal = intTotal + intDistances(I) End If Next I 'Format Table Columns. objTable.SetColumnWidth 0, 0.5 * varScale objTable.SetColumnWidth 1, 1.5 * varScale objTable.SetColumnWidth 2, 0.8 * varScale objTable.SetColumnWidth 3, 0.8 * varScale 'Insert totals in table. objTable.SetText I + 3, 2, "Total Circuit Length:" objTable.SetText I + 3, 3, intTotal objTable.SetText I + 4, 2, "Total Devices: " objTable.SetText I + 4, 3, CStr(I) ClearSets: 'Reset layer to previous layer. ThisDrawing.ActiveLayer = objCurLayer ssSelSet.Delete End Sub
Thanks!
MC
AutoCAD 2006 VBA

The GetXXX methods get specific types of data from the user. These methods make AutoCAD pause until the user supplies a value at the command prompt or picks a point in the drawing window. If the user supplies the wrong type of data, such as typing a string when a number is needed, AutoCAD displays a message at the command prompt that tells them to reenter the data.

The GetKeyword Method

The GetKeyword method gets a command line option from the user. You must call InitializeUserInput to establish the list of keywords before you use this method. It returns the keyword the user entered exactly as the keyword list specified it. If you want, you can include a prompt to display on the command line while the function waits for user input. This method has the following syntax:

strUserKeyWordInput = Object.GetKeyword([Prompt])

This method's Prompt parameter is a string that contains the prompt to display on the command line.

If the user tries to enter a string that's not in the keyword list, AutoCAD displays the error message Invalid option keyword in the command window. AutoCAD then tries to get valid user input by redisplaying the prompt if you specified one or by displaying a blank command line if you didn't. If you allow null input, the user can press Enter to return an empty string.

This example asks the user for an option and then starts the specified command, using the SendCommand method outlined in Appendix A:

Sub TestGetKeyword() Dim strInput As String

With ThisDrawing.Utility

.InitializeUserInput 0, "Line Arc Circle" strInput = .GetKeyword(vbCr & "Command [Line/Arc/Circle]: ") End With

Select Case strInput

Case "Line": ThisDrawing.SendCommand "_Line" & vbCr Case "Arc": ThisDrawing.SendCommand "_Arc" & vbCr Case "Circle": ThisDrawing.SendCommand "_Circle" & vbCr Case Else: MsgBox "You pressed Enter."

End Select

End Sub

The GetString Method

The GetString method gets string values from the user. AutoCAD pauses until the user enters a value. This method has the following syntax:

dblUserStringInput = UtilityObject.GetString(HasSpaces[ ,Prompt]) Table 7-3 lists this method's parameters.

This example gets a string from the user, including spaces, and then displays it:

Public Sub TestGetString() Dim strInput As String

With ThisDrawing.Utility strInput = .GetString(True, vbCr & "Enter a string: ") .Prompt vbCr & "You entered '" & strInput & "' " End With End Sub

This method lets the user enter up to 132 characters. Entering more than 132 characters generates the error Method 'GetString' of object 'IAcadUtility' failed, which is unfortunately the same description reported when a user issues a Cancel or Esc. If you need to distinguish between the overflow and the Cancel for this method, consider using the unique exception number instead of the description.

The Getlnteger Method

The GetInteger method gets an integer from the user. AutoCAD waits for the user to input an integer and returns the entered value. This method has the following syntax:

intUserIntegerInput = UtilityObject.GetInteger([Prompt])

This method has one parameter, Prompt, a string. Optionally use it to specify a prompt for input.

The user may enter either an integer in the range -32,768 to +32,767 or a keyword (see "The GetInput Method" later in the chapter for more information). If the user tries to enter any other value, AutoCAD returns the error message Requires an integer value or option keyword and asks the user to enter another value. Here's an example of GetInteger:

Public Sub TestGetInteger() Dim intInput As Integer

With ThisDrawing.Utility intInput = .GetInteger(vbCr & "Enter an integer: ") .Prompt vbCr & "You entered " & intInput End With End Sub

This method throws exceptions for null input, keyword entry, and canceled input.

The GetReal Method

The GetReal method is similar to GetInteger but gets floating-point numbers. It returns a value of data type Double.

dblUserRealInput = UtilityObject.GetReal([Prompt])

This method's Prompt parameter, a string, is optional. Use it to specify a prompt for input.

This method accepts any real (double-precision floating-point) value or any previously set keyword. For more about these keywords, see "The GetInput Method" later in this chapter. If the user enters any other value, AutoCAD returns the error message Requires numeric value and asks the user to enter another value. This example retrieves and displays a real value from the user:

Public Sub TestGetReal() Dim dblInput As Double

With ThisDrawing.Utility dblInput = .GetReal(vbCrLf & "Enter an real: ") .Prompt vbCr & "You entered " & dblInput End With End Sub

This method raises an exception for null input, keyword entry, and canceled input.

The GetPoint Method

The GetPoint method gets a point from the user, either by typing coordinates at the command prompt or by picking points in the drawing area. The return value is a Variant data type and contains a three-element array of doubles holding the point's World Coordinate System (WCS) coordinates. This method has the following syntax:

varUserPointInput = UtilityObject.GetPoint([BasePoint] [,Prompt])

Table 7-4 explains this method's parameters.

The optional BasePoint parameter sets a rubber-band line's start point. This line, which extends to the current crosshair position, can be a useful visual aid to the user during input. This example gets a point from the user and displays its coordinate values:

Public Sub TestGetPoint() Dim varPick As Variant

With ThisDrawing.Utility varPick = .GetPoint(, vbCr & "Pick a point: ") .Prompt vbCr & varPick(0) & "," & varPick(1) End With End Sub

This method raises exceptions for null input, keyword entry, and canceled input.

The GetCorner Method

Given a base point in a rectangle, the GetCorner method gets the diagonally opposing corner point. It returns a Variant data type and contains a three-element array of doubles showing the corner point's WCS coordinates. This method has the following syntax:

varUserCornerInput = UtilityObject.GetCorner(BasePoint [,Prompt])

Table 7-5 explains this method's parameters.

If the user picks a point on the graphic screen, the GetCorner method ignores the point's Z-coordinate and sets it to the current elevation. This example gets a point and then a corner from the user and displays the rectangle's values:

Public Sub TestGetCorner() Dim varBase As Variant Dim varPick As Variant

With ThisDrawing.Utility varBase = .GetPoint(, vbCr & "Pick the first corner: ") .Prompt vbCrLf & varBase(0) & "," & varBase(1) varPick = .GetCorner(varBase, vbLf & "Pick the second: ") .Prompt vbCr & varPick(0) & "," & varPick(1) End With End Sub

This method throws exceptions for null input, keyword entry, and canceled input.

The GetDistance Method

The GetDistance method gets a double from the user. It differs from GetReal in that the user can either type a distance in the current units format or pick the point(s) on the graphics screen. These two methods are otherwise similar, and most people prefer GetDistance because it's more flexible. This method has the following syntax:

dblUserDistanceInput = UtilityObject.GetDistance([BasePoint] [,Prompt]) Table 7-6 explains this method's parameters.

■ Note This method lets you enter a negative number at the command prompt and returns this negative number. But it calculates the absolute distance between points if you enter it on the graphics screen.

If the user chooses to pick points from the screen, AutoCAD draws a rubber-band line as a visual aid from the base point, or first pick point, to the current crosshair position. By default, the points are 3-D. You may force AutoCAD to calculate a planar distance by first calling InitializeUserInput with a bit code of 16 in OptionBits. This makes AutoCAD ignore the Z-coordinates.

This example code sets the base point to the origin of WCS, prompts the user for input, and then displays the value:

Public Sub TestGetDistance() Dim dblInput As Double Dim dblBase(2) As Double dblBase(0) = 0: dblBase(1) = 0: dblBase(2)

With ThisDrawing.Utility dblInput = .GetDistance(dblBase, vbCr & .Prompt vbCr & "You entered " & dblInput End With End Sub

This method raises an exception for null input, keyword entry, and canceled input.

The GetAngle Method

Use the GetAngle to get an angle, in radians, from the user. The user may either type the angle at the command prompt or pick point(s) on the screen. VBA ignores the points' Z-coordinates. It measures the angle counterclockwise with respect to the ANGBASE system variable's current value. This method has the following syntax:

dblUserAngleInput = UtilityObject.GetAngle([BasePoint] [,Prompt])

"Enter a distance: ")

Table 7-7 explains this method's parameters.

This method returns the angle in radians regardless of the current setting of the DIMAUNIT angular units system variable or the angular unit type the user entered. In this way, it acts in a similar manner to the Utility object's AngleToReal conversion method.

This example sets the angular units to degrees and then retrieves and displays an angle from the user:

Public Sub TestGetAngle() Dim dblInput As Double

ThisDrawing.SetVariable "DIMAUNIT", acDegrees

With ThisDrawing.Utility dblInput = .GetAngle(, vbCr & "Enter an angle: ") .Prompt vbCr & "Angle in radians: " & dblInput End With End Sub

This method throws exceptions for null input, keyword entry, and canceled input.

The GetOrientation Method

The GetOrientation method is similar to GetAngle, except that the angle returned is always measured from the east, or three o'clock, regardless of the ANGBASE system variable setting. This method has the following syntax:

dblUserOrientationInput = UtilityObject.GetOrientation([BasePoint] [,Prompt]) Table 7-8 explains this method's parameters.

This method throws an exception for both null input and keyword entry if allowed and supplied.

The Getlnput Method

As mentioned in the discussion of GetKeyword, you can use seven other input methods in conjunction with the keywords set using InitializeUserInput:

• GetInteger

• GetDistance

• GetAngle

• GetOrientation

• GetPoint

• GetCorner

When these methods have keywords and they are executed, the user can enter the data type requested or choose one of the available keywords. Because each of these input methods returns a specific data type, each can't also return the keyword string. Instead, the input methods use an exception with the description User input is a keyword to signal the presence of a keyword. Unless null input is disabled, VBA uses this same exception to indicate null input, such as when the user simply presses Enter at the input prompt.

Your code must handle the exception, or the program will stop and display an error message. After detecting this exception, use GetInput to retrieve the keyword before calling any other GetXXX method. The GetInput method takes no parameters. It returns either a string containing the keyword in InitializeUserInput or an empty string in the case of null input.

StrUserKeywordInput = UtilityObject.GetInput()

As shown in the previous examples, it is not necessary to call the GetInput method after the GetXXX methods when no keywords are offered to the user. If called independently, this method returns an empty string.

The following code retrieves either an integer or a keyword from the user. It uses GetInteger to demonstrate the GetInput method, but the technique is identical for each of the six other input methods:

Public Sub TestGetInput() Dim intInput As Integer Dim strInput As String

On Error Resume Next ' handle exceptions inline

With ThisDrawing.Utility strInput = .GetInput() .InitializeUserInput 0, "Line Arc Circle"

intInput = .GetInteger(vbCr & "Integer or [Line/Arc/Circle]: ")

If Err.Description Like "*error*" Then

.Prompt vbCr & "Input Cancelled" ElseIf Err.Description Like "*keyword*" Then strInput = .GetInput() Select Case strInput

Case "Line": ThisDrawing.SendCommand "_Line" & vbCr Case "Arc": ThisDrawing.SendCommand "_Arc" & vbCr Case "Circle": ThisDrawing.SendCommand "_Circle" & vbCr Case Else: .Prompt vbCr & "Null Input entered" End Select

Else

.Prompt vbCr & "You entered " & intInput End If End With

End Sub

This example first sets the keywords using InitializeUserInput and then uses an input method to get the user's input. Because the code sets keywords, the input method either returns an integer or throws an exception when the user enters a keyword. If there was an exception and it contains the word error, this code displays a cancel message. Otherwise, if the exception contains the word keyword, the code uses GetInput to retrieve the keyword and takes an appropriate action based on the keyword. If no exception was thrown, this code uses the Integer value the GetInteger method returned.

A bug causes GetInput to return the keyword from earlier calls to InitializeUserInput when the user enters null input at a later input method that takes keywords. The following code demonstrates the problem. Choose any option at the first input prompt and then press Enter for the second input. In case the user enters a keyword, the second call to GetInput should return a null—but instead it returns the keyword you selected in the previous input.

Public Sub TestGetInputBug()

On Error Resume Next ' handle exceptions inline

With ThisDrawing.Utility

'' first keyword input .InitializeUserInput 1, "Alpha Beta Ship" .GetInteger vbCr & "Option [Alpha/Beta/Ship]: " MsgBox "You entered: " & .GetInput()

'' second keyword input - hit Enter here .InitializeUserInput 0, "Bug May Slip" .GetInteger vbCr & "Hit enter [Bug/May/Slip]: " MsgBox "GetInput still returns: " & .GetInput() End With End Sub

Because null and keyword input throw the same exceptions, GetInput's return value is the only way to determine which the user entered. But because of this odd persistence of the previous keyword entry, no sure way exists to determine whether the user entered a keyword or nothing at all.

The following code demonstrates a partial workaround for this problem. The technique is to grab the existing keyword from GetInput before calling InitializeUserInput for the second GetXXX method. If, after getting input from the user, the newly entered keyword matches the previous keyword, it's possible that the user entered a null.

Public Sub TestGetInputWorkaround() Dim strBeforeKeyword As String Dim strKeyword As String

On Error Resume Next ' handle exceptions inline

With ThisDrawing.Utility

'' first keyword input .InitializeUserInput 1, "This Bug Stuff" .GetInteger vbCrLf & "Option [This/Bug/Stuff]: " MsgBox "You entered: " & .GetInput()

'' get lingering keyword strBeforeKeyword = .GetInput()

'' second keyword input - press Enter .InitializeUserInput 0, "Make Life Rough" .GetInteger vbCrLf & "Hit enter [Make/Life/Rough]: " strKeyword = .GetInput()

'' if input = lingering, it might be null input If strKeyword = strBeforeKeyword Then

MsgBox "Looks like null input: " & strKeyword

Else

MsgBox "This time you entered: " & strKeyword End If End With

End Sub

The GetEntity Method

Use the GetEntity method to select an AutoCAD object by letting the user pick an entity from the graphics screen.

■ Note Because the user may type L for the last entity in the drawing window, this method can return an invisible entity or an entity that's on a frozen layer. However, in 2005 and 2006, AutoCAD will select the last visible entity.

This method has the following syntax: UtilityObject.GetEntity PickedEntity, PickedPoint[, Prompt] Table 7-9 explains this method's parameters.

Table 7-9. TheGetEntity Method's Parameters

Name

Type

Description

PickedEntity

AcadEntity object

Output. Returns a reference to the drawing object that the user picked.

Output. A three-element array of doubles that specifies the point by which the entity was picked in WCS.

Optional. A prompt for input.

PickPoint

Variant

Prompt

String

This example gets an entity from the user and displays the point's object type and coordinates:

Public Sub TestGetEntity() Dim objEnt As AcadEntity Dim varPick As Variant

On Error Resume Next

With ThisDrawing.Utility

.GetEntity objEnt, varPick, vbCr & "Pick an entity: " If objEnt Is Nothing Then 'check if object was picked. .Prompt vbCrLf & "You did not pick as entity" Exit Sub End If

.Prompt vbCr & "You picked a " & objEnt.ObjectName .Prompt vbCrLf & "At " & varPick(0) & "," & varPick(1) End With End Sub

GetEntity raises an error if the input is null, such as when there is no entity at the picked point, or if the user presses Enter without selecting an entity. The example checks for this condition to avoid the error.

The GetSubEntity Method

Use the GetSubEntity method in place of GetEntity when you need to obtain subentity information based on the user's selection. A subentity is an entity that another entity contains, such as an entity in a block or a vertex entity contained in polylines. This method lets the user pick an entity or subentity from the graphics screen and returns details about that entity and any object that contains it.

■ Note Like GetEntity, this method can return an entity even if it is not currently visible or is on a frozen layer because the user can type L to select the last entity in the drawing window. However, in 2005 and 2006, AutoCAD will select the last visible entity.

This method has the following syntax: UtilityObject.GetSubEntity PickedEntity, PickPoint, Matrix, Context[, Prompt] Table 7-10 explains this method's parameters.

Table 7-10. TheGetSubEntity Method's Parameters

Name

Type

Description

PickedEntity

PickPoint

Matrix

Context

Prompt

AcadEntity object

Variant

Variant

Variant

String

Output. Returns a reference to the drawing object that the user picked.

Output. A three-element array of doubles that specifies an angle vector's first point in WCS.

Output. Returns a four-by-four element array of doubles that holds the selected entity's translation matrix.

Output. Returns an array of long integers holding the ObjectIds for each parent block containing the selected entity, if the entity is in a block.

Optional. A prompt for input.

The Matrix output parameter is the selected entity's Model to World Transformation Matrix. It is a composite of all the transformations involved in the entity's visible representation. Imagine a line stored in a block, which is also stored in a block. The Matrix output parameter encapsulates each scale, rotation, and translation involved in the nested line's display. You can use it to translate points from the internal Model Coordinate System (MCS) to WCS.

The Context output parameter is an array of the ObjectIds for any objects that contain the selected entity. For the example line, this would be an array of two ObjectIds, one for each nesting level of the containing blocks. To get information about each containing entity, use the ObjectIdToObject method of the Document object to convert the ObjectId to an object reference.

The following example uses the Prompt method to display information about the selected entity and any containing entities. Try it on a variety of entities, including those nested in blocks.

Public Sub TestGetSubEntity() Dim objEnt As AcadEntity Dim varPick As Variant Dim varMatrix As Variant Dim varParents As Variant Dim intI As Integer Dim intJ As Integer Dim varID As Variant

With ThisDrawing.Utility

'' get the subentity from the user

.GetSubEntity objEnt, varPick, varMatrix, varParents, _ vbCr & "Pick an entity: "

'' print some information about the entity .Prompt vbCr & "You picked a " & objEnt.ObjectName .Prompt vbCrLf & "At " & varPick(0) & "," & varPick(1)

'' dump the varMatrix

If Not IsEmpty(varMatrix) Then

.Prompt vbLf & "MCS to WCS Translation varMatrix:"

'' format varMatrix row For intI = 0 To 3

'' format varMatrix column For intJ = 0 To 3

.Prompt "(" & varMatrix(intI, intJ) & ")" Next intJ

.Prompt "]" Next intI .Prompt vbLf End If

'' if it has a parent nest If Not IsEmpty(varParents) Then

.Prompt vbLf & "Block nesting:"

'' traverse most to least deep (reverse order)

For intJ = UBound(varParents) To LBound(varParents) Step -1

'' indent output

'' parent object ID varID = varParents(intJ)

'' parent entity

Set objEnt = ThisDrawing.ObjectIdToObject(varID)

'' print info about parent

.Prompt objEnt.ObjectName & " : " & objEnt.Name Next intJ .Prompt vbLf End If .Prompt vbCr End With End Sub

GetSubEntity throws an exception if the input is null, such as when there is no entity at the picked point or when the user presses Enter without selecting an entity.

Figure 7-3 shows the result of picking a line that forms part of a block reference named Window.

Figure 7-3. The TestGetSubEntity command line output

Continue reading here: Handling Errors in User Input

Was this article helpful?