hands on introduction to v.net add ins for autoad sd197926

32
Page 1 SD197926-L - Hands-on Introducon to VB.NET Add-Ins for AutoCAD SD197926-L Hands-on Introducon to VB.NET Add-Ins for AutoCAD - SD197926-L Speaker Jerry Winters, VB CAD, Inc., Lab Assistants Karl Hill, Alaska Nave Tribal Health Consorum, IT Manager/CAD Equipment Manager James Johnson, Synergis Technologies LLC Sr. Applicaon Developer Gyorgy Ordody, Autodesk, Inc Soſtware Engineer Learning Objecves Learn how to create a new AutoCAD add-in in VB.NET Learn how to create a new AutoCAD command in VB.NET Learn the basics of drawing in AutoCAD through the .NET API Learn how to extract block and aribute informaon through the .NET API Lab Descripon Knowing how to write AutoCAD add-ins lets us create new AutoCAD commands that automate roune tasks, perform complex cal- culaons, or integrate mulple systems to help us be more producve, more precise, and more effecve. The use of Microsoſt's free Visual Studio Community together with the informaon presented in this class will help anyone immediately begin creang AutoCAD add-ins with VB.NET. Speaker Bio

Upload: others

Post on 09-Feb-2022

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 1

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

SD197926-L

Hands-on Introduction to VB.NET Add-Ins for AutoCAD - SD197926-L

Speaker

Jerry Winters, VB CAD, Inc.,

Lab Assistants

Karl Hill, Alaska Native Tribal Health Consortium, IT Manager/CAD Equipment Manager

James Johnson, Synergis Technologies LLC Sr. Application Developer

Gyorgy Ordody, Autodesk, Inc Software Engineer

Learning Objectives

• Learn how to create a new AutoCAD add-in in VB.NET

• Learn how to create a new AutoCAD command in VB.NET

• Learn the basics of drawing in AutoCAD through the .NET API

• Learn how to extract block and attribute information through the .NET API

Lab Description

Knowing how to write AutoCAD add-ins lets us create new AutoCAD commands that automate routine tasks, perform complex cal-

culations, or integrate multiple systems to help us be more productive, more precise, and more effective. The use of Microsoft's

free Visual Studio Community together with the information presented in this class will help anyone immediately begin creating

AutoCAD add-ins with VB.NET.

Speaker Bio

Page 2: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 2

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

First Things First

We will be using Visual Studio 2017 Community Edition during this Lab. This can be downloaded from the page with the URL:

https://visualstudio.microsoft.com/vs/community/

The download will be a 1.2 MB file. When this file is executed, it will download and install Visual Studio Community Edition.

During the installation process, you may be asked for your preferred language. If you are asked this, select “Visual Basic”.

Page 3: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 3

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Learn how to create a new AutoCAD add-in in VB.NET

This first step we work on is the most difficult, complex, challenging thing we will do during this lab. This is not

intended to scare you but to prepare you. There are very specific steps that need to be followed and if we

leave even one of these steps out we will not be able to do anything else.

Pre-requisites

• Visual Studio 2017 Community Edition is installed

• AutoCAD 2019 is installed

Here are the steps to creating a new AutoCAD Add-In in VB.NET:

1. Start Visual Studio

Create a New VB.NET Class Library Project

Add References to the following files: accoremgd.dll, acdbmgd.dll, acmgd.dll

Set the acad.exe file as the Debug Startup Application

Write amazing, fantastic, mind-blowing code

We will go through steps 1-4 multiple times because if we return home after attending Autodesk University

and can not create a new Add-In for AutoCAD, well, that would not be good.

1. Start Visual Studio

After installing Visual Studio, you will be able to start Visual Studio just as

you do any other application in Windows. If you plan on writing AutoCAD

Add-Ins on a regular basis, you may want to pin Visual Studio to your Task

Bar.

Page 4: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 4

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

2. Create a New VB.NET Class Library Project

In Visual Studio, go to the menu and click File -> New -> Project.

Now we need to select the type of project we want to create. There are 5 things we need to do here. First,

make sure the Visual Basic—Windows Desktop node is selected in the Tree (on the left). Second, select

“Class Library (.NET Framework)” is selected. Third, give the project a Name. Fourth, uncheck the “Create

directory” checkbox. Fifth, set the Framework to “.NET Framework 4.7”

Pay attention to the “Location” setting.

Page 5: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 5

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

3. Add References to the following files:

accoremgd.dll, acdbmgd.dll, acmgd.dll

We do this by going to the menu. Project -> Add

Reference

Page 6: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 6

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Click on “Browse” in the left-hand side list, then the “Browse” button.

Browse to the path, “C:\Program Files\Autodesk\AutoCAD 2019”

Next, in the File name combobox, type “ac*mgd.dll” and hit Enter

This filter reduces the number of files that show up in the list. We are looking for 3 files: accoremgd,dll,

acdbmgd.dll, and acmgd.dll

Page 7: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 7

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

After selecting the 3 magic .dll files, click on the “Add” button.

Next, click the “OK” button.

What did we just do? By adding References to these 3 DLLs, we added their capabilities to our program.

These DLLs are used to speak to AutoCAD, to ModelSpace, PaperSpace, they have the definitions of Lines,

Circles, Arcs, etc.

Page 8: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 8

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

4. Set the acad.exe file as the Debug Startup Application

Without doing anything else, we could jump right in and

start writing code. However, if we perform Step 4, we can

debug our code while AutoCAD is running which will help

us be much more productive.

Go to the menu Project -> Program A Properties

Click on the Debug tab.

Click the “Start external program” button, then either type

or browse to:

“C:\Program Files\Autodesk\AutoCAD 2019\acad.exe”.

Page 9: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 9

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Step 5 is to write amazing code. We’ll do plenty of code writing in a little while. Before we do that, let’s try

compiling and loading our application. This is done by clicking on the “Start” button.

If we set up the Startup Application correctly (from Step 4), clicking the “Start” button will start AutoCAD for

us. When this happens, we’ll start a new Drawing.

Page 10: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 10

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

When we click the “Start” button, here’s what happens in the background:

• Visual Studio saves all the files in the project.

• Visual Studio compiles the project into a .dll file.

• Visual Studio starts the program in the “Start external program” Debug page.

• A ‘link’ between Visual Studio and AutoCAD is created so Visual Studio ‘listens’ to what is happening in-

side AutoCAD.

Now, our code is compiled and AutoCAD is started. The next step is to have AutoCAD load our .NET Add-In.

Netload is the command we run to load our

program into AutoCAD. When we run

“Netload”, we browse to the directory where

the .dll is compiled into. Where is that, you

ask? What a great question.

When we created our project, the “Location” was put in for us by Visual Studio. It may or may not match what

we see below. But the important thing is that we take note of the Location because based on our settings

here, the path we want to browse to right now is:

C:\Users\JerryWinters\source\repos\ProgramA\bin\debug

Page 11: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 11

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Once we are in the correct directory, we want to select our DLL.

Page 12: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 12

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Now, if we have all of our steps completed correctly, after we select our DLL and click the “Open” button, we

will be taken back to AutoCAD.

Now, what do we do? Nothing. We didn't write any code so there’s nothing to do. Let’s close AutoCAD now.

That may seem like we didn't accomplish very much but that’s not the case. Here’s what we just did:

1. Start Visual Studio

Create a New VB.NET Class Library Project

Add References to the following files: accoremgd.dll, acdbmgd.dll, acmgd.dll

Set the acad.exe file as the Debug Startup Application

Started the debugging process

Netloaded our application.

If we can go through those steps a few more times during this Lab, we will be able to create a new project

when we get back home and are ready write amazing, incredible code.

Page 13: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 13

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Learn how to create a new AutoCAD command in VB.NET

Here’s code you can copy and paste into your Visual Studio project:

<Autodesk.AutoCAD.Runtime.CommandMethod("RunMe")>

Public Sub RunMe()

MsgBox("I hope this works.")

End Sub

Let’s talk about what this does.

<Autodesk.AutoCAD.Runtime.CommandMethod("RunMe")>

This code is used to define a new command in AutoCAD. The command name is “RunMe”. It is placed

directly above a Public Sub statement.

Public Sub RunMe()

This line tells Visual Studio that we are beginning a new procedure named “RunMe”. You may notice the

name of the Sub is the same as the name of the CommandMethod. This does not have to be the case but my

personal preference is to have them named the same.

MsgBox("I hope this works.")

This line is used to display a MessageBox with the text “I hope this works” in it.

End Sub

This line closed the procedure named “RunMe”. The code between “Sub” and “End Sub” runs line by line

when the “RunMe” command is run.

Page 14: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 14

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Let’s try debugging our program again. We are going to do this by clicking the “Start” button again.

Next, let’s start a new AutoCAD drawing.

Then use the Netload command and select your .DLL.

Now that we have defined a new AutoCAD command, we can run it by typing “RunMe” at the command line.

I really hope the program works on your computer. If it does, you will see a message box as shown above.

Now, before we close down AutoCAD, let’s see if we can debug our program.

Switch back over to Visual Studio and click in the grey column on line 4. This is called adding a “Breakpoint”.

Page 15: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 15

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Now, switch back over to AutoCAD and run the “RunMe” command again. What should happen is AutoCAD

should pass the code execution over to the Stop we created on Line 4.

The line of code highlighted yellow is the next line of code that will be run.

Hit the F11 button on the keyboard. This will run the line of code highlighted yellow.

There’s our MessagBox. After we click the “OK” button, we are taken back to

Visual Studio on Line 5.

Now that we are successfully debugging, let’s make a little change to our code. After all, the code does work.

Right?

Page 16: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 16

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Let’s change the MessageBox from “I hope this works.” to “I’m glad this works.”.

Now, remember, the line highlighted yellow is the next line to run. And while it’s true our wonderful command

only has one line of code inside it, this will not always be the case. You will notice the yellow arrow in the gray

column.

Let’s click and drag the yellow arrow from Line 5 up back to Line 4.

Now if we hit the F11 button again, Line 4 will be executed but with the new message.

Page 17: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 17

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Now, think about what just happened. We started the Debug process by

clicking the Start button. After netloading our application, we ran our

awesome command, “RunMe”. Since we added a Breakpoint, the

command’s execution jumped back over to Visual Studio. Once there we

were able to step through our code by using the F11 key on the keyboard.

We also modified our code and dragged the execution cursor back up to the

new code and ran it again by using the F11 key.

The better we get at the debugging process, the more efficient we become at

writing code. It takes time for Visual Studio to compile our code. And it takes

time to start AutoCAD. And it takes time to start a new Drawing. And it takes

time to Netload our application. If we add a breakpoint, we can modify our

code and try running it again without taking all of that time just discussed.

Dragging and dropping a little yellow arrow may work in some situations. But more often than not, there is a

better way to move execution to a different line.

If we Right-Click on the line of code we want to move execution to, one of the options is “Set Next

Statement”. Clicking on this is far more accurate than dragging and dropping a little arrow.

Page 18: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 18

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Learn the basics of drawing in AutoCAD through the .NET API

If we were to start AutoCAD and want to draw a line, we might click on an icon to start the “Line” command.

Then we would click in ModelSpace to select the line’s Start Point. Then we may click somewhere else in

ModelSpace to specify the line’s End Point. Then magically, a line would appear in ModelSpace. That’s what

most of us see in AutoCAD over and over and over again. But there’s more going on than what we see.

Here’s what’s going on ‘under the hood’:

1. A new Transaction is started for the current file under which all of the following actions take place.

2. ModelSpace is Opened “For Write” because a new line is going to be added to ModelSpace.

3. The first point is selected in ModelSpace.

4. Then a second point is selected while we see a ‘rubber band’ between the first point and the cursor.

5. Next, a new Line Entity is created using the selected points.

6. The Line is appended to ModelSpace.

7. The Line is added to the Transaction.

8. The Transaction is committed.

Before we look at the code, we need to add the following at the very top of the Class file.

Imports Autodesk.AutoCAD.ApplicationServices

Imports Autodesk.AutoCAD.ApplicationServices.Application

Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.AutoCAD.DatabaseServices

Imports Autodesk.AutoCAD.Geometry

Here’s the code:

<Autodesk.AutoCAD.Runtime.CommandMethod("DrawLine")>

Public Sub DrawLine()

Dim myDoc As Document = DocumentManager.MdiActiveDocument

Dim myDB As Database = myDoc.Database

Dim myEditor As Editor = myDoc.Editor

Using myTrans As Transaction = myDoc.TransactionManager.StartTransaction

Dim myBTR As BlockTableRecord = myDB.CurrentSpaceId.GetObject(OpenMode.ForWrite)

Dim startPoint As Point3d = myEditor.GetPoint("Select Start Point:").Value

Dim myPPO As New PromptPointOptions("Select End Point:")

myPPO.BasePoint = startPoint

myPPO.UseBasePoint = True

Dim endPoint As Point3d = myEditor.GetPoint(myPPO).Value

Dim myLine As New Line(startPoint, endPoint)

myBTR.AppendEntity(myLine)

myTrans.AddNewlyCreatedDBObject(myLine, True)

myTrans.Commit()

End Using

End Sub

Let’s copy and paste this code from the handout into our project. Then let’s add a Breakpoint, begin

debugging, run the command, and step through the code line by line.

Page 19: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 19

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Here’s another command to take a look at:

<Autodesk.AutoCAD.Runtime.CommandMethod("DrawGrid")>

Public Sub DrawGrid()

Dim myDoc As Document = DocumentManager.MdiActiveDocument

Dim myDB As Database = myDoc.Database

Dim myEditor As Editor = myDoc.Editor

Using myTrans As Transaction = myDoc.TransactionManager.StartTransaction

Dim myBTR As BlockTableRecord = myDB.CurrentSpaceId.GetObject(OpenMode.ForWrite)

For X As Double = 0 To 10 Step 0.5

For Y As Double = 0 To 10 Step 0.5

Dim startPoint As New Point3d(X, 0, 0)

Dim endPoint As New Point3d(X, 10, 0)

Dim myLine As New Line(startPoint, endPoint)

myBTR.AppendEntity(myLine)

myTrans.AddNewlyCreatedDBObject(myLine, True)

startPoint = New Point3d(0, Y, 0)

endPoint = New Point3d(10, Y, 0)

myLine = New Line(startPoint, endPoint)

myBTR.AppendEntity(myLine)

myTrans.AddNewlyCreatedDBObject(myLine, True)

Next

Next

myTrans.Commit()

End Using

End Sub

The result of this code is a 10x10 grid with 0.5 increments.

Let’s take a look at a little more code. First we will add a Function named “DrawLineFunction”. Then we will

create a new Command named “DrawLineTest”. Notice how the DrawLineFunction allows us to specify X, Y,

and Z values for both the Start and End points. Then “DrawLineTest” calls “DrawLineFunction” repeatedly.

Page 20: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 20

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Public Function DrawLineFunction(Xs As Double, Ys As Double, Zs As Double,

Xe As Double, Ye As Double, Ze As Double) As ObjectId

Dim myDoc As Document = DocumentManager.MdiActiveDocument

Dim myDB As Database = myDoc.Database

Using myTrans As Transaction = myDoc.TransactionManager.StartTransaction

Dim myBTR As BlockTableRecord = myDB.CurrentSpaceId.GetObject(OpenMode.ForWrite)

Dim startPoint As New Point3d(Xs, Ys, Zs)

Dim endPoint As New Point3d(Xe, Ye, Ze)

Dim myLine As New Line(startPoint, endPoint)

myBTR.AppendEntity(myLine)

myTrans.AddNewlyCreatedDBObject(myLine, True)

myTrans.Commit()

Return myLine.ObjectId

End Using

End Function

<Autodesk.AutoCAD.Runtime.CommandMethod("DrawLineTest")>

Public Sub DrawLineTest()

'draw square first

DrawLineFunction(0, 0, 0, 4, 0, 0)

DrawLineFunction(4, 0, 0, 4, 4, 0)

DrawLineFunction(4, 4, 0, 0, 4, 0)

DrawLineFunction(0, 4, 0, 0, 0, 0)

'now draw corner to corner

DrawLineFunction(0, 0, 0, 4, 4, 0)

DrawLineFunction(0, 4, 0, 4, 0, 0)

End Sub

If we create a Function like “DrawLineFunction” we can call it whenever we need to create a Line and we will

be more productive and our code will be easier to maintain.

Page 21: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 21

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Learn how to extract block and attribute information through the .NET API

Block attribute extraction is a very common requirement in AutoCAD Add-Ins. Before we jump into the code

to do this we need to discuss how Blocks, Block References, and Attributes are stored in an AutoCAD .dwg

file.

The Database

The first thing we need to understand is that an AutoCAD .dwg file is a database. And this database is

organized into Tables and Records.

Layers are in a Table called “LayerTable” with records called “LayerTableRecord”.

TextStyles are in a Table called “TextStyleTable” with records called “TextStyleTableRecord”.

Blocks are in a Table called “BlockTable” with records called “BlockTableRecord”.

Let’s take a look at this code:

Public Function GetAllBlockTableRecords() As List(Of String)

Dim myDB As Database = HostApplicationServices.WorkingDatabase

Dim retList As New List(Of String)

Using myTrans As Transaction = myDB.TransactionManager.StartTransaction

Dim myBT As BlockTable = myDB.BlockTableId.GetObject(OpenMode.ForRead)

For Each myBTRid As ObjectId In myBT

Dim myBTR As BlockTableRecord = myBTRid.GetObject(OpenMode.ForRead)

retList.Add(myBTR.Name)

Next

End Using

Return retList

End Function

You will notice a few things.

• We are using a variable named “myDB” and it is being assigned to the WorkingDatabase

(the current file open in AutoCAD).

• Before we read or write from/to an AutoCAD Database we always open a Transaction.

• Since we are Reading from the database we open the BlockTable “ForRead”. Objects in

AutoCAD are opened through their Object IDs.

• We want to look at each ‘record’ inside the BlockTable. We use a For Each loop to do

this. When we loop through the BlockTable, we are given an ObjectID that belongs to a

BlockTableRecord.

• We declare a variable as a BlockTableRecord and get that through its ObjectID.

• In this example we are adding the Name of the BlockTableRecord to a List.

Page 22: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 22

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Here’s some code that will use the Function we just looked at on the prior page:

<Autodesk.AutoCAD.Runtime.CommandMethod("GetBTRNames")>

Public Sub GetBTRNames()

For Each myBName As String In GetAllBlockTableRecords()

MsgBox(myBName)

Next

End Sub

If we run this code on a totally new AutoCAD drawing, we will see the following:

If you are familiar with AutoCAD, these names may look like something familiar.

ModelSpace is a BlockTableRecord in an AutoCAD Database.

PaperSpace Layouts are BlockTableRecords in an AutoCAD Database.

If I draw a dimension in my new AutoCAD drawing and run this same command again, we

will see this:

Dimensions are BlockTableRecords in an AutoCAD Database.

XRefs are BlockTableRecords in an AutoCAD Database.

And, as you may have guessed, Blocks are BlockTableRecords in an AutoCAD Database.

Go to this page:

https://knowledge.autodesk.com/support/autocad/downloads/caas/downloads/content/autocad-sample-files.html

Download one of the “Blocks and Tables” dwg files and open it in AutoCAD. If we run this same

GetBTRNames command we will see

Page 23: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 23

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Now we can see some actual ‘Blocks’ such as “Lighting Fixture”, “Label”, “ARCHBDR-D”, and “Window”.

Then we see something like “*B5”. What’s that about?

There was a time when we used to create Blocks in AutoCAD and insert them. For example, we may create a

Window Block that was for a 3’0” x 5’-0” window. We may have named it “Window 36x60”. Then we may have

added attributes to that Block for the Manufacturer, Supplier, Cost, etc. Then one magical day, Autodesk

introduced “Dynamic Blocks”. Dynamic Blocks are amazing. But they introduce a challenge or two when it

comes time to extract Blocks. Each time a Dynamic Block is inserted into AutoCAD and then ‘Dynamicized’, a

new BlockTableRecord is created called “*B1”, then “*B2” and so on. While we are not going to spend a great

deal of time discussing Dynamic Blocks, it was worth mentioning.

OK. Let’s get down to Block and Attribute Extraction.

Block Extraction

We are going to make a few assumptions here for a few minutes. First off, we are going to be extracting

Blocks from ModelSpace in an AutoCAD file. We are going to copy and past the following Function into our

Add-In:

Public Function GetBlockReferencesInModelSpace(DBin As Database) _

As Dictionary(Of String, List(Of ObjectId))

Dim retVal As New Dictionary(Of String, List(Of ObjectId))

Using myTrans As Transaction = DBin.TransactionManager.StartTransaction

Dim myBT As BlockTable = DBin.BlockTableId.GetObject(OpenMode.ForRead)

Dim myBTR As BlockTableRecord =

myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead)

For Each myEntID As ObjectId In myBTR

If myEntID.ObjectClass.DxfName = "INSERT" Then

Dim myBRef As BlockReference = myEntID.GetObject(OpenMode.ForRead)

If myBRef.Name.StartsWith("*") Then

Dim parentBTR As BlockTableRecord =

myBRef.DynamicBlockTableRecord.GetObject(OpenMode.ForRead)

If retVal.ContainsKey(parentBTR.Name) = False Then

retVal.Add(parentBTR.Name, New List(Of ObjectId))

End If

retVal(parentBTR.Name).Add(myEntID)

Else

If retVal.ContainsKey(myBRef.Name) = False Then

retVal.Add(myBRef.Name, New List(Of ObjectId)) End If retVal(myBRef.Name).Add(myEntID) End If End If Next myTrans.Commit() End Using Return retVal End Function

Page 24: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 24

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

This Function gets all of the Block References in an AutoCAD Drawing and returns them in a Dictionary.

Dictionaries are storage containers that have a Key and a Value. In this instance, the Dictionary’s Key is the

Block Name. The Value is a List of ObjectID Objects. It ‘looks’ something like this:

Window

ObjectIDa

ObjectIDb

ObjectIDc

Receptacle

ObjectIDd

ObjectIDe

ObjectIDf

ObjectIDg

Light

ObjectIDh

ObjectIDi

With this structure, we can look into the Dictionary and pull out whichever block we want to access.

<Autodesk.AutoCAD.Runtime.CommandMethod("WriteBlocksOut")>

Public Sub WriteBlocksOut()

Dim myDB As Database = HostApplicationServices.WorkingDatabase

Dim myBlocks As Dictionary(Of String, List(Of ObjectId)) =

GetBlockReferencesInModelSpace(myDB)

For Each myKVP As KeyValuePair(Of String, List(Of ObjectId)) In myBlocks

If myKVP.Key.ToUpper = "WINDOW" Then

Using myTrans As Transaction = myDB.TransactionManager.StartTransaction

Dim myDesktop As String =

My.Computer.FileSystem.SpecialDirectories.Desktop

Dim myOutput As New IO.StreamWriter(IO.Path.Combine(myDesktop,

"Windows.txt"))

For Each myOID As ObjectId In myKVP.Value

Dim myBRef As BlockReference = myOID.GetObject(OpenMode.ForRead)

myOutput.WriteLine(DateTime.Now.ToString & vbTab &

myKVP.Key & vbTab &

myBRef.Position.X & vbTab &

myBRef.Position.Y & vbTab &

myBRef.Position.Z & vbTab &

myBRef.ScaleFactors.X & vbTab &

myBRef.Rotation) Next myOutput.Close() End Using End If Next End Sub We will discuss this code in detail during the Lab. If we run this code, a file named “Windows.txt” is created on

our Desktop.

Page 25: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 25

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

There’s the output. Of course, there’s a lot more we could put out. And we could format it differently. But let’s

get some Attributes out first. Then we’ll take a look at other options.

Here’s the magic code that will write the Attributes out.

For Each myAttID As ObjectId In myBRef.AttributeCollection

Dim myAtt As AttributeReference =

myAttID.GetObject(OpenMode.ForRead)

myOutput.WriteLine(vbTab & myAtt.Tag & vbTab & myAtt.TextString)

Next

We are going to copy and paste ‘WriteBlocksOut” and create a new Command named

“WriteBlocksAndAttributesOut”.

Page 26: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 26

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

<Autodesk.AutoCAD.Runtime.CommandMethod("WriteBlocksAndAttributesOut")>

Public Sub WriteBlocksAndAttributesOut()

Dim myDB As Database = HostApplicationServices.WorkingDatabase

Dim myBlocks As Dictionary(Of String, List(Of ObjectId)) =

GetBlockReferencesInModelSpace(myDB)

For Each myKVP As KeyValuePair(Of String, List(Of ObjectId)) In myBlocks

If myKVP.Key.ToUpper = "WINDOW" Then

Using myTrans As Transaction = myDB.TransactionManager.StartTransaction

Dim myDesktop As String = My.Computer.FileSystem.SpecialDirectories.Desktop

Dim myOutput As New IO.StreamWriter(IO.Path.Combine(myDesktop, "WindowsAtts.txt"))

For Each myOID As ObjectId In myKVP.Value

Dim myBRef As BlockReference = myOID.GetObject(OpenMode.ForRead)

myOutput.WriteLine(DateTime.Now.ToString & vbTab &

myKVP.Key & vbTab &

myBRef.Position.X & vbTab &

myBRef.Position.Y & vbTab &

myBRef.Position.Z & vbTab &

myBRef.ScaleFactors.X & vbTab &

myBRef.Rotation)

For Each myAttID As ObjectId In myBRef.AttributeCollection

Dim myAtt As AttributeReference =

myAttID.GetObject(OpenMode.ForRead)

myOutput.WriteLine(vbTab & myAtt.Tag & vbTab & myAtt.TextString)

Next

Next

myOutput.Close()

End Using

End If

Next

End Sub

Here’s the output generated by this code:

Page 27: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 27

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Extra Content

It is always difficult to determine how long it will take for a group to work through a tutorial. In the event we

have enough time to continue, we’ll work through this section as well:

Let’s write our Blocks and Attributes out to Excel:

<Autodesk.AutoCAD.Runtime.CommandMethod("WriteBlocksAndAttributesOutToExcel")>

Public Sub WriteBlocksAndAttributesOutToExcel()

Dim myDB As Database = HostApplicationServices.WorkingDatabase

Dim myBlocks As Dictionary(Of String, List(Of ObjectId)) =

GetBlockReferencesInModelSpace(myDB)

For Each myKVP As KeyValuePair(Of String, List(Of ObjectId)) In myBlocks

If myKVP.Key.ToUpper = "WINDOW" Then

Using myTrans As Transaction = myDB.TransactionManager.StartTransaction

Dim myDesktop As String = My.Computer.FileSystem.SpecialDirectories.Desktop

Dim myExcel As Object = CreateObject("Excel.Application")

myExcel.Visible = True

Dim myWB As Object = myExcel.Workbooks.Add

Dim curRow As Integer = 1

For Each myOID As ObjectId In myKVP.Value

Dim myBRef As BlockReference = myOID.GetObject(OpenMode.ForRead)

myExcel.ActiveSheet.Cells(curRow, "A").value = DateTime.Now.ToString

myExcel.ActiveSheet.Cells(curRow, "B").value = myKVP.Key

myExcel.ActiveSheet.Cells(curRow, "C").value = myBRef.Position.X

myExcel.ActiveSheet.Cells(curRow, "D").value = myBRef.Position.Y

myExcel.ActiveSheet.Cells(curRow, "E").value = myBRef.Position.Z

myExcel.ActiveSheet.Cells(curRow, "F").value = myBRef.ScaleFactors.X

myExcel.ActiveSheet.Cells(curRow, "G").value = myBRef.Rotation

curRow += 1

For Each myAttID As ObjectId In myBRef.AttributeCollection

Dim myAtt As AttributeReference =

myAttID.GetObject(OpenMode.ForRead)

myExcel.ActiveSheet.Cells(curRow, "B").value = myAtt.Tag

myExcel.ActiveSheet.Cells(curRow, "C").value = myAtt.TextString

curRow += 1 Next Next myWB.SaveAs(IO.Path.Combine(myDesktop, "WindowsAtts.xlsx")) myWB = Nothing myExcel = Nothing End Using End If Next End Sub

Now, I understand this is an Introductory Lab. No one would expect anyone else to understand each and

every line of code here. However, if I were to ask you to put the Rotation in column “H” instead of column “G”,

my guess is that you would be able to find that and make that change.

As always, we will add a BreakPoint in our code so when it runs we can stop it and step through it.

By the way, this code assumes Microsoft Excel is installed on the machine it is run on.

Page 28: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 28

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

Here’s the output in Excel. It should look very similar to

the output in the .txt file we created.

More Extra Content

Let’s look at this one line of code. You will find it at the top of the “GetBlockReferencesInModelSpace” Func-

tion:

Public Function GetBlockReferencesInModelSpace(DBin As Database) _

As Dictionary(Of String, List(Of ObjectId))

This function has been used by a few of our commands thus far. If we break down this declaration’s individual

parts we would find the following:

Public Function—This is Public so it can be called by other pieces of code even outside of the Class in

which this Function resides. It is a Function which means it will be returning some sort of value for us.

GetBlockReferencesInModelSpace—This is the name of the Function.

(DBin As Database)—This Function has one Parameter. It wants a Database Object.

As Dictionary(Of String, List(Of ObjectId))—If we ask for it, this Function will return a Dictionary with a

String for the Key and a List of ObjectIDs as the value.

It may seem a little late in the game to be digging into the anatomy of a Function Call. But there’s a reason

why we’re doing it now.

(DBin As Database)

This Function asks for a Database. If we can give it a Database, it can give us the return value. In the exam-

ples we have worked with thus far, we have been giving it the “WorkingDatabase” which is the database of

the document currently in focus in AutoCAD. But it doesn’t have to be the WorkingDatabase.

Page 29: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 29

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

VERY IMPORTANT STEP WARNING:

Before we continue, we need to add a new Windows Form to our Project.

The name of the Form is not

important for this example. Go

ahead and click the “Add” button.

We added the Form to our Project for 1 reason only. It’s one of the easiest ways to get a Reference to the

System.Windows.Forms namespace.. And we need that for what we’re about to do.

This is an Introductory Tutorial. IF we can squeeze it in, I would like to introduce you to the power of VB.NET.

Page 30: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 30

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

<Autodesk.AutoCAD.Runtime.CommandMethod("WriteBlocksAndAttributesOutToExcel3")>

Public Sub WriteBlocksAndAttributesOutToExcel3()

Dim myOFD As New System.Windows.Forms.OpenFileDialog()

myOFD.Multiselect = True

myOFD.Filter = "AutoCAD Drawing (*.dwg)|*.dwg"

If myOFD.ShowDialog = System.Windows.Forms.DialogResult.OK Then

Dim myExcel As Object = CreateObject("Excel.Application")

myExcel.Visible = True

Dim myWB As Object = myExcel.Workbooks.Add

Dim myDesktop As String = My.Computer.FileSystem.SpecialDirectories.Desktop

Dim curRow As Integer = 1

For Each myFileName As String In myOFD.FileNames

Dim myDB As New Database(False, True)

myDB.ReadDwgFile(myOFD.FileName, FileOpenMode.OpenForReadAndAllShare, False, "")

Dim myBlocks As Dictionary(Of String, List(Of ObjectId)) =

GetBlockReferencesInModelSpace(myDB)

For Each myKVP As KeyValuePair(Of String, List(Of ObjectId)) In myBlocks

Using myTrans As Transaction = myDB.TransactionManager.StartTransaction

For Each myOID As ObjectId In myKVP.Value

Dim myBRef As BlockReference = myOID.GetObject(OpenMode.ForRead)

myExcel.ActiveSheet.Cells(curRow, "A").value = DateTime.Now.ToString

myExcel.ActiveSheet.Cells(curRow, "B").value = myFileName

myExcel.ActiveSheet.Cells(curRow, "C").value = myKVP.Key

myExcel.ActiveSheet.Cells(curRow, "D").value = myBRef.Position.X

myExcel.ActiveSheet.Cells(curRow, "E").value = myBRef.Position.Y

myExcel.ActiveSheet.Cells(curRow, "F").value = myBRef.Position.Z

myExcel.ActiveSheet.Cells(curRow, "G").value = myBRef.ScaleFactors.X

myExcel.ActiveSheet.Cells(curRow, "H").value = myBRef.Rotation

curRow += 1

For Each myAttID As ObjectId In myBRef.AttributeCollection

Dim myAtt As AttributeReference =

myAttID.GetObject(OpenMode.ForRead)

myExcel.ActiveSheet.Cells(curRow, "C").value = myAtt.Tag

myExcel.ActiveSheet.Cells(curRow, "D").value = myAtt.TextString curRow += 1 Next Next End Using Next myDB.Dispose() Next myWB.SaveAs(IO.Path.Combine(myDesktop, "WindowsAtts.xlsx")) myWB = Nothing myExcel = Nothing End If End Sub

In this example, we ask the user to select the file(s) they want to extract. Yes, more than one file can be

selected. Then we go through each of the selected files and open them IN MEMORY only. This means the

code can run very fast because the file does not have to be opened in the editor. And we have removed the

code that is looking just for the Window Block. So we get everything from every file selected.

Page 31: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 31

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD

There’s the output.

REVIEW

We have had 90 minutes to provide an Introduction to creating AutoCAD Add-Ins using VB.NET. That’s not a

lot of time. We could have spent that time discussing different variable types. We could have discussed

syntax. We could have discussed a million different things. But we didn’t. We showed the following:

• How to create a new AutoCAD add-in in VB.NET

• How to create a new AutoCAD command in VB.NET

• The basics of drawing in AutoCAD through the .NET API

• How to extract block and attribute information through the .NET API

I would love to help you continue on your journey to learning VB.NET Add-In Development. Please email me

and let me know how I can help.

Thanks for your time.

Jerry Winters

[email protected]

Page 32: Hands on Introduction to V.NET Add Ins for AutoAD SD197926

Page 32

SD197926-L - Hands-on Introduction to VB.NET Add-Ins for AutoCAD