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

updates blocks with attributes of a given Layout

5 REPLIES 5
Reply
Message 1 of 6
ccalvo12
599 Views, 5 Replies

updates blocks with attributes of a given Layout

Please help at this point, every time I try to update blocks with attributes of a given layout, this only updates the last active layout. example:
I have three layouts: Layout1, Layout2 and Layout3
layout of the three blocks I would need to update the reference but I can Layout1 default that always takes the last active layout.

 

In the following paper space specific code, but as it would to tell a particular layout.

Private Sub UpdateAttributesInDatabase(ByVal db As Database, ByVal blockName As String, ByVal attbName As String, ByVal attbValue As String)

            Dim psId As ObjectId
            Dim tr As Transaction = db.TransactionManager.StartTransaction()
            Using tr

                Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
                psId = bt(BlockTableRecord.PaperSpace)
                tr.Commit()
            End Using
            UpdateAttributesInBlock(db, psId, blockName, attbName, attbValue)

        End Sub

 

5 REPLIES 5
Message 2 of 6
khoa.ho
in reply to: ccalvo12

Hi,

 

You problem is not choosing the correct space to update the block reference with attributes. BlockTableRecord.PaperSpace point to the last active layout, you have to specify the layout that contains this block reference.

The following code will give you a hint to get your psId of given layout name to pass into UpdateAttributesInBlock():

public static ObjectId GetLayoutId(Database db, string layoutName)
{
    using (GetTransaction(db))
    {
        var layoutDict = (DBDictionary)db.LayoutDictionaryId.GetObject(OpenMode.ForRead);
        return layoutDict.GetAt(layoutName);
    }
}

-Khoa

Message 3 of 6
ccalvo12
in reply to: khoa.ho

Hello.

The function that I share "GetLayoutId", i returns a "objectids" type Layout.

The function "UpdateAttributesInBlock" receives as a parameter a "objectids" but it is of type "BlockTableRecord". It is here where there is an error at the time of running the application: how to convert a "objectids" type Layout to a "objectids" type "BlockTableRecord".

 

Thanks for the help,

 

Salutations

 

Private Function UpdateAttributesInBlock(ByVal db As Database, ByVal btrId As ObjectId, ByVal blockName As String, ByVal attbName As String, ByVal attbValue As String) As Integer

            ' Will return the number of attributes modified
            Dim changedCount As Integer = 0
            Dim tr As Transaction = db.TransactionManager.StartTransaction()
            Using tr
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(btrId, OpenMode.ForRead), BlockTableRecord)

                ' Test each entity in the container...
                For Each entId As ObjectId In btr
                    Dim ent As Entity = TryCast(tr.GetObject(btrId, OpenMode.ForRead), Entity)
                    If ent IsNot Nothing Then
                        Dim br As BlockReference = TryCast(ent, BlockReference)
                        If br IsNot Nothing Then
                            Dim bd As BlockTableRecord = DirectCast(tr.GetObject(br.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)

                            ' ... to see whether it's a block with
                            ' the name we're after
                            If bd.Name.ToUpper() = blockName Then
                                ' Check each of the attributes...
                                For Each arId As ObjectId In br.AttributeCollection
                                    Dim obj As DBObject = tr.GetObject(arId, OpenMode.ForRead)
                                    Dim ar As AttributeReference = TryCast(obj, AttributeReference)
                                    If ar IsNot Nothing Then
                                        ' ... to see whether it has

                                        ' the tag we're after

                                        If ar.Tag.ToUpper() = attbName Then
                                            ' If so, update the value
                                            ' and increment the counter
                                            ar.UpgradeOpen()
                                            ar.TextString = attbValue
                                            ar.DowngradeOpen()
                                            changedCount += 1
                                        End If
                                    End If
                                Next
                            End If

                            ' Recurse for nested blocks
                            changedCount += UpdateAttributesInBlock(db, br.BlockTableRecord, blockName, attbName, attbValue)
                        End If
                    End If
                Next
                tr.Commit()
            End Using
            Return changedCount
        End Function

 

Message 4 of 6
khoa.ho
in reply to: ccalvo12

Hi,

I forgot to check the layoutId that used as a blockTableRecordId. They are different. One represents an identity of a layout, one represents an identity of a block table record.

A DWG database has one block table that has many block table records which are model space, paper spaces, block definitions and anonymous blocks. The block reference is an instance of a block table record.

A block table record can store many entities. Model space and Paper spaces are special block table records which store all drawing entities. But Model and Paper spaces do not have their derived block references as they are unique. While block definition is not unique, it has many instances in form as block references with different attribute values.

When we create a block definition in AutoCAD, we create a new block table record on database that stores everything to define this block.

So a block table record is an enumerator that has all its objects inside. Then we use a loop to iterate all objects (identified by unique ObjectId) of this block table record.

Therefore when updating attributes of a block reference, we should know which block table record that stores this block reference. If we have a layout, layout.BlockTableRecordId will return an ObjectId of the block table record of this layout.

The following code will return the spaceId (blockTableRecordId) of a given layout name, and you use the return spaceId to pass into your UpdateAttributesInBlock() method. The spaceId will defined which space to work, it can be Model space or any Paper space (with its layout).

public static ObjectId GetSpaceId(Database db, string layoutName)
{
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        var layoutDict = (DBDictionary)trans.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        ObjectId layoutId = layoutDict.GetAt(layoutName);
        var layout = (Layout)trans.GetObject(layoutId, OpenMode.ForRead);
        return layout.BlockTableRecordId;
    }
}

 -Khoa

Message 5 of 6
ccalvo12
in reply to: ccalvo12

Hello,

thank you very much for the clarification, did not understand very well what in the documentation he explained to me about this topic.

The function works correctly.

Thank you very much.

Greetings

Message 6 of 6
khoa.ho
in reply to: ccalvo12

Happy to help. Please remember to Accept Solution to help later readers.

 

-Khoa

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