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
Solved! Go to Solution.
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
Solved! Go to Solution.
What do your 'Imports' statments look like? Are you using the Map 3D API for your ObjectData tables?
What do your 'Imports' statments look like? Are you using the Map 3D API for your ObjectData tables?
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.
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.
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:
'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?
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:
'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?
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
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
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.