Copy block from one layout to all other layouts same coordinates

Copy block from one layout to all other layouts same coordinates

David_Prontnicki
Collaborator Collaborator
859 Views
7 Replies
Message 1 of 8

Copy block from one layout to all other layouts same coordinates

David_Prontnicki
Collaborator
Collaborator

I am trying to copy a block reference to each paperspace layout tab to the same coordinates. The program currently inserts the block at the user's selected coordinates. I get the block objectId and the user selected coordinates and pass them to the sub below. I have tried may things but cant seem to get it to work. Any help would be greatly appreciated.

 

    Private Sub CopyToAllLayouts(acBlockReferenceObjectId As ObjectId, insertionPoint As Point3d)

        Dim acCurrentDatabase As Database = Active.Database
        Dim acDocumentEditor As Editor = Active.Editor

        Using acDocumentLock As DocumentLock = Active.Document.LockDocument()

            Using acTranaction As Transaction = Active.Database.TransactionManager.StartTransaction()

                Dim acLayoutDatabaseDictionary As DBDictionary = TryCast(acTranaction.GetObject(acCurrentDatabase.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)

                For Each acLayoutDatabaseDictionaryEntry As DBDictionaryEntry In acLayoutDatabaseDictionary

                    Dim acLayout As Layout = CType(acLayoutDatabaseDictionaryEntry.Value.GetObject(OpenMode.ForRead), Layout)
                    Dim acLayoutName As String = acLayout.LayoutName
                    Dim acLayoutObjectId As ObjectId = acLayoutDatabaseDictionary.GetAt(acLayoutName)

                    Dim acBlockTableRecord = CType(acTranaction.GetObject(acLayout.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)

                    Dim acBlockReference As BlockReference = New BlockReference(insertionPoint, acBlockReferenceObjectId)

                    'Dim acBlockTable = DirectCast(acTranaction.GetObject(acCurrentDatabase.BlockTableId, OpenMode.ForRead), BlockTable)
                    'Dim acBlockReference = New BlockReference(insertionPoint, acBlockReferenceObjectId)
                    'Dim acBlockTableRecord = DirectCast(acTranaction.GetObject(acCurrentDatabase.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)

                    'acBlockReference.TransformBy(acDocumentEditor.CurrentUserCoordinateSystem)

                    acBlockTableRecord.UpgradeOpen()
                    acBlockReference.TransformBy(acDocumentEditor.CurrentUserCoordinateSystem)
                    acBlockTableRecord.AppendEntity(acBlockReference)
                    acTranaction.AddNewlyCreatedDBObject(acBlockReference, True)

                Next

                acTranaction.Commit()

            End Using

        End Using

    End Sub
0 Likes
Accepted solutions (1)
860 Views
7 Replies
Replies (7)
Message 2 of 8

_gile
Consultant
Consultant

This should work.

 

        private static void CopyToAllLayouts(ObjectId blockTableRecordId, Point3d position)
        {
            var db = HostApplicationServices.WorkingDatabase;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                foreach (DBDictionaryEntry entry in layouts)
                {
                    if (entry.Key != "Model")
                    {
                        var layout = (Layout)tr.GetObject(entry.Value, OpenMode.ForRead);
                        var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
                        var br = new BlockReference(position, blockTableRecordId);
                        btr.AppendEntity(br);
                        tr.AddNewlyCreatedDBObject(br, true);
                    }
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 8

David_Prontnicki
Collaborator
Collaborator

@_gile 

Thank you for the speedy reply. One small problem. It is copying the block to the right location but the attributes are now empty. The block contains 5 attribute values that get applied on initial insertion. That works perfect. during the copy process the attributes are now blank. Any ideas why that may be?

Message 4 of 8

_gile
Consultant
Consultant
Accepted solution

With .NET, you have to explicitly create the attribute references using the attribute definitions as templates. See this topic.

private static void CopyToAllLayouts(ObjectId blockTableRecordId, Point3d position)
{
    var db = HostApplicationServices.WorkingDatabase;
    using (var tr = db.TransactionManager.StartTransaction())
    {
        var layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        foreach (DBDictionaryEntry entry in layouts)
        {
            if (entry.Key != "Model")
            {
                // insert the block reference
                var layout = (Layout)tr.GetObject(entry.Value, OpenMode.ForRead);
                var owner = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
                var br = new BlockReference(position, blockTableRecordId);
                owner.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);

                // add attribute references
                var btr = (BlockTableRecord)tr.GetObject(blockTableRecordId, OpenMode.ForRead);
                foreach (ObjectId id in btr)
                {
                    if (id.ObjectClass == RXObject.GetClass(typeof(AttributeDefinition)))
                    {
                        var attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                        if (!attDef.Constant)
                        {
                            var attRef = new AttributeReference();
                            attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                            br.AttributeCollection.AppendAttribute(attRef);
                            tr.AddNewlyCreatedDBObject(attRef, true);
                        }
                    }
                }
            }
        }
        tr.Commit();
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 8

lena.talkhina
Alumni
Alumni

Hello @David_Prontnicki !

 

Great to see you here on .NET forum.

Don't forget to accept a solution when you receive the answer which works for you.

Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям! | Do you find the posts helpful? "LIKE" these posts!
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.



Лена Талхина/Lena Talkhina
Менеджер Сообщества - Русский/Community Manager - Russian

0 Likes
Message 6 of 8

David_Prontnicki
Collaborator
Collaborator

@_gile 

 

Thank you very much. Works perfect. I appreciate all the help, and apologize for not mentioning the attributes in the OP. 

0 Likes
Message 7 of 8

David_Prontnicki
Collaborator
Collaborator

@_gile 

 

One last question....

One of the attributes may or may not contain a width factor that is set on insert. 

How can I assign the same width factor to each "copied" block's attribute. I have tried many things over the weekend and cant seem to figure it out. I have the tag name for the attribute and the width but cant seem to figure out how to apply it to that attribute during the copy process.

0 Likes
Message 8 of 8

David_Prontnicki
Collaborator
Collaborator

@_gile 

 

Never mind. Of course I figure it out after I post. LOL sometimes typing out the question gets you the answer. 

 

Private Sub CopyBlockToAllLayouts(acInsertedBlockTableRecordObjectId As ObjectId, insertionPoint As Point3d)

        Dim acCurrentDatabase As Database = Active.Database

        Dim professionalAttributeObjectId As ObjectId

        Using acDocumentLock As DocumentLock = Active.Document.LockDocument()

            Using acTranaction As Transaction = acCurrentDatabase.TransactionManager.StartTransaction()

                Dim acLayoutDatabaseDictionary = CType(acTranaction.GetObject(acCurrentDatabase.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)

                For Each acLayoutDatabaseDictionaryEntry As DBDictionaryEntry In acLayoutDatabaseDictionary

                    If acLayoutDatabaseDictionaryEntry.Key <> "Model" Then

                        Dim acLayout = CType(acTranaction.GetObject(acLayoutDatabaseDictionaryEntry.Value, OpenMode.ForRead), Layout)
                        Dim acBlockTableRecordOwner = CType(acTranaction.GetObject(acLayout.BlockTableRecordId, OpenMode.ForWrite), BlockTableRecord)
                        Dim acBlockReference = New BlockReference(insertionPoint, acInsertedBlockTableRecordObjectId)

                        acBlockTableRecordOwner.AppendEntity(acBlockReference)
                        acTranaction.AddNewlyCreatedDBObject(acBlockReference, True)

                        Dim acBlockTableRecord = CType(acTranaction.GetObject(acInsertedBlockTableRecordObjectId, OpenMode.ForRead), BlockTableRecord)

                        For Each acAtributeDefinitionObjectId As ObjectId In acBlockTableRecord

                            If acAtributeDefinitionObjectId.ObjectClass = RXObject.GetClass(GetType(AttributeDefinition)) Then

                                Dim acAttributeDefinition = CType(acTranaction.GetObject(acAtributeDefinitionObjectId, OpenMode.ForRead), AttributeDefinition)

                                If Not acAttributeDefinition.Constant Then

                                    Dim acAttributeReference As New AttributeReference()
                                    acAttributeReference.SetAttributeFromBlock(acAttributeDefinition, acBlockReference.BlockTransform)
'Added this line
                                    acAttributeReference.TextString = acAttributeDefinition.TextString
                                    acBlockReference.AttributeCollection.AppendAttribute(acAttributeReference)
                                    acTranaction.AddNewlyCreatedDBObject(acAttributeReference, True)
'added select case and ran my SetNameAttributeWidth sub
                                    Select Case acAttributeDefinition.Tag

                                        Case "PROFESSIONAL"

                                            professionalAttributeObjectId = acAttributeReference.ObjectId

                                            SetNameAttributeWidth(professionalAttributeObjectId, 2.7)

                                    End Select

                                End If

                            End If

                        Next

                    End If

                Next

                acTranaction.Commit()

            End Using

        End Using

    End Sub
0 Likes