AutoCAD Making VB.net as Easy as VBA

28
Making VB.NET as Easy as VBA Speaker: Jerry Winters ([email protected]) CP9200-2, CP9206-1 The writing is on the wall. VBA, though not gone, will be replaced in the future. But .NET is a different beast. Right? After all, I could draw a line in VBA with four lines of code. Why does it take over twice that number of lines of code to draw a simple line in VB.NET? If you find yourself saying, "It's hard. I don't like change", then this class is for you. Can VB.NET be as easy as VBA? It can. Learn how. About the Speaker: Jerry has emerged as one of the top-rated speakers at Autodesk University on programming topics (VBA, VB.NET, and C# in particular). Forget about the great "stress reduction techniques" that result in AU attendees leaving with everything from power tools, climbing ropes, and remote control carsthere's more to it than this. Jerry's sense of humor and his "I'm just a drafter" approach to programming results in students coming to an understanding of the topic and leaving with a few chuckles.

Transcript of AutoCAD Making VB.net as Easy as VBA

Page 1: AutoCAD Making VB.net as Easy as VBA

Making VB.NET as Easy as VBA Speaker: Jerry Winters ([email protected])

CP9200-2, CP9206-1 The writing is on the wall. VBA, though not gone, will be replaced in the

future. But .NET is a different beast. Right? After all, I could draw a line in VBA with four lines of code. Why does it take over twice that number of lines of code to draw a simple line in VB.NET? If you find yourself saying, "It's hard. I don't like change", then this class is for you. Can VB.NET be as easy as VBA? It can. Learn how.

About the Speaker: Jerry has emerged as one of the top-rated speakers at Autodesk University on programming topics (VBA, VB.NET, and C# in particular). Forget about the great "stress reduction techniques" that result in AU attendees leaving with everything from power tools, climbing ropes, and remote control cars—there's more to it than this. Jerry's sense of humor and his "I'm just a drafter" approach to programming results in students coming to an understanding of the topic and leaving with a few chuckles.

Page 2: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

2

This class will cover the following topics:? Object-oriented programming: why it's really easier

Why VB.NET is hard

Why VBA was easy

Refining programming techniques to simplify our lives

Re-use: only one of the simplification techniques

Object-Oriented Programming: Why it’s really easier Objects are not totally foreign to VBA programming. Right? A lot of variables were declared as things like “acadLayer”, “acadLine”, or “acadBlockReference”. Objects. They had Properties, Methods, and Events. But not everything was an Object. This meant that rather than using Objects to get our work done, we had to rely on a good number of VB Functions to get the job done. Ask yourself the following questions: 1. How do I convert a String to uppercase in VBA? 2. How do I find out the bounds of an Array in VBA? 3. How do I check to see if a file exists in VBA? Answers: 1. Use the UCase function. 2. Use the LBound and UBound functions. 3. Use the Dir Function. In VB.NET, we use Object methods to perform these same tasks instead of VBA functions. Take a look:

Notice the ToUpper, ToLower, and Length methods of the String Object. As for File handling, the FileInfo object has a large number of properties, three of which you see here. The beauty of having Objects to work with is that as we do our work, we are one keystroke away (the period key) from seeing what we can do with a particular Object.

Page 3: AutoCAD Making VB.net as Easy as VBA

3

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

For example, let‟s take the FileInfo Object. This is not AutoCAD-related, but illustrates the point well. We address the FileInfo object by using the variable name. Then we press the period key, and we see the Properties and Methods. This is true for all Objects in the .NET development environment. In review, one of the things that makes VB.NET as easy as, or easier than, VBA is the fact that everything is an Object. VB functions we used to use in VBA are still available for use in VB.NET but equivalent functionality is also available by using the correct variable type or .NET Framework Object.

Page 4: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

4

Why VB.NET is hard (And why VBA was Easy) The title of this section suggests that VB.NET is hard. And for many of it is, or at least it was when we first started writing code. One of the things that made VBA so easy is that we were insulated from many of the actions taking place behind the scenes. Let‟s take a look at an example. We will begin with VB.NET. As we do, let‟s identify the things that are both „harder‟ and „easier‟ between VBA and VB.NET.

Now, in VBA:

Let‟s start with what is similar between the two environments.

Each environment requires us to specify which space (ModelSpace in this example) we want to draw to. (See lines 5 and 25.)

Each environment requires us to specify the Start and End Point for the new line. In VB.NET, this is done through the use of a Point3d Object. In VBA this is done with a 3-element array of Doubles.

Each environment results in the creation of a Line Object (DatabaseServices.Line in VB.NET and AcadLine in VBA).

OK. Now for the differences.

VB.NET requires us to open a BlockTable (what‟s that?) for Read and a BlockTableRecord (what‟s that?) for write. Nothing like that happens in VBA.

VB.NET requires us to start a Transaction from a TransactionManager (whatever that is). Nothing like that happens in VBA.

VB.NET forces us to get the ActiveDocument whereas VBA already has ThisDrawing exposed without any effort on our part.

VB.NET creates a new Command that can be entered from the Command Line. VBA requires us to use the vbarun command or a couple of other methods.

Aside from VB.NET creating a new command for us (which is pretty cool), the differences don‟t look good. Why all of this code just to create a little line in ModelSpace? VBA was nice. Simple. Direct. Why did things have to change? POWER! SPEED! EFFICIENCY! Remember, each step shown in VB.NET code also occurs when VBA is used but we don‟t see it. Let‟s take a look at the steps now.

Page 5: AutoCAD Making VB.net as Easy as VBA

5

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

On the surface, it looks like it takes much more code to draw 10 lines in .NET. But in reality, much more code is executed to draw 10 lines in VBA. This significant increase in processing just to draw 10 lines in ModelSpace demonstrates the potential increase in speed when using VB.NET. So, to restate the question, why is VB.NET hard?

There are additional lines of code that must be used to accomplish a task in VB.NET.

We deal with AutoCAD at a much lower level—the database and transaction level. More detail appears to be greater complexity.

It‟s new to us. And new things take time to get used to.

It‟s not integrated inside AutoCAD so there are more things that can ‟go wrong‟. The rest of this class will demonstrate how we can overcome these „difficulties‟ and realize the power of .NET with the simplicity we enjoyed in VBA.

VB.NET VBA

Begin Transaction Begin Transaction

Open BlockTable for Read Open Block Table for Read

Open ModelSpace for Write Open ModelSpace for Write

Add Line 1 Add Line 1

Add Line 2 Commit Transaction

Add Line 3 Begin Transaction

Add Line 4 Open Block Table for Read

Add Line 5 Open ModelSpace for Write

Add Line 6 Add Line 2

Add Line 7 Commit Transaction

Add Line 8 Begin Transaction

Add Line 9 Open Block Table for Read

Add Line 10 Open ModelSpace for Write

Commit Transaction Add Line 3

Commit Transaction

Begin Transaction

Open Block Table for Read

Open ModelSpace for Write

Add Line 4

Commit Transaction

Begin Transaction

Open Block Table for Read

Open ModelSpace for Write

Add Line 5

Commit Transaction

You get the idea.

Page 6: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

6

Refining programming techniques to simplify our lives One way we can make VB.NET as easy as VBA is to replicate what Autodesk did when it gave us the COM API which is used in VBA. We are going to look at a good number of Functions in VB.NET that, when used, simplify our .NET Development. Let‟s start with drawing in AutoCAD.

We can feed this ModelSpaceAdd function any Object that can normally be drawn in ModelSpace and it gets added to ModelSpace. Let‟s try it.

Going forward, any time we want to draw anything in ModelSpace, we can use the ModelSpaceAdd Function to make VB.NET as easy as VBA. Easier, actually. One line of code, one line in ModelSpace. Not bad. Let‟s talk about what we‟re doing here. We are taking the repetitive steps of Transaction, BlockTable, BlockTableRecord (ModelSpace), and Commit out and creating a Function just to do those things. OK. So now it‟s as easy to add entities to ModelSpace in VB.NET as it was in VBA. What about PaperSpace? You gotta love copy and paste. Change one line of code, a variable name, and change the name of the Function and now we‟re drawing in PaperSpace just as easily as we are drawing in ModelSpace. Compare lines 1, 7, and 8 to lines 41, 47, and 48 to see the difference between the two Functions.

Page 7: AutoCAD Making VB.net as Easy as VBA

7

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

Our ModelSpaceAdd and PaperSpaceAdd Functions work well and replicate what is happening in VBA. Everything. Including creating a new transaction for each and every entity we want to add. Can we improve this function so we can add multiple entities under the umbrella of one Transaction? We can. But before we do, let‟s look at some numbers. A benchmark, if you will.

Here are the results of running three Functions. Each draws a 1000 x 1000 grid of lines in AutoCAD giving us 2002 lines total. At first, when we look at this, we think, “Hey, we‟re talking about milliseconds here. Who is going to notice the difference between a command running in 342 milliseconds versus 22 milliseconds? Fair enough. But the difference between the two is significant. One runs not twice as fast, not four times as fast, but ten times as fast as the other. Take that factor of 10 and use it in anything else you deal with on a daily basis and the difference means much more. What if you could drive your car 10 times faster than you can currently drive it? What if your computer were 10 times faster than it is right now? What if you were paid 10 times what you are being paid right now. Big difference? You bet!

The numbers presented here are interesting to be sure. But they are much more than simply „interesting‟. They should be compelling. Compelling enough to encourage us to „get with the program‟. Specifically, the VB.NET Program. DrawingManyA uses a function named “ModelSpaceAdd” which receives an array of Entity Objects. The BlockTable and ModelSpace are opened once. The Transaction is started once. Then each entity is added to ModelSpace and to the Transaction. Then the Transaction is Committed. DrawingManyA calls ModelSpaceAdd one time. DrawingManyB uses a function named “ModelSpaceAdd” which receives a single Entity and which is called 2002 times instead of one time. Each time ModelSpaceAdd is called, it begins a Transaction, opens the BlockTable and ModelSpace, adds the Entity, and commits the Transaction. DrawingManyC uses VBA code.

Times when debugging through VB.NET Debug Compile Setting 43 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 74 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 25 milliseconds for DrawingManyA 24 milliseconds for DrawingManyA

342 milliseconds for DrawingManyB 287 milliseconds for DrawingManyB 309 milliseconds for DrawingManyB 279 milliseconds for DrawingManyB 280 milliseconds for DrawingManyB 280 milliseconds for DrawingManyB 282 milliseconds for DrawingManyB 283 milliseconds for DrawingManyB 280 milliseconds for DrawingManyB 281 milliseconds for DrawingManyB 289 milliseconds for DrawingManyC 266 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 266 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC

Times when AutoCAD is started normally Release Compile Setting 25 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 54 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA 22 milliseconds for DrawingManyA

253 milliseconds for DrawingManyB 233 milliseconds for DrawingManyB 289 milliseconds for DrawingManyB 245 milliseconds for DrawingManyB 238 milliseconds for DrawingManyB 237 milliseconds for DrawingManyB 237 milliseconds for DrawingManyB 236 milliseconds for DrawingManyB 236 milliseconds for DrawingManyB 241 milliseconds for DrawingManyB 262 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC

Page 8: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

8

On the previous page, we looked at the results of a benchmark between VBA, VB.NET mimicking VBA, and VB.NET in its raw power. You may have noticed that both DrawingManyA and DrawingManyB used a function named “ModelSpaceAdd” but they provided different types of arguments. That‟s one of the beauties of the .NET world. It‟s called overloading a Function. One Function name, multiple Function definitions which each use a unique parameter fingerprint. Let‟s look at those functions now.

DrawingManyA uses the ModelSpaceAdd Function here on this page. It is called once and passed an Array of Entity Objects. DrawingManyB uses the ModelSpaceAdd Function on Page 6 and it is called once for every entity that needs to be drawn in ModelSpace. The VBA macro DrawingManyC is found on the next page. Not only is it similar structurally to DrawingManyB but it the time required to run is nearly identical to DrawingManyB.

NOTE: When run using the Debug Configuration and AutoCAD is started by VB.NET, the VB.NET code runs noticeably slower. And it looks as though VBA runs faster than VB.NET. However, when compiled as Released and AutoCAD is started normally, the times between DrawingManyB and DrawingManyC are nearly identical which is what we would expect to see.

Page 9: AutoCAD Making VB.net as Easy as VBA

9

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

All of this benchmarking and code comparisons may seem to be off topic, but it helps illustrate how we can take steps to make our .NET development as easy as VBA development while enjoying the benefits of potential performance gains in the VB.NET (and I should probably also mention C#) world. To illustrate this further, let‟s look at how we could use our two ModelSpaceAdd Functions.

Here‟s some code that is drawing entities one at a time. Notice how some entities can be drawn successfully as they are instantiated (using the New method). Others take a little more attention. Let‟s see how this code would look if we use the overloaded ModelSpaceAdd Function.

Page 10: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

10

The geometry created in AutoCAD is the same whether we run DrawSomeStuff or DrawSomeMoreStuff. Yes, my friends, it is a self portrait. I am a stick figure. More to the point, we can see that adding all entities using one transaction is fairly simple and straight forward when we have a function at our disposal as we do here. Now, the title of this section is “Refining our programming techniques”. One of those techniques is to create rock-solid functions that we can use over and over again. This simplifies our future code creation and it takes substantially less time overall in our programming if we do this. So, let‟s look at the above code, DrawSomeMoreStuff, and see what we can do to simplify our code. The first thing I see is that it takes several lines of code to add Text whereas it only takes one line of code to draw a line. Let‟s see if we can do something about that.

Page 11: AutoCAD Making VB.net as Easy as VBA

11

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

OK. Raise your right hand. Repeat after me. “I, (state your name) will forever and ever and ever use the CreateText Function whenever I want to add Text to an AutoCAD Drawing”. Why would we say something like that? Because look how easy it is now to add Text to AutoCAD.

And to make it even easier on us, we have followed the same parameter fingerprint as the VBA AddText call. So for those of us who have had the AddText call drilled into our permanent short, long, and forever-term memory, we‟ll feel right at home. Adding text? No problem. What about adding a Polyline? Hummmm. That is a different beast altogether. Let‟s see what we can work out.

Page 12: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

12

The two Functions on the previous page both return a Polyline. The ParamArray is a Parameter that can have any number of arguments supplied to it. We‟ll see how it‟s used in a little while. The Point2dCollection is just what it sounds like. Having two different ways to create a Polyline provides us flexibility as we make use of these Functions. And we can add more. For example, what is the most common polyline created? I don't‟ have statistics to back this up, but I would guess in most cases, it is a rectangle. Why not make a Function that creates a Rectangle Polygon based on X, Y, Width, and Height parameters? And what about a regular Polygon? That should be simple enough.

Now, creating Rectangles and regular Polygons can be done with one line of code.

Notice Line 42 where we supply X,Y values. We can supply as many as we want as long as they are supplied in pairs. And we must supply at least 3 pairs or else . . . or else what? Take a look at Line 23 on the previous page. You and I have put up with Exception errors so much that we‟re sick of them. Right? Well, now it‟s our turn to throw some errors. That‟s right. We get to throw errors. And the error message can be as nice or as harsh as we see fit. Yeah!!! (To be screamed with great fervor) But on second thought, we should be kind. So, after the Exception message is written in words we can normally only dream of using, we must remember to modify them to be more kind and gentle.

Page 13: AutoCAD Making VB.net as Easy as VBA

13

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

OK. We‟ve drawn lines, polylines, text, circles, arcs, ellipses. What‟s left? BLOCKS! WE WANT BLOCKS! Blocks are great. There are a few things we need to keep in mind as we insert Blocks. If the Block does not have Attributes, there is much less to do. If it does have Attributes, we need to insert the Block, and then we need to append the Block‟s Attributes to the Block Reference. It‟s a little more involved than the code we have worked with thus far but, remember my friends, once we have a rock-solid Function, we can use it over and over again without having to rewrite the code.

Yes, it‟s more code than our previous examples. But it takes a little more to insert a Block than it does to draw a line. After adding the BlockReference to ModelSpace, we must look at the Block Definition, find AttributeDefinitions, and add them to the inserted Block at their appropriate locations (See Line 26). Inserting a Block is nice. But what about the Attributes? How do we set their values? If we look carefully at the Function “ModelSpaceInsertBlock”, we will find that the ObjectID of the inserted Block is returned to us.

Page 14: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

14

The BlockReference ObjectID we get from ModelSpaceInsertBlock is used in our SetAttribute Procedure. We also provide an Attribute Tag and a Value. That‟s all it takes. Let‟s take a look at the code in action.

One line to insert a Block, one line to set an Attribute Value. Not bad. As Easy as VBA? You can‟t argue with one line of code.

Page 15: AutoCAD Making VB.net as Easy as VBA

15

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

OK. Ready for another example? We‟ve drawn in ModelSpace enough. Let‟s move on to extracting our drawing data. Shall we? Blocks and Attributes. We love to extract Blocks and Attributes.

OK. We‟re introducing something new here. In previous examples, we have retrieved the MdiActiveDocument and started the Transaction through either the Document or its Database. In this example, we are starting the Transaction from the Database of the ObjectID passed in the BlockObjectID Parameter. We‟ll appreciate why this is being done a little later on. Just remember that we can get the Database of an Object through its ObjectID. Also worthy of note is the Hashtable return type. This contains a list of paired items—a key and a value. How do we use this Function? Here‟s one way:

We use an If . . Then statement to determine if the Attribute Reference exists in the Hash Table. This example has the user select one Block Reference. Let‟s try expanding this now and export Block Attributes to Microsoft Excel. We are going to do a mass export, which means, every block with every attribute will be exported. Before we do that, though, let‟s talk about purpose of doing this. We have already identified the fact that at times, it takes more VB.NET code to perform something as compared with VBA. Our goal here is to make VB.NET as easy as VBA. We are going to look at a Function called “GetAllBlocksAndAtts” that does just as it states. We will get all inserted Blocks with their Names, handles, positions, scale factors, rotation, and attributes. There are many ways we could do this. We will show a couple of them.

Page 16: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

16

OK. This is fairly straight forward. We are getting all Blocks with their data into an Array List. Notice how we are using the GetBlockAtts Function we created earlier. One thing we can do to make VB.NET as easy as VBA is to create Functions that can be used in a variety of situations. Also notice that we are looking to see if the BlockReference is Dynamic. We do this because we do not have an ‟EffectiveName‟ property in .NET as we do in VBA. If we find a Dynamic Block, we get its DynamicBlockTableRecord to get the effective block name. Please note that we are getting the Blocks from the Active Document. This is important. We can use a Selection Filter (See Lines 6 and 7) when we select our Blocks if we have access to a Document‟s Editor. If we don‟t have access to a Document‟s Editor, we can not use the Selection Filter. So, why do we care? Won‟t we always have access to a Document? Well, not if you want to use the power of .NET. Using VBA, it was possible to access an AutoCAD .dwg file that was not open in AutoCAD. The same can be done in .NET. We‟ll get to that in a moment. Let‟s try using this GetAllBlocksAndAtts Function.

If you‟re thinking to yourself, “this code looks easy”, then we‟re going down the right path.

Page 17: AutoCAD Making VB.net as Easy as VBA

17

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

All we need is the GetAllBlocksAndAtts Function (which also uses the GetBlockAtts Function) and we can extract our Blocks and Attributes very easily. We can write data out into Excel, a Database, an XML file, .txt file. You name it. And it‟s easy once we have the Functions that make it easy. And now you have the Functions to make it easy. We mentioned earlier that the code we have depends on the Active Document. There are times when that will work just fine. At other times, however, we won‟t have a Document at all. All we‟ll have is a Database. Let‟s keep our existing GetAllBlocksAndAtts Function, copy and Paste it, and add one parameter, a Filename.

Instead of using a Filter to get only BlockReferences, we are looking at each entity in each Layout (ModelSpace and PaperSpace Layouts) and checking to see if it (the entity) is a BlockReference. If it is, we get the Object as a BlockReference and then we use the same GetBlockAtts code with the Block Reference‟s ObjectID. Let‟s see how we could use this Function.

Page 18: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

18

NOTE: In order for this code to work properly, a Reference needs to be made to System.Windows.Forms. Now we‟re browsing for a .dwg file to open and using it in our overloaded GetAllBlocksAndAtts Function.

Page 19: AutoCAD Making VB.net as Easy as VBA

19

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

REVIEW Let‟s review what we have discussed before we proceed. 1. It generally takes more code in VB.NET than it does in VBA to accomplish a specific task. 2. We can make VB.NET as easy as VBA by putting the „complicated code‟ into Functions that are then called by our

commands. 3. We have provided a good amount of code already during this class that can be used to draw in AutoCAD, insert

blocks, and extract Block data. 4. We have seen that communicating with Microsoft Excel is close to identical as when we do so in VBA.

Applying What We Have Discussed Thus Far OK. We know that defining a new AutoCAD command is easy.

We have created a number of Functions that do a number of things. Let‟s use what we already have and see if we can do something we haven‟t seen yet.

This is a Copy and Paste of WriteBlocksToExcel3. One piece of one line of code has changed. We are getting the Handle now instead of the Layer. But why? The Handle allows us to „get back‟ to the block. NOTE: It must be stated here that we could have gotten the Handle of the AttributeReference as well. This would be a more direct way to get to the AttributeReference to change its value.

Page 20: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

20

When I run WriteBlocksToExcel3, I see a number of blocks without Attributes at the top. After removing them, I see the following:

Look at all of those Receptacles with empty ESTCODE attributes. Let‟s fill them up in Excel.

That‟s better. Now, how can we update the drawing so the attributes have those same values? Is it going to be difficult in VB.NET? Well, there‟s a little logic involved but it‟s not different than it would be in VBA.

Page 21: AutoCAD Making VB.net as Easy as VBA

21

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

OK. First things first. We have a Handle. From that handle we need an ObjectID. Yes, there are a few steps leading up to getting the ObjectID as we can see here. But the beauty of this Function is that it is written and can be used from now on anytime we have a Handle and want an ObjectID. Now we‟re going to see how this ObjectIDFromHandle works.

We need to remember what our Excel Spreadsheeet looks like when we run the WriteBlocksToExcel3 code. We have the Block Name in Column “A” and the Block‟s Handle in Column “B”. Attribute Tags appear in Column “C” and Attribute Values appear in Column “D”. But wait a minute! Wasn‟t this supposed to be about making VB.NET simple? Yes. Please remember that the code shown above looks a little crazy because we are parsing an Excel Spreadsheet. The primary difference between this code and code written in VBA would be the ObjectIDFromHandle. In VBA we would use the HandleToObject call. Since there is not a single-call equivalent in VB.NET, we created one. NOTE: Notice the CommandFlags.Session in the CommandMethod. This is CRITICAL. When we open a new document and make it the Active Document, the Command that had been started in the other drawing will come to an end if this Flag is not set.

Page 22: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

22

We‟ve seen a number of examples now of how a Function can be used that hides some of the unpleasant details we must face when developing in VB.NET. Let‟s take a look at exactly how we can create a useful Function when we have an existing need. PROGRAMMING CHALLENGE: Our drawings are a mess. Whoever made them put everything on Layer “0” (Zero). Lines belong on the Line Layer, Circles belong on the Circles layer. Arcs belong on the Arcs Layer. Text belongs on the Text Layer. And everything should have ByLayer Color and ByLayer Linetype. STEP 1 Get a working prototype that has the ability to take a selected entity and change its layer.

Seems simple enough. And everything works great as long as the user selects an entity an as long as a Layer named “LINE” exists. If not, bad things happen. How bad, you ask? Bad. Bad, bad, bad. Baaaaaaaad. To see an example of Bad, hit the Escape key when the user is prompted to select an entity. Baaaaaaaad. But if the user follows directions and everything is in place as it should be, the code works great. Now, we want to create a Function to modify an entity‟s Layer. Perhaps it could look like this:

The code shown here is functionally the same as the code shown in Lines 1-9 above. Our goal here is to create a Function that can be used by any of our other programming. We supply an ObjectID and a Layername to the Function “ChangeEntLayer” and (hopefully), the layer of the provided Object will be changed. Why the word “hopefully”? That doesn‟t exactly fill us with confidence, does it? What happens if we ask an ObjectID to be placed on a Layer that does not exist?

Page 23: AutoCAD Making VB.net as Easy as VBA

23

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

STEP 2 Error Handling. We haven‟t done this as of yet because our focus has been on other concepts and principles. Well, it is now time to focus on this principle. What could possible go wrong with our ChangeEntLayer Function? If Mr. Murphy (of Murphy‟s Law fame) attempted to execute our code, what would go wrong? Answer: anything that could go wrong. What happens if the Layer doesn‟t exist? What happens if the ObjectID is null? What happens if the ObjectID is not valid? And how do we deal with things if these „issues‟ appear? Answers to these questions may depend on your individual situation. Perhaps we just ignore the entity if the Layer does not exist. Or perhaps we should create the Layer if the Layer does not exist.

Here‟s one way to handle problems that may arise. Enclose all of the code in one big Try Catch statement. This is equivalent to using the “On Error Resume Next” statement in VBA. The goal here is to ignore any problems that arise. The main difference between this and “On Error Resume Next” is that if the code has an error on Line 5, it jumps to Line 8 instead of attempting to execute Line 6. And if an error does occur, we don‟t know about it because we aren‟t doing anything after the Catch statement.

That‟s a different way of handling the „Layer does not exist‟ issue. We use a Try Catch statement around a single statement (see Line 5). And we are looking for a specific type of error. The KeyNotFound error will occur if we attempt to use something that has a specific name but that doesn't exist.

Page 24: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

24

STEP 3 Overload your Function. The Function “ChangeEntLayer” works well IF you can supply an ObjectID and a Layername. What if you don‟t have an ObjectID? What if you only have an Entity? Or a dbObject? Or an ObjectID Collection? Or a Selection Result?

And there‟s more where that came from.

Page 25: AutoCAD Making VB.net as Easy as VBA

25

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

As we can see in these Functions, small changes to the Parameters and inside the Functions is all that needs to happen to overload a Function.

Page 26: AutoCAD Making VB.net as Easy as VBA

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

26

The Functions on the previous two pages test well using the following „testing‟ commands. These are here for your benefit so you can test them on your own. They also show the small amount of code needed now that we have our layer change Functions in place.

STEP 4 USE YOUR FUNCTIONS!!!! OK. I apologize for shouting. But we spend so much time reinventing wheels that we have already invented many times before. I‟m guilty of this as well. In the next section, we will discuss ways to organize our code so we can reuse our Functions. STEP 5 Breathe. Breathing keeps you healthy.

Page 27: AutoCAD Making VB.net as Easy as VBA

27

CP9200-2, CP9206-1—Making VB.NET as Easy as VBA

Re-use: only one of the simplification techniques We just spoke about using our Functions once they have been created. How can we do this? (1) Copy and paste all code into a separate ASCII Text file. Notepad will do fine. Then save this file to a central

location where it can be inserted into VB.NET using the Edit > Insert File as Text menu picks. (2) Create separate Code Modules that can be referenced into our projects as needed. For example, a Module could

be created that is used just for Entity Modification. Another could be used for geometric calculations. (3) Use Code Snippets. A Code Snippet is a piece of code that can be inserted into our projects by right-clicking in

Visual Studio and selecting “Insert Snippet”. Snippets are XML files formatted to hold Code, Imports statements, and other programming elements.

(4) Microsoft Office OneNote 2007. I have been using this program more and more to organize data. It could be used to organize code. For example, a Note can be added with a Function. In the same Note, a PDF file can be embedded documenting the Function, how to test it, etc.

REVIEW VBA was nice. It was simple. Direct. No worrying about things such as Transactions, etc. Well, as the song goes, “That was then, this is now”. VB.NET is powerful. With that power comes a degree of responsibility we didn‟t deal with in VBA. That responsibility shows itself in giving us greater control over smaller details which often means more code. The biggest hurdle for VBA programmers migrating to VB.NET is the new API. As we become familiar with the .NET API, we can organize our code in ways that make VB.NET not only as easy as VBA but in many cases, easier and more powerful. I hope we have been able to demonstrate some of that today. And I hope your Autodesk University 2009 experience is a great one! Jerry Winters

Page 28: AutoCAD Making VB.net as Easy as VBA