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 Try ent = ed.GetNestedEntity(entopts) Catch ed.WriteMessage("You did not select a valid entity") End Try If ent.Status = PromptStatus.OK Then CreateDuplicateBlockInModelSpace(ent) 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) Try 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) acBlkTblRec.AppendEntity(blkToPlace) tr.AddNewlyCreatedDBObject(blkToPlace, True) tr.Commit() 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?
Solved! Go to Solution.
Solved by philippe.leefsma. Go to Solution.
Solved by _gile. Go to Solution.
Hi,
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).
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.
http://screencast.com/t/UJGlQ0OmbOqt
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?
Try this snippet (it works for me).
C#
[CommandMethod("Test")] 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) return; ObjectId[] ctnIds = res.GetContainers(); if (ctnIds.Length == 0) return; 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 }); tr.Commit(); } }
F#
[<CommandMethod("Test")>] 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 |]) tr.Commit()
VB
<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 Return End If Dim ctnIds() As ObjectId = res.GetContainers() If ctnIds.Length = 0 Then Return 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}) tr.Commit() End Using End Sub
Hi,
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
[CommandMethod("NestEntSelect")] 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) return; using (Transaction Tx = doc.TransactionManager.StartTransaction()) { //Containers 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; Tx.Commit(); } }
Regards,
Philippe.
Thank you both for the help. Same person, different accounts.
Can't find what you're looking for? Ask the community or share your knowledge.