.NET

Reply
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 1 of 6 (375 Views)

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

375 Views, 5 Replies
05-14-2013 05:12 PM

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

 

 

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 2 of 6 (348 Views)

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

05-15-2013 12:42 AM in reply to: bababarghi

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
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 3 of 6 (325 Views)

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

05-15-2013 03:21 PM 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. :smileywink:

 

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

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 4 of 6 (304 Views)

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

05-16-2013 01:28 PM in reply to: bababarghi

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

relatively to block name.

Happy  coding :smileyhappy:

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Mentor
conormccartney3897
Posts: 170
Registered: ‎08-18-2010
Message 5 of 6 (278 Views)

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

05-21-2013 01:48 PM in reply to: bababarghi

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

 

 

Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 6 of 6 (271 Views)

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

05-21-2013 02:49 PM in reply to: conormccartney3897

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 :smileywink:

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community