Jump to content

Help with a simple example


thereisnotime

Recommended Posts

I'm literally just getting into .NET programming and I'm having trouble figuring out how to request pipe information.

 

I've got something simple here where I've counted pipes in the drawing. Now I'm ultimately trying to loop through the pipes and list their slopes but I'm not quite sure how to do that. As you can see, I tried to first start with listing the different pipe IDs and I'm getting the following error...any help or explanation would be greatly appreciated as the API reference isn't doing a very good job with giving examples.

Value of type 'ObjectId' cannot be converted to 'string'

 

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices

Imports Autodesk.Civil.DatabaseServices


Public Class PipeSlope
   <CommandMethod("GetPipeSlope")>
   Public Sub cmdGetPipeSlope()

       Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

       Dim civDoc As Autodesk.Civil.ApplicationServices.CivilDocument
       civDoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument
       Dim pipeIds As ObjectIdCollection = civDoc.GetPipeNetworkIds

       ed.WriteMessage("There are " & pipeIds.Count & " pipes in the drawing.")

       Dim oCurrentPipe = civDoc.NetworkState.CurrentPipeId

       For i = 0 To pipeIds.Count
           ed.WriteMessage(oCurrentPipe)

       Next
   End Sub
End Class

Link to comment
Share on other sites

I hope that this helps steer you in the right direction. Feel free to ask specifics about what is happening in the code if you are having questions.

 


[color="red"]Imports Autodesk.Civil.ApplicationServices[/color]


<CommandMethod("GetPipeSlope")>
       Public Sub cmdGetPipeSlope()
           Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
           Dim civDoc As civilDocument = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument
           Dim aDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
           Dim db As Database = aDoc.Database
           Dim NetworkIds As ObjectIdCollection = civDoc.GetPipeNetworkIds
           Using trans As Transaction = db.TransactionManager.StartTransaction
               For Each NetId As ObjectId In NetworkIds
                   Dim net As Network = trans.GetObject(NetId, OpenMode.ForRead)
                   ed.WriteMessage(vbCrLf + net.Name)
                   Dim PipeIds As ObjectIdCollection = net.GetPipeIds
                   Using trans2 As Transaction = db.TransactionManager.StartTransaction
                       Dim cnt As Integer = 1
                       For Each PipeId As ObjectId In PipeIds
                           Dim pipe As Pipe = trans2.GetObject(PipeId, OpenMode.ForRead)
                           ed.WriteMessage(vbCrLf + cnt.ToString + " : " + pipe.Name + "   -   " + (pipe.Slope * 100.0).ToString("N2") + "%")
                           cnt = cnt + 1
                       Next
                       trans2.Commit()
                   End Using
               Next
               trans.Commit()
           End Using
       End Sub

Link to comment
Share on other sites

That's awesome, thanks so much.

 

I'm coming primarily from VBS and connecting/reading from a database is a little different; in VBS, you would use an ADO connection to connect to an MS Access database, but it's like any file...you have to open for reading, then close the connection once you're done. Do you have to close or disconnect from the DB here as well?

Link to comment
Share on other sites

Access to database objects are done through transactions. Since I am using the "Using" statement I do not need to dispose of the transaction as this is automatically completed for me at the "end using". If I wasn't using the "using" statement then I would have to call trans.dispose to dispose of the transaction object.

Link to comment
Share on other sites

Oh nice! So Using is akin to accessing the DB as read-only...that's really handy.

 

I guess I wouldn't look at "using" in that manner. "Using" is a way to easily work with disposable items, more or less. An instance of a transaction needs to be properly disposed of when you are done using it. I can use "using" in a transaction and write to the database as when. Transactions are simply the proper way to interact with the AutoCAD Database. "Using" is an easy way to dispose of an item when done using it.

Link to comment
Share on other sites

Okay, I took this one step further...not sure if I should create a new thread for this or not...wouldn't be a big deal if I need to...Anyway...

 

This code allows the user to select objects with a crossing window. Then it will take all the object IDs and compare them to the object IDs in the pipe network object collection. If they match, it's a pipe. It will then display the flow method on the screen for each pipe.

 

What I would like to do is make a variable as "ForWrite" to change the method to 3. I tried doing something like this but it gave me an error about how Entity is too broad of a name and I'm not sure how to fix it:

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.Civil.ApplicationServices
Imports Autodesk.Civil.DatabaseServices

Public Class DisplayPipeInfoSingleSelection
   <CommandMethod("DisplayPipeInfo")>
   Public Sub cmdDisplayPipeInfo()
       Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
       Dim civilDOC As CivilDocument = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument
       Dim cadDOC As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
       Dim cadDB As Database = cadDOC.Database
       Dim pipeNetIDs As ObjectIdCollection = civilDOC.GetPipeNetworkIds

       '// Open the DB query
       Using cadTrans As Transaction = cadDB.TransactionManager.StartTransaction()
           Dim cadSSPrompt As PromptSelectionResult = cadDOC.Editor.GetSelection()

           '// If user pressed enter after prompt
           If cadSSPrompt.Status = PromptStatus.OK Then
               Dim cadSSet As SelectionSet = cadSSPrompt.Value

               For Each item As SelectedObject In cadSSet
                   ed.WriteMessage(vbCrLf & "Object in CAD DB: " & item.ObjectId.ToString)
                   '// Check if the item is in the DB
                   If Not IsDBNull(item) Then
                       '// Loop through the networks and see if the object ID is a pipe
                       For Each netID As ObjectId In pipeNetIDs
                           Dim net As Network = cadTrans.GetObject(netID, OpenMode.ForRead)
                           Dim pipeIDs As ObjectIdCollection = net.GetPipeIds

                           Using cadTrans2 As Transaction = cadDB.TransactionManager.StartTransaction
                               For Each pipeID As ObjectId In pipeIDs
                                   Dim pipeOBJ As Pipe = cadTrans2.GetObject(pipeID, OpenMode.ForRead)

                                   If pipeID = item.ObjectId Then
                                       Select Case pipeOBJ.FlowDirectionMethod
                                           Case 0
                                               ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: Bi-Directional")
                                           Case 1
                                               ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: Start to End")
                                           Case 2
                                               ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: End to Start")
                                           Case 3
                                               ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: By Slope")
                                       End Select

                                       '// This is where the "Entity" error is
                                       Dim pipeOBJwrite As Entity = cadTrans2.GetObject(pipeID, OpenMode.ForWrite)

                                   End If
                               Next
                           End Using
                       Next
                   End If
               Next
           End If
       End Using
   End Sub
End Class

Link to comment
Share on other sites

If you know that you are only going to be working with pipes. Then only allow the user to select pipes.

 

 

Dim acTypValAr(0) As TypedValue
acTypValAr.SetValue(New TypedValue(DxfCode.Start, "AECC_PIPE"), 0)
Dim pSelFil As SelectionFilter = New SelectionFilter(acTypValAr)
Dim cadSSPrompt As PromptSelectionResult = cadDOC.Editor.GetSelection(pSelFil)

Link to comment
Share on other sites

You can read from an object that you have open for write.

 

There is also an upgrade open method. If you had previously opened for read to can upgrade open to write.

 

If you know that you are working with a pipe you should

Dim dbobj as Pipe = trans.GetObject(ObjID,openmode.forwrite)

Link to comment
Share on other sites

***NOTE***

 

Do not forget to:

 

trans.commit()

 

Otherwise your transaction will rollback as if nothing ever happened. This can be frustrating as all seems correct with the code but nothing is working.

Link to comment
Share on other sites

Alright, as a test, I clicked a single pipe only that I knew was "By slope" and I'm getting an "InvalidOperationException" error on the line:

Dim pipeOBJ As Pipe = cadTrans.GetObject(pipeID, OpenMode.ForWrite)

 

System.InvalidOperationException was unhandled by user code

HResult=-2146233079

Message=Operation is not valid due to the current state of the object.

Source=Acdbmgd

StackTrace:

at Autodesk.AutoCAD.DatabaseServices.Transaction.CheckTopTransaction()

at Autodesk.AutoCAD.DatabaseServices.Transaction.GetObject(ObjectId id, OpenMode mode)

at DisplayPipeInfo.DisplayPipeInfoSingleSelection.cmdDisplayPipeInfo() in H:\Civil3D\VBA .NET\Test Project\DisplayPipeInfo\DisplayPipeInfo\DisplayPipeInfo\DisplayPipeInfoSingleSelection.vb:line 40

at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)

at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)

at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)

at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()

InnerException:

 

**Edit: hang on, trying something...

Edited by thereisnotime
Link to comment
Share on other sites

Okay, no more error, but CAD crashes everytime I run the command lol

 

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.Civil.ApplicationServices
Imports Autodesk.Civil.DatabaseServices

Public Class DisplayPipeInfoSingleSelection
   <CommandMethod("DisplayPipeInfo")>
   Public Sub cmdDisplayPipeInfo()
       Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
       Dim civilDOC As CivilDocument = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument
       Dim cadDOC As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
       Dim cadDB As Database = cadDOC.Database
       Dim pipeNetIDs As ObjectIdCollection = civilDOC.GetPipeNetworkIds

       '// Open the DB query
       Using cadTrans As Transaction = cadDB.TransactionManager.StartTransaction()
           '// Use this to filter out ONLY pipes
           Dim acTypValAr(0) As TypedValue
           acTypValAr.SetValue(New TypedValue(DxfCode.Start, "AECC_PIPE"), 0)
           Dim pSelFil As SelectionFilter = New SelectionFilter(acTypValAr)
           Dim pSelFilOpt As New PromptSelectionOptions
           With pSelFilOpt
               .AllowDuplicates = False
               .AllowSubSelections = False
               .RejectObjectsFromNonCurrentSpace = True
               .RejectObjectsOnLockedLayers = False
           End With

           Dim cadSSPrompt As PromptSelectionResult = cadDOC.Editor.GetSelection(pSelFilOpt, pSelFil)
           Dim cadSSet As SelectionSet = cadSSPrompt.Value

           For Each item As SelectedObject In CadSSet
               If cadSSPrompt.Status = PromptStatus.OK Then
                   For Each netID As ObjectId In pipeNetIDs
                       Dim net As Network = cadTrans.GetObject(netID, OpenMode.ForWrite)
                       Dim pipeIDs As ObjectIdCollection = net.GetPipeIds

                       For Each pipeID As ObjectId In pipeIDs
                           Dim pipeOBJ As Pipe = cadTrans.GetObject(pipeID, OpenMode.ForWrite)

                           If pipeID = item.ObjectId Then
                               Select Case pipeOBJ.FlowDirectionMethod
                                   Case 0
                                       ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: Bi-Directional")
                                       pipeOBJ.FlowDirectionMethod = 3
                                       cadTrans.Commit()
                                   Case 1
                                       ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: Start to End")
                                       pipeOBJ.FlowDirectionMethod = 3
                                       cadTrans.Commit()
                                   Case 2
                                       ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: End to Start")
                                       pipeOBJ.FlowDirectionMethod = 3
                                       cadTrans.Commit()
                                   Case 3
                                       ed.WriteMessage(vbCrLf & pipeOBJ.Name & " flow method: By Slope")
                               End Select
                           End If
                       Next
                   Next
               End If
           Next
       End Using
   End Sub
End Class

Link to comment
Share on other sites

There were a few quirky things that you were doing that didn't seem to quite make sense. I have rewritten your code according to what I thought that you were trying to do.

 

<CommandMethod("SetPipeFlowMethodToSlope")>
       Public Sub setPipeFlowMethodToSlope()
           'Get Documents and Database
           Dim aDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
           Dim ed As Editor = aDoc.Editor
           Dim db As Database = aDoc.Database

           'Build SelectionSet Options and Filter
           Dim acTypValAr(0) As TypedValue
           acTypValAr.SetValue(New TypedValue(DxfCode.Start, "AECC_PIPE"), 0)
           Dim pSelFil As SelectionFilter = New SelectionFilter(acTypValAr)
           Dim pSelFilOpt As New PromptSelectionOptions
           With pSelFilOpt
               .AllowDuplicates = False
               .AllowSubSelections = False
               .RejectObjectsFromNonCurrentSpace = True
               .RejectObjectsOnLockedLayers = False
           End With
           'Prompt for Selection
           Dim PrmptSelRes As PromptSelectionResult = aDoc.Editor.GetSelection(pSelFilOpt, pSelFil)
           'Test for a Good Selection
           If PrmptSelRes.Status = PromptStatus.OK Then
               'Get the SelectionSet
               Dim ss As SelectionSet = PrmptSelRes.Value
               'Begin a database transaction
               Using trans As Transaction = db.TransactionManager.StartTransaction
                   For Each item As SelectedObject In ss
                       'Open each pipe in the selectionset for write
                       Dim pipeObj As Pipe = trans.GetObject(item.ObjectId, OpenMode.ForWrite)
                       'Print the Network Name, Pipe Name & Current Flow Method.
                       ed.WriteMessage(vbCrLf + "Network: " + pipeObj.NetworkName + "  Name: " + pipeObj.Name + " - " + pipeObj.FlowDirectionMethod.ToString)
                       'Set the Flow Direction to BySlope
                       pipeObj.FlowDirectionMethod = FlowDirectionMethodType.BySlope
                       'Print what we just did.
                       ed.WriteMessage(vbCrLf + "Name: " + pipeObj.Name + " FlowDirectionMethod has been set to BySlope.")
                   Next
                   'Commit the transaction.
                   trans.Commit()
               End Using
           End If
           ed.WriteMessage(vbCrLf + "Command has completed sucessfully.")
       End Sub

Link to comment
Share on other sites

Ah yes, I see where I was going wrong. Too much "patchwork" on my part. Thanks so much. This is a great starting point for me :)

 

That's so interesting how you can't just say the integer of the flow direction method...you have to say "BySlope", but I guess that makes sense since you have to assign it to the property. I think I understand how this all works now; the program will give you the numerical value of a property, but you can't just say "this property, instead of 2, make it 3", you have to physically make it equal to a raw property of that object.

 

Much different than Visual Basic Script lol but it makes sense now.

Edited by thereisnotime
Link to comment
Share on other sites

Actually you can use the enum value (in this case 3) instead of the enum. I prefer to use the enum when ever possible for better readability of the code.

 

<CommandMethod("SetPipeFlowMethodToSlope")>
       Public Sub setPipeFlowMethodToSlope()
           'Get Documents and Database
           Dim aDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
           Dim ed As Editor = aDoc.Editor
           Dim db As Database = aDoc.Database

           'Build SelectionSet Options and Filter
           Dim acTypValAr(0) As TypedValue
           acTypValAr.SetValue(New TypedValue(DxfCode.Start, "AECC_PIPE"), 0)
           Dim pSelFil As SelectionFilter = New SelectionFilter(acTypValAr)
           Dim pSelFilOpt As New PromptSelectionOptions
           With pSelFilOpt
               .AllowDuplicates = False
               .AllowSubSelections = False
               .RejectObjectsFromNonCurrentSpace = True
               .RejectObjectsOnLockedLayers = False
           End With
           'Prompt for Selection
           Dim PrmptSelRes As PromptSelectionResult = aDoc.Editor.GetSelection(pSelFilOpt, pSelFil)
           'Test for a Good Selection
           If PrmptSelRes.Status = PromptStatus.OK Then
               'Get the SelectionSet
               Dim ss As SelectionSet = PrmptSelRes.Value
               'Begin a database transaction
               Using trans As Transaction = db.TransactionManager.StartTransaction
                   For Each item As SelectedObject In ss
                       'Open each pipe in the selectionset for write
                       Dim pipeObj As Pipe = trans.GetObject(item.ObjectId, OpenMode.ForWrite)
                       'Print the Network Name, Pipe Name & Current Flow Method.
                       ed.WriteMessage(vbCrLf + "Network: " + pipeObj.NetworkName + "  Name: " + pipeObj.Name + " - " + pipeObj.FlowDirectionMethod.ToString)
                       'Set the Flow Direction to BySlope
                       [color="red"]pipeObj.FlowDirectionMethod = 3[/color]
                       'Print what we just did.
                       ed.WriteMessage(vbCrLf + "Name: " + pipeObj.Name + " FlowDirectionMethod has been set to BySlope.")
                   Next
                   'Commit the transaction.
                   trans.Commit()
               End Using
           End If
           ed.WriteMessage(vbCrLf + "Command has completed successfully.")
       End Sub

 

https://msdn.microsoft.com/en-us/library/3sd4y2w7.aspx

Edited by Hippe013
Typo
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...