Sunday, December 26, 2010

Using AutoCAD


So I have in mind to stick a block in my drawing...

A "block" is just another drawing, usually not a very complicated one. It could show a tree or a toilet or a road sign or whatever you need to show often, in the drawings that you do. You can "drag-and-drop" to bring the tree-block or any block into your main drawing. Or you can insert a block using the "insert" command. Or you can do what I like to do, and write a program in VBA to handle the insertion and whatever else I want to do with that block.


I have in mind to stick a block in my drawing, an "info" block that will hold info about the drawing.

My InfoBlock is just some text inside a rectangle, on the "NoPrint" layer because I don't want to see it on the plotted drawing. Told ya, blocks are simple.


It's definitely the kind of thing I want to automate as much as I can: Stick the block in the drawing, automatically... fill out the info as much as I can, automatically... look up that info when I need it, automatically... and make design and drafting decisions based on that info... automatically.

That's the idea. But it starts, as you might expect, with a first step. I put the InfoBlock into my test-drawing by hand -- drag-and-drop -- so the first step then was to be able to find it automatically. That's where the VBA code comes in.

I have a bunch of useful routines already written...

I put 'em in a "CommonProject" file, which is available to any other project I'm working on. (I just use TOOLS:REFERENCES from the VBA menu to select the CommonProject, and the common code is accessible.) Of course, I don't have the InfoBlock code figured out yet, so it's not in my CommonProject... yet.


Among the routines in my CommonProject is ssSelect(). I use it to create "selection sets" of different drawing entities, depending what entities I want to work on.

To find the InfoBlock, I just tell the computer to look for all the blocks named "INFOBLOCK" in the drawing. One minor complication: Internally, AutoCAD calls a block an "INSERT" for some reason. But... I don't really care about the reason; I only need to know what to call the block so that AutoCAD will find it for me.

The screen-capture shown below is as far as I got, when I was fixing an error and decided to write this post. The screen-cap shows two working routines (one "Sub" and one "Function"). The Function returns a value, just like a function in the C language and just like a function in math class.

That's why I needed the "Sub" at this early stage. To test the thing, I run the Sub. The Sub runs the Function for me, and the Function returns a value to the Sub. I needed the Sub so I could display the information returned by the Function.


Anyway, the name of the Function is "getInfoBlock" and you can even see that name used in the Sub, where the Sub runs the Function.

And in the Function you can see my use of "ssSelect" to select all the INSERTs named INFOBLOCK in the drawing. The value returned by "ssSelect" gets put into the variable I call "ss" so I know where it is, so that I can use it.

In the next line after that, I'm already using the "ss" variable. I'm using the built-in "Count" property of the "ss" variable. If you remember, "ss" is a selection-set...

A selection-set is pretty much just what it sounds like: a set of drawing-entities that are selected.


The "ss" is a selection-set, containing all the blocks (or INSERTs) named INFOBLOCK that are in the drawing. Depending what drawing I use it on, there could be zero or more of those INFOBLOCKS. I need to have exactly one of them, before I can proceed.

So, what I had in mind to do was check the count, and if the count is one then I can proceed.

If the count is zero the code will "insert" one. If the count is more than one, the code will delete all but one of 'em. But I didn't get that far yet.


When I ran the Sub to try the code, it was not working. The MsgBox kept telling me that the TypeName was "Empty" when it should have been an "INSERT" or something, but definitely not "Empty."

Why am I looking for the type name "INSERT" instead of the ss.Count value? Because this is the "development" stage. If the code tells me it has an INSERT then I trust that it found the INSERT named INFOBLOCK. That is a lot more feedback than I get from the value of ss.Count.


You can see in the Sub that I started revising my call to "getInfoBlock." The green lines are the first version. (They are green because I made them comments. That way, they don't do anything, but I still have them handy in case I need them again.)

And below the two green lines in the Sub is another attempt to have the thing tell me that an INSERT is an INSERT. Still didn't work. So then, since there was nothing left to look at in the Sub, I started looking for an error in the Function.

Got it!

The code I had in mind to write was

If ss.Count = 1

but what I actually wrote was

If ss.Count - 1


Nice, right? The EQUAL key and the MINUS key are right next to each other on the keyboard, and I hit the wrong one.

For test purposes, I had exactly one INFOBLOCK in my drawing, so the ss.Count value was always one in my tests.

But because I wrote

If ss.Count - 1

the code was subtracting one from the ss.Count, which gave the value zero. So the code was saying If zero, then do stuff.

If zero, on a computer, always comes back false. And because it came back false, my "do stuff" command just didn't get done.

So I changed the MINUS sign to an EQUAL sign, and then it worked okay.


Long story? That's because I'm doing in English something that is more easily done in VBA, and trying to provide some background besides. Forgive me.

And what's the point of this long story?

The whole big, long, seemingly complicated problem was solved by changing a MINUS sign to an EQUAL sign. Finding the problem took some doing, sure. But the problem itself was extremely simple. As was the fix.

Got it?

That's the same level of difficulty as our economic problem.

No comments: