Sie sind auf Seite 1von 28

Making VB.

NET as Easy as VBA


Speaker: Jerry Winters (jerryw@vbcad.com)

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.

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

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

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

For example, lets 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.

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

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. Lets take a look at an example. We will begin with VB.NET. As we do, lets identify the things that are both harder and easier between VBA and VB.NET.

Now, in VBA:

Lets 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 (whats that?) for Read and a BlockTableRecord (whats 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 dont 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 dont see it. Lets take a look at the steps now. 4

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

VB.NET Begin Transaction Open BlockTable for Read Open ModelSpace for Write Add Line 1 Add Line 2 Add Line 3 Add Line 4 Add Line 5 Add Line 6 Add Line 7 Add Line 8 Add Line 9 Add Line 10 Commit Transaction

VBA Begin Transaction Open Block Table for Read Open ModelSpace for Write Add Line 1 Commit Transaction Begin Transaction Open Block Table for Read Open ModelSpace for Write Add Line 2 Commit Transaction Begin Transaction Open Block Table for Read Open ModelSpace for Write 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.

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 levelthe database and transaction level. More detail appears to be greater complexity. Its new to us. And new things take time to get used to. Its 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.

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

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. Lets 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. Lets 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. Lets talk about what were 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 its 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 were 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.

CP9200-2, CP9206-1Making 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, lets look at some numbers. A benchmark, if you will. 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 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 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, were talking about milliseconds here. Who is going to notice the difference between a command running in 342 milliseconds versus 22 342 milliseconds for DrawingManyB 253 milliseconds for DrawingManyB milliseconds? Fair 287 milliseconds for DrawingManyB 233 milliseconds for DrawingManyB enough. But the 309 milliseconds for DrawingManyB 289 milliseconds for DrawingManyB difference between the 279 milliseconds for DrawingManyB 245 milliseconds for DrawingManyB two is significant. One 280 milliseconds for DrawingManyB 238 milliseconds for DrawingManyB runs not twice as fast, not 280 milliseconds for DrawingManyB 237 milliseconds for DrawingManyB four times as fast, but ten 282 milliseconds for DrawingManyB 237 milliseconds for DrawingManyB times as fast as the 283 milliseconds for DrawingManyB 236 milliseconds for DrawingManyB other. Take that factor of 280 milliseconds for DrawingManyB 236 milliseconds for DrawingManyB 10 and use it in anything 281 milliseconds for DrawingManyB 241 milliseconds for DrawingManyB else you deal with on a daily basis and the 289 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC difference means much 266 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC more. What if you could 262 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC drive your car 10 times 262 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC faster than you can 262 milliseconds for DrawingManyC 258 milliseconds for DrawingManyC currently drive it? What if 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC your computer were 10 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC times faster than it is 266 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC right now? What if you 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC were paid 10 times what 262 milliseconds for DrawingManyC 262 milliseconds for DrawingManyC 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. 7

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

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. Thats one of the beauties of the .NET world. Its called overloading a Function. One Function name, multiple Function definitions which each use a unique parameter fingerprint. Lets 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. 8

CP9200-2, CP9206-1Making 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, lets look at how we could use our two ModelSpaceAdd Functions.

Heres 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. Lets see how this code would look if we use the overloaded ModelSpaceAdd Function.

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

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, lets 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. Lets see if we can do something about that.

10

CP9200-2, CP9206-1Making 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 foreverterm memory, well feel right at home. Adding text? No problem. What about adding a Polyline? Hummmm. That is a different beast altogether. Lets see what we can work out.

11

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

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. Well see how its 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 were sick of them. Right? Well, now its our turn to throw some errors. Thats 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. 12

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

OK. Weve drawn lines, polylines, text, circles, arcs, ellipses. Whats 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 Blocks Attributes to the Block Reference. Its 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, its 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. 13

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

The BlockReference ObjectID we get from ModelSpaceInsertBlock is used in our SetAttribute Procedure. We also provide an Attribute Tag and a Value. Thats all it takes. Lets 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 cant argue with one line of code.

14

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

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

OK. Were 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. Well 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 itemsa key and a value. How do we use this Function? Heres 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. Lets 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, lets 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.

15

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

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 Documents Editor. If we dont have access to a Documents Editor, we can not use the Selection Filter. So, why do we care? Wont 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. Well get to that in a moment. Lets try using this GetAllBlocksAndAtts Function.

If youre thinking to yourself, this code looks easy, then were going down the right path. 16

CP9200-2, CP9206-1Making 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 its 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 wont have a Document at all. All well have is a Database. Lets 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 References ObjectID. Lets see how we could use this Function.

17

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

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

18

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

REVIEW
Lets 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. Lets use what we already have and see if we can do something we havent 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.

19

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

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. Lets fill them up in Excel.

Thats 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, theres a little logic involved but its not different than it would be in VBA.

20

CP9200-2, CP9206-1Making 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 were 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 Blocks Handle in Column B. Attribute Tags appear in Column C and Attribute Values appear in Column D. But wait a minute! Wasnt 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. 21

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

Weve 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. Lets 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 entitys 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 doesnt exactly fill us with confidence, does it? What happens if we ask an ObjectID to be placed on a Layer that does not exist?

22

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

STEP 2 Error Handling. We havent 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 Murphys Law fame) attempted to execute our code, what would go wrong? Answer: anything that could go wrong. What happens if the Layer doesnt 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.

Heres 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 dont know about it because we arent doing anything after the Catch statement.

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

23

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

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

And theres more where that came from.

24

CP9200-2, CP9206-1Making 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.

25

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

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

26

CP9200-2, CP9206-1Making 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 didnt 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

27