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

How to remove the 'user interaction' part from a code?

5 REPLIES 5
Reply
Message 1 of 6
Macia.Lopez
698 Views, 5 Replies

How to remove the 'user interaction' part from a code?

Hi all,

I have got this code by KEAN WALMSLEY.

His code will ask user to select a block and then list all of selected block's attributes. However, I need to tweak his code a little bit and instead of user interaction, the block has to be selected by its name and through my code.

Here is his code (with slight changes to suit my purpose):

 

rivate Sub ListAttributes()
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            Dim db As Database = HostApplicationServices.WorkingDatabase
            Dim tr As Transaction = db.TransactionManager.StartTransaction()
            Try
                Dim filList As TypedValue() = New TypedValue(0) {New TypedValue(CInt(DxfCode.Start), "INSERT")}
                Dim filter As New SelectionFilter(filList)
                Dim opts As New PromptSelectionOptions()
                opts.MessageForAdding = "Select block references: "
                Dim res As PromptSelectionResult = ed.GetSelection(opts, filter)
                If res.Status <> PromptStatus.OK Then
                    Return
                End If
                Dim selSet As SelectionSet = res.Value
                Dim idArray As ObjectId() = selSet.GetObjectIds()
                For Each blkId As ObjectId In idArray
                    Dim blkRef As BlockReference = DirectCast(tr.GetObject(blkId, OpenMode.ForRead), BlockReference)

                    Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                    ed.WriteMessage(vbLf & "Block: " + btr.Name)
                    btr.Dispose()
                    Dim attCol As AttributeCollection = blkRef.AttributeCollection
                    For Each attId As ObjectId In attCol
                        Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)
                        Dim str As String = (vbLf & attRef.Tag + "    " & attRef.TextString)
                        ed.WriteMessage(str)
                    Next
                Next
                tr.Commit()
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                ed.WriteMessage(("Exception: " + ex.Message))
            Finally
                tr.Dispose()
            End Try
        End Sub

 Now, I need to change this Sub to a Function as below:

Private Function ListAttributes (blockName As String) As Boolean

 The aim is to list all block attributes if the 'blockName' exists in drawing and return True afterwards. Oppositely it should return me False and print nothing to Editor if blockName does not exist.

Can anyone help me please?

Cheers

 

 

 

5 REPLIES 5
Message 2 of 6
Hallex
in reply to: Macia.Lopez

You have to create instead function to return your result,

pay attention to how attribute list added ByRef in the function

arguments, that's similar on OUT in C#,

thus the function will work with boolean result and also you

can get attributes if those exist

Here is a quick examole:

        Public Sub ListAttributes()
            Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
            Dim db As Database = HostApplicationServices.WorkingDatabase
            Dim tr As Transaction = db.TransactionManager.StartTransaction()
            Try
                Dim filList As TypedValue() = New TypedValue(0) {New TypedValue(CInt(DxfCode.Start), "INSERT")}
                Dim filter As New SelectionFilter(filList)
                Dim opts As New PromptSelectionOptions()
                opts.MessageForAdding = "Select block references: "
                Dim res As PromptSelectionResult = ed.GetSelection(opts, filter)
                If res.Status <> PromptStatus.OK Then
                    Return
                End If
                Dim selSet As SelectionSet = res.Value
                Dim idArray As ObjectId() = selSet.GetObjectIds()
                For Each blkId As ObjectId In idArray
                    Dim blkRef As BlockReference = DirectCast(tr.GetObject(blkId, OpenMode.ForRead), BlockReference)

                    Dim attDict As Dictionary(Of String, String) = New Dictionary(Of String, String)
                    Dim result As Boolean = (GetAttributes(tr, blkRef, attDict))
                    If result = False Then
                        ed.WriteMessage(vbLf + "{0}", result)
                    Else

                        For Each de As KeyValuePair(Of String, String) In attDict
                            ed.WriteMessage(vbLf + "{0}" + vbTab + "{1}" + vbLf, de.Key, de.Value)
                        Next
                        ed.WriteMessage(vbLf + "{0}", result)

                    End If


                Next
                tr.Commit()
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                ed.WriteMessage(("Exception: " + ex.Message))
            Finally
                tr.Dispose()
            End Try
        End Sub

        Private Function GetAttributes(ByVal tr As Transaction, ByVal blkRef As BlockReference, ByRef attDict As Dictionary(Of String, String)) As Boolean
            Dim result As Boolean = True
            Try
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                If Not btr.HasAttributeDefinitions Then
                    result = False
                Else
                    Dim attCol As AttributeCollection = blkRef.AttributeCollection
                    For Each attId As ObjectId In attCol
                        Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)

                        attDict.Add(attRef.Tag, attRef.TextString)
                    Next
                End If
            Catch ex As Exception
                result = False
            End Try
            Return result
        End Function

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 3 of 6
Macia.Lopez
in reply to: Hallex

Thank you my frined.

 

I am afraid my thread was more concerned about removing 'user interaction' part of the code. Although you clearly addressed the second part of my question, I am still confused how to GetObjectIds of my block through the code.

 

 

In other words, there is no need for user to select the block in AutoCAD. Rather, I need to pass blockname as String in my code and the code has to take care of the rest (I know it sounds less primitive than it actually is)

 

Additionally, thumb up to your idea of making a dictionary out of attribute tags and values. I can take advantage of that somewhere else in my code. Smiley Wink

 

As I mentioned in my previous post, my ideal would be to convert ListAttribute() sub to a function and return Boolean insted of embeding the RETURN functionality inside ListAttribute subroutine. I am more willing to call ListAttributes  function several times in my code. That's why I need a return value for ListAttribute() as following:

 

Private Function ListAttributes (blockName As String) As Boolean

 

Message 4 of 6
Hallex
in reply to: Macia.Lopez

I'm quite sure that you are could be able to rewrite the function from my example above

relatively to block name.

Happy  coding 🙂

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 6

try removing the PromptSelectionOptions and modifying your filter list similar to this?

 Dim filter As TypedValue() = {New TypedValue(0, "INSERT"), New TypedValue(2, "blockname1,blockname2,blockname3,")}
        Dim psr As PromptSelectionResult = ed.SelectAll(New SelectionFilter(filter))
        If psr.Status = PromptStatus.OK Then
            Return
        End If

 

 

Message 6 of 6

Thanks conormccartney3897. I am no longer intrested in this approach as the .NET app developing for my small size drawing office looks like to be a ridiculously tough and challenging task. 

I changed my mind from .NET to Visual LISP. 

 

I know that I will loose the joy of Visual Studio coding but I will get rid of lots of mysterious errors and behaviours toward makeing a safe communication between AutoCAD and my EXE application.

 

The current and new obstacle, for me, is to model the same functionalities that I previously had in my EXE application into LISP.

 

I may bother you guys again in other threads 😉

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost