Using ACAD 2014, VB.NET code.
I am attempting to develop an app that has to insert block references into the active Paper Space layout. I've found numerous code examples for inserting blocks, including the recent one in this forum. Through various iterations of my code I still have not been successful. The code works for inserting blocks in Model space. The odd part about the Model space functionality is that I have to save and exit the drawing, then reopen it for the block to appear.
My function is included below. You will see the variations I have tried preceeded by the comments #Attempt 1, #Attempt 2, and #Attempt 3.
Thanks for any help you can provide.
Public Function InsertBlock(ByVal BlockName As String, ByVal ptPosition As Point3d, Optional ByVal inPaperSpace As Boolean = False, Optional ByVal LayoutName As String = "") As Boolean ' Get the current database and start a transaction Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acCurDb As Autodesk.AutoCAD.DatabaseServices.Database acCurDb = Application.DocumentManager.MdiActiveDocument.Database InsertBlock = False Using acLckDocCur As DocumentLock = acDoc.LockDocument Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction() ' Open the Block table for read Dim acBlkTbl As BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) Dim blkRecId As ObjectId = ObjectId.Null If acBlkTbl.Has(BlockName) Then blkRecId = acBlkTbl(BlockName) Else Exit Function End If ' Insert the block reference into the current space If blkRecId <> ObjectId.Null Then Using acBlkRef As New BlockReference(New Point3d(0, 0, 0), blkRecId) With acBlkRef .SetDatabaseDefaults() .Visible = True .Position = ptPosition .ScaleFactors = New Autodesk.AutoCAD.Geometry.Scale3d(10, 10, 10) .Rotation = 0 End With Dim acBlkTblRec As BlockTableRecord 'Attempt #1 'acBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) 'Attempt #2 If inPaperSpace Then 'acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.PaperSpace), OpenMode.ForWrite) 'Attempt #3 If LayoutName.Length = 0 Then Exit Function End If Dim loMgr As LayoutManager = LayoutManager.Current Dim loID As ObjectId = loMgr.GetLayoutId(LayoutName) Dim lo As Layout = acTrans.GetObject(loID, OpenMode.ForRead) acBlkTblRec = acTrans.GetObject(lo.BlockTableRecordId, OpenMode.ForWrite) Else acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite) End If acBlkTblRec.AppendEntity(acBlkRef) acTrans.AddNewlyCreatedDBObject(acBlkRef, True) End Using End If ' Save the new object to the database acTrans.Commit() ' Dispose of the transaction InsertBlock = True End Using End Using End Function
Solved! Go to Solution.
Solved by RodWing. Go to Solution.
Just wrote this sample which inserted a simple block in the uninitialised Layout1.
Hope this might help you find you're problem.
Also simplified the call to InsertBlock a bit, if layoutName=="" then insert into Modelspace.
Tip: You also might add rotation, scale and a list of attributes to increase usability
[CommandMethod("TestInsert")] public void TestInsert() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; string blockName = "Block1"; Point3d insPnt = new Point3d(10, 10, 0); string layoutName = "Layout1"; try { InsertBlock(db, layoutName, blockName, insPnt); } catch (System.Exception ex) { ed.WriteMessage("\n {0}", ex.Message); } } public bool InsertBlock(Database db, string layoutName, string blockName, Point3d insPnt) { LayoutManager layoutManager = LayoutManager.Current; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (!bt.Has(blockName)) return false; ObjectId blkId=bt[blockName]; BlockTableRecord btr = null; if (string.IsNullOrEmpty(layoutName)) btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead); else { ObjectId layoutId = layoutManager.GetLayoutId(layoutName); Layout layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead); btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead); } BlockReference blkRef = new BlockReference(insPnt, blkId); btr.UpgradeOpen(); btr.AppendEntity(blkRef); tr.AddNewlyCreatedDBObject(blkRef, true); tr.Commit(); } return true; }
The layouts are initialized.
The block I was testing has multiple visibility states. When I switched to a block with no visibilty states defined it ran perfectly. Now I have to use more if my google skills to find some examples to deal with inserting dynamic blocks.
Thanks for your help.
Can't find what you're looking for? Ask the community or share your knowledge.