TheSwamp
Code Red => .NET => Topic started by: Matt__W on December 08, 2011, 02:12:04 PM
-
The following code works fine in VBA, but in VB.NET I'm struggling with trying to get these declared properly. I get the message "Type 'AcadBlockReference' is not defined". I'm
Dim objBlock As AcadBlockReference
Dim objEnt As AcadEntity
Dim objLayout As AcadLayout
Dim dbxDoc as AxDbDocument
I've noticed that if I copy this code from a separate class and paste it in the code for my form then it works but then I get an error about it being ambiguous in the namespace.
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Colors
Imports Microsoft.Office.Interop.Excel
So what's the correct way to go about doing this?
Right now I have a form, 2 classes and 1 module that has some global declarations.
-
You do need import the Autodesk stuff, otherwise you won't have access to those objects. Without looking at your code, I can't tell why you have an ambiguous definition error. Are you importing the stuff more than once or in multiple locations?
-
I had it in one location, but it wasn't recognizing AcadBlockReference, AcadEntity, AcadLayout or AxDbDocument. When I copied it to another location, it started recognizing them (except for the AxDbDocument). That's when I started getting the ambiguous errors.
So I guess for starters, WHERE should the Imports go and is there a "special" way of making them global?
-
Just skimming through real quick.
Make sure you know the difference between a class and a module(Shared Class)
You need a imports statement for each .vb file at the top.
Also for VB.NET in properties on reference tab you can check them so it you do not have to import it.
-
Just skimming through real quick.
Make sure you know the difference between a class and a module(Shared Class)
You need a imports statement for each .vb file at the top.
Also for VB.NET in properties on reference tab you can check them so it you do not have to import it.
So if I toggle the items I want to import, I don't have to write the "Imports Autodesk....." code? Is that what you're saying?
-
Yes
-
Where's the one for ObjectDBX? Do you know? I have it referenced in already.
Basically what I'm rewriting is code that opens drawings using DBX and reads & counts block attributes and dumps them into Excel.
-
Forget ObjectDBX.....in .NET this is no longer needed. Create a Database Object, then 'open' the drawing using the Database object's ReadDwgFile method. You can still use the COM objects you are used to (although if you switch to the managed objects you wouldn't need a separate version for each version of Acad). I don't have any VB code handy, but I'll see if I can find some (unless Jeff_H posts first).
-
Forget ObjectDBX.....in .NET this is no longer needed. Create a Database Object, then 'open' the drawing using the Database object's ReadDwgFile method. You can still use the COM objects you are used to (although if you switch to the managed objects you wouldn't need a separate version for each version of Acad). I don't have any VB code handy, but I'll see if I can find some (unless Jeff_H posts first).
*sigh* Okay... now I'm TOTALLY lost. :)
*off to abuse Google.... again*
-
The reason of being lost is because you are probably trying to directly move your VBA code into .NET API project. While it is technically doable, it is not desired in most cases.
You'd better forget the VBA/COM code/knowledge (excepting the knowledge you know how AutoCAD works), and focus on using Acad's .NET API. After 8 versions of releases, Acad's NET API gets a lot more mature, you can hardly find something you can do with COM API that you cannot with .NET API. You also eliminate unnecessary dependency (to AutoCAD.Interop/Common) from your project.
-
Matt, this is a very simplified example that leaves a lot to do, but it shows how simple it is to get the remote database object (what we used to need ObjectDBX for).
Public Sub DoIt(ByVal filename As String)
Dim sourceDb As Database = New Database(False, True)
sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, False, "")
countblocks(sourceDb)
End Sub
Private Sub countblocks(ByVal db As Database)
''code to count the blocks in a database
End Sub
-
The reason of being lost is because you are probably trying to directly move your VBA code into .NET API project.
No. I fully understand that it's not possible to just simply copy/paste the code and I'm cool with that. I'm just struggling to get a grip on the changes. I was pretty good with VBA/VB 6. Not so much with .NET (yet).
Matt, this is a very simplified example that leaves a lot to do, but it shows how simple it is to get the remote database object (what we used to need ObjectDBX for).
Thanks, Jeff! I'm sure I'll be back with more questions as I get further along with this. :)
-
I'm making progress. Down to only 8 errors from 25 earlier. :) My next issue is with the database (instead of ObjectDBX).
In my VBA app, I had code that would open a DWG using ObjectDBX then cycle through each of the layout tabs. How is this done with the Database?
Public dbxDoc As Database = New Database(False, True)
dbxDoc.ReadDwgFile("e:\temp\" & RetrieveFileName(strFile), FileOpenMode.OpenForReadAndAllShare, False, "")
For Each objLayout In dbxDoc.Layouts
For Each objEnt In objLayout.Block
If TypeOf objEnt Is BlockReference Then
objBlock = objEnt
If objBlock.IsDynamicBlock Then....
-
I will post some code later today when I will have some spare time.
But since you are getting attributes you can go through the block definitions with attributes then get all the blockReferences.
-
Of course not good coding practice hard-coding values, should be broken, etc...........
but here is some code to maybe get you started that just prints all the attribute reference's to the command line, and of course you need to change the drawing path.
<CommandMethod("OpenDrawingInSideDatabase")> _
Public Sub OpenDrawingInSideDatabase()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Using sideDb As New Database(False, True)
sideDb.ReadDwgFile("C:\Testing\AutoCAD\AttTest.dwg", FileOpenMode.OpenForReadAndAllShare, False, "")
Using trx As Transaction = sideDb.TransactionManager.StartTransaction
Dim bt As BlockTable = trx.GetObject(sideDb.BlockTableId, OpenMode.ForRead)
For Each btrId As ObjectId In bt
Dim btr As BlockTableRecord = trx.GetObject(btrId, OpenMode.ForRead)
If btr.IsLayout Or btr.IsFromExternalReference Or btr.IsDependent Then
Continue For
End If
If btr.HasAttributeDefinitions Then
Dim brefIds As ObjectIdCollection = btr.GetBlockReferenceIds(True, False)
For Each brefId As ObjectId In brefIds
Dim bref As BlockReference = trx.GetObject(brefId, OpenMode.ForRead)
For Each attRefId As ObjectId In bref.AttributeCollection
Dim attref As AttributeReference = trx.GetObject(attRefId, OpenMode.ForRead)
ed.WriteMessage("{0}{1} = {2}{0}", Environment.NewLine, attRef.Tag, attRef.TextString)
Next
Next
End If
Next
End Using
End Using
End Sub
-
Of course not good coding practice hard-coding values, should be broken, etc...........
but here is some code to maybe get you started that just prints all the attribute reference's to the command line, and of course you need to change the drawing path.
<CommandMethod("OpenDrawingInSideDatabase")> _
Public Sub OpenDrawingInSideDatabase()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Using sideDb As New Database(False, True)
sideDb.ReadDwgFile("C:\Testing\AutoCAD\AttTest.dwg", FileOpenMode.OpenForReadAndAllShare, False, "")
Using trx As Transaction = sideDb.TransactionManager.StartTransaction
Dim bt As BlockTable = trx.GetObject(sideDb.BlockTableId, OpenMode.ForRead)
For Each btrId As ObjectId In bt
Dim btr As BlockTableRecord = trx.GetObject(btrId, OpenMode.ForRead)
If btr.IsLayout Or btr.IsFromExternalReference Or btr.IsDependent Then
Continue For
End If
If btr.HasAttributeDefinitions Then
Dim brefIds As ObjectIdCollection = btr.GetBlockReferenceIds(True, False)
For Each brefId As ObjectId In brefIds
Dim bref As BlockReference = trx.GetObject(brefId, OpenMode.ForRead)
For Each attRefId As ObjectId In bref.AttributeCollection
Dim attref As AttributeReference = trx.GetObject(attRefId, OpenMode.ForRead)
ed.WriteMessage("{0}{1} = {2}{0}", Environment.NewLine, attRef.Tag, attRef.TextString)
Next
Next
End If
Next
End Using
End Using
End Sub
I'll have to disect this next week. Seems everybody wants everything NOW!!
Thanks! :)