.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

VB.NET ObjectData records

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
Anonymous
2671 Views, 5 Replies

VB.NET ObjectData records

Anonymous
Not applicable

So, I have been trying to get this right but its not working as i thought it would

 

what i need is to read a dwg and get all the Obeject table records from that drawing. 

 

Should I be using Application.DocumentManager.Open() ? Application.DocumentManager.Add() ? or acCurDb.ReadDwgFile() ?

 

and then 

 

how do i find only layers that startWith("CP")

 

my code that i have tried is . . .

 

Sub getRecs(ByVal acro As String, ByVal map As String)

Dim circuitNames() As String

'' Iterate through each document
For Each acDoc As Document In Application.DocumentManager

Dim acCurDb As Database = acDoc.Database
Dim proj As ProjectModel = HostMapApplicationServices.Application.GetProjectForDB(acCurDb)

'' Start a transaction
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

'' Open the Layer table for read
Dim acLyrTbl As LayerTable
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)

Dim count As Integer = 0

'' Iterate through each Layer Table
For Each acObjID As ObjectId In acLyrTbl

'' Get the Layer Table Record
Dim acLyrTbleRec As LayerTableRecord
acLyrTbleRec = acTrans.GetObject(acObjID, OpenMode.ForRead)

'' Check for starting with 'CP'
If acLyrTbleRec.Name.StartsWith("CP") Then

'' Get Project Object Data Tables
Dim ODTbls As ObjectData.Tables = proj.ODTables

'' Loop through all tables in project
For index = 0 To ODTbls.TablesCount - 1

'' Get Objects Data Table from Objects Data Table's
Dim ODTbl As ObjectData.Table = ODTbls.Item(ODTbls.GetTableNames(index))

'' Get all records from Objects Data Table
Dim ODRecs As Records = ODTbl.GetObjectTableRecords(0, acLyrTbleRec.ObjectId(), Constants.OpenMode.OpenForRead, True)

'' If Objects Data Records count is greater than ZERO
If ODRecs.Count > 0 Then
Dim odRecord As Record = ODRecs.Item(0)

For Each ODRec As Record In ODRecs
Dim a = ODRec.TableName

Next
End If
Next
End If
count = count + 1
Next

End Using

'popDB(circuitNames, acro, map)
Next
quitSub:
End Sub

 

I know its not working and i hope to get some direction on how to get this working, so anything might help. thanks

0 Likes

VB.NET ObjectData records

So, I have been trying to get this right but its not working as i thought it would

 

what i need is to read a dwg and get all the Obeject table records from that drawing. 

 

Should I be using Application.DocumentManager.Open() ? Application.DocumentManager.Add() ? or acCurDb.ReadDwgFile() ?

 

and then 

 

how do i find only layers that startWith("CP")

 

my code that i have tried is . . .

 

Sub getRecs(ByVal acro As String, ByVal map As String)

Dim circuitNames() As String

'' Iterate through each document
For Each acDoc As Document In Application.DocumentManager

Dim acCurDb As Database = acDoc.Database
Dim proj As ProjectModel = HostMapApplicationServices.Application.GetProjectForDB(acCurDb)

'' Start a transaction
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

'' Open the Layer table for read
Dim acLyrTbl As LayerTable
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)

Dim count As Integer = 0

'' Iterate through each Layer Table
For Each acObjID As ObjectId In acLyrTbl

'' Get the Layer Table Record
Dim acLyrTbleRec As LayerTableRecord
acLyrTbleRec = acTrans.GetObject(acObjID, OpenMode.ForRead)

'' Check for starting with 'CP'
If acLyrTbleRec.Name.StartsWith("CP") Then

'' Get Project Object Data Tables
Dim ODTbls As ObjectData.Tables = proj.ODTables

'' Loop through all tables in project
For index = 0 To ODTbls.TablesCount - 1

'' Get Objects Data Table from Objects Data Table's
Dim ODTbl As ObjectData.Table = ODTbls.Item(ODTbls.GetTableNames(index))

'' Get all records from Objects Data Table
Dim ODRecs As Records = ODTbl.GetObjectTableRecords(0, acLyrTbleRec.ObjectId(), Constants.OpenMode.OpenForRead, True)

'' If Objects Data Records count is greater than ZERO
If ODRecs.Count > 0 Then
Dim odRecord As Record = ODRecs.Item(0)

For Each ODRec As Record In ODRecs
Dim a = ODRec.TableName

Next
End If
Next
End If
count = count + 1
Next

End Using

'popDB(circuitNames, acro, map)
Next
quitSub:
End Sub

 

I know its not working and i hope to get some direction on how to get this working, so anything might help. thanks

5 REPLIES 5
Message 2 of 6
Anonymous
in reply to: Anonymous

Anonymous
Not applicable

What do your 'Imports' statments look like? Are you using the Map 3D API for your ObjectData tables?

 

 

0 Likes

What do your 'Imports' statments look like? Are you using the Map 3D API for your ObjectData tables?

 

 

Message 3 of 6
Anonymous
in reply to: Anonymous

Anonymous
Not applicable

Here are my imports


'' Autodesk AutoCAD
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Windows

 

'' Autodesk GIS
Imports Autodesk.Gis.Map.ObjectData
Imports Autodesk.Gis.Map.Project
Imports Autodesk.Gis.Map.Query
Imports Autodesk.Gis.Map

 

'' Autodesk
Imports Autodesk.Windows
Imports System.IO

 

If you find out how to do this then cool and I might switch back to this way, but I have switched to using promptselection with a filter instead. I dont think this is the correct way or fastest way, but it seems to be working. 

0 Likes

Here are my imports


'' Autodesk AutoCAD
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Windows

 

'' Autodesk GIS
Imports Autodesk.Gis.Map.ObjectData
Imports Autodesk.Gis.Map.Project
Imports Autodesk.Gis.Map.Query
Imports Autodesk.Gis.Map

 

'' Autodesk
Imports Autodesk.Windows
Imports System.IO

 

If you find out how to do this then cool and I might switch back to this way, but I have switched to using promptselection with a filter instead. I dont think this is the correct way or fastest way, but it seems to be working. 

Message 4 of 6
Anonymous
in reply to: Anonymous

Anonymous
Not applicable

At a quick glance, I'm noticing you're not disposing of the ObjectData objects. Ensure you clean up after the tables, records, mapvalues, when defining them within a loop. 

 

From the Map 3D ObjectARX .NET Developer's Guide: 

"When you have finished processing the records, release any of the disposable objects with their Dispose() methods. This applies to any classes inheriting Autodesk.AutoCAD.Runtime.DisposableWrapper, like ObjectData.Table, ObjectData.Records, or Utilities.MapValue."

 

'clean up at the end of the for statement
ODTbls.Dispose()
ODTbl.Dispose()
ODRecs.Dispose()
odRecord.Dispose()

 

Are you receiving any sort of unhandled exception or fatal error? Or is this just silently producing nothing?

 

 

0 Likes

At a quick glance, I'm noticing you're not disposing of the ObjectData objects. Ensure you clean up after the tables, records, mapvalues, when defining them within a loop. 

 

From the Map 3D ObjectARX .NET Developer's Guide: 

"When you have finished processing the records, release any of the disposable objects with their Dispose() methods. This applies to any classes inheriting Autodesk.AutoCAD.Runtime.DisposableWrapper, like ObjectData.Table, ObjectData.Records, or Utilities.MapValue."

 

'clean up at the end of the for statement
ODTbls.Dispose()
ODTbl.Dispose()
ODRecs.Dispose()
odRecord.Dispose()

 

Are you receiving any sort of unhandled exception or fatal error? Or is this just silently producing nothing?

 

 

Message 5 of 6
norman.yuan
in reply to: Anonymous

norman.yuan
Mentor
Mentor

From your post, it seems difficult for me to know what problem you are having. How do you know the code is not working? Does it error out or does it work through without error but the result is not you expected?

 

Also, your code is trying to get ODRecord from Layer object. Theoretically, ObjectData in AutoCAD Map can be attached to any DBObject, but it does not make much sense to attach ODRecord to layer object in practice. In fact, In AutoCAD Map, user has no way to attach ObjectData to non-visual object, such as Layer, unless you write code to do it. So, are you sure the drawing your code is running against has layers with ObjectData attached and that is what you are after?

 

In your next post, you mentioned you tried to use PromptSelectionOption. How does it have anything to do to Layer object? Maybe, what you actually want is to get ObjectData from entities only on certain layer(s)? If that is the case, then you can loop all entities in the drawing and only do try to get ODRecord from entitles if the entities on the given layer(s). Better yet, you can get a selectionset with proper filter (layer), and then loop through the smaller set of entities.

 

I suggest that if you show code that does not work as you expected, point out where the code breaks, rather than just saying "it is not working",

Norman Yuan

Drive CAD With Code

EESignature

From your post, it seems difficult for me to know what problem you are having. How do you know the code is not working? Does it error out or does it work through without error but the result is not you expected?

 

Also, your code is trying to get ODRecord from Layer object. Theoretically, ObjectData in AutoCAD Map can be attached to any DBObject, but it does not make much sense to attach ODRecord to layer object in practice. In fact, In AutoCAD Map, user has no way to attach ObjectData to non-visual object, such as Layer, unless you write code to do it. So, are you sure the drawing your code is running against has layers with ObjectData attached and that is what you are after?

 

In your next post, you mentioned you tried to use PromptSelectionOption. How does it have anything to do to Layer object? Maybe, what you actually want is to get ObjectData from entities only on certain layer(s)? If that is the case, then you can loop all entities in the drawing and only do try to get ODRecord from entitles if the entities on the given layer(s). Better yet, you can get a selectionset with proper filter (layer), and then loop through the smaller set of entities.

 

I suggest that if you show code that does not work as you expected, point out where the code breaks, rather than just saying "it is not working",

Norman Yuan

Drive CAD With Code

EESignature

Message 6 of 6
Anonymous
in reply to: Anonymous

Anonymous
Not applicable
Accepted solution

So I tried it this way and it seems to work. if you have any suggestions please let me know. 

   Sub getRecs(ByVal newDoc As Document, ByVal acro As String, ByVal map As String)

        '' Get Database based on New Document
        Dim acCurDb As Database = newDoc.Database

        '' Get Project Model based on New Document Database
        Dim proj As ProjectModel = HostMapApplicationServices.Application.GetProjectForDB(acCurDb)

        '' Get Editor of the New document
        Dim acDocEd As Editor = newDoc.Editor

        '' Create a TypedValue array to define the filter criteria
        Dim acTypValAr() As TypedValue = {New TypedValue(DxfCode.LayerName, "CP*")}

        '' Assign the filter criteria to a SelectionFilter object
        Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)

        '' Request for objects to be selected in the drawing area
        Dim acSSPrompt As PromptSelectionResult = acDocEd.SelectAll(acSelFtr)

        '' If the prompt status is ERROR, objects were not selected so ask user to select them
        If acSSPrompt.Status = PromptStatus.Error Then
            Dim acSSetOpts As PromptSelectionOptions
            acSSetOpts = New PromptSelectionOptions
            acDocEd.WriteMessage("FAILED to auto select CP*" & vbCrLf)
            Exit Sub
        End If

        Dim circuitNames() As String
        ReDim circuitNames(0)
        Dim cirCount = 0
        Dim objSS As SelectionSet
        Dim ODTbl As ObjectData.Table
        Dim ODRecs As ObjectData.Records

        '' If the prompt status is OK, objects were selected
        If acSSPrompt.Status = PromptStatus.OK Then

            '' Get the Object SelectionSet Results
            objSS = acSSPrompt.Value

            '' Iterate over selection
            For index = objSS.Count - 1 To 0 Step -1

                '' Get Project Object Data Table with name "Circuit"
                ODTbl = proj.ODTables("Circuit")

                '' Get Records
                ODRecs = ODTbl.GetObjectTableRecords(0, objSS(index).ObjectId, Constants.OpenMode.OpenForRead, True)

                '' If Objects Data Records count is greater than ZERO
                If ODRecs.Count > 0 Then

                    '' Get the Record from Records
                    Dim ODRec As ObjectData.Record = ODRecs.Item(0)

                    '' Get Circuit Name from Record
                    Dim cir As String = ODRec.Item(0).StrValue

                    '' Only add if NEW
                    If Not circuitNames.Contains(cir) Then

                        '' Get Circuits in this map
                        cirCount = cirCount + 1
                        ReDim Preserve circuitNames(cirCount - 1)
                        circuitNames(cirCount - 1) = cir
                    End If
                End If

                '' Clean up at the end of the for statement
                ODTbl.Dispose()
                ODRecs.Dispose()
            Next
        End If

        'popDB(circuitNames, acro, map)
    End Sub

 

So I tried it this way and it seems to work. if you have any suggestions please let me know. 

   Sub getRecs(ByVal newDoc As Document, ByVal acro As String, ByVal map As String)

        '' Get Database based on New Document
        Dim acCurDb As Database = newDoc.Database

        '' Get Project Model based on New Document Database
        Dim proj As ProjectModel = HostMapApplicationServices.Application.GetProjectForDB(acCurDb)

        '' Get Editor of the New document
        Dim acDocEd As Editor = newDoc.Editor

        '' Create a TypedValue array to define the filter criteria
        Dim acTypValAr() As TypedValue = {New TypedValue(DxfCode.LayerName, "CP*")}

        '' Assign the filter criteria to a SelectionFilter object
        Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)

        '' Request for objects to be selected in the drawing area
        Dim acSSPrompt As PromptSelectionResult = acDocEd.SelectAll(acSelFtr)

        '' If the prompt status is ERROR, objects were not selected so ask user to select them
        If acSSPrompt.Status = PromptStatus.Error Then
            Dim acSSetOpts As PromptSelectionOptions
            acSSetOpts = New PromptSelectionOptions
            acDocEd.WriteMessage("FAILED to auto select CP*" & vbCrLf)
            Exit Sub
        End If

        Dim circuitNames() As String
        ReDim circuitNames(0)
        Dim cirCount = 0
        Dim objSS As SelectionSet
        Dim ODTbl As ObjectData.Table
        Dim ODRecs As ObjectData.Records

        '' If the prompt status is OK, objects were selected
        If acSSPrompt.Status = PromptStatus.OK Then

            '' Get the Object SelectionSet Results
            objSS = acSSPrompt.Value

            '' Iterate over selection
            For index = objSS.Count - 1 To 0 Step -1

                '' Get Project Object Data Table with name "Circuit"
                ODTbl = proj.ODTables("Circuit")

                '' Get Records
                ODRecs = ODTbl.GetObjectTableRecords(0, objSS(index).ObjectId, Constants.OpenMode.OpenForRead, True)

                '' If Objects Data Records count is greater than ZERO
                If ODRecs.Count > 0 Then

                    '' Get the Record from Records
                    Dim ODRec As ObjectData.Record = ODRecs.Item(0)

                    '' Get Circuit Name from Record
                    Dim cir As String = ODRec.Item(0).StrValue

                    '' Only add if NEW
                    If Not circuitNames.Contains(cir) Then

                        '' Get Circuits in this map
                        cirCount = cirCount + 1
                        ReDim Preserve circuitNames(cirCount - 1)
                        circuitNames(cirCount - 1) = cir
                    End If
                End If

                '' Clean up at the end of the for statement
                ODTbl.Dispose()
                ODRecs.Dispose()
            Next
        End If

        'popDB(circuitNames, acro, map)
    End Sub

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report