Active Contributor
Posts: 29
Registered: ‎07-13-2011
Message 1 of 6 (523 Views)
Accepted Solution

Nested Blocks From Selected Subentity

523 Views, 5 Replies
09-27-2013 08:48 AM

I'm attempting to have the user select mText from a nested block within a block and then copy the nested block to model space out of the block. I'm able to change the mText successfully, but when I attempt to get the nested block it is not in the list of GetContainers() it only contains the block in model space and the model space block. The nested block is missing in the list. I'm using AutoCAD Civil 3D 2013. 


Here is the code to select the mText object which works correctly.


Sub GetNestedMtext()
        ' Have the user select an object. Using the prompt provided.
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
        Dim entopts As New PromptNestedEntityOptions(Environment.NewLine & "Select a mText in block to replace: ")
        entopts.Message = Environment.NewLine & "Select a mText in block to replace: "

        Dim ent As PromptNestedEntityResult = Nothing

            ent = ed.GetNestedEntity(entopts)
            ed.WriteMessage("You did not select a valid entity")

        End Try

        If ent.Status = PromptStatus.OK Then
        End If
    End Sub



Here is the code that attempts to get the nested block which is missing the nested block.


    Private Shared Sub CreateDuplicateBlockInModelSpace(ByVal ent As PromptNestedEntityResult)
            Dim containerObjIds As ObjectId() = ent.GetContainers()
            Dim blkToExtract As BlockReference = DirectCast(containerObjIds(1).GetObject(OpenMode.ForRead), BlockReference)
            Dim blkToPlace As BlockReference = blkToExtract.Clone()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Using tr As Transaction = db.TransactionManager.StartTransaction
                Dim acBlkTbl As BlockTable
                acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim acBlkTblRec As BlockTableRecord
                acBlkTblRec = tr.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                tr.AddNewlyCreatedDBObject(blkToPlace, True)
            End Using
        Catch ex As System.Exception

        End Try

    End Sub

 Is there another way I can get the parent block object for the nested object? 

*Expert Elite*
Posts: 2,082
Registered: ‎04-29-2006
Message 2 of 6 (505 Views)

Re : Nested Blocks From Selected Subentity

09-28-2013 12:52 AM in reply to: christopher



The ObjectId array returned by GetContainers() method is 0 based.


So, if the selected mtext owns to block 'A' which is nested in block 'B' inserted in model space, GetContainers()(0) returns 'A', GetContainers()(1) returns 'B' and GetContainers()(2) returns the model space ObjectId.


In your code, you get the ObjectId at the 1 index (the second item in the array).

Gilles Chanteau
Active Contributor
Posts: 29
Registered: ‎07-13-2011
Message 3 of 6 (494 Views)

Re : Nested Blocks From Selected Subentity

09-29-2013 09:40 AM in reply to: _gile

Yes, that is my expectation of how it supposed to work also. Unfortunately when I run the code I only get two objects back in the collection, it's missing the 0 value we are expecting and insteads returns the block the block is inside of and model space. The nested, nested block is missing. 


Here is a video showing my experience with it. The block in blue is the nested block with the blue mtext the item the user needs to select. I then want the blue block's ObjectId to copy it from the block into model space so the user can move it and use it elsewhere in the drawing. The red is the block that holds the blue block.



I'd prefer the user only clicks once and not have to fake a click for the user, which if it is a bug that I'll have to do.


Could it be a version related bug?

*Expert Elite*
Posts: 2,082
Registered: ‎04-29-2006
Message 4 of 6 (482 Views)

Re : Nested Blocks From Selected Subentity

09-29-2013 01:15 PM in reply to: christopher

Try this snippet (it works for me).



        public void Test()
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptNestedEntityResult res = ed.GetNestedEntity("\nSelect a nested entity: ");
            if (res.Status != PromptStatus.OK)

            ObjectId[] ctnIds = res.GetContainers();
            if (ctnIds.Length == 0)

            using (Transaction tr = db.TransactionManager.StartTransaction())
                BlockReference br = (BlockReference)tr.GetObject(ctnIds[0], OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                BlockReference clone = (BlockReference)br.Clone();
                ObjectId id = btr.AppendEntity(clone);
                tr.AddNewlyCreatedDBObject(clone, true);
                clone.TransformBy(res.Transform * br.BlockTransform.Inverse());
                ed.SetImpliedSelection(new ObjectId[1] { id });



let test () =
    let doc = Application.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor

    let res = ed.GetNestedEntity("\nSelect a nested entity: ")
    if res.Status = PromptStatus.OK then
        let ctnIds = res.GetContainers()
        if ctnIds.Length > 0 then
            use tr = db.TransactionManager.StartTransaction()
            let br = tr.GetObject(ctnIds.[0], OpenMode.ForRead) :?> BlockReference
            let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
            let clone = br.Clone() :?> BlockReference
            let id = btr.AppendEntity(clone)
            tr.AddNewlyCreatedDBObject(clone, true)
            clone.TransformBy(res.Transform * br.BlockTransform.Inverse())
            ed.SetImpliedSelection([| id |])



        <CommandMethod("Test")> _
        Public Sub Test()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim res As PromptNestedEntityResult = ed.GetNestedEntity("Select a nested entity: ")
            If res.Status <> PromptStatus.OK Then
            End If

            Dim ctnIds() As ObjectId = res.GetContainers()
            If ctnIds.Length = 0 Then
            End If

            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim br As BlockReference = DirectCast(tr.GetObject(ctnIds(0), OpenMode.ForRead), BlockReference)
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
                Dim clone As BlockReference = DirectCast(br.Clone(), BlockReference)
                Dim id As ObjectId = btr.AppendEntity(clone)
                tr.AddNewlyCreatedDBObject(clone, True)
                clone.TransformBy(res.Transform * br.BlockTransform.Inverse())
                ed.SetImpliedSelection(New ObjectId(0) {id})
            End Using

        End Sub
Gilles Chanteau
ADN Support Specialist
Posts: 616
Registered: ‎06-02-2009
Message 5 of 6 (444 Views)

Re : Nested Blocks From Selected Subentity

10-01-2013 01:54 AM in reply to: _gile



You can retrieve the nested block the selected entity belongs to using Entity.BlockName and Entity.BlockId properties.


In the attached drawing I have MText inside "Nested" block, which is nested inside topblk. Here is the output of the following code:


Select nested entity:
Container: topblk
Container: *Model_Space
Entity: Autodesk.AutoCAD.DatabaseServices.MText
Block: nested


public void NestEntSelect()
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;

    PromptNestedEntityOptions pneo = new PromptNestedEntityOptions(
        "\nSelect nested entity:");

    PromptNestedEntityResult pner = ed.GetNestedEntity(pneo);

    if (pner.Status != PromptStatus.OK) 

    using (Transaction Tx = doc.TransactionManager.StartTransaction())
        ObjectId[] containerIds = pner.GetContainers();

        foreach (ObjectId id in containerIds)
            DBObject container = Tx.GetObject(id, OpenMode.ForRead);

            if (container is BlockReference)
                BlockReference bref = container as BlockReference;

                ed.WriteMessage("\nContainer: " + bref.BlockName);

        Entity entity = Tx.GetObject(pner.ObjectId, OpenMode.ForRead) 
            as Entity;

        ed.WriteMessage("\nEntity: " + entity.ToString());

        ed.WriteMessage("\nBlock: " + entity.BlockName);

        BlockTableRecord btr = Tx.GetObject(entity.BlockId, OpenMode.ForRead)
            as BlockTableRecord;




Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

*Expert Elite*
Posts: 2,448
Registered: ‎10-13-2005
Message 6 of 6 (423 Views)

Re: Nested Blocks From Selected Subentity

10-01-2013 09:19 AM in reply to: christopher

Thank you both for the help. Same person, different accounts. 

Civil Reminders
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 or visit the Installation and Licensing Forum to get help installing your software.