VBA
Discuss AutoCAD ActiveX and VBA (Visual Basic for Applications) questions here.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Getting Constant Attribute using VB.net

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
hakand
1720 Views, 6 Replies

Getting Constant Attribute using VB.net

Hey guys,

 

Just wondering how I would be able to grab the block constant attribute by searching via tag.

 

eg block has a constant attribute 'Color' with value of 'red' and I wish to attain 'red'

 

I am currently obtaining non constant attributes using:

Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)

and grabbing the '.textstring' when looking at the '.tag'

 

How do I go about this with similar logic but pointing to constant attributes?

 

I have tried searching thoroughly and almost all results for me were in VBA.

 

Many thanks

6 REPLIES 6
Message 2 of 7
StephenPreston
in reply to: hakand

Constant attributes are stored as AttributeDefinitions in the BlockTableRecord. They're not stored with the BlockReference because they are constant across all BlockReferences.

 

Cheers,

Stephen Preston
Autodesk Developer Network
Message 3 of 7
hakand
in reply to: StephenPreston

Ah thank you for the answer. I'm still trying to get my head around this as there aren't many examples available.

 

How would I cycle through my blocks and point to a specific constant tag and grab the textstring?

 

Could anyone please provide an example or something related in vb.net?

 

Or if anyone could please show how I would implement it into the below code I am currently using, that would be much appreciated.

 

 

 

            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)

 

                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 & "  Attribute Tag: " + attRef.Tag & vbLf & "    Attribute String: ") + attRef.TextString)

                    If attRef.Tag = "COLOR" Then

                        If grouparray.Contains(attRef.TextString) = False Then

                            grouparray.Add(attRef.TextString)

                        End If

                    End If

                Next

            Next

 

 

Many thanks,

HD

Message 4 of 7
norman.yuan
in reply to: hakand

As Stephem has already pointed out, constant attribute is defined in BlockTableRecord (block definition). There is no AttributeReference created in Blockreference if an AttributeDefinition is defined as Constant.

 

You need to understand

 

1. AttributeReference is an entitiy created in BlockReference with AttributeDefinition as TEMPLATE, but does not have to be te same as he AttributeDefinition. In fact, you can add AttributeReference to a BlockReference without AttributeDefition.

 

2. Constant AttributeDefition defined in a BlockTableRecord acts the same as a Text entity in BlockTableRecord. That is, the Attribute will go with all other entities in the block definition into a BlockReference.

 

So, if you need to get value of a constant atribute, the code would like this (assume you seelcteda BlockReferenece' ObjectId, just off my head, not compiled/tested):

 

using (Transaction tran=theDatabase.TransactionManager.StartTransaction())
{
    BlockReference bRef=(BlockReference)tran.GetObject(blkrefId, OpenMode.ForRead);
    BlockTableRecord blk=(BlockTableRecord)tran.GetObject(bRef.BlockTableRecord, OpenMode.ForRead);

    foreach (ObjectId id in blk)
    {
        AttributeDefinition att=tran.GetObject(id,OpenMode.ForRead) As AttributeDefinition;

        if (att!=null)
        {
            if (att.Constant)
            {
                if (att.Tag.ToUpper()=="MY_TARGET_ATT")
                {
                    MessageBox.Show("The value I am looking for is " + att.TextString);
                    att.UpgradeOpen();
                    att.TextString="New Value;
                }
            }
        }
    }

    tran.Commit();
}

//since you changed constant attribute's value in block definition, all
//Blockreferences of this block in the drawing will also change. Do
//a Regen will show the effect
Editor.Regen();

 HTH.

Message 5 of 7
hakand
in reply to: hakand

Thank you very much for the reply. That has helped me a lot in gauging a clear understanding.

 

I have implemented your suggestion into my code but there is still an issue.

 

I keep getting this error on creating the Attributedefinition:

 

Unable to cast object of type

'Autodesk.AutoCAD.DatabaseServices.Polyline' to type 'Autodesk.AutoCAD.DatabaseServices.Attributedefinition'

 

This happens to all types of blocks, whether it be polyline, solid3d etc.

 

What type should the object be for it to be changed successfully?

 

Here is my new code below, the 'For Each id As ObjectId In btr' loop has been added in as suggested.

What am I doing wrong here?

 

 

        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        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.Valu
            Dim idArray As ObjectId() = selSet.GetObjectIds()

            For Each blkId As ObjectId In idArray

                Dim obj As DBObject = tr.GetObject(blkId, OpenMode.ForRead)
                 
                Dim blkRef As BlockReference = DirectCast(tr.GetObject(blkId, OpenMode.ForRead), BlockReference)
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)


                For Each id As ObjectId In btr

                    Dim ad As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)

                    If ad IsNot Nothing Then

                        If ad.Constant = False Then

                            If ad.Tag.ToUpper = "CATEGORY" Then

                                grouparray.Add(ad.TextString)

                            End If

                        End If

                    End If
                Next

 

Again .. Many thanks for everyones time, it is much appreciated,

HD

Message 6 of 7
norman.yuan
in reply to: hakand

The c# statement

 

[Type] something=...... as [Type]

 

is not the same as DirectCast() in VB, rather it is similar to TryCast(). You cannot DirectCast() whatever in a block definition into an AttributeDefinition, if it is not an AttributeDefinition.

 

So, simple change this line:

 

Dim ad As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)

To:

 

Dim ad As AttributeDefinition = TryCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)

Message 7 of 7
hakand
in reply to: norman.yuan

Thanks Norman, that did the trick!

 

Much appreciated with the time spent helping me with my issue.

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

Post to forums  

Autodesk Design & Make Report

”Boost